From 51e2b385bb5ab06d2a7ba94c8571cec7ba607ed6 Mon Sep 17 00:00:00 2001 From: Jay DeLuca Date: Tue, 31 Dec 2024 18:12:45 -0500 Subject: [PATCH] add code attributes to dropwizard views --- .../dropwizardviews/DropwizardSingletons.java | 2 ++ .../ViewCodeAttributesGetter.java | 25 ++++++++++++++ .../dropwizardviews/ViewRenderTest.java | 34 ++++++++++++++----- 3 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 instrumentation/dropwizard/dropwizard-views-0.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/ViewCodeAttributesGetter.java diff --git a/instrumentation/dropwizard/dropwizard-views-0.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/DropwizardSingletons.java b/instrumentation/dropwizard/dropwizard-views-0.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/DropwizardSingletons.java index f9c799c12e65..ddd5c68f37a8 100644 --- a/instrumentation/dropwizard/dropwizard-views-0.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/DropwizardSingletons.java +++ b/instrumentation/dropwizard/dropwizard-views-0.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/DropwizardSingletons.java @@ -7,6 +7,7 @@ import io.dropwizard.views.View; import io.opentelemetry.api.GlobalOpenTelemetry; +import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesExtractor; import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter; import io.opentelemetry.javaagent.bootstrap.internal.ExperimentalConfig; @@ -17,6 +18,7 @@ public final class DropwizardSingletons { private static final Instrumenter INSTRUMENTER = Instrumenter.builder( GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, DropwizardSingletons::spanName) + .addAttributesExtractor(CodeAttributesExtractor.create(new ViewCodeAttributesGetter())) .setEnabled(ExperimentalConfig.get().controllerTelemetryEnabled()) .buildInstrumenter(); diff --git a/instrumentation/dropwizard/dropwizard-views-0.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/ViewCodeAttributesGetter.java b/instrumentation/dropwizard/dropwizard-views-0.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/ViewCodeAttributesGetter.java new file mode 100644 index 000000000000..4fd88ede4618 --- /dev/null +++ b/instrumentation/dropwizard/dropwizard-views-0.7/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/ViewCodeAttributesGetter.java @@ -0,0 +1,25 @@ +/* + * Copyright The OpenTelemetry Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package io.opentelemetry.javaagent.instrumentation.dropwizardviews; + +import io.dropwizard.views.View; +import io.opentelemetry.instrumentation.api.incubator.semconv.code.CodeAttributesGetter; +import javax.annotation.Nullable; + +public class ViewCodeAttributesGetter implements CodeAttributesGetter { + + @Nullable + @Override + public Class getCodeClass(View view) { + return view.getClass(); + } + + @Nullable + @Override + public String getMethodName(View view) { + return "render"; + } +} diff --git a/instrumentation/dropwizard/dropwizard-views-0.7/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/ViewRenderTest.java b/instrumentation/dropwizard/dropwizard-views-0.7/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/ViewRenderTest.java index dbba452d344e..7d85f2084188 100644 --- a/instrumentation/dropwizard/dropwizard-views-0.7/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/ViewRenderTest.java +++ b/instrumentation/dropwizard/dropwizard-views-0.7/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/dropwizardviews/ViewRenderTest.java @@ -5,12 +5,16 @@ package io.opentelemetry.javaagent.instrumentation.dropwizardviews; +import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_FUNCTION; +import static io.opentelemetry.semconv.incubating.CodeIncubatingAttributes.CODE_NAMESPACE; import static org.assertj.core.api.Assertions.assertThat; import io.dropwizard.views.View; import io.dropwizard.views.ViewRenderer; import io.dropwizard.views.freemarker.FreemarkerViewRenderer; import io.dropwizard.views.mustache.MustacheViewRenderer; +import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.SpanKind; import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension; import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension; @@ -38,22 +42,36 @@ private static Stream provideParameters() { Arguments.of(new MustacheViewRenderer(), "/views/mustache/utf8.mustache")); } + // Used to avoid the View class being instantiated as an anonymous inner class, which results in + // the class name being ViewRenderTest$1 instead of ViewRenderTest when asserting CODE_NAMESPACE. + private static class TestView extends View { + protected TestView(String templateName) { + super(templateName, StandardCharsets.UTF_8); + } + } + @ParameterizedTest @MethodSource("provideParameters") void testSpan(ViewRenderer renderer, String template) throws IOException { - View view = new View(template, StandardCharsets.UTF_8) {}; + View view = new TestView(template); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - testing.runWithSpan( - "parent", - () -> { - renderer.render(view, Locale.ENGLISH, outputStream); - }); + testing.runWithSpan("parent", () -> renderer.render(view, Locale.ENGLISH, outputStream)); + assertThat(outputStream.toString("UTF-8")).contains("This is an example of a view"); testing.waitAndAssertTraces( trace -> trace.hasSpansSatisfyingExactly( - span -> span.hasName("parent").hasKind(SpanKind.INTERNAL).hasNoParent(), - span -> span.hasName("Render " + template).hasParent(trace.getSpan(0)))); + span -> + span.hasName("parent") + .hasKind(SpanKind.INTERNAL) + .hasNoParent() + .hasAttributes(Attributes.empty()), + span -> + span.hasName("Render " + template) + .hasParent(trace.getSpan(0)) + .hasAttributesSatisfyingExactly( + equalTo(CODE_FUNCTION, "render"), + equalTo(CODE_NAMESPACE, TestView.class.getName())))); } @Test