Conversation
Introduce a reporter.ParcaReporter interface that extends otel's
TraceReporter with Logger(scope string) log.Logger so any producer
(uprobes or otherwise) can ship OTel log records through a shared gRPC
connection without owning its own pipeline.
The existing struct is renamed arrowReporter and now owns a
*sdklog.LoggerProvider built from:
- go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc as the
transport, configured with WithGRPCConn so it shares the connection
already established for profile data;
- sdklog.NewBatchProcessor for queue + batch + retry (size 512, age
250ms, queue depth 4096), tuned tighter than the SDK default so
individual events show up on the server within a few hundred ms;
- sdklog.WithResource fills service.name = "parca-agent",
service.version = build VCS revision, host.name = agent --node.
Constructed only when a gRPC conn is provided; offline mode returns the
OTel no-op Logger so callers can use Logger() unconditionally and emit
calls become inert.
Also fold in per-sample relabeling for probe-origin trace samples:
labelsForTID now runs a second relabel.ProcessBuilder pass against the
patched per-sample labels (thread_id, thread_name, cpu) when meta.Origin
is TraceOriginProbe, so relabel rules can derive custom labels from
per-sample fields without touching the cached per-PID fast path used by
CPU/off-CPU/memory/cuda samples.
When set, install a logrus hook on the global logger that converts each
entry to an OTel log.Record and emits it via a Logger obtained from the
shared LoggerProvider (scope "parca-agent.agent"), so logrus calls flow
alongside probe events and any other log producers through the same
batch processor and gRPC connection. The hook captures every level
logrus emits — actual filtering is left to the logger's own configuration.
Severity/SeverityText come straight from the logrus level, and a `level`
attribute is always emitted alongside (the OTLP server doesn't store
severity_text, so the attribute is the only way to filter by level
downstream).
OTLPSkipField ("otlp_skip") is a tagged opt-out: entries with this
field set to true are dropped before emit. Used by the probes service's
per-fire debug logging to avoid double-shipping the same event (once as
a probe record, once as an agent log).
In offline mode (no remote-store), the flag logs a one-shot warning at
startup and otherwise behaves as off, since the LoggerProvider is itself
absent in that case and Logger() returns the no-op variant.
metalmatze
approved these changes
Jun 17, 2026
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds OTLP/gRPC logs support to parca-agent so any in-process producer
(the eBPF probes service in PR #3181, the agent's own logrus output via
the new
--otlp-loggingflag) can ship structured log records over thesame gRPC connection already used for profile data.
Built on the upstream OTel Go SDK (
sdklog.LoggerProvider+otlploggrpc.Exporter), so retry, backoff, queue, batch, andPartialSuccess handling come from the SDK rather than being
hand-rolled.
Commits
reporter: add ParcaReporter log-event interface and per-sample relabelParcaReporterinterface extending OTel'sTraceReporterwithLogger(scope string) log.Logger. Producers obtain a per-scopelog.Loggerand emit records directly.arrowReporterand now owns a*sdklog.LoggerProvider. The provider usesotlploggrpc.New(... WithGRPCConn(conn))so it shares the agent's existing gRPCconnection.
sdklog.NewBatchProcessorconfigured with size 512 / age 250 ms /queue depth 4096 — tighter than the SDK default so individual events
land on the server within a few hundred ms.
sdklog.WithResourcefillsservice.name,service.version,host.nameas required attributes.calls become inert and producers don't need an extra nil check.
(
labelsForTIDruns a secondrelabel.ProcessBuilderagainstpatched per-sample labels when
meta.Origin == TraceOriginProbe).reporter: --otlp-logging flag forwards agent logs over OTLP--otlp-loggingflag, default off. When set, installs a logrushook that converts each entry to an OTel
log.Recordand emits viaLogger(\"parca-agent.agent\").levelattribute is always emitted so consumers can filter by level even
though the OTLP server doesn't store severity_text directly.
OTLPSkipField("otlp_skip") is an opt-out: entries tagged withthis field set to true are dropped before emit. Used by the probes
service's per-fire debug logging to avoid double-shipping.
off, since
Logger()returns the no-op variant.gRPC codec extension
flags/codec.gogains handling for pdata'sSizeProto/MarshalProtoshape so the global vtproto codec doesn't reject the pdata-typed
requests
otlploggrpcsends. No change in behavior for existingprofile-data paths (which use vtproto or gogoproto).
Test plan
cover the logrus hook (severity / attribute / skip-field / level
mapping) using an in-process `captureExporter` + SDK
`SimpleProcessor`
agent logs flow as OTLP records under `attributes_resource.host.name`
profile-data path (no second TCP/TLS handshake) — `WithGRPCConn`
should make this trivial to verify with `ss -tnp`
Stacked on
PR #3181 (`simple-probes-v1`) rebases on top of this branch and adds
the eBPF probes service as a third Logger consumer.