Skip to content
Closed
Show file tree
Hide file tree
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
33 changes: 33 additions & 0 deletions .github/workflows/dependency-submission.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# This workflow submits dependency information to GitHub's dependency graph
# for analysis by security features like Dependabot, security advisories, and supply chain reports.
# It runs on the default branch to ensure accurate dependency information is submitted.
#
# Source: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/configuring-automatic-dependency-submission-for-your-repository

name: Dependency submission

on:
push:
branches:
- main

permissions:
contents: read

jobs:
dependency-submission:
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Set up JDK
uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1
with:
distribution: temurin
java-version: 17

- name: Generate and submit dependency graph
uses: gradle/actions/dependency-submission@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ final class ExtendedSdkLogRecordBuilder extends SdkLogRecordBuilder

@Nullable private ExtendedAttributesMap extendedAttributes;

ExtendedSdkLogRecordBuilder(
LoggerSharedState loggerSharedState, InstrumentationScopeInfo instrumentationScopeInfo, @Nullable SdkLogger logger) {
super(loggerSharedState, instrumentationScopeInfo, logger);
}

// Backward compatible constructor
ExtendedSdkLogRecordBuilder(
LoggerSharedState loggerSharedState, InstrumentationScopeInfo instrumentationScopeInfo) {
super(loggerSharedState, instrumentationScopeInfo);
Expand Down Expand Up @@ -133,6 +139,23 @@ public void emit() {
return;
}
Context context = this.context == null ? Context.current() : this.context;

// Apply filtering rules if logger is available
if (logger != null) {
// 1. Check minimum severity level
if (severity != Severity.UNDEFINED_SEVERITY_NUMBER && severity.getSeverityNumber() < logger.minimumSeverity) {
return;
}

// 2. Check trace-based filtering
if (logger.traceBased) {
Span span = Span.fromContext(context);
if (span.getSpanContext().isValid() && !span.getSpanContext().getTraceFlags().isSampled()) {
return;
}
}
}

long observedTimestampEpochNanos =
this.observedTimestampEpochNanos == 0
? this.loggerSharedState.getClock().now()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.logs.internal.LoggerConfig;
import javax.annotation.Nullable;

/**
* Utilities for interacting with {@code io.opentelemetry:opentelemetry-api-incubator}, which is not
Expand All @@ -25,7 +26,7 @@ static SdkLogger createExtendedLogger(
}

static SdkLogRecordBuilder createExtendedLogRecordBuilder(
LoggerSharedState loggerSharedState, InstrumentationScopeInfo instrumentationScopeInfo) {
return new ExtendedSdkLogRecordBuilder(loggerSharedState, instrumentationScopeInfo);
LoggerSharedState loggerSharedState, InstrumentationScopeInfo instrumentationScopeInfo, @Nullable SdkLogger logger) {
return new ExtendedSdkLogRecordBuilder(loggerSharedState, instrumentationScopeInfo, logger);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class SdkLogRecordBuilder implements LogRecordBuilder {

protected final LoggerSharedState loggerSharedState;
protected final LogLimits logLimits;
@Nullable protected final SdkLogger logger;

protected final InstrumentationScopeInfo instrumentationScopeInfo;
protected long timestampEpochNanos;
Expand All @@ -34,10 +35,17 @@ class SdkLogRecordBuilder implements LogRecordBuilder {
@Nullable private AttributesMap attributes;

SdkLogRecordBuilder(
LoggerSharedState loggerSharedState, InstrumentationScopeInfo instrumentationScopeInfo) {
LoggerSharedState loggerSharedState, InstrumentationScopeInfo instrumentationScopeInfo, @Nullable SdkLogger logger) {
this.loggerSharedState = loggerSharedState;
this.logLimits = loggerSharedState.getLogLimits();
this.instrumentationScopeInfo = instrumentationScopeInfo;
this.logger = logger;
}

// Backward compatible constructor for existing usages
SdkLogRecordBuilder(
LoggerSharedState loggerSharedState, InstrumentationScopeInfo instrumentationScopeInfo) {
this(loggerSharedState, instrumentationScopeInfo, null);
}

@Override
Expand Down Expand Up @@ -121,6 +129,23 @@ public void emit() {
return;
}
Context context = this.context == null ? Context.current() : this.context;

// Apply filtering rules if logger is available
if (logger != null) {
// 1. Check minimum severity level
if (severity != Severity.UNDEFINED_SEVERITY_NUMBER && severity.getSeverityNumber() < logger.minimumSeverity) {
return;
}

// 2. Check trace-based filtering
if (logger.traceBased) {
Span span = Span.fromContext(context);
if (span.getSpanContext().isValid() && !span.getSpanContext().getTraceFlags().isSampled()) {
return;
}
}
}

long observedTimestampEpochNanos =
this.observedTimestampEpochNanos == 0
? this.loggerSharedState.getClock().now()
Expand Down
31 changes: 28 additions & 3 deletions sdk/logs/src/main/java/io/opentelemetry/sdk/logs/SdkLogger.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import io.opentelemetry.api.logs.Logger;
import io.opentelemetry.api.logs.LoggerProvider;
import io.opentelemetry.api.logs.Severity;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.context.Context;
import io.opentelemetry.sdk.common.InstrumentationScopeInfo;
import io.opentelemetry.sdk.logs.internal.LoggerConfig;
Expand Down Expand Up @@ -36,6 +38,8 @@ class SdkLogger implements Logger {
// deliberately not volatile because of performance concerns
// - which means its eventually consistent
protected boolean loggerEnabled;
protected int minimumSeverity;
protected boolean traceBased;

SdkLogger(
LoggerSharedState loggerSharedState,
Expand All @@ -44,6 +48,8 @@ class SdkLogger implements Logger {
this.loggerSharedState = loggerSharedState;
this.instrumentationScopeInfo = instrumentationScopeInfo;
this.loggerEnabled = loggerConfig.isEnabled();
this.minimumSeverity = loggerConfig.getMinimumSeverity();
this.traceBased = loggerConfig.isTraceBased();
}

static SdkLogger create(
Expand All @@ -60,8 +66,8 @@ public LogRecordBuilder logRecordBuilder() {
if (loggerEnabled) {
return INCUBATOR_AVAILABLE
? IncubatingUtil.createExtendedLogRecordBuilder(
loggerSharedState, instrumentationScopeInfo)
: new SdkLogRecordBuilder(loggerSharedState, instrumentationScopeInfo);
loggerSharedState, instrumentationScopeInfo, this)
: new SdkLogRecordBuilder(loggerSharedState, instrumentationScopeInfo, this);
}
return NOOP_LOGGER.logRecordBuilder();
}
Expand All @@ -73,10 +79,29 @@ InstrumentationScopeInfo getInstrumentationScopeInfo() {

// Visible for testing
public boolean isEnabled(Severity severity, Context context) {
return loggerEnabled;
if (!loggerEnabled) {
return false;
}

// Check minimum severity level
if (severity != Severity.UNDEFINED_SEVERITY_NUMBER && severity.getSeverityNumber() < minimumSeverity) {
return false;
}

// Check trace-based filtering
if (traceBased) {
SpanContext spanContext = Span.fromContext(context).getSpanContext();
if (spanContext.isValid() && !spanContext.getTraceFlags().isSampled()) {
return false;
}
}

return true;
}

void updateLoggerConfig(LoggerConfig loggerConfig) {
loggerEnabled = loggerConfig.isEnabled();
minimumSeverity = loggerConfig.getMinimumSeverity();
traceBased = loggerConfig.isTraceBased();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
public abstract class LoggerConfig {

private static final LoggerConfig DEFAULT_CONFIG =
new AutoValue_LoggerConfig(/* enabled= */ true);
new AutoValue_LoggerConfig(/* enabled= */ true, /* minimumSeverity= */ 0, /* traceBased= */ false);
private static final LoggerConfig DISABLED_CONFIG =
new AutoValue_LoggerConfig(/* enabled= */ false);
new AutoValue_LoggerConfig(/* enabled= */ false, /* minimumSeverity= */ 0, /* traceBased= */ false);

/** Returns a disabled {@link LoggerConfig}. */
public static LoggerConfig disabled() {
Expand All @@ -44,6 +44,33 @@ public static LoggerConfig enabled() {
return DEFAULT_CONFIG;
}

/**
* Returns a {@link LoggerConfig} with the specified parameters.
*
* @param enabled whether the logger is enabled
* @param minimumSeverity minimum severity level for log records to be processed (default 0)
* @param traceBased whether to only process log records from sampled traces (default false)
*/
public static LoggerConfig create(boolean enabled, int minimumSeverity, boolean traceBased) {
return new AutoValue_LoggerConfig(enabled, minimumSeverity, traceBased);
}

/**
* Returns a {@link LoggerConfig} with the specified minimum severity level.
*
* @param minimumSeverity minimum severity level for log records to be processed
*/
public static LoggerConfig withMinimumSeverity(int minimumSeverity) {
return create(/* enabled= */ true, minimumSeverity, /* traceBased= */ false);
}

/**
* Returns a {@link LoggerConfig} with trace-based filtering enabled.
*/
public static LoggerConfig withTraceBased() {
return create(/* enabled= */ true, /* minimumSeverity= */ 0, /* traceBased= */ true);
}

/**
* Returns the default {@link LoggerConfig}, which is used when no configurator is set or when the
* logger configurator returns {@code null} for a {@link InstrumentationScopeInfo}.
Expand All @@ -64,4 +91,18 @@ public static ScopeConfiguratorBuilder<LoggerConfig> configuratorBuilder() {

/** Returns {@code true} if this logger is enabled. Defaults to {@code true}. */
public abstract boolean isEnabled();

/**
* Returns the minimum severity level for log records to be processed.
* Log records with severity below this level are dropped.
* Defaults to {@code 0}.
*/
public abstract int getMinimumSeverity();

/**
* Returns {@code true} if this logger should only process log records from sampled traces.
* When {@code true}, log records not associated with sampled traces are dropped.
* Defaults to {@code false}.
*/
public abstract boolean isTraceBased();
}
Loading