From da8bd86f99d6a4802f526cf4736c7576e7d9ac62 Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Wed, 20 Mar 2024 17:48:38 -0700 Subject: [PATCH 01/30] Add Otel support --- google-cloud-logging/pom.xml | 4 ++ .../com/google/cloud/logging/Context.java | 38 ++++++++++++++++++- .../google/cloud/logging/ContextHandler.java | 15 ++++++++ .../com/google/cloud/logging/LoggingImpl.java | 17 ++++++++- .../cloud/logging/TraceLoggingEnhancer.java | 29 +++++++++++++- pom.xml | 7 ++++ 6 files changed, 107 insertions(+), 3 deletions(-) diff --git a/google-cloud-logging/pom.xml b/google-cloud-logging/pom.xml index 94b09183a..83359eb0e 100644 --- a/google-cloud-logging/pom.xml +++ b/google-cloud-logging/pom.xml @@ -17,6 +17,10 @@ google-cloud-logging + + io.opentelemetry + opentelemetry-api + com.google.guava guava diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java index 109edfafc..71b719602 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java @@ -26,6 +26,9 @@ import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; +import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.Span; /** Class to hold context attributes including information about {@see HttpRequest} and tracing. */ public class Context { @@ -38,11 +41,15 @@ public class Context { private final String traceId; private final String spanId; + private final boolean traceSampled; + + /** A builder for {@see Context} objects. */ public static final class Builder { private HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(); private String traceId; private String spanId; + private boolean traceSampled; Builder() {} @@ -50,6 +57,7 @@ public static final class Builder { this.requestBuilder = context.request.toBuilder(); this.traceId = context.traceId; this.spanId = context.spanId; + this.traceSampled = context.traceSampled; } /** Sets the HTTP request. */ @@ -118,6 +126,13 @@ public Builder setSpanId(String spanId) { return this; } + /** Sets the boolean as trace sampled flag. */ + @CanIgnoreReturnValue + public Builder setTraceSampled(boolean traceSampled) { + this.traceSampled = traceSampled; + return this; + } + /** * Sets the trace id and span id values by parsing the string which represents xCloud Trace * Context. The Cloud Trace Context is passed as {@code x-cloud-trace-context} header (can be in @@ -176,6 +191,20 @@ public Builder loadW3CTraceParentContext(String traceParent) { return this; } + @CanIgnoreReturnValue + public Builder loadOpenTelemetryContext() { + if (Span.current().getSpanContext() != null && Span.current().getSpanContext().isValid()) + { + setTraceId(Span.current().getSpanContext().getTraceId()); + setSpanId(Span.current().getSpanContext().getSpanId()); + setTraceSampled(Span.current().getSpanContext().isSampled()); + + System.out.println("TraceID: " + Span.current().getSpanContext().getTraceId() + "; Span Id: " + Span.current().getSpanContext().getSpanId() + ", isSampled: " + Span.current().getSpanContext().isSampled()); + } + + return this; + } + /** Creates a {@see Context} object for this builder. */ public Context build() { return new Context(this); @@ -191,6 +220,7 @@ public Context build() { } this.traceId = builder.traceId; this.spanId = builder.spanId; + this.traceSampled = builder.traceSampled; } public HttpRequest getHttpRequest() { @@ -205,6 +235,10 @@ public String getSpanId() { return this.spanId; } + public boolean getTraceSampled() { + return this.traceSampled; + } + @Override public int hashCode() { return Objects.hash(request, traceId, spanId); @@ -216,6 +250,7 @@ public String toString() { .add("request", request) .add("traceId", traceId) .add("spanId", spanId) + .add("traceSampled", traceSampled) .toString(); } @@ -230,7 +265,8 @@ public boolean equals(Object obj) { Context other = (Context) obj; return Objects.equals(request, other.request) && Objects.equals(traceId, other.traceId) - && Objects.equals(spanId, other.spanId); + && Objects.equals(spanId, other.spanId) + && Objects.equals(traceSampled, other.traceSampled); } /** Returns a builder for this object. */ diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java index 8af084f27..03a70294d 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java @@ -18,7 +18,13 @@ /** Class provides a per-thread storage of the {@see Context} instances. */ public class ContextHandler { + + public enum ContextPriority { + NO_INPUT, XCLOUD_HEADER, W3_HEADER, OTEL_EXTRACTED + } + private static final ThreadLocal contextHolder = initContextHolder(); + private static final ThreadLocal currentPriority = new ThreadLocal(); /** * Initializes the context holder to {@link InheritableThreadLocal} if {@link LogManager} @@ -44,6 +50,15 @@ public void setCurrentContext(Context context) { contextHolder.set(context); } + public void setCurrentContextWithPriority(Context context, ContextPriority priority) { + if (currentPriority.get() == null || priority.compareTo(currentPriority.get()) >= 0) + { + contextHolder.set(context); + currentPriority.set(priority); + } + } + + public void removeCurrentContext() { contextHolder.remove(); } diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java index d1e3b0ae9..40f689699 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java @@ -98,6 +98,8 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import io.opentelemetry.api.trace.Span; +import com.google.cloud.logging.ContextHandler.ContextPriority; class LoggingImpl extends BaseService implements Logging { protected static final String RESOURCE_NAME_FORMAT = "projects/%s/traces/%s"; @@ -822,7 +824,7 @@ public Iterable populateMetadata( customResource == null ? MonitoredResourceUtil.getResource(getOptions().getProjectId(), null) : customResource; - final Context context = new ContextHandler().getCurrentContext(); + final ArrayList populatedLogEntries = Lists.newArrayList(); // populate empty metadata fields of log entries before calling write API @@ -834,6 +836,18 @@ public Iterable populateMetadata( if (resourceMetadata != null && entry.getResource() == null) { entityBuilder.setResource(resourceMetadata); } + + ContextHandler contextHandler = new ContextHandler(); + // Populate trace/span ID from OpenTelemetry span context to logging context. + System.out.println("Starting reading Otel context"); + if (Span.current().getSpanContext().isValid()) + { + System.out.println("Span context detected."); + Context.Builder contextBuilder = Context.newBuilder().loadOpenTelemetryContext(); + contextHandler.setCurrentContextWithPriority(contextBuilder.build(), ContextPriority.OTEL_EXTRACTED); + } + + Context context = contextHandler.getCurrentContext(); if (context != null && entry.getHttpRequest() == null) { entityBuilder.setHttpRequest(context.getHttpRequest()); } @@ -841,6 +855,7 @@ public Iterable populateMetadata( MonitoredResource resource = entry.getResource() != null ? entry.getResource() : resourceMetadata; entityBuilder.setTrace(getFormattedTrace(context.getTraceId(), resource)); + entityBuilder.setTraceSampled(context.getTraceSampled()); } if (context != null && Strings.isNullOrEmpty(entry.getSpanId())) { entityBuilder.setSpanId(context.getSpanId()); diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/TraceLoggingEnhancer.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/TraceLoggingEnhancer.java index 8b7b4aea7..9e2baae30 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/TraceLoggingEnhancer.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/TraceLoggingEnhancer.java @@ -24,6 +24,7 @@ public TraceLoggingEnhancer() {} public TraceLoggingEnhancer(String prefix) {} private static final ThreadLocal traceId = new ThreadLocal<>(); + private static final ThreadLocal spanId = new ThreadLocal<>(); /** * Set the Trace ID associated with any logging done by the current thread. @@ -38,20 +39,46 @@ public static void setCurrentTraceId(String id) { } } + /** + * Set the Span ID associated with any logging done by the current thread. + * + * @param id The spanID + */ + public static void setCurrentSpanId(String id) { + if (id == null) { + spanId.remove(); + } else { + spanId.set(id); + } + } + /** * Get the Trace ID associated with any logging done by the current thread. * - * @return id The traceID + * @return id The trace ID */ public static String getCurrentTraceId() { return traceId.get(); } + /** + * Get the Span ID associated with any logging done by the current thread. + * + * @return id The span ID + */ + public static String getCurrentSpanId() { + return spanId.get(); + } + @Override public void enhanceLogEntry(LogEntry.Builder builder) { String traceId = getCurrentTraceId(); if (traceId != null) { builder.setTrace(traceId); } + String spanId = getCurrentSpanId(); + if (spanId != null) { + builder.setSpanId(spanId); + } } } diff --git a/pom.xml b/pom.xml index c102d5f86..f01a960c4 100644 --- a/pom.xml +++ b/pom.xml @@ -56,8 +56,15 @@ google-cloud-logging-parent + + + io.opentelemetry + opentelemetry-api + 1.36.0 + + com.google.api.grpc proto-google-cloud-logging-v2 From ab654962f725849417fdc96fd9aec5b2e5afc154 Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Tue, 26 Mar 2024 12:37:35 -0700 Subject: [PATCH 02/30] Use overloading setCurrentContext function --- .../google/cloud/logging/ContextHandler.java | 87 +++++++++++-------- .../com/google/cloud/logging/LoggingImpl.java | 2 +- 2 files changed, 54 insertions(+), 35 deletions(-) diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java index 03a70294d..1a39223c3 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java @@ -16,50 +16,69 @@ package com.google.cloud.logging; -/** Class provides a per-thread storage of the {@see Context} instances. */ +/** + * Class provides a per-thread storage of the {@see Context} instances. + */ public class ContextHandler { - public enum ContextPriority { - NO_INPUT, XCLOUD_HEADER, W3_HEADER, OTEL_EXTRACTED - } + public enum ContextPriority { + NO_INPUT, XCLOUD_HEADER, W3_HEADER, OTEL_EXTRACTED + } - private static final ThreadLocal contextHolder = initContextHolder(); - private static final ThreadLocal currentPriority = new ThreadLocal(); + private static final ThreadLocal contextHolder = initContextHolder(); + private static final ThreadLocal currentPriority = new ThreadLocal(); - /** - * Initializes the context holder to {@link InheritableThreadLocal} if {@link LogManager} - * configuration property {@code com.google.cloud.logging.ContextHandler.useInheritedContext} is - * set to {@code true} or to {@link ThreadLocal} otherwise. - * - * @return instance of the context holder. - */ - private static ThreadLocal initContextHolder() { - LoggingConfig config = new LoggingConfig(ContextHandler.class.getName()); - if (config.getUseInheritedContext()) { - return new InheritableThreadLocal<>(); - } else { - return new ThreadLocal<>(); + /** + * Initializes the context holder to {@link InheritableThreadLocal} if {@link LogManager} + * configuration property {@code com.google.cloud.logging.ContextHandler.useInheritedContext} is + * set to {@code true} or to {@link ThreadLocal} otherwise. + * + * @return instance of the context holder. + */ + private static ThreadLocal initContextHolder() { + LoggingConfig config = new LoggingConfig(ContextHandler.class.getName()); + if (config.getUseInheritedContext()) { + return new InheritableThreadLocal<>(); + } else { + return new ThreadLocal<>(); + } } - } - public Context getCurrentContext() { - return contextHolder.get(); - } + public Context getCurrentContext() { + return contextHolder.get(); + } - public void setCurrentContext(Context context) { - contextHolder.set(context); - } - public void setCurrentContextWithPriority(Context context, ContextPriority priority) { - if (currentPriority.get() == null || priority.compareTo(currentPriority.get()) >= 0) - { + public void setCurrentContext(Context context) { contextHolder.set(context); - currentPriority.set(priority); } - } + /** + * Sets the context based on the priority. Overrides traceId, spanId and TraceSampled if the passed priority is higher. + * HttpRequest values will be retrieved and combined from existing context if HttpRequest in the new context is empty . + */ + + public void setCurrentContext(Context context, ContextPriority priority) { + if ((currentPriority.get() == null || priority.compareTo(currentPriority.get()) >= 0) && context != null) { + Context.Builder combinedContextBuilder = Context.newBuilder().setTraceId(context.getTraceId()).setSpanId(context.getSpanId()).setTraceSampled(context.getTraceSampled()); + Context currentContext = getCurrentContext(); + + if (context.getHttpRequest() != null) + { + combinedContextBuilder.setRequest(context.getHttpRequest()); + } + // Combines HttpRequest from the existing context if HttpRequest in new context is empty. + else if (currentContext != null && currentContext.getHttpRequest() != null ){ + combinedContextBuilder.setRequest(currentContext.getHttpRequest()); + } - public void removeCurrentContext() { - contextHolder.remove(); - } + contextHolder.set(combinedContextBuilder.build()); + currentPriority.set(priority); + } + } + + + public void removeCurrentContext() { + contextHolder.remove(); + } } diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java index 40f689699..cc11d0d50 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java @@ -844,7 +844,7 @@ public Iterable populateMetadata( { System.out.println("Span context detected."); Context.Builder contextBuilder = Context.newBuilder().loadOpenTelemetryContext(); - contextHandler.setCurrentContextWithPriority(contextBuilder.build(), ContextPriority.OTEL_EXTRACTED); + contextHandler.setCurrentContext(contextBuilder.build(), ContextPriority.OTEL_EXTRACTED); } Context context = contextHandler.getCurrentContext(); From 246c1f5172500756c4ce7b312c1ad6de83c578b4 Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Thu, 25 Apr 2024 10:53:25 +0800 Subject: [PATCH 03/30] Add logging handler test for traceEnhancer --- .../cloud/logging/TraceLoggingEnhancer.java | 27 +++++++++++++++++++ .../cloud/logging/LoggingHandlerTest.java | 4 +++ 2 files changed, 31 insertions(+) diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/TraceLoggingEnhancer.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/TraceLoggingEnhancer.java index 9e2baae30..834e3b735 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/TraceLoggingEnhancer.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/TraceLoggingEnhancer.java @@ -25,6 +25,7 @@ public TraceLoggingEnhancer(String prefix) {} private static final ThreadLocal traceId = new ThreadLocal<>(); private static final ThreadLocal spanId = new ThreadLocal<>(); + private static final ThreadLocal traceSampled = new ThreadLocal(); /** * Set the Trace ID associated with any logging done by the current thread. @@ -52,6 +53,19 @@ public static void setCurrentSpanId(String id) { } } + /** + * Set the trace sampled flag associated with any logging done by the current thread. + * + * @param isTraceSampled The traceSampled flag + */ + public static void setCurrentTraceSampled(Boolean isTraceSampled) { + if (isTraceSampled == null) { + traceSampled.remove(); + } else { + traceSampled.set(isTraceSampled); + } + } + /** * Get the Trace ID associated with any logging done by the current thread. * @@ -70,6 +84,15 @@ public static String getCurrentSpanId() { return spanId.get(); } + /** + * Get the trace sampled flag associated with any logging done by the current thread. + * + * @return traceSampled The traceSampled flag + */ + public static Boolean getCurrentTraceSampled() { + return traceSampled.get(); + } + @Override public void enhanceLogEntry(LogEntry.Builder builder) { String traceId = getCurrentTraceId(); @@ -80,5 +103,9 @@ public void enhanceLogEntry(LogEntry.Builder builder) { if (spanId != null) { builder.setSpanId(spanId); } + Boolean isTraceSampled = getCurrentTraceSampled(); + if (isTraceSampled != null) { + builder.setTraceSampled(isTraceSampled); + } } } diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/LoggingHandlerTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/LoggingHandlerTest.java index c6267e22e..abd88053e 100644 --- a/google-cloud-logging/src/test/java/com/google/cloud/logging/LoggingHandlerTest.java +++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/LoggingHandlerTest.java @@ -165,6 +165,8 @@ public class LoggingHandlerTest { .addLabel("levelName", "FINEST") .addLabel("levelValue", String.valueOf(Level.FINEST.intValue())) .setTrace("projects/projectId/traces/traceId") + .setSpanId("test_span_id") + .setTraceSampled(true) .setTimestamp(123456789L) .build(); private static final LogEntry DIAGNOSTIC_ENTRY = @@ -454,6 +456,8 @@ public void testTraceEnhancedLogEntry() { replay(options, logging); LoggingEnhancer enhancer = new TraceLoggingEnhancer(); TraceLoggingEnhancer.setCurrentTraceId("projects/projectId/traces/traceId"); + TraceLoggingEnhancer.setCurrentSpanId("test_span_id"); + TraceLoggingEnhancer.setCurrentTraceSampled(true); Handler handler = new LoggingHandler(LOG_NAME, options, DEFAULT_RESOURCE, ImmutableList.of(enhancer)); handler.setLevel(Level.ALL); From 107144b4694cad43a16aaadbac083300522e670d Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Tue, 30 Apr 2024 14:02:23 +0800 Subject: [PATCH 04/30] "Add tracehandler test" --- .../com/google/cloud/logging/Context.java | 13 ++++++- .../google/cloud/logging/LoggingHandler.java | 2 +- .../com/google/cloud/logging/ContextTest.java | 34 +++++++++++++------ 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java index 71b719602..b601fd75a 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java @@ -37,6 +37,9 @@ public class Context { private static final Pattern W3C_TRACE_CONTEXT_FORMAT = Pattern.compile( "^00-(?!00000000000000000000000000000000)[0-9a-f]{32}-(?!0000000000000000)[0-9a-f]{16}-[0-9a-f]{2}$"); + // Trace sampled flag for bit masking + // see https://www.w3.org/TR/trace-context/#trace-flags for details + private static final byte FLAG_SAMPLED = 1; // 00000001 private final HttpRequest request; private final String traceId; private final String spanId; @@ -144,7 +147,9 @@ public Builder setTraceSampled(boolean traceSampled) { @CanIgnoreReturnValue public Builder loadCloudTraceContext(String cloudTrace) { if (cloudTrace != null) { + String traceSampledString = Iterables.get(Splitter.on(";o=").split(cloudTrace), 1); cloudTrace = Iterables.get(Splitter.on(';').split(cloudTrace), 0); + int split = cloudTrace.indexOf('/'); if (split >= 0) { String traceId = cloudTrace.substring(0, split); @@ -155,6 +160,10 @@ public Builder loadCloudTraceContext(String cloudTrace) { if (!spanId.isEmpty()) { setSpanId(spanId); } + // do not set trace sampled flag without trace Id + if (!traceSampledString.isEmpty()) { + setTraceSampled(traceSampledString.equals("1")); + } } } else if (!cloudTrace.isEmpty()) { setTraceId(cloudTrace); @@ -186,7 +195,9 @@ public Builder loadW3CTraceParentContext(String traceParent) { List fields = Splitter.on('-').splitToList(traceParent); setTraceId(fields.get(1)); setSpanId(fields.get(2)); - // fields[3] contains flag(s) + boolean sampled = (Integer.parseInt(fields.get(3), 16) & FLAG_SAMPLED) == FLAG_SAMPLED; + System.out.println("trace: " + fields.get(1) + ", span: " + fields.get(2) + ", sampled string " + fields.get(3) + ", sampled boolean: " + sampled); + setTraceSampled(sampled); } return this; } diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingHandler.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingHandler.java index 06108a303..d1e56762a 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingHandler.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingHandler.java @@ -171,7 +171,7 @@ public enum LogTarget { private final WriteOption[] defaultWriteOptions; - /** Creates an handler that publishes messages to Cloud Logging. */ + /** Creates a handler that publishes messages to Cloud Logging. */ public LoggingHandler() { this(null, null, null); } diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java index 512c99aa8..a6faf562c 100644 --- a/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java +++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java @@ -37,6 +37,7 @@ public class ContextTest { // DO NOT use dash in trace and span id because W3C traceparent format uses dash as a delimieter private static final String TEST_TRACE_ID = "test_trace_id"; private static final String TEST_SPAN_ID = "test_span_id"; + private static final boolean TEST_TRACE_SAMPLED = true; private static final HttpRequest REQUEST = HttpRequest.newBuilder() @@ -68,6 +69,7 @@ public class ContextTest { .setRequest(PARTIAL_REQUEST) .setTraceId(TEST_TRACE_ID) .setSpanId(TEST_SPAN_ID) + .setTraceSampled(TEST_TRACE_SAMPLED) .build(); @Test @@ -87,6 +89,7 @@ public void testCompareContexts() { .setServerIp(SERVER_IP) .setTraceId(TEST_TRACE_ID) .setSpanId(TEST_SPAN_ID) + .setTraceSampled(TEST_TRACE_SAMPLED) .build(); assertNotEquals(TEST_CONTEXT, context1); @@ -103,9 +106,11 @@ public void testContextBuilder() { assertEquals(PARTIAL_REQUEST, TEST_CONTEXT.getHttpRequest()); assertEquals(TEST_TRACE_ID, TEST_CONTEXT.getTraceId()); assertEquals(TEST_SPAN_ID, TEST_CONTEXT.getSpanId()); + assertEquals(TEST_TRACE_SAMPLED, TEST_CONTEXT.getTraceSampled()); assertNull(emptyContext.getHttpRequest()); assertNull(emptyContext.getTraceId()); assertNull(emptyContext.getSpanId()); + assertFalse(emptyContext.getTraceSampled()); assertEquals(TEST_CONTEXT, anotherContext); } @@ -114,40 +119,47 @@ public void testParsingCloudTraceContext() { final String X_CLOUD_TRACE_NO_TRACE = "/SPAN_ID;o=TRACE_TRUE"; final String X_CLOUD_TRACE_ONLY = TEST_TRACE_ID; final String X_CLOUD_TRACE_WITH_SPAN = TEST_TRACE_ID + "/" + TEST_SPAN_ID; - final String X_CLOUD_TRACE_FULL = TEST_TRACE_ID + "/" + TEST_SPAN_ID + ";o=TRACE_TRUE"; + final String X_CLOUD_TRACE_FULL = TEST_TRACE_ID + "/" + TEST_SPAN_ID + ";o=" + TEST_TRACE_SAMPLED; Context.Builder builder = Context.newBuilder(); builder.loadCloudTraceContext(null); - assertTraceAndSpan(builder.build(), null, null); + assertTraceSpanAndSampled(builder.build(), null, null, false); builder.loadCloudTraceContext(""); - assertTraceAndSpan(builder.build(), null, null); + assertTraceSpanAndSampled(builder.build(), null, null, false); builder.loadCloudTraceContext(X_CLOUD_TRACE_NO_TRACE); - assertTraceAndSpan(builder.build(), null, null); + assertTraceSpanAndSampled(builder.build(), null, null, false); builder.loadCloudTraceContext(X_CLOUD_TRACE_ONLY); - assertTraceAndSpan(builder.build(), TEST_TRACE_ID, null); + assertTraceSpanAndSampled(builder.build(), TEST_TRACE_ID, null, false); builder.loadCloudTraceContext(X_CLOUD_TRACE_WITH_SPAN); - assertTraceAndSpan(builder.build(), TEST_TRACE_ID, TEST_SPAN_ID); + assertTraceSpanAndSampled(builder.build(), TEST_TRACE_ID, TEST_SPAN_ID, false); builder.loadCloudTraceContext(X_CLOUD_TRACE_FULL); - assertTraceAndSpan(builder.build(), TEST_TRACE_ID, TEST_SPAN_ID); + assertTraceSpanAndSampled(builder.build(), TEST_TRACE_ID, TEST_SPAN_ID, TEST_TRACE_SAMPLED); } @Test public void testParsingW3CTraceParent() { final String W3C_TEST_TRACE_ID = "12345678901234567890123456789012"; final String W3C_TEST_SPAN_ID = "1234567890123456"; - final String W3C_TRACE_CONTEXT = "00-" + W3C_TEST_TRACE_ID + "-" + W3C_TEST_SPAN_ID + "-00"; + final String W3C_TEST_TRACE_SAMPLED = "0f"; + final String W3C_TRACE_CONTEXT = "00-" + W3C_TEST_TRACE_ID + "-" + W3C_TEST_SPAN_ID + "-" + W3C_TEST_TRACE_SAMPLED; Context.Builder builder = Context.newBuilder(); builder.loadW3CTraceParentContext(null); - assertTraceAndSpan(builder.build(), null, null); + assertTraceSpanAndSampled(builder.build(), null, null, false); builder.loadW3CTraceParentContext(W3C_TRACE_CONTEXT); - assertTraceAndSpan(builder.build(), W3C_TEST_TRACE_ID, W3C_TEST_SPAN_ID); + assertTraceSpanAndSampled(builder.build(), W3C_TEST_TRACE_ID, W3C_TEST_SPAN_ID, true); } - private void assertTraceAndSpan(Context context, String expectedTraceId, String expectedSpanId) { + private void assertTraceAndSpan1(Context context, String expectedTraceId, String expectedSpanId) { assertEquals(expectedTraceId, context.getTraceId()); assertEquals(expectedSpanId, context.getSpanId()); } + + private void assertTraceSpanAndSampled(Context context, String expectedTraceId, String expectedSpanId, boolean expectedTraceSampled) { + assertEquals(expectedTraceId, context.getTraceId()); + assertEquals(expectedSpanId, context.getSpanId()); + assertEquals(expectedTraceSampled, context.getTraceSampled()); + } } From b4d3ee783e139df6368da47ed342d3229aefdad6 Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Tue, 30 Apr 2024 16:43:31 +0800 Subject: [PATCH 05/30] Add otel unit tests --- google-cloud-logging/pom.xml | 12 +++ .../com/google/cloud/logging/ContextTest.java | 73 +++++++++++++++++++ pom.xml | 41 ++++++++++- 3 files changed, 125 insertions(+), 1 deletion(-) diff --git a/google-cloud-logging/pom.xml b/google-cloud-logging/pom.xml index 83359eb0e..767b998e8 100644 --- a/google-cloud-logging/pom.xml +++ b/google-cloud-logging/pom.xml @@ -137,6 +137,18 @@ grpc-google-cloud-logging-v2 test + + + io.opentelemetry + opentelemetry-sdk + test + + + io.opentelemetry + opentelemetry-sdk-testing + test + + com.google.api diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java index a6faf562c..25e7d502e 100644 --- a/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java +++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java @@ -16,15 +16,34 @@ package com.google.cloud.logging; + +import static com.google.logging.v2.LoggingServiceV2Grpc.SERVICE_NAME; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNull; +import io.opentelemetry.api.OpenTelemetry; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.threeten.bp.Duration; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.*; +import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.api.common.AttributeKey; +import io.opentelemetry.api.common.Attributes; +import io.opentelemetry.api.trace.StatusCode; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.resources.Resource; +import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.SpanProcessor; +import io.opentelemetry.sdk.trace.data.EventData; +import io.opentelemetry.sdk.trace.data.SpanData; +import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; +import io.opentelemetry.sdk.trace.samplers.Sampler; + @RunWith(JUnit4.class) public class ContextTest { @@ -152,6 +171,60 @@ public void testParsingW3CTraceParent() { assertTraceSpanAndSampled(builder.build(), W3C_TEST_TRACE_ID, W3C_TEST_SPAN_ID, true); } + + @Test + public void testParsingOtelContext() { + InMemorySpanExporter testExporter = InMemorySpanExporter.create(); + // OpenTelemetrySdk myOpenTelemetrySdk = OpenTelemetrySdk.builder().build(); + +/* OpenTelemetrySdk.builder() + .setTracerProvider( + SdkTracerProvider.builder() + .addSpanProcessor(BatchSpanProcessor.builder(traceExporter).build()) + .build()) + .buildAndRegisterGlobal();*/ + + + // Create with an in-memory span exporter. + // GlobalOpenTelemetry.resetForTest(); + /* Resource resource = + Resource.getDefault().merge(Resource.builder().put(SERVICE_NAME, "Sparky").build()); + + + OpenTelemetry sdk = OpenTelemetrySdk.builder() + .setTracerProvider( + SdkTracerProvider.builder() + .setResource(resource) + .addSpanProcessor(inMemorySpanProcessor) + .setSampler(Sampler.alwaysOn()) + .build()) + .buildAndRegisterGlobal(); +*/ + + + /////////////// + + SpanProcessor inMemorySpanProcessor = SimpleSpanProcessor.create(testExporter); + OpenTelemetrySdk openTelemetrySdk = + OpenTelemetrySdk.builder() + .setTracerProvider( + SdkTracerProvider.builder() + .addSpanProcessor(inMemorySpanProcessor) + .build()) + .build(); + + // OpenTelemetry has a maximum of 128 Attributes by default for Spans, Links, and Events. + Tracer tracer = openTelemetrySdk.getTracer("ContextTest"); + Span multiAttrSpan = tracer.spanBuilder("Example Span Attributes").startSpan(); + multiAttrSpan.setAttribute("Attribute 1", "first attribute value"); + multiAttrSpan.setAttribute("Attribute 2", "second attribute value"); + multiAttrSpan.end(); + Context.Builder builder = Context.newBuilder(); + SpanContext currentOtelContext = multiAttrSpan.getSpanContext(); + builder.loadOpenTelemetryContext(); + assertTraceSpanAndSampled(builder.build(), currentOtelContext.getTraceId(), currentOtelContext.getSpanId(), currentOtelContext.isSampled()); + } + private void assertTraceAndSpan1(Context context, String expectedTraceId, String expectedSpanId) { assertEquals(expectedTraceId, context.getTraceId()); assertEquals(expectedSpanId, context.getSpanId()); diff --git a/pom.xml b/pom.xml index f01a960c4..91d122470 100644 --- a/pom.xml +++ b/pom.xml @@ -54,6 +54,7 @@ UTF-8 github google-cloud-logging-parent + 1.36.0 @@ -62,7 +63,7 @@ io.opentelemetry opentelemetry-api - 1.36.0 + ${opentelemetry.version} @@ -124,6 +125,44 @@ + + + io.opentelemetry + opentelemetry-sdk + ${opentelemetry.version} + test + + + io.opentelemetry + opentelemetry-sdk-testing + ${opentelemetry.version} + test + + + io.opentelemetry + opentelemetry-semconv + ${opentelemetry.version}-alpha + test + + + io.opentelemetry + opentelemetry-sdk-trace + ${opentelemetry.version} + test + + + io.opentelemetry + opentelemetry-sdk-common + ${opentelemetry.version} + test + + + com.google.cloud.opentelemetry + exporter-trace + 0.15.0 + test + + From 4808c99a0aa64c29f4722b23ecd5c969383b8bbd Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Tue, 30 Apr 2024 17:19:53 +0800 Subject: [PATCH 06/30] fix otel context unit test --- .../com/google/cloud/logging/Context.java | 3 - .../com/google/cloud/logging/LoggingImpl.java | 2 - .../com/google/cloud/logging/ContextTest.java | 65 +++++-------------- 3 files changed, 16 insertions(+), 54 deletions(-) diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java index b601fd75a..666a687b3 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java @@ -196,7 +196,6 @@ public Builder loadW3CTraceParentContext(String traceParent) { setTraceId(fields.get(1)); setSpanId(fields.get(2)); boolean sampled = (Integer.parseInt(fields.get(3), 16) & FLAG_SAMPLED) == FLAG_SAMPLED; - System.out.println("trace: " + fields.get(1) + ", span: " + fields.get(2) + ", sampled string " + fields.get(3) + ", sampled boolean: " + sampled); setTraceSampled(sampled); } return this; @@ -209,8 +208,6 @@ public Builder loadOpenTelemetryContext() { setTraceId(Span.current().getSpanContext().getTraceId()); setSpanId(Span.current().getSpanContext().getSpanId()); setTraceSampled(Span.current().getSpanContext().isSampled()); - - System.out.println("TraceID: " + Span.current().getSpanContext().getTraceId() + "; Span Id: " + Span.current().getSpanContext().getSpanId() + ", isSampled: " + Span.current().getSpanContext().isSampled()); } return this; diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java index cc11d0d50..45b3eec13 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java @@ -839,10 +839,8 @@ public Iterable populateMetadata( ContextHandler contextHandler = new ContextHandler(); // Populate trace/span ID from OpenTelemetry span context to logging context. - System.out.println("Starting reading Otel context"); if (Span.current().getSpanContext().isValid()) { - System.out.println("Span context detected."); Context.Builder contextBuilder = Context.newBuilder().loadOpenTelemetryContext(); contextHandler.setCurrentContext(contextBuilder.build(), ContextPriority.OTEL_EXTRACTED); } diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java index 25e7d502e..d299aeab8 100644 --- a/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java +++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java @@ -17,32 +17,23 @@ package com.google.cloud.logging; -import static com.google.logging.v2.LoggingServiceV2Grpc.SERVICE_NAME; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNull; -import io.opentelemetry.api.OpenTelemetry; +import io.opentelemetry.context.Scope; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.threeten.bp.Duration; import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.*; -import io.opentelemetry.api.GlobalOpenTelemetry; -import io.opentelemetry.api.common.AttributeKey; -import io.opentelemetry.api.common.Attributes; -import io.opentelemetry.api.trace.StatusCode; import io.opentelemetry.sdk.OpenTelemetrySdk; -import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter; import io.opentelemetry.sdk.trace.SdkTracerProvider; import io.opentelemetry.sdk.trace.SpanProcessor; -import io.opentelemetry.sdk.trace.data.EventData; -import io.opentelemetry.sdk.trace.data.SpanData; import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; -import io.opentelemetry.sdk.trace.samplers.Sampler; @RunWith(JUnit4.class) @@ -173,37 +164,8 @@ public void testParsingW3CTraceParent() { @Test - public void testParsingOtelContext() { - InMemorySpanExporter testExporter = InMemorySpanExporter.create(); - // OpenTelemetrySdk myOpenTelemetrySdk = OpenTelemetrySdk.builder().build(); - -/* OpenTelemetrySdk.builder() - .setTracerProvider( - SdkTracerProvider.builder() - .addSpanProcessor(BatchSpanProcessor.builder(traceExporter).build()) - .build()) - .buildAndRegisterGlobal();*/ - - - // Create with an in-memory span exporter. - // GlobalOpenTelemetry.resetForTest(); - /* Resource resource = - Resource.getDefault().merge(Resource.builder().put(SERVICE_NAME, "Sparky").build()); - - - OpenTelemetry sdk = OpenTelemetrySdk.builder() - .setTracerProvider( - SdkTracerProvider.builder() - .setResource(resource) - .addSpanProcessor(inMemorySpanProcessor) - .setSampler(Sampler.alwaysOn()) - .build()) - .buildAndRegisterGlobal(); -*/ - - - /////////////// - + public void testParsingOpenTelemetryContext() { + InMemorySpanExporter testExporter = InMemorySpanExporter.create(); SpanProcessor inMemorySpanProcessor = SimpleSpanProcessor.create(testExporter); OpenTelemetrySdk openTelemetrySdk = OpenTelemetrySdk.builder() @@ -213,16 +175,21 @@ public void testParsingOtelContext() { .build()) .build(); - // OpenTelemetry has a maximum of 128 Attributes by default for Spans, Links, and Events. Tracer tracer = openTelemetrySdk.getTracer("ContextTest"); - Span multiAttrSpan = tracer.spanBuilder("Example Span Attributes").startSpan(); - multiAttrSpan.setAttribute("Attribute 1", "first attribute value"); - multiAttrSpan.setAttribute("Attribute 2", "second attribute value"); - multiAttrSpan.end(); + Span otelSpan = tracer.spanBuilder("Example Span Attributes").startSpan(); + SpanContext currentOtelContext; Context.Builder builder = Context.newBuilder(); - SpanContext currentOtelContext = multiAttrSpan.getSpanContext(); - builder.loadOpenTelemetryContext(); - assertTraceSpanAndSampled(builder.build(), currentOtelContext.getTraceId(), currentOtelContext.getSpanId(), currentOtelContext.isSampled()); + try (Scope scope = otelSpan.makeCurrent()) { + otelSpan.setAttribute("Attribute 1", "first attribute value"); + currentOtelContext = otelSpan.getSpanContext(); + builder.loadOpenTelemetryContext(); + assertTraceSpanAndSampled(builder.build(), currentOtelContext.getTraceId(), currentOtelContext.getSpanId(), currentOtelContext.isSampled()); + } catch(Throwable t) { + otelSpan.recordException(t); + throw t; + } finally { + otelSpan.end(); + } } private void assertTraceAndSpan1(Context context, String expectedTraceId, String expectedSpanId) { From 8416b668378d57e6643b4a99d6ab67ba0e936208 Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Tue, 30 Apr 2024 17:42:07 +0800 Subject: [PATCH 07/30] Remove comments --- .../com/google/cloud/logging/Context.java | 26 +++++++++---------- .../logging/AutoPopulateMetadataTests.java | 21 ++++++++------- .../com/google/cloud/logging/ContextTest.java | 8 ------ 3 files changed, 24 insertions(+), 31 deletions(-) diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java index 666a687b3..78b527aa7 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java @@ -26,8 +26,6 @@ import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; -import io.opentelemetry.api.OpenTelemetry; -import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.Span; /** Class to hold context attributes including information about {@see HttpRequest} and tracing. */ @@ -43,10 +41,7 @@ public class Context { private final HttpRequest request; private final String traceId; private final String spanId; - private final boolean traceSampled; - - /** A builder for {@see Context} objects. */ public static final class Builder { private HttpRequest.Builder requestBuilder = HttpRequest.newBuilder(); @@ -137,7 +132,7 @@ public Builder setTraceSampled(boolean traceSampled) { } /** - * Sets the trace id and span id values by parsing the string which represents xCloud Trace + * Sets the trace id, span id and trace sampled flag values by parsing the string which represents xCloud Trace * Context. The Cloud Trace Context is passed as {@code x-cloud-trace-context} header (can be in * Pascal case format). The string format is TRACE_ID/SPAN_ID;o=TRACE_TRUE. * @@ -147,9 +142,10 @@ public Builder setTraceSampled(boolean traceSampled) { @CanIgnoreReturnValue public Builder loadCloudTraceContext(String cloudTrace) { if (cloudTrace != null) { - String traceSampledString = Iterables.get(Splitter.on(";o=").split(cloudTrace), 1); + if (cloudTrace.indexOf("o=") >= 0) { + setTraceSampled(Iterables.get(Splitter.on("o=").split(cloudTrace), 1).equals("1")); + } cloudTrace = Iterables.get(Splitter.on(';').split(cloudTrace), 0); - int split = cloudTrace.indexOf('/'); if (split >= 0) { String traceId = cloudTrace.substring(0, split); @@ -160,10 +156,6 @@ public Builder loadCloudTraceContext(String cloudTrace) { if (!spanId.isEmpty()) { setSpanId(spanId); } - // do not set trace sampled flag without trace Id - if (!traceSampledString.isEmpty()) { - setTraceSampled(traceSampledString.equals("1")); - } } } else if (!cloudTrace.isEmpty()) { setTraceId(cloudTrace); @@ -173,7 +165,7 @@ public Builder loadCloudTraceContext(String cloudTrace) { } /** - * Sets the trace id and span id values by parsing the string which represents the standard W3C + * Sets the trace id, span id and trace sampled flag values by parsing the string which represents the standard W3C * trace context propagation header. The context propagation header is passed as {@code * traceparent} header. The method currently supports ONLY version {@code "00"}. The string * format is 00-TRACE_ID-SPAN_ID-FLAGS. field of the {@code version-format} value. @@ -201,6 +193,13 @@ public Builder loadW3CTraceParentContext(String traceParent) { return this; } + /** + * Sets the trace id, span id and trace sampled flag values by parsing detected OpenTelemetry + * span context. + * + * @see OpenTelemetry + * SpanContext. + */ @CanIgnoreReturnValue public Builder loadOpenTelemetryContext() { if (Span.current().getSpanContext() != null && Span.current().getSpanContext().isValid()) @@ -209,7 +208,6 @@ public Builder loadOpenTelemetryContext() { setSpanId(Span.current().getSpanContext().getSpanId()); setTraceSampled(Span.current().getSpanContext().isSampled()); } - return this; } diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/AutoPopulateMetadataTests.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/AutoPopulateMetadataTests.java index f415f8c4c..fee5f69c5 100644 --- a/google-cloud-logging/src/test/java/com/google/cloud/logging/AutoPopulateMetadataTests.java +++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/AutoPopulateMetadataTests.java @@ -22,8 +22,7 @@ import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.newCapture; import static org.easymock.EasyMock.replay; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; +import static org.junit.Assert.*; import com.google.api.core.ApiFutures; import com.google.cloud.MonitoredResource; @@ -74,6 +73,7 @@ public class AutoPopulateMetadataTests { private static final String FORMATTED_TRACE_ID = String.format(LoggingImpl.RESOURCE_NAME_FORMAT, RESOURCE_PROJECT_ID, TRACE_ID); private static final String SPAN_ID = "1"; + private static final boolean TRACE_SAMPLED = true; private LoggingRpcFactory mockedRpcFactory; private LoggingRpc mockedRpc; @@ -111,15 +111,15 @@ public void teardown() { new ContextHandler().removeCurrentContext(); } - private void mockCurrentContext(HttpRequest request, String traceId, String spanId) { + private void mockCurrentContext(HttpRequest request, String traceId, String spanId, boolean traceSampled) { Context mockedContext = - Context.newBuilder().setRequest(request).setTraceId(traceId).setSpanId(spanId).build(); + Context.newBuilder().setRequest(request).setTraceId(traceId).setSpanId(spanId).setTraceSampled(traceSampled).build(); new ContextHandler().setCurrentContext(mockedContext); } @Test public void testAutoPopulationEnabledInLoggingOptions() { - mockCurrentContext(HTTP_REQUEST, TRACE_ID, SPAN_ID); + mockCurrentContext(HTTP_REQUEST, TRACE_ID, SPAN_ID, TRACE_SAMPLED); logging.write(ImmutableList.of(SIMPLE_LOG_ENTRY)); @@ -127,6 +127,7 @@ public void testAutoPopulationEnabledInLoggingOptions() { assertEquals(HTTP_REQUEST, actual.getHttpRequest()); assertEquals(FORMATTED_TRACE_ID, actual.getTrace()); assertEquals(SPAN_ID, actual.getSpanId()); + assertEquals(TRACE_SAMPLED, actual.getTraceSampled()); assertEquals(RESOURCE, actual.getResource()); } @@ -136,7 +137,7 @@ public void testAutoPopulationEnabledInWriteOptionsAndDisabledInLoggingOptions() LoggingOptions options = logging.getOptions().toBuilder().setAutoPopulateMetadata(false).build(); logging = options.getService(); - mockCurrentContext(HTTP_REQUEST, TRACE_ID, SPAN_ID); + mockCurrentContext(HTTP_REQUEST, TRACE_ID, SPAN_ID, TRACE_SAMPLED); logging.write(ImmutableList.of(SIMPLE_LOG_ENTRY), WriteOption.autoPopulateMetadata(true)); @@ -144,12 +145,13 @@ public void testAutoPopulationEnabledInWriteOptionsAndDisabledInLoggingOptions() assertEquals(HTTP_REQUEST, actual.getHttpRequest()); assertEquals(FORMATTED_TRACE_ID, actual.getTrace()); assertEquals(SPAN_ID, actual.getSpanId()); + assertEquals(TRACE_SAMPLED, actual.getTraceSampled()); assertEquals(RESOURCE, actual.getResource()); } @Test public void testAutoPopulationDisabledInWriteOptions() { - mockCurrentContext(HTTP_REQUEST, TRACE_ID, SPAN_ID); + mockCurrentContext(HTTP_REQUEST, TRACE_ID, SPAN_ID, TRACE_SAMPLED); logging.write(ImmutableList.of(SIMPLE_LOG_ENTRY), WriteOption.autoPopulateMetadata(false)); @@ -157,6 +159,7 @@ public void testAutoPopulationDisabledInWriteOptions() { assertNull(actual.getHttpRequest()); assertNull(actual.getTrace()); assertNull(actual.getSpanId()); + assertFalse(actual.getTraceSampled()); assertNull(actual.getResource()); } @@ -174,7 +177,7 @@ public void testSourceLocationPopulation() { @Test public void testNotFormattedTraceId() { - mockCurrentContext(HTTP_REQUEST, TRACE_ID, SPAN_ID); + mockCurrentContext(HTTP_REQUEST, TRACE_ID, SPAN_ID, TRACE_SAMPLED); final MonitoredResource expectedResource = MonitoredResource.newBuilder("custom").build(); @@ -186,7 +189,7 @@ public void testNotFormattedTraceId() { @Test public void testMonitoredResourcePopulationInWriteOptions() { - mockCurrentContext(HTTP_REQUEST, TRACE_ID, SPAN_ID); + mockCurrentContext(HTTP_REQUEST, TRACE_ID, SPAN_ID, TRACE_SAMPLED); final MonitoredResource expectedResource = MonitoredResource.newBuilder("custom").build(); diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java index d299aeab8..17d06e53a 100644 --- a/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java +++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java @@ -16,7 +16,6 @@ package com.google.cloud.logging; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; @@ -35,7 +34,6 @@ import io.opentelemetry.sdk.trace.SpanProcessor; import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; - @RunWith(JUnit4.class) public class ContextTest { @@ -162,7 +160,6 @@ public void testParsingW3CTraceParent() { assertTraceSpanAndSampled(builder.build(), W3C_TEST_TRACE_ID, W3C_TEST_SPAN_ID, true); } - @Test public void testParsingOpenTelemetryContext() { InMemorySpanExporter testExporter = InMemorySpanExporter.create(); @@ -192,11 +189,6 @@ public void testParsingOpenTelemetryContext() { } } - private void assertTraceAndSpan1(Context context, String expectedTraceId, String expectedSpanId) { - assertEquals(expectedTraceId, context.getTraceId()); - assertEquals(expectedSpanId, context.getSpanId()); - } - private void assertTraceSpanAndSampled(Context context, String expectedTraceId, String expectedSpanId, boolean expectedTraceSampled) { assertEquals(expectedTraceId, context.getTraceId()); assertEquals(expectedSpanId, context.getSpanId()); From 7ca6f19743c9a96d9642a16e83af921564733c06 Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Tue, 30 Apr 2024 17:57:28 +0800 Subject: [PATCH 08/30] fix test failures and dependency conflict --- .../com/google/cloud/logging/Context.java | 21 ++-- .../google/cloud/logging/ContextHandler.java | 110 +++++++++--------- .../com/google/cloud/logging/LoggingImpl.java | 7 +- .../logging/AutoPopulateMetadataTests.java | 10 +- .../com/google/cloud/logging/ContextTest.java | 41 ++++--- pom.xml | 2 +- 6 files changed, 104 insertions(+), 87 deletions(-) diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java index 78b527aa7..3f4a9abc1 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java @@ -22,11 +22,11 @@ import com.google.common.base.Splitter; import com.google.common.collect.Iterables; import com.google.errorprone.annotations.CanIgnoreReturnValue; +import io.opentelemetry.api.trace.Span; import java.util.List; import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; -import io.opentelemetry.api.trace.Span; /** Class to hold context attributes including information about {@see HttpRequest} and tracing. */ public class Context { @@ -132,9 +132,10 @@ public Builder setTraceSampled(boolean traceSampled) { } /** - * Sets the trace id, span id and trace sampled flag values by parsing the string which represents xCloud Trace - * Context. The Cloud Trace Context is passed as {@code x-cloud-trace-context} header (can be in - * Pascal case format). The string format is TRACE_ID/SPAN_ID;o=TRACE_TRUE. + * Sets the trace id, span id and trace sampled flag values by parsing the string which + * represents xCloud Trace Context. The Cloud Trace Context is passed as {@code + * x-cloud-trace-context} header (can be in Pascal case format). The string format is + * TRACE_ID/SPAN_ID;o=TRACE_TRUE. * * @see Cloud Trace header * format. @@ -165,10 +166,11 @@ public Builder loadCloudTraceContext(String cloudTrace) { } /** - * Sets the trace id, span id and trace sampled flag values by parsing the string which represents the standard W3C - * trace context propagation header. The context propagation header is passed as {@code - * traceparent} header. The method currently supports ONLY version {@code "00"}. The string - * format is 00-TRACE_ID-SPAN_ID-FLAGS. field of the {@code version-format} value. + * Sets the trace id, span id and trace sampled flag values by parsing the string which + * represents the standard W3C trace context propagation header. The context propagation header + * is passed as {@code traceparent} header. The method currently supports ONLY version {@code + * "00"}. The string format is 00-TRACE_ID-SPAN_ID-FLAGS. field of the {@code + * version-format} value. * * @see traceparent header @@ -202,8 +204,7 @@ public Builder loadW3CTraceParentContext(String traceParent) { */ @CanIgnoreReturnValue public Builder loadOpenTelemetryContext() { - if (Span.current().getSpanContext() != null && Span.current().getSpanContext().isValid()) - { + if (Span.current().getSpanContext() != null && Span.current().getSpanContext().isValid()) { setTraceId(Span.current().getSpanContext().getTraceId()); setSpanId(Span.current().getSpanContext().getSpanId()); setTraceSampled(Span.current().getSpanContext().isSampled()); diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java index 1a39223c3..9f3e7674e 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java @@ -16,69 +16,73 @@ package com.google.cloud.logging; -/** - * Class provides a per-thread storage of the {@see Context} instances. - */ +/** Class provides a per-thread storage of the {@see Context} instances. */ public class ContextHandler { - public enum ContextPriority { - NO_INPUT, XCLOUD_HEADER, W3_HEADER, OTEL_EXTRACTED - } - - private static final ThreadLocal contextHolder = initContextHolder(); - private static final ThreadLocal currentPriority = new ThreadLocal(); + public enum ContextPriority { + NO_INPUT, + XCLOUD_HEADER, + W3_HEADER, + OTEL_EXTRACTED + } - /** - * Initializes the context holder to {@link InheritableThreadLocal} if {@link LogManager} - * configuration property {@code com.google.cloud.logging.ContextHandler.useInheritedContext} is - * set to {@code true} or to {@link ThreadLocal} otherwise. - * - * @return instance of the context holder. - */ - private static ThreadLocal initContextHolder() { - LoggingConfig config = new LoggingConfig(ContextHandler.class.getName()); - if (config.getUseInheritedContext()) { - return new InheritableThreadLocal<>(); - } else { - return new ThreadLocal<>(); - } - } + private static final ThreadLocal contextHolder = initContextHolder(); + private static final ThreadLocal currentPriority = + new ThreadLocal(); - public Context getCurrentContext() { - return contextHolder.get(); + /** + * Initializes the context holder to {@link InheritableThreadLocal} if {@link LogManager} + * configuration property {@code com.google.cloud.logging.ContextHandler.useInheritedContext} is + * set to {@code true} or to {@link ThreadLocal} otherwise. + * + * @return instance of the context holder. + */ + private static ThreadLocal initContextHolder() { + LoggingConfig config = new LoggingConfig(ContextHandler.class.getName()); + if (config.getUseInheritedContext()) { + return new InheritableThreadLocal<>(); + } else { + return new ThreadLocal<>(); } + } + public Context getCurrentContext() { + return contextHolder.get(); + } - public void setCurrentContext(Context context) { - contextHolder.set(context); - } - - /** - * Sets the context based on the priority. Overrides traceId, spanId and TraceSampled if the passed priority is higher. - * HttpRequest values will be retrieved and combined from existing context if HttpRequest in the new context is empty . - */ + public void setCurrentContext(Context context) { + contextHolder.set(context); + } - public void setCurrentContext(Context context, ContextPriority priority) { - if ((currentPriority.get() == null || priority.compareTo(currentPriority.get()) >= 0) && context != null) { - Context.Builder combinedContextBuilder = Context.newBuilder().setTraceId(context.getTraceId()).setSpanId(context.getSpanId()).setTraceSampled(context.getTraceSampled()); - Context currentContext = getCurrentContext(); + /** + * Sets the context based on the priority. Overrides traceId, spanId and TraceSampled if the + * passed priority is higher. HttpRequest values will be retrieved and combined from existing + * context if HttpRequest in the new context is empty . + */ + public void setCurrentContext(Context context, ContextPriority priority) { + if ((currentPriority.get() == null || priority.compareTo(currentPriority.get()) >= 0) + && context != null) { + Context.Builder combinedContextBuilder = + Context.newBuilder() + .setTraceId(context.getTraceId()) + .setSpanId(context.getSpanId()) + .setTraceSampled(context.getTraceSampled()); + Context currentContext = getCurrentContext(); - if (context.getHttpRequest() != null) - { - combinedContextBuilder.setRequest(context.getHttpRequest()); - } - // Combines HttpRequest from the existing context if HttpRequest in new context is empty. - else if (currentContext != null && currentContext.getHttpRequest() != null ){ - combinedContextBuilder.setRequest(currentContext.getHttpRequest()); - } + if (context.getHttpRequest() != null) { + combinedContextBuilder.setRequest(context.getHttpRequest()); + } + // Combines HttpRequest from the existing context if HttpRequest in new context is empty. + else if (currentContext != null && currentContext.getHttpRequest() != null) { + combinedContextBuilder.setRequest(currentContext.getHttpRequest()); + } - contextHolder.set(combinedContextBuilder.build()); - currentPriority.set(priority); - } + contextHolder.set(combinedContextBuilder.build()); + currentPriority.set(priority); } + } - - public void removeCurrentContext() { - contextHolder.remove(); - } + public void removeCurrentContext() { + contextHolder.remove(); + } } diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java index 45b3eec13..20bf4b507 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java @@ -41,6 +41,7 @@ import com.google.cloud.MonitoredResourceDescriptor; import com.google.cloud.PageImpl; import com.google.cloud.Tuple; +import com.google.cloud.logging.ContextHandler.ContextPriority; import com.google.cloud.logging.spi.v2.LoggingRpc; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Ascii; @@ -89,6 +90,7 @@ import com.google.logging.v2.WriteLogEntriesResponse; import com.google.protobuf.Empty; import com.google.protobuf.util.Durations; +import io.opentelemetry.api.trace.Span; import java.text.ParseException; import java.util.ArrayList; import java.util.List; @@ -98,8 +100,6 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import io.opentelemetry.api.trace.Span; -import com.google.cloud.logging.ContextHandler.ContextPriority; class LoggingImpl extends BaseService implements Logging { protected static final String RESOURCE_NAME_FORMAT = "projects/%s/traces/%s"; @@ -839,8 +839,7 @@ public Iterable populateMetadata( ContextHandler contextHandler = new ContextHandler(); // Populate trace/span ID from OpenTelemetry span context to logging context. - if (Span.current().getSpanContext().isValid()) - { + if (Span.current().getSpanContext().isValid()) { Context.Builder contextBuilder = Context.newBuilder().loadOpenTelemetryContext(); contextHandler.setCurrentContext(contextBuilder.build(), ContextPriority.OTEL_EXTRACTED); } diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/AutoPopulateMetadataTests.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/AutoPopulateMetadataTests.java index fee5f69c5..7972ca7bf 100644 --- a/google-cloud-logging/src/test/java/com/google/cloud/logging/AutoPopulateMetadataTests.java +++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/AutoPopulateMetadataTests.java @@ -111,9 +111,15 @@ public void teardown() { new ContextHandler().removeCurrentContext(); } - private void mockCurrentContext(HttpRequest request, String traceId, String spanId, boolean traceSampled) { + private void mockCurrentContext( + HttpRequest request, String traceId, String spanId, boolean traceSampled) { Context mockedContext = - Context.newBuilder().setRequest(request).setTraceId(traceId).setSpanId(spanId).setTraceSampled(traceSampled).build(); + Context.newBuilder() + .setRequest(request) + .setTraceId(traceId) + .setSpanId(spanId) + .setTraceSampled(traceSampled) + .build(); new ContextHandler().setCurrentContext(mockedContext); } diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java index 17d06e53a..b2b3ea17a 100644 --- a/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java +++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java @@ -21,18 +21,18 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNull; -import io.opentelemetry.context.Scope; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; -import org.threeten.bp.Duration; -import io.opentelemetry.api.trace.Span; import io.opentelemetry.api.trace.*; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.context.Scope; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter; import io.opentelemetry.sdk.trace.SdkTracerProvider; import io.opentelemetry.sdk.trace.SpanProcessor; import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.threeten.bp.Duration; @RunWith(JUnit4.class) public class ContextTest { @@ -127,7 +127,7 @@ public void testParsingCloudTraceContext() { final String X_CLOUD_TRACE_NO_TRACE = "/SPAN_ID;o=TRACE_TRUE"; final String X_CLOUD_TRACE_ONLY = TEST_TRACE_ID; final String X_CLOUD_TRACE_WITH_SPAN = TEST_TRACE_ID + "/" + TEST_SPAN_ID; - final String X_CLOUD_TRACE_FULL = TEST_TRACE_ID + "/" + TEST_SPAN_ID + ";o=" + TEST_TRACE_SAMPLED; + final String X_CLOUD_TRACE_FULL = TEST_TRACE_ID + "/" + TEST_SPAN_ID + ";o=1"; Context.Builder builder = Context.newBuilder(); @@ -150,7 +150,8 @@ public void testParsingW3CTraceParent() { final String W3C_TEST_TRACE_ID = "12345678901234567890123456789012"; final String W3C_TEST_SPAN_ID = "1234567890123456"; final String W3C_TEST_TRACE_SAMPLED = "0f"; - final String W3C_TRACE_CONTEXT = "00-" + W3C_TEST_TRACE_ID + "-" + W3C_TEST_SPAN_ID + "-" + W3C_TEST_TRACE_SAMPLED; + final String W3C_TRACE_CONTEXT = + "00-" + W3C_TEST_TRACE_ID + "-" + W3C_TEST_SPAN_ID + "-" + W3C_TEST_TRACE_SAMPLED; Context.Builder builder = Context.newBuilder(); @@ -165,12 +166,10 @@ public void testParsingOpenTelemetryContext() { InMemorySpanExporter testExporter = InMemorySpanExporter.create(); SpanProcessor inMemorySpanProcessor = SimpleSpanProcessor.create(testExporter); OpenTelemetrySdk openTelemetrySdk = - OpenTelemetrySdk.builder() - .setTracerProvider( - SdkTracerProvider.builder() - .addSpanProcessor(inMemorySpanProcessor) - .build()) - .build(); + OpenTelemetrySdk.builder() + .setTracerProvider( + SdkTracerProvider.builder().addSpanProcessor(inMemorySpanProcessor).build()) + .build(); Tracer tracer = openTelemetrySdk.getTracer("ContextTest"); Span otelSpan = tracer.spanBuilder("Example Span Attributes").startSpan(); @@ -180,8 +179,12 @@ public void testParsingOpenTelemetryContext() { otelSpan.setAttribute("Attribute 1", "first attribute value"); currentOtelContext = otelSpan.getSpanContext(); builder.loadOpenTelemetryContext(); - assertTraceSpanAndSampled(builder.build(), currentOtelContext.getTraceId(), currentOtelContext.getSpanId(), currentOtelContext.isSampled()); - } catch(Throwable t) { + assertTraceSpanAndSampled( + builder.build(), + currentOtelContext.getTraceId(), + currentOtelContext.getSpanId(), + currentOtelContext.isSampled()); + } catch (Throwable t) { otelSpan.recordException(t); throw t; } finally { @@ -189,7 +192,11 @@ public void testParsingOpenTelemetryContext() { } } - private void assertTraceSpanAndSampled(Context context, String expectedTraceId, String expectedSpanId, boolean expectedTraceSampled) { + private void assertTraceSpanAndSampled( + Context context, + String expectedTraceId, + String expectedSpanId, + boolean expectedTraceSampled) { assertEquals(expectedTraceId, context.getTraceId()); assertEquals(expectedSpanId, context.getSpanId()); assertEquals(expectedTraceSampled, context.getTraceSampled()); diff --git a/pom.xml b/pom.xml index 91d122470..a92de2d08 100644 --- a/pom.xml +++ b/pom.xml @@ -54,7 +54,7 @@ UTF-8 github google-cloud-logging-parent - 1.36.0 + 1.37.0 From 72aa518dc1d7937932d1e50b753df88498a3f4b7 Mon Sep 17 00:00:00 2001 From: Owl Bot Date: Tue, 30 Apr 2024 10:01:17 +0000 Subject: [PATCH 09/30] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot=20?= =?UTF-8?q?post-processor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2e563e8da..035353f4c 100644 --- a/README.md +++ b/README.md @@ -52,20 +52,20 @@ If you are using Maven without the BOM, add this to your dependencies: If you are using Gradle 5.x or later, add this to your dependencies: ```Groovy -implementation platform('com.google.cloud:libraries-bom:26.34.0') +implementation platform('com.google.cloud:libraries-bom:26.37.0') implementation 'com.google.cloud:google-cloud-logging' ``` If you are using Gradle without BOM, add this to your dependencies: ```Groovy -implementation 'com.google.cloud:google-cloud-logging:3.16.1' +implementation 'com.google.cloud:google-cloud-logging:3.17.0' ``` If you are using SBT, add this to your dependencies: ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-logging" % "3.16.1" +libraryDependencies += "com.google.cloud" % "google-cloud-logging" % "3.17.0" ``` @@ -452,7 +452,7 @@ Java is a registered trademark of Oracle and/or its affiliates. [kokoro-badge-link-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-logging/java11.html [stability-image]: https://img.shields.io/badge/stability-stable-green [maven-version-image]: https://img.shields.io/maven-central/v/com.google.cloud/google-cloud-logging.svg -[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-logging/3.16.1 +[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-logging/3.17.0 [authentication]: https://github.com/googleapis/google-cloud-java#authentication [auth-scopes]: https://developers.google.com/identity/protocols/oauth2/scopes [predefined-iam-roles]: https://cloud.google.com/iam/docs/understanding-roles#predefined_roles From e67c9074cdfccc4f135c54d2c8f8ad5f4c7bf66e Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Thu, 2 May 2024 21:17:34 +0800 Subject: [PATCH 10/30] Add open-telemetry context dependency --- pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pom.xml b/pom.xml index 55eba627b..e4c269e8c 100644 --- a/pom.xml +++ b/pom.xml @@ -150,6 +150,11 @@ ${opentelemetry.version} test + + io.opentelemetry + opentelemetry-context + ${opentelemetry.version} + io.opentelemetry opentelemetry-sdk-common From 42a49e11df2158b9648a0ceaf8a2a5ff0d591c64 Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Fri, 3 May 2024 11:44:09 +0800 Subject: [PATCH 11/30] Resolve otel context dependency --- google-cloud-logging/pom.xml | 9 +++++++++ pom.xml | 10 +++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/google-cloud-logging/pom.xml b/google-cloud-logging/pom.xml index 6b4b3306a..091178df3 100644 --- a/google-cloud-logging/pom.xml +++ b/google-cloud-logging/pom.xml @@ -21,6 +21,10 @@ io.opentelemetry opentelemetry-api + + io.opentelemetry + opentelemetry-context + com.google.guava guava @@ -148,6 +152,11 @@ opentelemetry-sdk-testing test + + io.opentelemetry + opentelemetry-sdk-trace + test + diff --git a/pom.xml b/pom.xml index e4c269e8c..583b05beb 100644 --- a/pom.xml +++ b/pom.xml @@ -65,6 +65,11 @@ opentelemetry-api ${opentelemetry.version} + + io.opentelemetry + opentelemetry-context + ${opentelemetry.version} + com.google.api.grpc @@ -150,11 +155,6 @@ ${opentelemetry.version} test - - io.opentelemetry - opentelemetry-context - ${opentelemetry.version} - io.opentelemetry opentelemetry-sdk-common From e4c3f06cb6438b7e3b783f59e0a556aa1cdc1cbf Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Fri, 3 May 2024 11:50:17 +0800 Subject: [PATCH 12/30] Make otel-context as test dependency --- google-cloud-logging/pom.xml | 9 +++++---- pom.xml | 11 ++++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/google-cloud-logging/pom.xml b/google-cloud-logging/pom.xml index 091178df3..1c10f8f35 100644 --- a/google-cloud-logging/pom.xml +++ b/google-cloud-logging/pom.xml @@ -21,10 +21,6 @@ io.opentelemetry opentelemetry-api - - io.opentelemetry - opentelemetry-context - com.google.guava guava @@ -152,6 +148,11 @@ opentelemetry-sdk-testing test + + io.opentelemetry + opentelemetry-context + test + io.opentelemetry opentelemetry-sdk-trace diff --git a/pom.xml b/pom.xml index 583b05beb..f539993ba 100644 --- a/pom.xml +++ b/pom.xml @@ -65,11 +65,6 @@ opentelemetry-api ${opentelemetry.version} - - io.opentelemetry - opentelemetry-context - ${opentelemetry.version} - com.google.api.grpc @@ -149,6 +144,12 @@ ${opentelemetry.version}-alpha test + + io.opentelemetry + opentelemetry-context + ${opentelemetry.version} + test + io.opentelemetry opentelemetry-sdk-trace From 9f09a850ac864992a874afcde602f3083d4a04df Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Fri, 3 May 2024 12:05:03 +0800 Subject: [PATCH 13/30] make otel-context as compile dependency --- google-cloud-logging/pom.xml | 9 ++++----- pom.xml | 11 +++++------ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/google-cloud-logging/pom.xml b/google-cloud-logging/pom.xml index 1c10f8f35..091178df3 100644 --- a/google-cloud-logging/pom.xml +++ b/google-cloud-logging/pom.xml @@ -21,6 +21,10 @@ io.opentelemetry opentelemetry-api + + io.opentelemetry + opentelemetry-context + com.google.guava guava @@ -148,11 +152,6 @@ opentelemetry-sdk-testing test - - io.opentelemetry - opentelemetry-context - test - io.opentelemetry opentelemetry-sdk-trace diff --git a/pom.xml b/pom.xml index f539993ba..583b05beb 100644 --- a/pom.xml +++ b/pom.xml @@ -65,6 +65,11 @@ opentelemetry-api ${opentelemetry.version} + + io.opentelemetry + opentelemetry-context + ${opentelemetry.version} + com.google.api.grpc @@ -144,12 +149,6 @@ ${opentelemetry.version}-alpha test - - io.opentelemetry - opentelemetry-context - ${opentelemetry.version} - test - io.opentelemetry opentelemetry-sdk-trace From cefcd738e8be9258183f4ff1fa847e63a7ed42ac Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Sat, 4 May 2024 09:45:48 +0800 Subject: [PATCH 14/30] Add span context import --- .../src/main/java/com/google/cloud/logging/LoggingImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java index 20bf4b507..8e73b766f 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java @@ -91,6 +91,7 @@ import com.google.protobuf.Empty; import com.google.protobuf.util.Durations; import io.opentelemetry.api.trace.Span; +import io.opentelemetry.context.ImplicitContextKeyed; import java.text.ParseException; import java.util.ArrayList; import java.util.List; From c600f0d0ded79c8f8c5d7023af90e55c8799e30a Mon Sep 17 00:00:00 2001 From: Owl Bot Date: Sat, 4 May 2024 01:47:51 +0000 Subject: [PATCH 15/30] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot=20?= =?UTF-8?q?post-processor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --- .../src/main/java/com/google/cloud/logging/LoggingImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java index 8e73b766f..20bf4b507 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/LoggingImpl.java @@ -91,7 +91,6 @@ import com.google.protobuf.Empty; import com.google.protobuf.util.Durations; import io.opentelemetry.api.trace.Span; -import io.opentelemetry.context.ImplicitContextKeyed; import java.text.ParseException; import java.util.ArrayList; import java.util.List; From 1d481668260c1623d6ea5b9a69f59864a6ce8380 Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Sat, 4 May 2024 16:21:14 +0800 Subject: [PATCH 16/30] Add test and compile dependency --- google-cloud-logging/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/google-cloud-logging/pom.xml b/google-cloud-logging/pom.xml index 091178df3..ddf7e2392 100644 --- a/google-cloud-logging/pom.xml +++ b/google-cloud-logging/pom.xml @@ -147,6 +147,11 @@ opentelemetry-sdk test + + io.opentelemetry + opentelemetry-context + test + io.opentelemetry opentelemetry-sdk-testing From 0e61c7da2cfa81e3ba89e1d50b1517eabe245fa3 Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Sat, 4 May 2024 17:41:19 +0800 Subject: [PATCH 17/30] Use transitive dependency --- google-cloud-logging/pom.xml | 13 ++++--------- pom.xml | 10 +++++----- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/google-cloud-logging/pom.xml b/google-cloud-logging/pom.xml index ddf7e2392..301e9fdf8 100644 --- a/google-cloud-logging/pom.xml +++ b/google-cloud-logging/pom.xml @@ -21,10 +21,10 @@ io.opentelemetry opentelemetry-api - - io.opentelemetry - opentelemetry-context - + + + + com.google.guava guava @@ -147,11 +147,6 @@ opentelemetry-sdk test - - io.opentelemetry - opentelemetry-context - test - io.opentelemetry opentelemetry-sdk-testing diff --git a/pom.xml b/pom.xml index 583b05beb..931d953af 100644 --- a/pom.xml +++ b/pom.xml @@ -65,11 +65,11 @@ opentelemetry-api ${opentelemetry.version} - - io.opentelemetry - opentelemetry-context - ${opentelemetry.version} - + + + + + com.google.api.grpc From 9cf24ab879da54182a0b28d8e9743fb45b367d6b Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Sat, 4 May 2024 17:56:07 +0800 Subject: [PATCH 18/30] Ignore otel context non-test warning --- google-cloud-logging/pom.xml | 8 ++++---- pom.xml | 15 ++++++++++----- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/google-cloud-logging/pom.xml b/google-cloud-logging/pom.xml index 301e9fdf8..091178df3 100644 --- a/google-cloud-logging/pom.xml +++ b/google-cloud-logging/pom.xml @@ -21,10 +21,10 @@ io.opentelemetry opentelemetry-api - - - - + + io.opentelemetry + opentelemetry-context + com.google.guava guava diff --git a/pom.xml b/pom.xml index 931d953af..e454a5f24 100644 --- a/pom.xml +++ b/pom.xml @@ -65,11 +65,12 @@ opentelemetry-api ${opentelemetry.version} - - - - - + + io.opentelemetry + opentelemetry-context + ${opentelemetry.version} + false + com.google.api.grpc @@ -179,6 +180,10 @@ maven-dependency-plugin org.objenesis:objenesis + + + io.opentelemetry:opentelemetry-context + From e59fd6b5176223e33a2c3ab0f9775440e1719389 Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Sun, 5 May 2024 15:18:10 +0800 Subject: [PATCH 19/30] comment otel-context --- google-cloud-logging/pom.xml | 8 ++++---- pom.xml | 24 ++++++++++++++---------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/google-cloud-logging/pom.xml b/google-cloud-logging/pom.xml index 091178df3..301e9fdf8 100644 --- a/google-cloud-logging/pom.xml +++ b/google-cloud-logging/pom.xml @@ -21,10 +21,10 @@ io.opentelemetry opentelemetry-api - - io.opentelemetry - opentelemetry-context - + + + + com.google.guava guava diff --git a/pom.xml b/pom.xml index e454a5f24..cd8f64f4e 100644 --- a/pom.xml +++ b/pom.xml @@ -65,12 +65,12 @@ opentelemetry-api ${opentelemetry.version} - - io.opentelemetry - opentelemetry-context - ${opentelemetry.version} - false - + + + + + + com.google.api.grpc @@ -179,11 +179,15 @@ org.apache.maven.plugins maven-dependency-plugin - org.objenesis:objenesis + + org.objenesis:objenesis + + + - - io.opentelemetry:opentelemetry-context - + + + From 4ff6738c4ef1a4fb281408e9af0ab448b98e41b7 Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Sun, 5 May 2024 16:02:00 +0800 Subject: [PATCH 20/30] Add otel current context detection --- google-cloud-logging/pom.xml | 8 +++---- .../com/google/cloud/logging/Context.java | 11 ++++++---- pom.xml | 21 ++++++------------- 3 files changed, 17 insertions(+), 23 deletions(-) diff --git a/google-cloud-logging/pom.xml b/google-cloud-logging/pom.xml index 301e9fdf8..091178df3 100644 --- a/google-cloud-logging/pom.xml +++ b/google-cloud-logging/pom.xml @@ -21,10 +21,10 @@ io.opentelemetry opentelemetry-api - - - - + + io.opentelemetry + opentelemetry-context + com.google.guava guava diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java index 3f4a9abc1..582706a31 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java @@ -23,6 +23,7 @@ import com.google.common.collect.Iterables; import com.google.errorprone.annotations.CanIgnoreReturnValue; import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanContext; import java.util.List; import java.util.Objects; import java.util.regex.Matcher; @@ -204,10 +205,12 @@ public Builder loadW3CTraceParentContext(String traceParent) { */ @CanIgnoreReturnValue public Builder loadOpenTelemetryContext() { - if (Span.current().getSpanContext() != null && Span.current().getSpanContext().isValid()) { - setTraceId(Span.current().getSpanContext().getTraceId()); - setSpanId(Span.current().getSpanContext().getSpanId()); - setTraceSampled(Span.current().getSpanContext().isSampled()); + io.opentelemetry.context.Context currentContext = io.opentelemetry.context.Context.current(); + SpanContext spanContext = Span.fromContext(currentContext).getSpanContext(); + if (spanContext != null && spanContext.isValid()) { + setTraceId(spanContext.getTraceId()); + setSpanId(spanContext.getSpanId()); + setTraceSampled(spanContext.isSampled()); } return this; } diff --git a/pom.xml b/pom.xml index cd8f64f4e..583b05beb 100644 --- a/pom.xml +++ b/pom.xml @@ -65,12 +65,11 @@ opentelemetry-api ${opentelemetry.version} - - - - - - + + io.opentelemetry + opentelemetry-context + ${opentelemetry.version} + com.google.api.grpc @@ -179,15 +178,7 @@ org.apache.maven.plugins maven-dependency-plugin - - org.objenesis:objenesis - - - - - - - + org.objenesis:objenesis From d560806b578585d2015ba46513354c52baf79f2f Mon Sep 17 00:00:00 2001 From: Owl Bot Date: Sun, 5 May 2024 08:04:30 +0000 Subject: [PATCH 21/30] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot=20?= =?UTF-8?q?post-processor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --- .../src/main/java/com/google/cloud/logging/Context.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java index 582706a31..3466ecd2c 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/Context.java @@ -205,7 +205,7 @@ public Builder loadW3CTraceParentContext(String traceParent) { */ @CanIgnoreReturnValue public Builder loadOpenTelemetryContext() { - io.opentelemetry.context.Context currentContext = io.opentelemetry.context.Context.current(); + io.opentelemetry.context.Context currentContext = io.opentelemetry.context.Context.current(); SpanContext spanContext = Span.fromContext(currentContext).getSpanContext(); if (spanContext != null && spanContext.isValid()) { setTraceId(spanContext.getTraceId()); From c8e4ecab74e45d2d7a8df728594dafcf3b4cade0 Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Mon, 6 May 2024 21:51:38 +0800 Subject: [PATCH 22/30] Add system tests --- .../google/cloud/logging/ContextHandler.java | 3 +- .../cloud/logging/it/ITTracingLogsTest.java | 240 ++++++++++++++++++ 2 files changed, 241 insertions(+), 2 deletions(-) create mode 100644 google-cloud-logging/src/test/java/com/google/cloud/logging/it/ITTracingLogsTest.java diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java index 9f3e7674e..3ec984edf 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java @@ -27,8 +27,7 @@ public enum ContextPriority { } private static final ThreadLocal contextHolder = initContextHolder(); - private static final ThreadLocal currentPriority = - new ThreadLocal(); + private static final ThreadLocal currentPriority = ThreadLocal.withInitial(()->ContextPriority.NO_INPUT); /** * Initializes the context holder to {@link InheritableThreadLocal} if {@link LogManager} diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/it/ITTracingLogsTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/it/ITTracingLogsTest.java new file mode 100644 index 000000000..0c8bc41d4 --- /dev/null +++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/it/ITTracingLogsTest.java @@ -0,0 +1,240 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.logging.it; + +import com.google.cloud.MonitoredResource; +import com.google.cloud.logging.*; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.logging.v2.LogName; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanContext; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.context.Scope; +import io.opentelemetry.sdk.OpenTelemetrySdk; +import io.opentelemetry.sdk.testing.exporter.InMemorySpanExporter; +import io.opentelemetry.sdk.trace.SdkTracerProvider; +import io.opentelemetry.sdk.trace.SpanProcessor; +import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; +import org.junit.After; +import org.junit.BeforeClass; +import org.junit.Test; + +import java.util.Iterator; + +import static com.google.cloud.logging.testing.RemoteLoggingHelper.formatForTest; +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.*; + +public class ITTracingLogsTest extends BaseSystemTest { + + private static final String LOG_ID = formatForTest("test-write-log-entries-log"); + private static final Payload.StringPayload STRING_PAYLOAD = + Payload.StringPayload.of("stringPayload"); + private static final Payload.JsonPayload OTEL_PAYLOAD = + Payload.JsonPayload.of(ImmutableMap.of("jsonKey", "jsonValue")); + + private static final MonitoredResource GLOBAL_RESOURCE = + MonitoredResource.newBuilder("global").build(); + private static final MonitoredResource[] MONITORED_RESOURCES_IN_TEST = + new MonitoredResource[] {GLOBAL_RESOURCE}; + + private static final ContextHandler contextHandler = new ContextHandler(); + + private static final String W3C_TEST_TRACE_ID = "12345678901234567890123456789012"; + private static final String W3C_TEST_SPAN_ID = "1234567890123456"; + private static final String W3C_TEST_TRACE_SAMPLED = "0f"; + private static final String W3C_TRACE_CONTEXT = + "00-" + W3C_TEST_TRACE_ID + "-" + W3C_TEST_SPAN_ID + "-" + W3C_TEST_TRACE_SAMPLED; + + private static final String XCTC_TEST_TRACE_ID = "98765432101234569876543210123456"; + private static final String XCTC_TEST_SPAN_ID = "9876543210123456"; + private static final String X_CLOUD_TRACE_CONTEXT = XCTC_TEST_TRACE_ID + "/" + XCTC_TEST_SPAN_ID + ";o=1"; + + private static String otelTraceId; + private static String otelSpanId; + private static boolean isSampled; + private static Tracer tracer; + private static LogEntry w3cEntry; + private static LogEntry xctcEntry; + private static LogEntry otelEntry; + private static LogName logName; + + @BeforeClass + public static void prepareLogs() throws InterruptedException { + LoggingOptions loggingOptions = logging.getOptions(); + logName = LogName.ofProjectLogName(loggingOptions.getProjectId(), LOG_ID); + logging.setWriteSynchronicity(Synchronicity.SYNC); + w3cEntry = + LogEntry.newBuilder(STRING_PAYLOAD) + .setLogName(LOG_ID) + .addLabel("tracing_source", "w3c") + .setHttpRequest(HttpRequest.newBuilder().setStatus(500).build()) + .setResource(GLOBAL_RESOURCE) + .build(); + xctcEntry = + LogEntry.newBuilder(STRING_PAYLOAD) + .setLogName(LOG_ID) + .addLabel("tracing_source", "xctc") + .setHttpRequest(HttpRequest.newBuilder().setRequestUrl("www.google.com").build()) + .setResource(GLOBAL_RESOURCE) + .build(); + otelEntry = + LogEntry.newBuilder(OTEL_PAYLOAD) + .addLabel("tracing_source", "otel") + .setLogName(LOG_ID) + .setResource(GLOBAL_RESOURCE) + .build(); + + // Initializes open telemetry SDK + InMemorySpanExporter testExporter = InMemorySpanExporter.create(); + SpanProcessor inMemorySpanProcessor = SimpleSpanProcessor.create(testExporter); + OpenTelemetrySdk openTelemetrySdk = + OpenTelemetrySdk.builder() + .setTracerProvider( + SdkTracerProvider.builder().addSpanProcessor(inMemorySpanProcessor).build()) + .build(); + tracer = openTelemetrySdk.getTracer("ContextTest"); + } + + @After + public void cleanUpLogs() throws InterruptedException { + assertTrue(cleanupLog(LOG_ID)); + } + + @Test(timeout = 600_000) + public void testDetectW3CTraceId() throws InterruptedException { + // Loads w3c tracing context and writes a log entry + Context.Builder builder = Context.newBuilder(); + builder.loadW3CTraceParentContext(W3C_TRACE_CONTEXT); + contextHandler.setCurrentContext(builder.build()); + logging.write(ImmutableList.of(w3cEntry)); + logging.flush(); + + // Find the log name and wait until we have at least 1 entry + Iterator iterator = waitForLogs(logName, MONITORED_RESOURCES_IN_TEST, 1); + assertThat(iterator.hasNext()).isTrue(); + + LogEntry entry = iterator.next(); + assertEquals(LOG_ID, entry.getLogName()); + assertEquals(ImmutableMap.of("tracing_source", "w3c"), entry.getLabels()); + assertEquals(HttpRequest.newBuilder().setStatus(500).build(), entry.getHttpRequest()); + assertEquals(W3C_TEST_TRACE_ID, entry.getTrace()); + assertEquals(W3C_TEST_SPAN_ID, entry.getSpanId()); + assertEquals(true, entry.getTraceSampled()); + } + + @Test(timeout = 600_000) + public void testDetectXCTCTraceId() throws InterruptedException { + // Loads cloud trace context and writes a log entry + Context.Builder builder = Context.newBuilder(); + builder.loadCloudTraceContext(X_CLOUD_TRACE_CONTEXT); + contextHandler.setCurrentContext(builder.build()); + logging.write(ImmutableList.of(xctcEntry)); + logging.flush(); + + // Find the log name and wait until we have at least 1 entry + Iterator iterator = waitForLogs(logName, MONITORED_RESOURCES_IN_TEST, 1); + assertThat(iterator.hasNext()).isTrue(); + + LogEntry entry = iterator.next(); + assertEquals(LOG_ID, entry.getLogName()); + assertEquals(ImmutableMap.of("tracing_source", "xctc"), entry.getLabels()); + assertEquals(HttpRequest.newBuilder().setRequestUrl("www.google.com").build(), entry.getHttpRequest()); + assertEquals(XCTC_TEST_TRACE_ID, entry.getTrace()); + assertEquals(XCTC_TEST_SPAN_ID, entry.getSpanId()); + assertEquals(true, entry.getTraceSampled()); + } + @Test(timeout = 600_000) + public void testDetectOtelTraceId() throws InterruptedException { + // Writes a log entry in open telemetry context + writeLogEntryWithOtelContext(otelEntry); + + // Find the log name and wait until we have at least 1 entry + Iterator iterator = waitForLogs(logName, MONITORED_RESOURCES_IN_TEST, 1); + assertThat(iterator.hasNext()).isTrue(); + + LogEntry entry = iterator.next(); + assertEquals(LOG_ID, entry.getLogName()); + assertEquals(OTEL_PAYLOAD, entry.getPayload()); + assertEquals(ImmutableMap.of("tracing_source", "otel"), entry.getLabels()); + assertNull(entry.getHttpRequest()); + assertEquals(otelTraceId, entry.getTrace()); + assertEquals(otelSpanId, entry.getSpanId()); + assertEquals(isSampled, entry.getTraceSampled()); + } + + @Test(timeout = 600_000) + public void testW3CTraceIdWithOtelContext() throws InterruptedException { + // Writes a log entry with W3C context and Open Telemetry context + Context.Builder builder = Context.newBuilder(); + builder.loadW3CTraceParentContext(W3C_TRACE_CONTEXT); + contextHandler.setCurrentContext(builder.build()); + writeLogEntryWithOtelContext(w3cEntry); + + // Find the log name and wait until we have at least 1 entry + Iterator iterator = waitForLogs(logName, MONITORED_RESOURCES_IN_TEST, 1); + assertThat(iterator.hasNext()).isTrue(); + + LogEntry entry = iterator.next(); + assertEquals(LOG_ID, entry.getLogName()); + assertEquals(HttpRequest.newBuilder().setStatus(500).build(), entry.getHttpRequest()); + // Expect to get trace Id, span Id and isSampled flag from Open Telemetry context when it exists. + assertEquals(otelTraceId, entry.getTrace()); + assertEquals(otelSpanId, entry.getSpanId()); + assertEquals(isSampled, entry.getTraceSampled()); + } + + @Test(timeout = 600_000) + public void testXCTCTraceIdWithOtelContext() throws InterruptedException { + // Writes a log entry with cloud trace context and Open Telemetry context + Context.Builder builder = Context.newBuilder(); + builder.loadCloudTraceContext(X_CLOUD_TRACE_CONTEXT); + contextHandler.setCurrentContext(builder.build()); + writeLogEntryWithOtelContext(xctcEntry); + + // Find the log name and wait until we have at least 1 entry + Iterator iterator = waitForLogs(logName, MONITORED_RESOURCES_IN_TEST, 1); + assertThat(iterator.hasNext()).isTrue(); + + LogEntry entry = iterator.next(); + assertEquals(LOG_ID, entry.getLogName()); + // Expect to get trace Id, span Id and isSampled flag from Open telemetry context when it exists. + assertEquals(otelTraceId, entry.getTrace()); + assertEquals(otelSpanId, entry.getSpanId()); + assertEquals(isSampled, entry.getTraceSampled()); + } + + // Writes a log entry with otel context + private static void writeLogEntryWithOtelContext(LogEntry entry) throws InterruptedException { + Span otelSpan = tracer.spanBuilder("Example Span").startSpan(); + SpanContext currentOtelContext; + try (Scope scope = otelSpan.makeCurrent()) { + currentOtelContext = otelSpan.getSpanContext(); + otelTraceId = currentOtelContext.getTraceId(); + otelSpanId = currentOtelContext.getSpanId(); + isSampled = currentOtelContext.isSampled(); + logging.write(ImmutableList.of(entry)); + } catch (Throwable t) { + otelSpan.recordException(t); + throw t; + } finally { + otelSpan.end(); + } + logging.flush(); + } +} From ae6031105c3b87e1f30e5a0a0ba6a261449d7348 Mon Sep 17 00:00:00 2001 From: Owl Bot Date: Mon, 6 May 2024 13:54:59 +0000 Subject: [PATCH 23/30] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot=20?= =?UTF-8?q?post-processor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --- .../google/cloud/logging/ContextHandler.java | 3 +- .../cloud/logging/it/ITTracingLogsTest.java | 58 ++++++++++--------- 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java index 3ec984edf..5e5c95a65 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java @@ -27,7 +27,8 @@ public enum ContextPriority { } private static final ThreadLocal contextHolder = initContextHolder(); - private static final ThreadLocal currentPriority = ThreadLocal.withInitial(()->ContextPriority.NO_INPUT); + private static final ThreadLocal currentPriority = + ThreadLocal.withInitial(() -> ContextPriority.NO_INPUT); /** * Initializes the context holder to {@link InheritableThreadLocal} if {@link LogManager} diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/it/ITTracingLogsTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/it/ITTracingLogsTest.java index 0c8bc41d4..cdd52af39 100644 --- a/google-cloud-logging/src/test/java/com/google/cloud/logging/it/ITTracingLogsTest.java +++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/it/ITTracingLogsTest.java @@ -16,6 +16,10 @@ package com.google.cloud.logging.it; +import static com.google.cloud.logging.testing.RemoteLoggingHelper.formatForTest; +import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.*; + import com.google.cloud.MonitoredResource; import com.google.cloud.logging.*; import com.google.common.collect.ImmutableList; @@ -30,16 +34,11 @@ import io.opentelemetry.sdk.trace.SdkTracerProvider; import io.opentelemetry.sdk.trace.SpanProcessor; import io.opentelemetry.sdk.trace.export.SimpleSpanProcessor; +import java.util.Iterator; import org.junit.After; import org.junit.BeforeClass; import org.junit.Test; -import java.util.Iterator; - -import static com.google.cloud.logging.testing.RemoteLoggingHelper.formatForTest; -import static com.google.common.truth.Truth.assertThat; -import static org.junit.Assert.*; - public class ITTracingLogsTest extends BaseSystemTest { private static final String LOG_ID = formatForTest("test-write-log-entries-log"); @@ -59,11 +58,12 @@ public class ITTracingLogsTest extends BaseSystemTest { private static final String W3C_TEST_SPAN_ID = "1234567890123456"; private static final String W3C_TEST_TRACE_SAMPLED = "0f"; private static final String W3C_TRACE_CONTEXT = - "00-" + W3C_TEST_TRACE_ID + "-" + W3C_TEST_SPAN_ID + "-" + W3C_TEST_TRACE_SAMPLED; + "00-" + W3C_TEST_TRACE_ID + "-" + W3C_TEST_SPAN_ID + "-" + W3C_TEST_TRACE_SAMPLED; private static final String XCTC_TEST_TRACE_ID = "98765432101234569876543210123456"; private static final String XCTC_TEST_SPAN_ID = "9876543210123456"; - private static final String X_CLOUD_TRACE_CONTEXT = XCTC_TEST_TRACE_ID + "/" + XCTC_TEST_SPAN_ID + ";o=1"; + private static final String X_CLOUD_TRACE_CONTEXT = + XCTC_TEST_TRACE_ID + "/" + XCTC_TEST_SPAN_ID + ";o=1"; private static String otelTraceId; private static String otelSpanId; @@ -80,19 +80,19 @@ public static void prepareLogs() throws InterruptedException { logName = LogName.ofProjectLogName(loggingOptions.getProjectId(), LOG_ID); logging.setWriteSynchronicity(Synchronicity.SYNC); w3cEntry = - LogEntry.newBuilder(STRING_PAYLOAD) - .setLogName(LOG_ID) - .addLabel("tracing_source", "w3c") - .setHttpRequest(HttpRequest.newBuilder().setStatus(500).build()) - .setResource(GLOBAL_RESOURCE) - .build(); + LogEntry.newBuilder(STRING_PAYLOAD) + .setLogName(LOG_ID) + .addLabel("tracing_source", "w3c") + .setHttpRequest(HttpRequest.newBuilder().setStatus(500).build()) + .setResource(GLOBAL_RESOURCE) + .build(); xctcEntry = - LogEntry.newBuilder(STRING_PAYLOAD) - .setLogName(LOG_ID) - .addLabel("tracing_source", "xctc") - .setHttpRequest(HttpRequest.newBuilder().setRequestUrl("www.google.com").build()) - .setResource(GLOBAL_RESOURCE) - .build(); + LogEntry.newBuilder(STRING_PAYLOAD) + .setLogName(LOG_ID) + .addLabel("tracing_source", "xctc") + .setHttpRequest(HttpRequest.newBuilder().setRequestUrl("www.google.com").build()) + .setResource(GLOBAL_RESOURCE) + .build(); otelEntry = LogEntry.newBuilder(OTEL_PAYLOAD) .addLabel("tracing_source", "otel") @@ -104,10 +104,10 @@ public static void prepareLogs() throws InterruptedException { InMemorySpanExporter testExporter = InMemorySpanExporter.create(); SpanProcessor inMemorySpanProcessor = SimpleSpanProcessor.create(testExporter); OpenTelemetrySdk openTelemetrySdk = - OpenTelemetrySdk.builder() - .setTracerProvider( - SdkTracerProvider.builder().addSpanProcessor(inMemorySpanProcessor).build()) - .build(); + OpenTelemetrySdk.builder() + .setTracerProvider( + SdkTracerProvider.builder().addSpanProcessor(inMemorySpanProcessor).build()) + .build(); tracer = openTelemetrySdk.getTracer("ContextTest"); } @@ -154,11 +154,13 @@ public void testDetectXCTCTraceId() throws InterruptedException { LogEntry entry = iterator.next(); assertEquals(LOG_ID, entry.getLogName()); assertEquals(ImmutableMap.of("tracing_source", "xctc"), entry.getLabels()); - assertEquals(HttpRequest.newBuilder().setRequestUrl("www.google.com").build(), entry.getHttpRequest()); + assertEquals( + HttpRequest.newBuilder().setRequestUrl("www.google.com").build(), entry.getHttpRequest()); assertEquals(XCTC_TEST_TRACE_ID, entry.getTrace()); assertEquals(XCTC_TEST_SPAN_ID, entry.getSpanId()); assertEquals(true, entry.getTraceSampled()); } + @Test(timeout = 600_000) public void testDetectOtelTraceId() throws InterruptedException { // Writes a log entry in open telemetry context @@ -193,7 +195,8 @@ public void testW3CTraceIdWithOtelContext() throws InterruptedException { LogEntry entry = iterator.next(); assertEquals(LOG_ID, entry.getLogName()); assertEquals(HttpRequest.newBuilder().setStatus(500).build(), entry.getHttpRequest()); - // Expect to get trace Id, span Id and isSampled flag from Open Telemetry context when it exists. + // Expect to get trace Id, span Id and isSampled flag from Open Telemetry context when it + // exists. assertEquals(otelTraceId, entry.getTrace()); assertEquals(otelSpanId, entry.getSpanId()); assertEquals(isSampled, entry.getTraceSampled()); @@ -213,7 +216,8 @@ public void testXCTCTraceIdWithOtelContext() throws InterruptedException { LogEntry entry = iterator.next(); assertEquals(LOG_ID, entry.getLogName()); - // Expect to get trace Id, span Id and isSampled flag from Open telemetry context when it exists. + // Expect to get trace Id, span Id and isSampled flag from Open telemetry context when it + // exists. assertEquals(otelTraceId, entry.getTrace()); assertEquals(otelSpanId, entry.getSpanId()); assertEquals(isSampled, entry.getTraceSampled()); From 43d69d02c3037aae7162742c042bb844dd6386ef Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Tue, 7 May 2024 11:34:24 +0800 Subject: [PATCH 24/30] Remove current priority null check --- .../src/main/java/com/google/cloud/logging/ContextHandler.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java index 5e5c95a65..187d339b0 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java @@ -60,8 +60,7 @@ public void setCurrentContext(Context context) { * context if HttpRequest in the new context is empty . */ public void setCurrentContext(Context context, ContextPriority priority) { - if ((currentPriority.get() == null || priority.compareTo(currentPriority.get()) >= 0) - && context != null) { + if (priority != null && priority.compareTo(currentPriority.get()) >= 0 && context != null) { Context.Builder combinedContextBuilder = Context.newBuilder() .setTraceId(context.getTraceId()) From 2d8345ec259e175141c631e97e2bb298d42a5834 Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Tue, 7 May 2024 15:56:43 +0800 Subject: [PATCH 25/30] Add context handler unit tests --- .../google/cloud/logging/ContextHandler.java | 12 +- .../cloud/logging/ContextHandlerTest.java | 280 ++++++++++++++++++ 2 files changed, 290 insertions(+), 2 deletions(-) create mode 100644 google-cloud-logging/src/test/java/com/google/cloud/logging/ContextHandlerTest.java diff --git a/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java b/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java index 187d339b0..54b7b1854 100644 --- a/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java +++ b/google-cloud-logging/src/main/java/com/google/cloud/logging/ContextHandler.java @@ -22,7 +22,7 @@ public class ContextHandler { public enum ContextPriority { NO_INPUT, XCLOUD_HEADER, - W3_HEADER, + W3C_HEADER, OTEL_EXTRACTED } @@ -51,7 +51,11 @@ public Context getCurrentContext() { } public void setCurrentContext(Context context) { - contextHolder.set(context); + setCurrentContext(context, ContextPriority.NO_INPUT); + } + + public ContextPriority getCurrentContextPriority() { + return currentPriority.get(); } /** @@ -84,4 +88,8 @@ else if (currentContext != null && currentContext.getHttpRequest() != null) { public void removeCurrentContext() { contextHolder.remove(); } + + public void removeCurrentContextPriority() { + currentPriority.remove(); + } } diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextHandlerTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextHandlerTest.java new file mode 100644 index 000000000..a47ef9a2b --- /dev/null +++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextHandlerTest.java @@ -0,0 +1,280 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.logging; + +import static org.junit.Assert.*; + +import com.google.cloud.logging.ContextHandler.ContextPriority; +import com.google.cloud.logging.HttpRequest.RequestMethod; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +@RunWith(JUnit4.class) +public class ContextHandlerTest { + private static final HttpRequest OLD_HTTP_REQUEST = + HttpRequest.newBuilder() + .setRequestMethod(RequestMethod.POST) + .setRequestUrl("https://old.com") + .setUserAgent("Test User Agent") + .build(); + private static final HttpRequest HTTP_REQUEST = + HttpRequest.newBuilder() + .setRequestMethod(RequestMethod.GET) + .setRequestUrl("https://example.com") + .setUserAgent("Test User Agent") + .build(); + private static final String OLD_TRACE_ID = "10100101010101010101010101010101"; + private static final String OLD_SPAN_ID = "0"; + private static final boolean OLD_TRACE_SAMPLED = false; + private static final String TRACE_ID = "01010101010101010101010101010101"; + private static final String SPAN_ID = "1"; + private static final boolean TRACE_SAMPLED = true; + + @After + public void teardown() { + new ContextHandler().removeCurrentContext(); + new ContextHandler().removeCurrentContextPriority(); + } + + @Test + public void testDefaultSetContext() { + Context newContext = + Context.newBuilder() + .setRequest(HTTP_REQUEST) + .setTraceId(TRACE_ID) + .setSpanId(SPAN_ID) + .setTraceSampled(TRACE_SAMPLED) + .build(); + new ContextHandler().setCurrentContext(newContext); + Context currentContext = new ContextHandler().getCurrentContext(); + assertEquals(HTTP_REQUEST, currentContext.getHttpRequest()); + assertEquals(TRACE_ID, currentContext.getTraceId()); + assertEquals(SPAN_ID, currentContext.getSpanId()); + assertEquals(TRACE_SAMPLED, currentContext.getTraceSampled()); + assertEquals(ContextPriority.NO_INPUT, new ContextHandler().getCurrentContextPriority()); + } + + @Test + public void testSetContextWithPriorityFromNoInput() { + Context newContext = + Context.newBuilder() + .setRequest(HTTP_REQUEST) + .setTraceId(TRACE_ID) + .setSpanId(SPAN_ID) + .setTraceSampled(TRACE_SAMPLED) + .build(); + new ContextHandler().setCurrentContext(newContext, ContextPriority.NO_INPUT); + Context currentContext = new ContextHandler().getCurrentContext(); + assertEquals(ContextPriority.NO_INPUT, new ContextHandler().getCurrentContextPriority()); + assertEquals(HTTP_REQUEST, currentContext.getHttpRequest()); + assertEquals(TRACE_ID, currentContext.getTraceId()); + assertEquals(SPAN_ID, currentContext.getSpanId()); + assertEquals(TRACE_SAMPLED, currentContext.getTraceSampled()); + } + + @Test + public void testSetContextWithPriorityFromW3CHeader() { + Context newContext = + Context.newBuilder() + .setRequest(HTTP_REQUEST) + .setTraceId(TRACE_ID) + .setSpanId(SPAN_ID) + .setTraceSampled(TRACE_SAMPLED) + .build(); + new ContextHandler().setCurrentContext(newContext, ContextPriority.W3C_HEADER); + Context currentContext = new ContextHandler().getCurrentContext(); + assertEquals(ContextPriority.W3C_HEADER, new ContextHandler().getCurrentContextPriority()); + assertEquals(HTTP_REQUEST, currentContext.getHttpRequest()); + assertEquals(TRACE_ID, currentContext.getTraceId()); + assertEquals(SPAN_ID, currentContext.getSpanId()); + assertEquals(TRACE_SAMPLED, currentContext.getTraceSampled()); + } + + @Test + public void testSetContextFromXCloudHeader() { + Context newContext = + Context.newBuilder() + .setRequest(HTTP_REQUEST) + .setTraceId(TRACE_ID) + .setSpanId(SPAN_ID) + .setTraceSampled(TRACE_SAMPLED) + .build(); + new ContextHandler().setCurrentContext(newContext, ContextPriority.XCLOUD_HEADER); + Context currentContext = new ContextHandler().getCurrentContext(); + assertEquals(ContextPriority.XCLOUD_HEADER, new ContextHandler().getCurrentContextPriority()); + assertEquals(HTTP_REQUEST, currentContext.getHttpRequest()); + assertEquals(TRACE_ID, currentContext.getTraceId()); + assertEquals(SPAN_ID, currentContext.getSpanId()); + assertEquals(TRACE_SAMPLED, currentContext.getTraceSampled()); + } + + @Test + public void testSetContextFromOpenTelemetry() { + Context newContext = + Context.newBuilder() + .setRequest(HTTP_REQUEST) + .setTraceId(TRACE_ID) + .setSpanId(SPAN_ID) + .setTraceSampled(TRACE_SAMPLED) + .build(); + new ContextHandler().setCurrentContext(newContext, ContextPriority.OTEL_EXTRACTED); + Context currentContext = new ContextHandler().getCurrentContext(); + assertEquals(ContextPriority.OTEL_EXTRACTED, new ContextHandler().getCurrentContextPriority()); + assertEquals(HTTP_REQUEST, currentContext.getHttpRequest()); + assertEquals(TRACE_ID, currentContext.getTraceId()); + assertEquals(SPAN_ID, currentContext.getSpanId()); + assertEquals(TRACE_SAMPLED, currentContext.getTraceSampled()); + } + + @Test + public void testOverrideW3CContextFromOpenTelemetry() { + Context oldContext = + Context.newBuilder() + .setRequest(OLD_HTTP_REQUEST) + .setTraceId(OLD_TRACE_ID) + .setSpanId(OLD_SPAN_ID) + .setTraceSampled(OLD_TRACE_SAMPLED) + .build(); + new ContextHandler().setCurrentContext(oldContext, ContextPriority.W3C_HEADER); + Context newContext = + Context.newBuilder() + .setRequest(HTTP_REQUEST) + .setTraceId(TRACE_ID) + .setSpanId(SPAN_ID) + .setTraceSampled(TRACE_SAMPLED) + .build(); + new ContextHandler().setCurrentContext(newContext, ContextPriority.OTEL_EXTRACTED); + // Expects context being overridden when context was set with higher priority. + assertEquals(ContextPriority.OTEL_EXTRACTED, new ContextHandler().getCurrentContextPriority()); + Context currentContext = new ContextHandler().getCurrentContext(); + assertEquals(HTTP_REQUEST, currentContext.getHttpRequest()); + assertEquals(TRACE_ID, currentContext.getTraceId()); + assertEquals(SPAN_ID, currentContext.getSpanId()); + assertEquals(TRACE_SAMPLED, currentContext.getTraceSampled()); + } + + @Test + public void testOverrideXCTCContextFromOpenTelemetry() { + Context oldContext = + Context.newBuilder() + .setRequest(OLD_HTTP_REQUEST) + .setTraceId(OLD_TRACE_ID) + .setSpanId(OLD_SPAN_ID) + .setTraceSampled(OLD_TRACE_SAMPLED) + .build(); + new ContextHandler().setCurrentContext(oldContext, ContextPriority.XCLOUD_HEADER); + + Context newContext = + Context.newBuilder() + .setRequest(HTTP_REQUEST) + .setTraceId(TRACE_ID) + .setSpanId(SPAN_ID) + .setTraceSampled(TRACE_SAMPLED) + .build(); + new ContextHandler().setCurrentContext(newContext, ContextPriority.OTEL_EXTRACTED); + // Expects context being overridden when context was set with higher priority. + assertEquals(ContextPriority.OTEL_EXTRACTED, new ContextHandler().getCurrentContextPriority()); + Context currentContext = new ContextHandler().getCurrentContext(); + assertEquals(HTTP_REQUEST, currentContext.getHttpRequest()); + assertEquals(TRACE_ID, currentContext.getTraceId()); + assertEquals(SPAN_ID, currentContext.getSpanId()); + assertEquals(TRACE_SAMPLED, currentContext.getTraceSampled()); + } + + @Test + public void testOverrideOtelContextFromDefaultSetContext() { + Context oldContext = + Context.newBuilder() + .setRequest(OLD_HTTP_REQUEST) + .setTraceId(OLD_TRACE_ID) + .setSpanId(OLD_SPAN_ID) + .setTraceSampled(OLD_TRACE_SAMPLED) + .build(); + new ContextHandler().setCurrentContext(oldContext, ContextPriority.OTEL_EXTRACTED); + Context newContext = + Context.newBuilder() + .setRequest(HTTP_REQUEST) + .setTraceId(TRACE_ID) + .setSpanId(SPAN_ID) + .setTraceSampled(TRACE_SAMPLED) + .build(); + new ContextHandler().setCurrentContext(newContext); + // Expects open telemetry context not being overridden when context was set with lower priority. + assertEquals(ContextPriority.OTEL_EXTRACTED, new ContextHandler().getCurrentContextPriority()); + Context currentContext = new ContextHandler().getCurrentContext(); + assertEquals(OLD_HTTP_REQUEST, currentContext.getHttpRequest()); + assertEquals(OLD_TRACE_ID, currentContext.getTraceId()); + assertEquals(OLD_SPAN_ID, currentContext.getSpanId()); + assertEquals(OLD_TRACE_SAMPLED, currentContext.getTraceSampled()); + } + + @Test + public void testOverrideOtelContextFromW3C() { + Context oldContext = + Context.newBuilder() + .setRequest(OLD_HTTP_REQUEST) + .setTraceId(OLD_TRACE_ID) + .setSpanId(OLD_SPAN_ID) + .setTraceSampled(OLD_TRACE_SAMPLED) + .build(); + new ContextHandler().setCurrentContext(oldContext, ContextPriority.OTEL_EXTRACTED); + Context newContext = + Context.newBuilder() + .setRequest(HTTP_REQUEST) + .setTraceId(TRACE_ID) + .setSpanId(SPAN_ID) + .setTraceSampled(TRACE_SAMPLED) + .build(); + new ContextHandler().setCurrentContext(newContext, ContextPriority.W3C_HEADER); + // Expects open telemetry context not being overridden when context was set with lower priority. + assertEquals(ContextPriority.OTEL_EXTRACTED, new ContextHandler().getCurrentContextPriority()); + Context currentContext = new ContextHandler().getCurrentContext(); + assertEquals(OLD_HTTP_REQUEST, currentContext.getHttpRequest()); + assertEquals(OLD_TRACE_ID, currentContext.getTraceId()); + assertEquals(OLD_SPAN_ID, currentContext.getSpanId()); + assertEquals(OLD_TRACE_SAMPLED, currentContext.getTraceSampled()); + } + + @Test + public void testOverrideOtelContextFromXCTC() { + Context oldContext = + Context.newBuilder() + .setRequest(OLD_HTTP_REQUEST) + .setTraceId(OLD_TRACE_ID) + .setSpanId(OLD_SPAN_ID) + .setTraceSampled(OLD_TRACE_SAMPLED) + .build(); + new ContextHandler().setCurrentContext(oldContext, ContextPriority.OTEL_EXTRACTED); + Context newContext = + Context.newBuilder() + .setRequest(HTTP_REQUEST) + .setTraceId(TRACE_ID) + .setSpanId(SPAN_ID) + .setTraceSampled(TRACE_SAMPLED) + .build(); + new ContextHandler().setCurrentContext(newContext, ContextPriority.XCLOUD_HEADER); + // Expects open telemetry context not being overridden when context was set with lower priority. + assertEquals(ContextPriority.OTEL_EXTRACTED, new ContextHandler().getCurrentContextPriority()); + Context currentContext = new ContextHandler().getCurrentContext(); + assertEquals(OLD_HTTP_REQUEST, currentContext.getHttpRequest()); + assertEquals(OLD_TRACE_ID, currentContext.getTraceId()); + assertEquals(OLD_SPAN_ID, currentContext.getSpanId()); + assertEquals(OLD_TRACE_SAMPLED, currentContext.getTraceSampled()); + } +} From a8bba3cd99f94c1f420cc64e9a014460faf9d5c5 Mon Sep 17 00:00:00 2001 From: Owl Bot Date: Tue, 7 May 2024 07:59:19 +0000 Subject: [PATCH 26/30] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot=20?= =?UTF-8?q?post-processor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7d16e07c0..ee3ae55d4 100644 --- a/README.md +++ b/README.md @@ -59,13 +59,13 @@ implementation 'com.google.cloud:google-cloud-logging' If you are using Gradle without BOM, add this to your dependencies: ```Groovy -implementation 'com.google.cloud:google-cloud-logging:3.17.0' +implementation 'com.google.cloud:google-cloud-logging:3.17.1' ``` If you are using SBT, add this to your dependencies: ```Scala -libraryDependencies += "com.google.cloud" % "google-cloud-logging" % "3.17.0" +libraryDependencies += "com.google.cloud" % "google-cloud-logging" % "3.17.1" ``` @@ -452,7 +452,7 @@ Java is a registered trademark of Oracle and/or its affiliates. [kokoro-badge-link-5]: http://storage.googleapis.com/cloud-devrel-public/java/badges/java-logging/java11.html [stability-image]: https://img.shields.io/badge/stability-stable-green [maven-version-image]: https://img.shields.io/maven-central/v/com.google.cloud/google-cloud-logging.svg -[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-logging/3.17.0 +[maven-version-link]: https://central.sonatype.com/artifact/com.google.cloud/google-cloud-logging/3.17.1 [authentication]: https://github.com/googleapis/google-cloud-java#authentication [auth-scopes]: https://developers.google.com/identity/protocols/oauth2/scopes [predefined-iam-roles]: https://cloud.google.com/iam/docs/understanding-roles#predefined_roles From 4270847ce95ef198d879bf0eef6a12c4b6c14658 Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Mon, 3 Jun 2024 09:05:45 +0800 Subject: [PATCH 27/30] Add otel bom to pom --- google-cloud-logging/pom.xml | 22 +++++ .../com/google/cloud/logging/ContextTest.java | 2 +- pom.xml | 84 +++++++++++-------- 3 files changed, 73 insertions(+), 35 deletions(-) diff --git a/google-cloud-logging/pom.xml b/google-cloud-logging/pom.xml index 0f4190bfa..b514c8503 100644 --- a/google-cloud-logging/pom.xml +++ b/google-cloud-logging/pom.xml @@ -157,6 +157,28 @@ opentelemetry-sdk-trace test + + + + + + + + + io.opentelemetry + opentelemetry-semconv + test + + + io.opentelemetry + opentelemetry-sdk-common + test + + + com.google.cloud.opentelemetry + exporter-trace + test + diff --git a/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java b/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java index b2b3ea17a..7ef8f90de 100644 --- a/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java +++ b/google-cloud-logging/src/test/java/com/google/cloud/logging/ContextTest.java @@ -169,7 +169,7 @@ public void testParsingOpenTelemetryContext() { OpenTelemetrySdk.builder() .setTracerProvider( SdkTracerProvider.builder().addSpanProcessor(inMemorySpanProcessor).build()) - .build(); + .buildAndRegisterGlobal(); Tracer tracer = openTelemetrySdk.getTracer("ContextTest"); Span otelSpan = tracer.spanBuilder("Example Span Attributes").startSpan(); diff --git a/pom.xml b/pom.xml index 7915f66fd..a1359a7ec 100644 --- a/pom.xml +++ b/pom.xml @@ -54,7 +54,6 @@ UTF-8 github google-cloud-logging-parent - 1.37.0 @@ -62,14 +61,21 @@ io.opentelemetry - opentelemetry-api - ${opentelemetry.version} - - - io.opentelemetry - opentelemetry-context - ${opentelemetry.version} + opentelemetry-bom + 1.38.0 + pom + import + + + + + + + + + + com.google.api.grpc @@ -130,37 +136,47 @@ - - - io.opentelemetry - opentelemetry-sdk - ${opentelemetry.version} - test - - - io.opentelemetry - opentelemetry-sdk-testing - ${opentelemetry.version} - test - + + + + + + + + + + + + + + + + + + + + + + + io.opentelemetry opentelemetry-semconv - ${opentelemetry.version}-alpha - test - - - io.opentelemetry - opentelemetry-sdk-trace - ${opentelemetry.version} - test - - - io.opentelemetry - opentelemetry-sdk-common - ${opentelemetry.version} + 1.1.0-alpha test + + + + + + + + + + + + com.google.cloud.opentelemetry exporter-trace From e4b8de11b1e2f36b87d032d310a7fd1e87181a9d Mon Sep 17 00:00:00 2001 From: Owl Bot Date: Mon, 3 Jun 2024 01:37:00 +0000 Subject: [PATCH 28/30] =?UTF-8?q?=F0=9F=A6=89=20Updates=20from=20OwlBot=20?= =?UTF-8?q?post-processor?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See https://github.com/googleapis/repo-automation-bots/blob/main/packages/owl-bot/README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 68a888e3e..7ce685279 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ If you are using Maven without the BOM, add this to your dependencies: If you are using Gradle 5.x or later, add this to your dependencies: ```Groovy -implementation platform('com.google.cloud:libraries-bom:26.39.0') +implementation platform('com.google.cloud:libraries-bom:26.40.0') implementation 'com.google.cloud:google-cloud-logging' ``` From fe58cd8614c09217aa27c2fb97f3be4d102d9dbe Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Mon, 3 Jun 2024 09:40:47 +0800 Subject: [PATCH 29/30] Remove unused dependency --- google-cloud-logging/pom.xml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/google-cloud-logging/pom.xml b/google-cloud-logging/pom.xml index b514c8503..448e53f0c 100644 --- a/google-cloud-logging/pom.xml +++ b/google-cloud-logging/pom.xml @@ -164,21 +164,6 @@ - - io.opentelemetry - opentelemetry-semconv - test - - - io.opentelemetry - opentelemetry-sdk-common - test - - - com.google.cloud.opentelemetry - exporter-trace - test - From ba86d2586feb5cb37e3daf604d0665f37134df2c Mon Sep 17 00:00:00 2001 From: cindy-peng Date: Mon, 3 Jun 2024 10:30:46 +0800 Subject: [PATCH 30/30] Remove comment --- google-cloud-logging/pom.xml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/google-cloud-logging/pom.xml b/google-cloud-logging/pom.xml index 448e53f0c..0f4190bfa 100644 --- a/google-cloud-logging/pom.xml +++ b/google-cloud-logging/pom.xml @@ -157,13 +157,6 @@ opentelemetry-sdk-trace test - - - - - - -