Skip to content

Commit

Permalink
add code attributes to dropwizard views
Browse files Browse the repository at this point in the history
  • Loading branch information
jaydeluca committed Dec 31, 2024
1 parent d69fd1a commit 51e2b38
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -17,6 +18,7 @@ public final class DropwizardSingletons {
private static final Instrumenter<View, Void> INSTRUMENTER =
Instrumenter.<View, Void>builder(
GlobalOpenTelemetry.get(), INSTRUMENTATION_NAME, DropwizardSingletons::spanName)
.addAttributesExtractor(CodeAttributesExtractor.create(new ViewCodeAttributesGetter()))
.setEnabled(ExperimentalConfig.get().controllerTelemetryEnabled())
.buildInstrumenter();

Expand Down
Original file line number Diff line number Diff line change
@@ -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<View> {

@Nullable
@Override
public Class<?> getCodeClass(View view) {
return view.getClass();
}

@Nullable
@Override
public String getMethodName(View view) {
return "render";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -38,22 +42,36 @@ private static Stream<Arguments> 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
Expand Down

0 comments on commit 51e2b38

Please sign in to comment.