Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sample logs consistently with trace sampling #6814

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import io.opentelemetry.api.logs.LogRecordBuilder;
import io.opentelemetry.api.logs.Severity;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.api.trace.TraceFlags;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.internal.AttributesMap;
Expand Down Expand Up @@ -119,20 +121,24 @@ public void emit() {
this.observedTimestampEpochNanos == 0
? this.loggerSharedState.getClock().now()
: this.observedTimestampEpochNanos;
loggerSharedState
.getLogRecordProcessor()
.onEmit(
context,
SdkReadWriteLogRecord.create(
loggerSharedState.getLogLimits(),
loggerSharedState.getResource(),
instrumentationScopeInfo,
timestampEpochNanos,
observedTimestampEpochNanos,
Span.fromContext(context).getSpanContext(),
severity,
severityText,
body,
attributes));
SpanContext spanContext = Span.fromContext(context).getSpanContext();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole thing needs to be configurable.

For an approach consistent with tracing (which I think is a good baseline to consider), we need a new LogSampler interface analagous to Sampler.

The key should sample method might have a contract like:

boolean shouldSample(
      Context context,
      Severity severity,
      Value<?> body,
      Attributes attributes);

Notes:

  • Pass individual components of LogRecord instead of SdkReadWriteLogRecord so we can avoid allocations if shouldSample returns false. Also for consistency with tracing.
  • Omit resource, scope arguments for consistency with tracing
  • Omit timestamp, observed timesamp arguments for consistency with tracing
  • Omit severityText because it mostly duplicates severity
  • Return a boolean instead of the SamplingResult returned by tracing because log sampling is less complicated that trace sampling

With an interface like this, we could have built in samplers for common use cases. I.e. we could have a "trace based" sampler that retains logs if the span in context is sampled.

TraceFlags traceFlags = spanContext.getTraceFlags();
if (!traceFlags.isSampled()) {
loggerSharedState
.getLogRecordProcessor()
.onEmit(
context,
SdkReadWriteLogRecord.create(
loggerSharedState.getLogLimits(),
loggerSharedState.getResource(),
instrumentationScopeInfo,
timestampEpochNanos,
observedTimestampEpochNanos,
spanContext,
severity,
severityText,
body,
attributes));
}
}
}
Loading