boltZharp Docs
sellLogs

Tags & parsing

Every line is filed under a service, and can carry an environment, a version and a source. The source decides how Zharp reads fields out of the line.

Unified service tagging

Three tags tie a log line, a metric and a trace from the same deployment together: service, env and version. Logs also carry a source — the technology that wrote them (nginx, postgresql, java, json …). In Zharp they're the OpenTelemetry resource attributes service.name, deployment.environment.name (the older deployment.environment is read too), service.version and zharp.source. Log monitors can be scoped to an environment and a source, and the API's log query filters on all four.

WhereServiceEnvironmentVersionSource
Environment variables (container or sidecar)ZHARP_SERVICEZHARP_ENVZHARP_VERSIONZHARP_SOURCE (sidecar)
Docker labelszharp.servicezharp.envzharp.versionzharp.source
Kubernetes pod annotationszharp.io/servicezharp.io/envzharp.io/versionzharp.io/source
Zharp SDK optionsserviceenvironmentrelease—
OpenTelemetry resourceservice.namedeployment.environment.nameservice.versionzharp.source
HTTP APIserviceenv / environmentversionsource

A container's labels — or the ZHARP_* variables set on it — name its logs; without them the agent uses the Compose service (or container name) and, for well-known images such as nginx, postgres, redis or mongo, sets the source from the image. In Kubernetes, annotate the pod; app.kubernetes.io/name and app.kubernetes.io/version are the fallbacks, and a pod with several containers can tag each one with zharp.io/<container>.env and so on.

docker-compose.yml
services:
  checkout:
    image: ghcr.io/acme/checkout:1.4.2
    labels:
      zharp.service: checkout
      zharp.env: prod
      zharp.version: "1.4.2"
      zharp.source: node
Pod annotations
metadata:
  annotations:
    zharp.io/service: checkout
    zharp.io/env: prod
    zharp.io/version: "1.4.2"
    zharp.io/source: node
    # one container of several: zharp.io/<container>.service, .env, .version, .source

An app instrumented with OpenTelemetry sets the same tags as resource attributes, and they reach logs, metrics and traces alike:

OpenTelemetry SDK
OTEL_RESOURCE_ATTRIBUTES="service.name=checkout,deployment.environment.name=prod,service.version=1.4.2"

Untagged lines still arrive; tags are never required. Tags are stored as sent (up to 128 characters), so prod and production are two environments — pick one spelling.

Parsed formats

When a line arrives, its source picks a parser; a line without one is recognised by its shape. What the parser finds is stored beside the message — the message itself is never changed — and is included in the log's metadata. Search on it from the Logs page with an @, as in @http.status_code>=500. When the line states a level, that level is kept: a 5xx in an access log is error, a 4xx warn, a JSON level field is read as is. A level you send explicitly (anything other than info) wins over the line.

SourceRecognisedFields
nginxAccess log (combined / common, with $request_time or rt=/urt= appended) and error loghttp.method http.path http.status_code bytes client.ip http.user_agent http.referer duration_ms
apacheAccess log (common / combined, %D appended) and error log (2.2 and 2.4)the access-log fields, plus apache.module error.code process.pid on error lines
postgresqlDefault log_line_prefix (%m [%p]) and Debian's %m [%p] %q%u@%dduration_ms db.statement db.user db.name error.message process.pid
mysqlError log, 5.5 to 8.xerror.code (MY-…) mysql.subsystem mysql.thread_id error.message
redisServer log (pid:role date level message), and pre-3.0redis.role process.pid; level from . - * #
mongodbStructured JSON log (4.4+)mongodb.component duration_ms (slow queries) db.name db.collection client.ip attr.*
jsonAny line that is one JSON object (pino, bunyan, winston, zap, structlog …)every field flattened to dotted keys, with http.* duration_ms error.* trace_id taken from their common names
logfmtLines of key=value pairs (logrus, Heroku router …)every pair, with the same common names mapped
javaSpring Boot and Logback/Log4j default patterns; stack traceslogger.name thread.name error.type error.message error.stack
pythonThe logging module's common formats; tracebackslogger.name error.type error.message error.stack
node, goJSON or logfmt first; then uncaught errors with a stack, Go panics and the standard loggererror.type error.message error.stack

Lines over 16 KB aren't parsed (they're still stored), parsers read the first line of a multi-line message (stack traces are searched further), and a line keeps at most 64 parsed fields of up to 1,024 characters each. A detected format also sets the source when you didn't send one — except plain access logs, which nginx and Apache share.

Next