Skip to main content

LogRecord fields

The internal representation of a log line. Every binding exposes a typed LogRecord dataclass with the fields below; wire serialisation lives in separate functions (see Wire formats).

Field table​

FieldTypeOptionalDefaultSet byMeaning
time_unix_nanoint (uint64)notime.time_ns() at emitproducerEmit timestamp, nanoseconds since Unix epoch (OTel TimeUnixNano).
severity_numberintno—callerOTel severity 1-24.
severity_textstrnoderived from severity_numberbindingOne of six canonical strings (TRACE, DEBUG, INFO, WARN, ERROR, FATAL).
bodyValueno—callerPrimary message — string or structured (map/array/scalar).
attributesdict[str, Value]yes{}caller + bindingPer-record key-value context. Redaction applies before fan-out.
instrumentation_scopeInstrumentationScope?yesnullbindingLogger self-descriptor (name, version). Set when Logger.get(name, version) is used.
resourceResource?yesnullbindingProcess/service/host attributes. Inherited from the root logger after configure(resource_attributes=...).
trace_idbytes(16)?yesnullbindingW3C Trace Context — 16 random bytes. Filled from the OTel context if a span is active.
span_idbytes(8)?yesnullbindingW3C Trace Context — 8 random bytes. Same source as trace_id.
trace_flagsint (uint8)no0bindingW3C flags (sampled bit, etc.). 0 = not-sampled.
observed_time_unix_nanoint? (uint64)yesnullsink (on ingest)Ingest timestamp at the sink. Producer leaves null; sink fills it before wire serialisation (per spec §1).

The Value type​

Value is a recursive sum type used for body and attribute values. Concrete shape:

Value = str | int | float | bool | null | dict[str, Value] | list[Value]

The same shape backs ConfigTree in config-spec §1; consumers may reuse a single language-level type to represent both. Values are JSON-serialisable (the Value set is exactly the JSON value set).

InstrumentationScope​

Self-descriptor for the logger that emitted the record:

FieldTypeMeaning
namestrLogger name (matches Logger.get(name) argument).
versionstr?Semantic version, set by Logger.get(name, version).
attributesdict[str, Value]Optional scope-level attributes.

For records emitted by a plugin, the scope is recommended to match the plugin's id and version from its PluginManifest (see dagstack/plugin-system-spec).

Resource​

Process-level attributes shared across every logger in the process:

FieldTypeMeaning
attributesdict[str, Value]OTel Resource attributes — service.name, service.version, service.instance.id, deployment.environment, host.name, process.pid, telemetry.sdk.{name,version,language}, etc.

A binding detects Resource attributes through:

  1. OTel autodetect (OTEL_RESOURCE_ATTRIBUTES env var, OTel Resource Detectors).
  2. Explicit config from the logging.resource.* section.
  3. Merge: env-detected ∪ config-supplied (config wins).

Field ownership​

Per spec §1 ownership rules:

  • Caller sets severity_number, body, optional attributes. The caller never sets time_unix_nano directly; the binding fills it at emit.
  • Binding fills time_unix_nano, severity_text, instrumentation_scope, resource, trace_id, span_id, trace_flags, plus any attributes injected via Baggage propagation.
  • Sink fills observed_time_unix_nano if the producer left it null. Doing so guarantees that wire output always carries an ingest timestamp.

Wire encoding overview​

The same field set serialises to three wire formats with format-specific encoding rules. See Wire formats for the full table; a short version:

FieldOTLP protobufOTel JSONdagstack JSON-lines
time_unix_nanofixed64string-decimalint (Canonical JSON allows int64)
trace_idbytes(16)lowercase 32-hexlowercase 32-hex
span_idbytes(8)lowercase 16-hexlowercase 16-hex
severity_numberintintint
severity_textstringstringstring
Casing(binary)camelCasesnake_case

See also​