Logging

Mayros registra i log in due posti:

  • Log su file (righe JSON) scritti dal Gateway.
  • Output console mostrato nei terminali e nella Control UI.

Questa pagina spiega dove si trovano i log, come leggerli e come configurare i livelli di log e i formati.

Dove si trovano i log

Per impostazione predefinita, il Gateway scrive un file di log rotante in:

/tmp/mayros/mayros-YYYY-MM-DD.log

La data utilizza il fuso orario locale dell'host del gateway.

Puoi sovrascriverlo in ~/.mayros/mayros.json:

json
{
  "logging": {
    "file": "/percorso/a/mayros.log"
  }
}

Come leggere i log

CLI: tail in tempo reale (consigliato)

Usa la CLI per seguire il file di log del gateway tramite RPC:

bash
mayros logs --follow

Modalità di output:

  • Sessioni TTY: righe di log strutturate, colorate e formattate.
  • Sessioni non-TTY: testo semplice.
  • --json: JSON delimitato da riga (un evento di log per riga).
  • --plain: forza testo semplice nelle sessioni TTY.
  • --no-color: disabilita i colori ANSI.

In modalità JSON, la CLI emette oggetti taggati con type:

  • meta: metadati stream (file, cursore, dimensione)
  • log: voce di log parsata
  • notice: hint di troncamento / rotazione
  • raw: riga di log non parsata

Se il Gateway non è raggiungibile, la CLI stampa un breve suggerimento per eseguire:

bash
mayros doctor

Control UI (web)

La scheda Logs della Control UI segue lo stesso file usando logs.tail. Vedi /web/control-ui per come aprirla.

Log solo canali

Per filtrare l'attività dei canali (WhatsApp/Telegram/ecc.), usa:

bash
mayros channels logs --channel whatsapp

Formati log

Log su file (JSONL)

Ogni riga nel file di log è un oggetto JSON. La CLI e la Control UI parsano queste voci per renderizzare output strutturato (ora, livello, sottosistema, messaggio).

Output console

I log console sono consapevoli del TTY e formattati per leggibilità:

  • Prefissi sottosistema (es. gateway/channels/whatsapp)
  • Colorazione livello (info/warn/error)
  • Modalità compatta o JSON opzionale

La formattazione console è controllata da logging.consoleStyle.

Configurazione logging

Tutta la configurazione del logging si trova in logging in ~/.mayros/mayros.json.

json
{
  "logging": {
    "level": "info",
    "file": "/tmp/mayros/mayros-YYYY-MM-DD.log",
    "consoleLevel": "info",
    "consoleStyle": "pretty",
    "redactSensitive": "tools",
    "redactPatterns": ["sk-.*"]
  }
}

Livelli di log

  • logging.level: livello log su file (JSONL).
  • logging.consoleLevel: livello verbosità console.

--verbose influisce solo sull'output console; non cambia i livelli di log su file.

Stili console

logging.consoleStyle:

  • pretty: user-friendly, colorato, con timestamp.
  • compact: output più stretto (migliore per sessioni lunghe).
  • json: JSON per riga (per processori di log).

Redazione

I riepiloghi degli strumenti possono oscurare token sensibili prima di raggiungere la console:

  • logging.redactSensitive: off | tools (predefinito: tools)
  • logging.redactPatterns: lista di stringhe regex per sovrascrivere il set predefinito

La redazione influisce solo sull'output console e non altera i log su file.

Diagnostica + OpenTelemetry

Le diagnostiche sono eventi strutturati e leggibili da macchina per le esecuzioni del modello e telemetria del flusso di messaggi (webhook, accodamento, stato sessione). Non sostituiscono i log; esistono per alimentare metriche, tracce e altri esportatori.

Gli eventi diagnostici vengono emessi in-process, ma gli esportatori si collegano solo quando diagnostica + il plugin esportatore sono abilitati.

OpenTelemetry vs OTLP

  • OpenTelemetry (OTel): il modello dati + SDK per tracce, metriche e log.
  • OTLP: il protocollo wire utilizzato per esportare dati OTel a un collector/backend.
  • Mayros esporta tramite OTLP/HTTP (protobuf) oggi.

Segnali esportati

  • Metriche: contatori + istogrammi (uso token, flusso messaggi, accodamento).
  • Tracce: span per uso modello + elaborazione webhook/messaggio.
  • Log: esportati su OTLP quando diagnostics.otel.logs è abilitato. Il volume di log può essere alto; tieni a mente logging.level e i filtri dell'esportatore.

Catalogo eventi diagnostici

Uso modello:

  • model.usage: token, costo, durata, contesto, provider/modello/canale, id sessione.

Flusso messaggi:

  • webhook.received: ingresso webhook per canale.
  • webhook.processed: webhook gestito + durata.
  • webhook.error: errori gestore webhook.
  • message.queued: messaggio accodato per elaborazione.
  • message.processed: risultato + durata + errore opzionale.

Coda + sessione:

  • queue.lane.enqueue: accodamento corsia coda comando + profondità.
  • queue.lane.dequeue: deaccodamento corsia coda comando + tempo attesa.
  • session.state: transizione stato sessione + motivo.
  • session.stuck: avviso sessione bloccata + età.
  • run.attempt: metadati tentativo/retry esecuzione.
  • diagnostic.heartbeat: contatori aggregati (webhook/coda/sessione).

Abilita diagnostica (senza esportatore)

Usa questo se vuoi eventi diagnostici disponibili per plugin o sink personalizzati:

json
{
  "diagnostics": {
    "enabled": true
  }
}

Flag diagnostica (log mirati)

Usa i flag per attivare log di debug extra e mirati senza alzare logging.level. I flag sono case-insensitive e supportano wildcard (es. telegram.* o *).

json
{
  "diagnostics": {
    "flags": ["telegram.http"]
  }
}

Override env (una tantum):

MAYROS_DIAGNOSTICS=telegram.http,telegram.payload

Note:

  • I log dei flag vanno nel file di log standard (lo stesso di logging.file).
  • L'output è ancora oscurato secondo logging.redactSensitive.
  • Guida completa: /diagnostics/flags.

Esporta su OpenTelemetry

Le diagnostiche possono essere esportate tramite il plugin diagnostics-otel (OTLP/HTTP). Questo funziona con qualsiasi collector/backend OpenTelemetry che accetti OTLP/HTTP.

json
{
  "plugins": {
    "allow": ["diagnostics-otel"],
    "entries": {
      "diagnostics-otel": {
        "enabled": true
      }
    }
  },
  "diagnostics": {
    "enabled": true,
    "otel": {
      "enabled": true,
      "endpoint": "http://otel-collector:4318",
      "protocol": "http/protobuf",
      "serviceName": "mayros-gateway",
      "traces": true,
      "metrics": true,
      "logs": true,
      "sampleRate": 0.2,
      "flushIntervalMs": 60000
    }
  }
}

Note:

  • Puoi anche abilitare il plugin con mayros plugins enable diagnostics-otel.
  • protocol attualmente supporta solo http/protobuf. grpc è ignorato.
  • Le metriche includono uso token, costo, dimensione contesto, durata esecuzione e contatori/istogrammi flusso messaggi (webhook, accodamento, stato sessione, profondità/attesa coda).
  • Tracce/metriche possono essere attivate con traces / metrics (predefinito: on). Le tracce includono span uso modello più span elaborazione webhook/messaggio quando abilitato.
  • Imposta headers quando il tuo collector richiede autenticazione.
  • Variabili d'ambiente supportate: OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_SERVICE_NAME, OTEL_EXPORTER_OTLP_PROTOCOL.

Metriche esportate (nomi + tipi)

Uso modello:

  • mayros.tokens (contatore, attr: mayros.token, mayros.channel, mayros.provider, mayros.model)
  • mayros.cost.usd (contatore, attr: mayros.channel, mayros.provider, mayros.model)
  • mayros.run.duration_ms (istogramma, attr: mayros.channel, mayros.provider, mayros.model)
  • mayros.context.tokens (istogramma, attr: mayros.context, mayros.channel, mayros.provider, mayros.model)

Flusso messaggi:

  • mayros.webhook.received (contatore, attr: mayros.channel, mayros.webhook)
  • mayros.webhook.error (contatore, attr: mayros.channel, mayros.webhook)
  • mayros.webhook.duration_ms (istogramma, attr: mayros.channel, mayros.webhook)
  • mayros.message.queued (contatore, attr: mayros.channel, mayros.source)
  • mayros.message.processed (contatore, attr: mayros.channel, mayros.outcome)
  • mayros.message.duration_ms (istogramma, attr: mayros.channel, mayros.outcome)

Code + sessioni:

  • mayros.queue.lane.enqueue (contatore, attr: mayros.lane)
  • mayros.queue.lane.dequeue (contatore, attr: mayros.lane)
  • mayros.queue.depth (istogramma, attr: mayros.lane o mayros.channel=heartbeat)
  • mayros.queue.wait_ms (istogramma, attr: mayros.lane)
  • mayros.session.state (contatore, attr: mayros.state, mayros.reason)
  • mayros.session.stuck (contatore, attr: mayros.state)
  • mayros.session.stuck_age_ms (istogramma, attr: mayros.state)
  • mayros.run.attempt (contatore, attr: mayros.attempt)

Span esportati (nomi + attributi chiave)

  • mayros.model.usage
    • mayros.channel, mayros.provider, mayros.model
    • mayros.sessionKey, mayros.sessionId
    • mayros.tokens.* (input/output/cache_read/cache_write/total)
  • mayros.webhook.processed
    • mayros.channel, mayros.webhook, mayros.chatId
  • mayros.webhook.error
    • mayros.channel, mayros.webhook, mayros.chatId, mayros.error
  • mayros.message.processed
    • mayros.channel, mayros.outcome, mayros.chatId, mayros.messageId, mayros.sessionKey, mayros.sessionId, mayros.reason
  • mayros.session.stuck
    • mayros.state, mayros.ageMs, mayros.queueDepth, mayros.sessionKey, mayros.sessionId

Campionamento + flushing

  • Campionamento tracce: diagnostics.otel.sampleRate (0.0–1.0, solo span radice).
  • Intervallo export metriche: diagnostics.otel.flushIntervalMs (min 1000ms).

Note protocollo

  • Gli endpoint OTLP/HTTP possono essere impostati tramite diagnostics.otel.endpoint o OTEL_EXPORTER_OTLP_ENDPOINT.
  • Se l'endpoint contiene già /v1/traces o /v1/metrics, viene usato così com'è.
  • Se l'endpoint contiene già /v1/logs, viene usato così com'è per i log.
  • diagnostics.otel.logs abilita l'export log OTLP per l'output del logger principale.

Comportamento export log

  • I log OTLP usano gli stessi record strutturati scritti in logging.file.
  • Rispettano logging.level (livello log file). La redazione console non si applica ai log OTLP.
  • Le installazioni ad alto volume dovrebbero preferire campionamento/filtraggio collector OTLP.

Suggerimenti per risoluzione problemi

  • Gateway non raggiungibile? Esegui prima mayros doctor.
  • Log vuoti? Verifica che il Gateway sia in esecuzione e scriva nel percorso file in logging.file.
  • Serve più dettaglio? Imposta logging.level a debug o trace e riprova.