Marreta emits structured JSON logs. There are two kinds: a request record for every HTTP
call the server handles, and an app_log record for each message your code emits. Both
carry a trace id, so you can follow a single request across all of its log lines.
Emit your own logs
Use the log namespace, which has info, warn, and
error:
route GET "/work"
log.info("starting work")
result = 21 * 2
log.warn("about to finish")
reply 200, { result: result }Each call produces an app_log record with the level and your message in data:
{"timestamp":"2026-06-06T18:00:42Z","kind":"app_log","level":"info","trace_id":"0a85c287...","span_id":"4978d297...","data":"starting work"}
{"timestamp":"2026-06-06T18:00:42Z","kind":"app_log","level":"warn","trace_id":"0a85c287...","span_id":"4978d297...","data":"about to finish"}Every request is logged
The server logs one request record per HTTP call, with the method, path, status, and
duration:
{"timestamp":"2026-06-06T18:00:42.809Z","kind":"request","trace_id":"0a85c287...","span_id":"4978d297...","method":"GET","path":"/work","route":"/work","status":200,"duration_ms":1.04}Notice the trace_id is the same as the two app_log lines above. The request and the logs
your code emitted while handling it share one trace, so you can group them. Turn the
per-request record off with MARRETA_REQUEST_LOG=false if you only want your own logs.
Tie a request’s logs together
Because the request line and every app_log it produced share one trace_id, you can pull a
single request’s whole story by that id. While developing, that is one filter on the JSON lines:
# every line for one request, in the order it happened
marreta serve | grep '"trace_id":"0a85c287'A log collector (Loki, CloudWatch, Datadog, and so on) does the same with a trace_id filter,
which is how you read one request end to end in production. The duration_ms on the request
line is that request’s total server time, so sorting requests by it is the first step when a
route feels slow.
Set the level
MARRETA_LOG_LEVEL filters by severity (debug, info, warn, error, default info).
Raising it to warn drops the info line and keeps the warn:
# Only warn and error app logs are emitted
MARRETA_LOG_LEVEL=warn marreta serveFollow a trace across services
Each request is assigned a trace, and the trace_id ties its logs together. With
MARRETA_TRACE_CONTEXT on (the default), an outbound http_client
request carries the W3C traceparent header, so a downstream service that also speaks trace
context continues the same trace instead of starting a new one. That is what lets you follow
one logical request across several services.
Notes
- Logs go to the process output as JSON lines, ready for any log collector to parse.
- The relevant variables (
MARRETA_LOG_LEVEL,MARRETA_REQUEST_LOG,MARRETA_TRACE_CONTEXT) are in the Configuration reference.