OpenTelemetry Logs Are Finally Ready — Here Is What You Need to Know
Structured logs. Clear thinking. After years of waiting, the OpenTelemetry (OTel) Logs Specification has matured into a production-ready standard. Here is how it changes the game and how LogKit integrates with it.
The Long Wait
When OpenTelemetry first burst onto the scene, it promised a unified standard for observability signals: Traces, Metrics, and Logs. For the first two years, Traces and Metrics raced ahead, fully supported in every major tooling stack. Logs, however, were often treated as an afterthought or an "append-only" text stream.
This created a disjointed experience for developers. You had to stitch together Traces to find the relevant Logs, or rely on vendor-specific exporters that didn't play nice with the OTel ecosystem. The wait for a unified OTel Logs Specification (v1.0) has finally ended, and the outcome is a data model that treats logs as first-class citizens rather than strings.
What Changed in the Spec
The new OTel Logs specification introduces the LogRecord. This isn't just a log line; it's a structured object containing:
- Timestamp: Nanosecond precision time when the event occurred.
- Severity: A standardized numeric severity (Trace, Debug, Info, Warn, Error, Fatal).
- Attributes: Key-value pairs describing the event context (e.g.,
http.method,user.id). - Body: The actual log message, which can be a string or a structured JSON object.
LogKit Meets OTel
Integrating OTel-compatible logging into your stack shouldn't require a new abstraction layer. With LogKit, emitting OTel logs is as simple as initializing a logger with the OTel exporter. Below is a four-line implementation in Go that emits logs compatible with the OTel collector.
log := logkit.New(
logkit.WithExporter(logkit.NewOTelExporter(
logkit.WithEndpoint("http://localhost:4317"),
logkit.WithServiceName("api-gateway"),
)),
)
// Emit OTel-compliant log record
log.Info("order.processed",
"trace_id", "a1b2c3d4",
"order_id", "992810",
"amount_usd", 49.50,
)
Exporting to Your Stack
One of the biggest wins of the OTel standard is the ecosystem of exporters. You are no longer locked into a single vendor. LogKit's OTel exporter can route logs to:
- Grafana Loki: Use the OTel Receiver to ingest logs into Loki for cheap, scalable log storage.
- Datadog: Leverage the Datadog OTel Collector to push logs directly into Datadog with full context.
- The OTel Collector: A central pipeline to filter, transform, and ship logs anywhere (Elasticsearch, Splunk, your own DB).
Gotchas & Implementation Lessons
While the spec is stable, we noticed a few patterns when migrating legacy logs to OTel:
- Severity Mapping: Be explicit when mapping application levels (INFO, WARN, ERROR) to OTel severity numbers. Vendors like Datadog interpret these differently; OTel is the source of truth.
- Attribute Limits: OTel has a hard limit of 128 attributes per log record. If you're passing massive JSON blobs as attributes, you'll hit this limit. LogKit enforces this check at the SDK level to prevent dropped logs.
- Timestamps: OTel expects UTC timestamps. Ensure your application's time zone configuration doesn't drift your logs by hours during daylight savings transitions.
Related Articles
Why Structured Logging Matters
Understanding how indexing and searchability are built into the architecture.
Getting Started with LogKit
A 5-minute guide to integrating LogKit into your existing Node.js or Go services.
Ready to modernize your logging?
Join 2,000+ engineers using LogKit to debug faster and ship with confidence.