Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add experimental span attribute job.system #6586

Merged
merged 2 commits into from
Sep 13, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions instrumentation/quartz-2.0/javaagent/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ dependencies {

testImplementation(project(":instrumentation:quartz-2.0:testing"))
}

tasks.withType<Test>().configureEach {
// TODO run tests both with and without experimental span attributes
jvmArgs("-Dotel.instrumentation.quartz.experimental-span-attributes=true")
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@
package io.opentelemetry.javaagent.instrumentation.quartz.v2_0;

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;
import io.opentelemetry.instrumentation.quartz.v2_0.QuartzTelemetry;

public final class QuartzSingletons {

public static final QuartzTelemetry TELEMETRY = QuartzTelemetry.create(GlobalOpenTelemetry.get());
public static final QuartzTelemetry TELEMETRY =
QuartzTelemetry.builder(GlobalOpenTelemetry.get())
.setCaptureExperimentalSpanAttributes(
ConfigPropertiesUtil.getBoolean(
"otel.instrumentation.quartz.experimental-span-attributes", false))
.build();

private QuartzSingletons() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package io.opentelemetry.instrumentation.quartz.v2_0;

import io.opentelemetry.api.OpenTelemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
Expand All @@ -24,6 +25,8 @@ public final class QuartzTelemetryBuilder {
private final List<AttributesExtractor<? super JobExecutionContext, ? super Void>>
additionalExtractors = new ArrayList<>();

private boolean captureExperimentalSpanAttributes;

QuartzTelemetryBuilder(OpenTelemetry openTelemetry) {
this.openTelemetry = openTelemetry;
}
Expand All @@ -38,13 +41,28 @@ public QuartzTelemetryBuilder addAttributeExtractor(
return this;
}

/**
* Sets whether experimental attributes should be set to spans. These attributes may be changed or
* removed in the future, so only enable this if you know you do not require attributes filled by
* this instrumentation to be stable across versions
*/
public QuartzTelemetryBuilder setCaptureExperimentalSpanAttributes(
boolean captureExperimentalSpanAttributes) {
this.captureExperimentalSpanAttributes = captureExperimentalSpanAttributes;
return this;
}

/**
* Returns a new {@link QuartzTelemetry} with the settings of this {@link QuartzTelemetryBuilder}.
*/
public QuartzTelemetry build() {
InstrumenterBuilder<JobExecutionContext, Void> instrumenter =
Instrumenter.builder(openTelemetry, INSTRUMENTATION_NAME, new QuartzSpanNameExtractor());

if (captureExperimentalSpanAttributes) {
instrumenter.addAttributesExtractor(
AttributesExtractor.constant(AttributeKey.stringKey("job.system"), "quartz"));
}
instrumenter.setErrorCauseExtractor(new QuartzErrorCauseExtractor());
instrumenter.addAttributesExtractor(
CodeAttributesExtractor.create(new QuartzCodeAttributesGetter()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ class QuartzTest extends AbstractQuartzTest {

@Override
protected void configureScheduler(Scheduler scheduler) {
QuartzTelemetry.create(testing.getOpenTelemetry()).configure(scheduler);
QuartzTelemetry.builder(testing.getOpenTelemetry())
// TODO run tests both with and without experimental span attributes
.setCaptureExperimentalSpanAttributes(true)
.build()
.configure(scheduler);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@

package io.opentelemetry.instrumentation.quartz.v2_0;

import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.assertThat;
import static io.opentelemetry.sdk.testing.assertj.OpenTelemetryAssertions.equalTo;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.api.trace.SpanKind;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import io.opentelemetry.sdk.trace.data.StatusData;
Expand Down Expand Up @@ -67,14 +68,12 @@ void successfulJob() throws Exception {
.hasKind(SpanKind.INTERNAL)
.hasNoParent()
.hasStatus(StatusData.unset())
.hasAttributesSatisfying(
attrs ->
assertThat(attrs)
.containsEntry(
SemanticAttributes.CODE_NAMESPACE,
SuccessfulJob.class.getName())
.containsEntry(
SemanticAttributes.CODE_FUNCTION, "execute")),
.hasAttributesSatisfyingExactly(
equalTo(AttributeKey.stringKey("job.system"), "quartz"),
equalTo(
SemanticAttributes.CODE_NAMESPACE,
SuccessfulJob.class.getName()),
equalTo(SemanticAttributes.CODE_FUNCTION, "execute")),
span ->
span.hasName("child")
.hasKind(SpanKind.INTERNAL)
Expand All @@ -99,14 +98,11 @@ void failingJob() throws Exception {
.hasNoParent()
.hasStatus(StatusData.error())
.hasException(new IllegalStateException("Bad job"))
.hasAttributesSatisfying(
attrs ->
assertThat(attrs)
.containsEntry(
SemanticAttributes.CODE_NAMESPACE,
FailingJob.class.getName())
.containsEntry(
SemanticAttributes.CODE_FUNCTION, "execute"))));
.hasAttributesSatisfyingExactly(
equalTo(AttributeKey.stringKey("job.system"), "quartz"),
equalTo(
SemanticAttributes.CODE_NAMESPACE, FailingJob.class.getName()),
equalTo(SemanticAttributes.CODE_FUNCTION, "execute"))));
}

private static Scheduler createScheduler(String name) throws Exception {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ dependencies {
}

tasks.withType<Test>().configureEach {
// TODO run tests both with and without experimental span attributes
jvmArgs("-Dotel.instrumentation.spring-scheduling.experimental-span-attributes=true")

// required on jdk17
jvmArgs("--add-opens=java.base/java.lang=ALL-UNNAMED")
jvmArgs("-XX:+IgnoreUnrecognizedVMOptions")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,39 @@
package io.opentelemetry.javaagent.instrumentation.spring.scheduling;

import io.opentelemetry.api.GlobalOpenTelemetry;
import io.opentelemetry.api.common.AttributeKey;
import io.opentelemetry.instrumentation.api.instrumenter.AttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.Instrumenter;
import io.opentelemetry.instrumentation.api.instrumenter.InstrumenterBuilder;
import io.opentelemetry.instrumentation.api.instrumenter.code.CodeAttributesExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.code.CodeSpanNameExtractor;
import io.opentelemetry.instrumentation.api.internal.ConfigPropertiesUtil;

public final class SpringSchedulingSingletons {

private static final boolean CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES =
ConfigPropertiesUtil.getBoolean(
"otel.instrumentation.spring-scheduling.experimental-span-attributes", false);

private static final Instrumenter<Runnable, Void> INSTRUMENTER;

static {
SpringSchedulingCodeAttributesGetter codeAttributesGetter =
new SpringSchedulingCodeAttributesGetter();
INSTRUMENTER =

InstrumenterBuilder<Runnable, Void> builder =
Instrumenter.<Runnable, Void>builder(
GlobalOpenTelemetry.get(),
"io.opentelemetry.spring-scheduling-3.1",
CodeSpanNameExtractor.create(codeAttributesGetter))
.addAttributesExtractor(CodeAttributesExtractor.create(codeAttributesGetter))
.buildInstrumenter();
.addAttributesExtractor(CodeAttributesExtractor.create(codeAttributesGetter));

if (CAPTURE_EXPERIMENTAL_SPAN_ATTRIBUTES) {
builder.addAttributesExtractor(
AttributesExtractor.constant(AttributeKey.stringKey("job.system"), "spring_scheduling"));
}

INSTRUMENTER = builder.buildInstrumenter();
}

public static Instrumenter<Runnable, Void> instrumenter() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class SpringSchedulingTest extends AgentInstrumentationSpecification {
name "TriggerTask.run"
hasNoParent()
attributes {
"job.system" "spring_scheduling"
"code.namespace" "TriggerTask"
"code.function" "run"
}
Expand All @@ -49,6 +50,7 @@ class SpringSchedulingTest extends AgentInstrumentationSpecification {
name "IntervalTask.run"
hasNoParent()
attributes {
"job.system" "spring_scheduling"
"code.namespace" "IntervalTask"
"code.function" "run"
}
Expand All @@ -71,6 +73,7 @@ class SpringSchedulingTest extends AgentInstrumentationSpecification {
nameContains "LambdaTaskConfigurer\$\$Lambda\$"
hasNoParent()
attributes {
"job.system" "spring_scheduling"
"code.namespace" { it.contains("LambdaTaskConfigurer\$\$Lambda\$") }
"code.function" "run"
}
Expand Down Expand Up @@ -98,6 +101,7 @@ class SpringSchedulingTest extends AgentInstrumentationSpecification {
name "EnhancedClassTaskConfig.run"
hasNoParent()
attributes {
"job.system" "spring_scheduling"
"code.namespace" "EnhancedClassTaskConfig"
"code.function" "run"
}
Expand Down