From 3255ee6a067b887e2b7cff73c270a7539ebff1a5 Mon Sep 17 00:00:00 2001 From: Patrik Beqo Date: Fri, 18 Sep 2026 16:31:54 -0400 Subject: [PATCH 1/4] feat: replay-safe logger provider --- .../v2/ReplaySafeOpenTelemetry.java | 57 +++++- .../v2/internal/ReplaySafeLogger.java | 168 ++++++++++++++++++ .../temporal/opentelemetry/v2/LoggerTest.java | 133 ++++++++++++++ .../opentelemetry/v2/OtelTestBase.java | 15 +- 4 files changed, 368 insertions(+), 5 deletions(-) create mode 100644 contrib/temporal-opentelemetry-v2/src/main/java/io/temporal/opentelemetry/v2/internal/ReplaySafeLogger.java create mode 100644 contrib/temporal-opentelemetry-v2/src/test/java/io/temporal/opentelemetry/v2/LoggerTest.java diff --git a/contrib/temporal-opentelemetry-v2/src/main/java/io/temporal/opentelemetry/v2/ReplaySafeOpenTelemetry.java b/contrib/temporal-opentelemetry-v2/src/main/java/io/temporal/opentelemetry/v2/ReplaySafeOpenTelemetry.java index 7d05111c70..6cb0494470 100644 --- a/contrib/temporal-opentelemetry-v2/src/main/java/io/temporal/opentelemetry/v2/ReplaySafeOpenTelemetry.java +++ b/contrib/temporal-opentelemetry-v2/src/main/java/io/temporal/opentelemetry/v2/ReplaySafeOpenTelemetry.java @@ -3,6 +3,8 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator; +import io.opentelemetry.api.logs.Logger; +import io.opentelemetry.api.logs.LoggerBuilder; import io.opentelemetry.api.logs.LoggerProvider; import io.opentelemetry.api.metrics.Meter; import io.opentelemetry.api.metrics.MeterBuilder; @@ -21,6 +23,7 @@ import io.opentelemetry.sdk.trace.SdkTracerProviderBuilder; import io.temporal.common.Experimental; import io.temporal.opentelemetry.v2.internal.ReplaySafeIdGenerator; +import io.temporal.opentelemetry.v2.internal.ReplaySafeLogger; import io.temporal.opentelemetry.v2.internal.ReplaySafeMeter; import io.temporal.opentelemetry.v2.internal.ReplaySafeTracer; import java.io.Closeable; @@ -35,9 +38,7 @@ public final class ReplaySafeOpenTelemetry implements OpenTelemetry, Closeable { private final ReplaySafeTracerProvider tracerProvider; private final ReplaySafeMeterProvider meterProvider; - // TODO: Make the logger provider replay safe and add logger interceptor methods for Temporal and - // OpenTelemetry loggers. - private final SdkLoggerProvider loggerProvider; + private final ReplaySafeLoggerProvider loggerProvider; private final ContextPropagators propagators; private ReplaySafeOpenTelemetry(Builder builder) { @@ -45,7 +46,7 @@ private ReplaySafeOpenTelemetry(Builder builder) { new ReplaySafeTracerProvider( builder.tracerProviderBuilder.setIdGenerator(new ReplaySafeIdGenerator()).build()); this.meterProvider = new ReplaySafeMeterProvider(builder.meterProviderBuilder.build()); - this.loggerProvider = builder.loggerProviderBuilder.build(); + this.loggerProvider = new ReplaySafeLoggerProvider(builder.loggerProviderBuilder.build()); this.propagators = builder.propagators; } @@ -207,6 +208,54 @@ public Meter build() { } } + private static final class ReplaySafeLoggerProvider implements LoggerProvider, Closeable { + private final SdkLoggerProvider delegate; + + private ReplaySafeLoggerProvider(SdkLoggerProvider delegate) { + this.delegate = delegate; + } + + @Override + public Logger get(@Nonnull String instrumentationScopeName) { + return new ReplaySafeLogger(delegate.get(instrumentationScopeName)); + } + + @Override + public LoggerBuilder loggerBuilder(@Nonnull String instrumentationScopeName) { + return new ReplaySafeLoggerBuilder(delegate.loggerBuilder(instrumentationScopeName)); + } + + @Override + public void close() { + delegate.close(); + } + } + + private static final class ReplaySafeLoggerBuilder implements LoggerBuilder { + private final LoggerBuilder delegate; + + private ReplaySafeLoggerBuilder(LoggerBuilder delegate) { + this.delegate = delegate; + } + + @Override + public LoggerBuilder setSchemaUrl(@Nonnull String schemaUrl) { + delegate.setSchemaUrl(schemaUrl); + return this; + } + + @Override + public LoggerBuilder setInstrumentationVersion(@Nonnull String instrumentationScopeVersion) { + delegate.setInstrumentationVersion(instrumentationScopeVersion); + return this; + } + + @Override + public Logger build() { + return new ReplaySafeLogger(delegate.build()); + } + } + private static final class ReplaySafeTracerBuilder implements TracerBuilder { private final TracerBuilder delegate; private final String instrumentationScopeName; diff --git a/contrib/temporal-opentelemetry-v2/src/main/java/io/temporal/opentelemetry/v2/internal/ReplaySafeLogger.java b/contrib/temporal-opentelemetry-v2/src/main/java/io/temporal/opentelemetry/v2/internal/ReplaySafeLogger.java new file mode 100644 index 0000000000..44c4f2aa3b --- /dev/null +++ b/contrib/temporal-opentelemetry-v2/src/main/java/io/temporal/opentelemetry/v2/internal/ReplaySafeLogger.java @@ -0,0 +1,168 @@ +package io.temporal.opentelemetry.v2.internal; + +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.common.Value; +import io.opentelemetry.api.logs.LogRecordBuilder; +import io.opentelemetry.api.logs.Logger; +import io.opentelemetry.api.logs.Severity; +import io.opentelemetry.context.Context; +import java.time.Instant; +import java.util.concurrent.TimeUnit; + +/** + * Wraps a logger so the records it builds are not emitted by replaying workflow code, which would + * otherwise emit them again on every replay. + */ +public final class ReplaySafeLogger implements Logger { + private final Logger delegate; + + public ReplaySafeLogger(Logger delegate) { + this.delegate = delegate; + } + + @Override + public LogRecordBuilder logRecordBuilder() { + return new ReplaySafeLogRecordBuilder(delegate.logRecordBuilder()); + } + + @Override + public boolean isEnabled(Severity severity, Context context) { + return delegate.isEnabled(severity, context); + } + + @Override + public boolean isEnabled(Severity severity) { + return delegate.isEnabled(severity); + } + + private static final class ReplaySafeLogRecordBuilder implements LogRecordBuilder { + private final LogRecordBuilder delegate; + + ReplaySafeLogRecordBuilder(LogRecordBuilder delegate) { + this.delegate = delegate; + } + + @Override + public void emit() { + if (OpenTelemetrySuppression.shouldSuppress()) { + return; + } + delegate.emit(); + } + + @Override + public LogRecordBuilder setTimestamp(long timestamp, TimeUnit unit) { + delegate.setTimestamp(timestamp, unit); + return this; + } + + @Override + public LogRecordBuilder setTimestamp(Instant instant) { + delegate.setTimestamp(instant); + return this; + } + + @Override + public LogRecordBuilder setObservedTimestamp(long timestamp, TimeUnit unit) { + delegate.setObservedTimestamp(timestamp, unit); + return this; + } + + @Override + public LogRecordBuilder setObservedTimestamp(Instant instant) { + delegate.setObservedTimestamp(instant); + return this; + } + + @Override + public LogRecordBuilder setContext(Context context) { + delegate.setContext(context); + return this; + } + + @Override + public LogRecordBuilder setSeverity(Severity severity) { + delegate.setSeverity(severity); + return this; + } + + @Override + public LogRecordBuilder setSeverityText(String severityText) { + delegate.setSeverityText(severityText); + return this; + } + + @Override + public LogRecordBuilder setBody(String body) { + delegate.setBody(body); + return this; + } + + @Override + public LogRecordBuilder setBody(Value body) { + delegate.setBody(body); + return this; + } + + @Override + public LogRecordBuilder setAllAttributes(Attributes attributes) { + delegate.setAllAttributes(attributes); + return this; + } + + @Override + public LogRecordBuilder setAttribute(AttributeKey key, T value) { + delegate.setAttribute(key, value); + return this; + } + + @Override + public LogRecordBuilder setAttribute(String key, String value) { + delegate.setAttribute(key, value); + return this; + } + + @Override + public LogRecordBuilder setAttribute(String key, long value) { + delegate.setAttribute(key, value); + return this; + } + + @Override + public LogRecordBuilder setAttribute(String key, double value) { + delegate.setAttribute(key, value); + return this; + } + + @Override + public LogRecordBuilder setAttribute(String key, boolean value) { + delegate.setAttribute(key, value); + return this; + } + + @Override + public LogRecordBuilder setAttribute(String key, int value) { + delegate.setAttribute(key, value); + return this; + } + + @Override + public LogRecordBuilder setAttribute(String key, Value value) { + delegate.setAttribute(key, value); + return this; + } + + @Override + public LogRecordBuilder setEventName(String eventName) { + delegate.setEventName(eventName); + return this; + } + + @Override + public LogRecordBuilder setException(Throwable throwable) { + delegate.setException(throwable); + return this; + } + } +} diff --git a/contrib/temporal-opentelemetry-v2/src/test/java/io/temporal/opentelemetry/v2/LoggerTest.java b/contrib/temporal-opentelemetry-v2/src/test/java/io/temporal/opentelemetry/v2/LoggerTest.java new file mode 100644 index 0000000000..bc779469e4 --- /dev/null +++ b/contrib/temporal-opentelemetry-v2/src/test/java/io/temporal/opentelemetry/v2/LoggerTest.java @@ -0,0 +1,133 @@ +package io.temporal.opentelemetry.v2; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.logs.Severity; +import io.opentelemetry.sdk.logs.data.LogRecordData; +import io.temporal.api.common.v1.WorkflowExecution; +import io.temporal.client.WorkflowClient; +import io.temporal.client.WorkflowStub; +import io.temporal.testing.WorkflowReplayer; +import io.temporal.testing.internal.SDKTestWorkflowRule; +import io.temporal.workflow.QueryMethod; +import io.temporal.workflow.SignalMethod; +import io.temporal.workflow.Workflow; +import io.temporal.workflow.WorkflowInterface; +import io.temporal.workflow.WorkflowMethod; +import java.util.ArrayList; +import java.util.List; +import org.junit.Rule; +import org.junit.Test; + +/** + * Verifies that log records emit during live execution and that replaying a workflow run does not + * emit duplicate records. + */ +public class LoggerTest extends OtelTestBase { + private static final AttributeKey ATTR = AttributeKey.stringKey("attr"); + private static final String LOGGER_NAME = "custom-logger"; + private static final String RUN_BODY = "custom workflow run"; + private static final String QUERY_BODY = "custom workflow query"; + + @WorkflowInterface + public interface TestWorkflow { + @WorkflowMethod + void run(); + + @QueryMethod + String queryAndEmit(); + + @SignalMethod + void proceed(); + } + + public static class TestWorkflowImpl implements TestWorkflow { + private boolean proceed; + + @Override + public void run() { + emit(RUN_BODY); + Workflow.await(() -> proceed); + } + + @Override + public String queryAndEmit() { + emit(QUERY_BODY); + return "ok"; + } + + @Override + public void proceed() { + proceed = true; + } + + private static void emit(String body) { + GlobalOpenTelemetry.get() + .getLogsBridge() + .get(LOGGER_NAME) + .logRecordBuilder() + .setBody(body) + .emit(); + } + } + + @Rule + public SDKTestWorkflowRule testWorkflowRule = + newRuleBuilder(false).setWorkflowTypes(TestWorkflowImpl.class).build(); + + @Test + public void recordsEmitOutsideWorkflows() { + GlobalOpenTelemetry.get() + .getLogsBridge() + .get("outside-workflow") + .logRecordBuilder() + .setSeverity(Severity.WARN) + .setBody("outside") + .setAllAttributes(Attributes.of(ATTR, "val")) + .setEventName("outside.event") + .emit(); + + List logs = emittedLogs(); + assertEquals(1, logs.size()); + LogRecordData log = logs.get(0); + assertEquals(Severity.WARN, log.getSeverity()); + assertEquals("outside", log.getBodyValue().asString()); + assertEquals("val", log.getAttributes().get(ATTR)); + assertEquals("outside.event", log.getEventName()); + } + + /** + * The live run and the live query handler each emit once; replaying the finished run drops its + * record. + */ + @Test + public void liveExecutionEmitsAndReplayDoesNotDuplicate() throws Exception { + TestWorkflow workflow = testWorkflowRule.newWorkflowStub(TestWorkflow.class); + WorkflowExecution execution = WorkflowClient.start(workflow::run); + + assertEquals("ok", workflow.queryAndEmit()); + workflow.proceed(); + WorkflowStub.fromTyped(workflow).getResult(Void.class); + + // Replay the full workflow history and verify the run's record is suppressed on replay + WorkflowReplayer.replayWorkflowExecution( + testWorkflowRule.getExecutionHistory(execution.getWorkflowId()), TestWorkflowImpl.class); + + List bodies = emittedBodies(); + assertEquals(bodies.toString(), 2, bodies.size()); + assertTrue(bodies.toString(), bodies.contains(RUN_BODY)); + assertTrue(bodies.toString(), bodies.contains(QUERY_BODY)); + } + + private static List emittedBodies() { + List bodies = new ArrayList<>(); + for (LogRecordData log : emittedLogs()) { + bodies.add(log.getBodyValue().asString()); + } + return bodies; + } +} diff --git a/contrib/temporal-opentelemetry-v2/src/test/java/io/temporal/opentelemetry/v2/OtelTestBase.java b/contrib/temporal-opentelemetry-v2/src/test/java/io/temporal/opentelemetry/v2/OtelTestBase.java index 8a1d9ed6d4..70b316358f 100644 --- a/contrib/temporal-opentelemetry-v2/src/test/java/io/temporal/opentelemetry/v2/OtelTestBase.java +++ b/contrib/temporal-opentelemetry-v2/src/test/java/io/temporal/opentelemetry/v2/OtelTestBase.java @@ -6,8 +6,12 @@ import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.sdk.logs.SdkLoggerProvider; +import io.opentelemetry.sdk.logs.data.LogRecordData; +import io.opentelemetry.sdk.logs.export.SimpleLogRecordProcessor; import io.opentelemetry.sdk.metrics.SdkMeterProvider; import io.opentelemetry.sdk.metrics.data.MetricData; +import io.opentelemetry.sdk.testing.exporter.InMemoryLogRecordExporter; import io.opentelemetry.sdk.testing.exporter.InMemoryMetricReader; import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter; import io.opentelemetry.sdk.trace.SdkTracerProvider; @@ -27,6 +31,7 @@ public abstract class OtelTestBase { static final InMemorySpanExporter spanExporter = InMemorySpanExporter.create(); static final InMemoryMetricReader metricReader = InMemoryMetricReader.create(); + static final InMemoryLogRecordExporter logExporter = InMemoryLogRecordExporter.create(); private static ReplaySafeOpenTelemetry openTelemetry; @BeforeClass @@ -37,6 +42,9 @@ public static void registerGlobalOpenTelemetry() { SdkTracerProvider.builder() .addSpanProcessor(SimpleSpanProcessor.create(spanExporter))) .setMeterProviderBuilder(SdkMeterProvider.builder().registerMetricReader(metricReader)) + .setLoggerProviderBuilder( + SdkLoggerProvider.builder() + .addLogRecordProcessor(SimpleLogRecordProcessor.create(logExporter))) .build(); GlobalOpenTelemetry.set(openTelemetry); } @@ -48,8 +56,9 @@ public static void resetGlobalOpenTelemetry() { } @Before - public void clearSpans() { + public void clearSpansAndLogs() { spanExporter.reset(); + logExporter.reset(); } /** @@ -70,6 +79,10 @@ static List endedSpans() { return spanExporter.getFinishedSpanItems(); } + static List emittedLogs() { + return logExporter.getFinishedLogRecordItems(); + } + static SpanData requireSpanNamed(List spans, String name) { for (SpanData span : spans) { if (span.getName().equals(name)) { From df8835e2c2dcf1bca5144b8380bd1f2763b432fe Mon Sep 17 00:00:00 2001 From: Patrik Beqo Date: Fri, 18 Sep 2026 18:53:56 -0400 Subject: [PATCH 2/4] docs: mention replay-safe loggers and end replay comment with a period --- .../io/temporal/opentelemetry/v2/ReplaySafeOpenTelemetry.java | 4 ++-- .../test/java/io/temporal/opentelemetry/v2/LoggerTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/temporal-opentelemetry-v2/src/main/java/io/temporal/opentelemetry/v2/ReplaySafeOpenTelemetry.java b/contrib/temporal-opentelemetry-v2/src/main/java/io/temporal/opentelemetry/v2/ReplaySafeOpenTelemetry.java index 6cb0494470..63d70866e0 100644 --- a/contrib/temporal-opentelemetry-v2/src/main/java/io/temporal/opentelemetry/v2/ReplaySafeOpenTelemetry.java +++ b/contrib/temporal-opentelemetry-v2/src/main/java/io/temporal/opentelemetry/v2/ReplaySafeOpenTelemetry.java @@ -31,8 +31,8 @@ /** * The {@link OpenTelemetry} to use for OpenTelemetry integration with Temporal. Register it with - * {@code GlobalOpenTelemetry.set}; tracers and meters obtained from it are replay safe inside - * workflows. + * {@code GlobalOpenTelemetry.set}; tracers, meters, and loggers obtained from it are replay safe + * inside workflows. */ @Experimental public final class ReplaySafeOpenTelemetry implements OpenTelemetry, Closeable { diff --git a/contrib/temporal-opentelemetry-v2/src/test/java/io/temporal/opentelemetry/v2/LoggerTest.java b/contrib/temporal-opentelemetry-v2/src/test/java/io/temporal/opentelemetry/v2/LoggerTest.java index bc779469e4..fedae53822 100644 --- a/contrib/temporal-opentelemetry-v2/src/test/java/io/temporal/opentelemetry/v2/LoggerTest.java +++ b/contrib/temporal-opentelemetry-v2/src/test/java/io/temporal/opentelemetry/v2/LoggerTest.java @@ -113,7 +113,7 @@ public void liveExecutionEmitsAndReplayDoesNotDuplicate() throws Exception { workflow.proceed(); WorkflowStub.fromTyped(workflow).getResult(Void.class); - // Replay the full workflow history and verify the run's record is suppressed on replay + // Replay the full workflow history and verify the run's record is suppressed on replay. WorkflowReplayer.replayWorkflowExecution( testWorkflowRule.getExecutionHistory(execution.getWorkflowId()), TestWorkflowImpl.class); From c746de314bf26128d51990f723feeac40c5157db Mon Sep 17 00:00:00 2001 From: Patrik Beqo Date: Fri, 18 Sep 2026 19:09:23 -0400 Subject: [PATCH 3/4] docs: add OpenTelemetry v2 README --- contrib/temporal-opentelemetry-v2/README.md | 110 ++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 contrib/temporal-opentelemetry-v2/README.md diff --git a/contrib/temporal-opentelemetry-v2/README.md b/contrib/temporal-opentelemetry-v2/README.md new file mode 100644 index 0000000000..a53bc119cc --- /dev/null +++ b/contrib/temporal-opentelemetry-v2/README.md @@ -0,0 +1,110 @@ +# OpenTelemetry v2 integration for the Temporal Java SDK + +Module `io.temporal:temporal-opentelemetry-v2` provides replay-safe +OpenTelemetry tracing, metrics, and logs for Temporal. + +## Setup + +Use the same version as the rest of your Temporal Java SDK dependencies: + +```groovy +implementation 'io.temporal:temporal-opentelemetry-v2:' +// Add the exporters you use, for example: +implementation 'io.opentelemetry:opentelemetry-exporter-otlp' +``` + +Create a replay-safe OpenTelemetry instance, register it as the global, and +attach the plugin to your service stubs: + +```java +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; +import io.temporal.client.WorkflowClient; +import io.temporal.opentelemetry.v2.OpenTelemetryPlugin; +import io.temporal.opentelemetry.v2.ReplaySafeOpenTelemetry; +import io.temporal.serviceclient.WorkflowServiceStubs; +import io.temporal.serviceclient.WorkflowServiceStubsOptions; +import io.temporal.worker.WorkerFactory; + +ReplaySafeOpenTelemetry openTelemetry = + ReplaySafeOpenTelemetry.newBuilder() + .setTracerProviderBuilder( + SdkTracerProvider.builder() + .addSpanProcessor( + BatchSpanProcessor.builder(OtlpGrpcSpanExporter.builder().build()).build())) + .build(); +GlobalOpenTelemetry.set(openTelemetry); + +WorkflowServiceStubs service = + WorkflowServiceStubs.newServiceStubs( + WorkflowServiceStubsOptions.newBuilder() + .setPlugins(OpenTelemetryPlugin.newBuilder().build()) + .build()); + +WorkflowClient client = WorkflowClient.newInstance(service); +WorkerFactory factory = WorkerFactory.newInstance(client); +``` + +Plugins configured on `WorkflowServiceStubsOptions` propagate to clients and +workers created from those stubs. It can also be configured directly on +`WorkflowClientOptions` or `WorkerFactoryOptions`. + +## Tracing + +The plugin propagates application trace context through Temporal headers. +Application spans remain connected across clients, workflows, activities, and +Nexus operations. + +Set `OpenTelemetryPlugin.Builder.setAddTemporalSpans(true)` to emit spans for +operations such as `StartWorkflow`, `RunWorkflow`, `RunActivity`, and +`ContinueAsNew`. + +Create spans in workflow, client, and activity code with the standard OpenTelemetry API: + +```java +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.context.Scope; + +Span span = + GlobalOpenTelemetry.getTracer("my-workflows") + .spanBuilder("my-span") + .startSpan(); +try (Scope ignored = span.makeCurrent()) { + activity.doWork(); +} finally { + span.end(); +} +``` + +## Metrics + +Create synchronous metrics in workflow, client, and activity code with the standard OpenTelemetry API: + +```java +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.metrics.LongCounter; + +LongCounter counter = + GlobalOpenTelemetry.getMeter("my-workflows") + .counterBuilder("workflow.items.processed") + .build(); +counter.add(1); +``` + +## Logs + +Create log records in workflow, client, and activity code with the standard OpenTelemetry API: + +```java +import io.opentelemetry.api.GlobalOpenTelemetry; + +GlobalOpenTelemetry.get() + .getLogsBridge() + .get("my-workflows") + .logRecordBuilder() + .setBody("workflow step completed") + .emit(); +``` From 6e78bfe5dec7a6a949ac42db792b7554035a0a3a Mon Sep 17 00:00:00 2001 From: Patrik Beqo Date: Fri, 18 Sep 2026 19:51:29 -0400 Subject: [PATCH 4/4] fix: address codex comments --- contrib/temporal-opentelemetry-v2/README.md | 2 +- .../temporal/opentelemetry/v2/internal/ReplaySafeLogger.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contrib/temporal-opentelemetry-v2/README.md b/contrib/temporal-opentelemetry-v2/README.md index a53bc119cc..0475828489 100644 --- a/contrib/temporal-opentelemetry-v2/README.md +++ b/contrib/temporal-opentelemetry-v2/README.md @@ -9,7 +9,7 @@ Use the same version as the rest of your Temporal Java SDK dependencies: ```groovy implementation 'io.temporal:temporal-opentelemetry-v2:' -// Add the exporters you use, for example: +// Add the exporters you use, such as this OTLP exporter. implementation 'io.opentelemetry:opentelemetry-exporter-otlp' ``` diff --git a/contrib/temporal-opentelemetry-v2/src/main/java/io/temporal/opentelemetry/v2/internal/ReplaySafeLogger.java b/contrib/temporal-opentelemetry-v2/src/main/java/io/temporal/opentelemetry/v2/internal/ReplaySafeLogger.java index 44c4f2aa3b..8cb3511176 100644 --- a/contrib/temporal-opentelemetry-v2/src/main/java/io/temporal/opentelemetry/v2/internal/ReplaySafeLogger.java +++ b/contrib/temporal-opentelemetry-v2/src/main/java/io/temporal/opentelemetry/v2/internal/ReplaySafeLogger.java @@ -28,12 +28,12 @@ public LogRecordBuilder logRecordBuilder() { @Override public boolean isEnabled(Severity severity, Context context) { - return delegate.isEnabled(severity, context); + return !OpenTelemetrySuppression.shouldSuppress() && delegate.isEnabled(severity, context); } @Override public boolean isEnabled(Severity severity) { - return delegate.isEnabled(severity); + return !OpenTelemetrySuppression.shouldSuppress() && delegate.isEnabled(severity); } private static final class ReplaySafeLogRecordBuilder implements LogRecordBuilder {