Skip to main content
Under Reviewv0.1.0-alpha

Logs

AxCom uses the pkg/logger package for all structured logging. Every log line produced in production is a JSON object conforming to Elastic Common Schema (ECS) 8.11, ready for ingestion by the OTel Collector → Loki pipeline.

For Go API usage (how to call the logger from application code), see pkg/logger.


Log Formats

Two formats are available, resolved dynamically based on the APP_ENV environment variable.

text - Development

Human-readable, colour-coded terminal output. Not suitable for log shippers.

2026-06-28 14:32:01.123 INFO server started on port 8080
2026-06-28 14:32:05.456 ERROR payment failed: connection refused trace_id=abc123 span_id=def456

json — Production (ECS)

Each log line is a self-contained JSON object. Produced when LOG_FORMAT=json.

{
"@timestamp": "2026-06-28T14:32:05.456Z",
"log.level": "error",
"message": "payment failed: connection refused",
"service.name": "ecom-engine",
"ecs.version": "8.11",
"trace.id": "4bf92f3577b34da6a3ce929d0e0e4736",
"span.id": "00f067aa0ba902b7"
}

ECS Field Reference

FieldTypeAlways presentDescription
@timestampISO 8601 stringYesLog emission time in UTC
log.levelstringYesdebug, info, warn, error
messagestringYesThe log message
service.namestringYesValue of SERVICE_NAME env var (default: ecom-engine)
ecs.versionstringYesAlways 8.11
trace.idhex stringWhen span activeW3C TraceID of the active OTel span
span.idhex stringWhen span activeW3C SpanID of the active OTel span
additional fieldsanyWhen logged with With()Module names, IDs, or any extra key-value pairs

The slog attributes trace_id and span_id are automatically remapped to ECS field names trace.id and span.id by the ECS handler.


Log Levels

LevelWhen to use
debugDetailed internal state - cache keys, SQL queries, loop counters. Off by default (LOG_LEVEL=debug to enable).
infoNormal operational events - server start, request handled, order placed.
warnDegraded state that does not require immediate action - cache miss rate elevated, retry attempted.
errorAction required - unhandled error, external service failure, data inconsistency.

The minimum log level is set automatically based on the APP_ENV environment variable.


Log-to-Trace Correlation

When a request has an active OpenTelemetry span (i.e. OTEL_ENABLED=true), the *Ctx logger methods automatically extract the trace and span IDs and attach them to the log line.

// In a handler — ctx carries the active OTel span
logger.ErrorCtx(ctx, "payment failed: %v", err)

This produces:

{
"@timestamp": "2026-06-28T14:32:05.456Z",
"log.level": "error",
"message": "payment failed: connection timeout",
"service.name": "ecom-engine",
"ecs.version": "8.11",
"trace.id": "4bf92f3577b34da6a3ce929d0e0e4736",
"span.id": "00f067aa0ba902b7"
}

In Grafana:

  1. Open the Logs dashboard and find the error log line.
  2. Click the trace.id value — Grafana opens the corresponding Tempo trace.
  3. From the trace, click any span to inspect its timing and attributes.

If OTEL_ENABLED=false or no active span exists, trace.id and span.id are simply omitted logging continues normally.


Structured Fields with With()

Attach fixed context fields to every log line from a component:

log := logger.With("module", "checkout", "order_id", orderID)

log.InfoCtx(ctx, "payment initiated")
// → { "message": "payment initiated", "module": "checkout", "order_id": "ord_..." }

log.ErrorCtx(ctx, "payment failed: %v", err)
// → { "message": "payment failed: ...", "module": "checkout", "order_id": "ord_..." }

Log Pipeline

App (stdout JSON) → Docker log driver → OTel Collector filelog receiver
→ Loki (push)
→ Grafana (query)

The OTel Collector uses a filelog receiver to tail Docker JSON log files. Structured fields in the JSON log are parsed automatically — no additional parsing configuration is needed.


Configuration Reference

Env VarValuesDefaultDescription
APP_ENVproduction, staging, development, testdevelopmentSets log level, log format, and Gin mode dynamically.
SERVICE_NAMEstringecom-engineInjected as service.name in ECS output
GIN_MODErelease, debug, test(dynamic)Sets Gin's mode. Overrides the default set by APP_ENV.

Environment Mapping

Environment (APP_ENV)Log LevelFormatGin Mode
production / prodinfojsonrelease
staging / stageinfojsonrelease
development / dev / (empty)debugtextdebug
test / testingdebugtexttest

Loki in Grafana

The Logs dashboard (ecom-engine-logs) provides:

  • Log Events by Level - timeseries panel showing error/warn/info/debug volume over time
  • Log Level Distribution - pie chart of proportions across the selected time range
  • Live Log Stream - raw log panel with multi-select level filter and trace ID search

Use the Log Level variable at the top of the dashboard to filter to error or warn during an incident.

For the full dashboard description, see Dashboards → Logs.