Skip to content

Add OTLP log sink - #541

Open
jeremyudis wants to merge 2 commits into
pinterest:masterfrom
jeremyudis:add-otlp-log-sink
Open

Add OTLP log sink#541
jeremyudis wants to merge 2 commits into
pinterest:masterfrom
jeremyudis:add-otlp-log-sink

Conversation

@jeremyudis

Copy link
Copy Markdown

Summary

  • Adds a standalone OtlpWriter LogStreamWriter that exports log messages directly to an OpenTelemetry collector over OTLP/gRPC or OTLP/HTTP (JSON or protobuf), with retry/backoff, request-size-based batch splitting, and optional Docker JSON / CRI container-log unwrapping for Kubernetes pod logs.
  • Wires up the previously dead KafkaWriterConfig.messageFormat/otlpFormatConfig schema so kafka.messageFormat=otlp_json/otlp_proto actually serializes Kafka record values as single-record OTLP envelopes instead of silently writing raw bytes.
  • Fixes the injected messageCRC Kafka header to reflect the actual record value (the OTLP envelope, when configured) rather than always the pre-transform raw bytes, so downstream consumers recomputing CRC32 over what they read from Kafka get a match. RAW format (the default) is unaffected.

Test plan

  • mvn test -pl singer -Dtest=TestOtlpConfigParsing,com.pinterest.singer.writer.otlp.* (44 tests) — config parsing, container log parsers, gRPC exporter against a real in-process gRPC server, HTTP exporter against a real HttpServer, log record conversion, writer batching/retry/backoff/partial-success semantics.
  • mvn test -pl singer -Dtest=TestKafkaWriter,TestCommittableKafkaWriter (20 tests) — both Kafka write paths route through the OTLP formatter when configured and are unchanged for the RAW default; messageCRC header now matches the actual record value.
  • mvn clean package -pl singer -am -DskipTests — full module build.
  • Verified the four pre-existing DefaultLogStreamProcessorTest/TestMemoryEfficientLogStreamProcessor failures seen in a full mvn test run are present on master too (unrelated to this change) by reverting these commits locally and re-running.

Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com

🤖 Generated with Claude Code

https://claude.ai/code/session_01JuL9Hi8NSsf2sAhdJf1p4N

jeremyudis and others added 2 commits September 9, 2026 23:59
Adds a standalone OtlpWriter (LogStreamWriter) that exports log messages
to an OpenTelemetry collector over OTLP/gRPC or OTLP/HTTP (JSON or
protobuf), alongside the existing Kafka/S3/Pulsar writers.

- OtlpWriter: batch and committable write paths, exponential backoff on
  retryable failures, request splitting by max size, OTLP partial-success
  handling per spec.
- OtlpGrpcExporter / OtlpHttpExporter behind a shared OtlpExporter
  transport interface; OtlpChannelManager shares one gRPC channel per
  endpoint, mirroring KafkaProducerManager.
- OtlpLogRecordConverter maps LogMessage -> OTLP LogRecord/Resource,
  including k8s pod metadata as semantic-convention attributes and
  optional Docker JSON / CRI container log unwrapping.
- New WriterType.OTLP config schema (OtlpWriterConfig, OtlpFormatConfig,
  ContainerLogFormat) plus config parsing and DefaultLogMonitor wiring.
- Also adds the KafkaMessageFormat/OtlpFormatConfig schema and config
  parsing for an OTLP envelope mode on the Kafka writer (wired up to
  KafkaWriter in a follow-up commit).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JuL9Hi8NSsf2sAhdJf1p4N
The KafkaWriterConfig.messageFormat/otlpFormatConfig schema and parsing
already existed but nothing in KafkaWriter or CommittableKafkaWriter ever
used them, so kafka.messageFormat=otlp_json/otlp_proto silently wrote raw
bytes instead of the OTLP envelope.

- KafkaWriter#initOtlpMessageFormat builds an OtlpMessageFormatter when
  messageFormat != RAW; #serializeValue routes both the batch
  (messageCollation) and committable (CommittableKafkaWriter) write paths
  through it. DefaultLogMonitor now calls this after constructing either
  writer variant.
- The injected "messageCRC" Kafka header is now computed from the actual
  record value (the OTLP envelope, when configured) instead of always
  using the pre-transform raw-bytes checksum, so a consumer recomputing
  CRC32 over what it received from Kafka gets a match. RAW format is
  unaffected (record value and raw bytes are identical).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JuL9Hi8NSsf2sAhdJf1p4N
@jeremyudis
jeremyudis requested a review from a team as a code owner September 10, 2026 06:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant