Skip to content

Commit a6941c1

Browse files
zeitlingerotelbot[bot]psx95
authored
declarative config: support Span stacktrace (#2262)
Co-authored-by: otelbot <[email protected]> Co-authored-by: Pranav Sharma <[email protected]>
1 parent 88cde77 commit a6941c1

File tree

6 files changed

+115
-9
lines changed

6 files changed

+115
-9
lines changed

span-stacktrace/README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
# Span stacktrace capture
32

43
This module provides a `SpanProcessor` that captures the [`code.stacktrace`](https://opentelemetry.io/docs/specs/semconv/attributes-registry/code/).
@@ -25,6 +24,21 @@ SDK when included in the application runtime dependencies.
2524
- value is the class name of a class implementing `java.util.function.Predicate<ReadableSpan>`
2625
- filter class must be publicly accessible and provide a no-arg constructor
2726

27+
### Usage with declarative configuration
28+
29+
You can enable the stacktrace span processor using declarative YAML configuration with the OpenTelemetry SDK. For example:
30+
31+
```yaml
32+
file_format: 1.0-rc.1
33+
tracer_provider:
34+
processors:
35+
- experimental_stacktrace:
36+
min_duration: 10 # minimal duration in ms, default is 5, MUST be an integer
37+
filter: my.class.Name # optional, default is to include all spans
38+
```
39+
40+
This configuration will register the StackTraceSpanProcessor for all spans.
41+
2842
## Component owners
2943
3044
- [Jack Shirazi](https://github.com/jackshirazi), Elastic

span-stacktrace/build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,13 @@ dependencies {
1515

1616
compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure")
1717
compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi")
18+
compileOnly("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure")
19+
compileOnly("io.opentelemetry:opentelemetry-sdk-extension-incubator")
20+
compileOnly("io.opentelemetry.instrumentation:opentelemetry-declarative-config-bridge")
1821
testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure")
1922
testImplementation("io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi")
23+
testImplementation("io.opentelemetry:opentelemetry-sdk-extension-incubator")
24+
testImplementation("io.opentelemetry.instrumentation:opentelemetry-declarative-config-bridge")
2025

2126
compileOnly("io.opentelemetry.semconv:opentelemetry-semconv")
2227
testImplementation("io.opentelemetry.semconv:opentelemetry-semconv")

span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceAutoConfig.java

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,26 @@ public class StackTraceAutoConfig implements AutoConfigurationCustomizerProvider
2626

2727
private static final Logger log = Logger.getLogger(StackTraceAutoConfig.class.getName());
2828

29-
private static final String CONFIG_MIN_DURATION =
30-
"otel.java.experimental.span-stacktrace.min.duration";
29+
static final String PREFIX = "otel.java.experimental.span-stacktrace.";
30+
static final String CONFIG_MIN_DURATION = PREFIX + "min.duration";
3131
private static final Duration CONFIG_MIN_DURATION_DEFAULT = Duration.ofMillis(5);
32-
33-
private static final String CONFIG_FILTER = "otel.java.experimental.span-stacktrace.filter";
32+
private static final String CONFIG_FILTER = PREFIX + "filter";
3433

3534
@Override
3635
public void customize(AutoConfigurationCustomizer config) {
3736
config.addTracerProviderCustomizer(
3837
(providerBuilder, properties) -> {
39-
long minDuration = getMinDuration(properties);
40-
if (minDuration >= 0) {
41-
Predicate<ReadableSpan> filter = getFilterPredicate(properties);
42-
providerBuilder.addSpanProcessor(new StackTraceSpanProcessor(minDuration, filter));
38+
if (getMinDuration(properties) >= 0) {
39+
providerBuilder.addSpanProcessor(create(properties));
4340
}
4441
return providerBuilder;
4542
});
4643
}
4744

45+
static StackTraceSpanProcessor create(ConfigProperties properties) {
46+
return new StackTraceSpanProcessor(getMinDuration(properties), getFilterPredicate(properties));
47+
}
48+
4849
// package-private for testing
4950
static long getMinDuration(ConfigProperties properties) {
5051
long minDuration =
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.contrib.stacktrace;
7+
8+
import com.google.auto.service.AutoService;
9+
import io.opentelemetry.api.incubator.config.DeclarativeConfigProperties;
10+
import io.opentelemetry.instrumentation.config.bridge.DeclarativeConfigPropertiesBridgeBuilder;
11+
import io.opentelemetry.sdk.autoconfigure.spi.internal.ComponentProvider;
12+
import io.opentelemetry.sdk.trace.SpanProcessor;
13+
14+
@SuppressWarnings("rawtypes")
15+
@AutoService(ComponentProvider.class)
16+
public class StackTraceComponentProvider implements ComponentProvider<SpanProcessor> {
17+
@Override
18+
public String getName() {
19+
return "experimental_stacktrace";
20+
}
21+
22+
@Override
23+
public SpanProcessor create(DeclarativeConfigProperties config) {
24+
return StackTraceAutoConfig.create(
25+
new DeclarativeConfigPropertiesBridgeBuilder()
26+
.addMapping(StackTraceAutoConfig.CONFIG_MIN_DURATION, "min_duration")
27+
.addMapping(StackTraceAutoConfig.PREFIX, "")
28+
.build(config));
29+
}
30+
31+
@Override
32+
public Class<SpanProcessor> getType() {
33+
return SpanProcessor.class;
34+
}
35+
}

span-stacktrace/src/main/java/io/opentelemetry/contrib/stacktrace/StackTraceSpanProcessor.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,14 @@ private static String removeInternalFrames(String stackTrace) {
9494
}
9595
return stackTrace.substring(nextNewLine + 1);
9696
}
97+
98+
@Override
99+
public String toString() {
100+
return "StackTraceSpanProcessor{"
101+
+ "minSpanDurationNanos="
102+
+ minSpanDurationNanos
103+
+ ", filterPredicate="
104+
+ filterPredicate
105+
+ '}';
106+
}
97107
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
package io.opentelemetry.contrib.stacktrace;
7+
8+
import static org.assertj.core.api.Assertions.assertThat;
9+
10+
import io.opentelemetry.sdk.OpenTelemetrySdk;
11+
import io.opentelemetry.sdk.extension.incubator.fileconfig.DeclarativeConfiguration;
12+
import java.io.ByteArrayInputStream;
13+
import java.nio.charset.StandardCharsets;
14+
import java.util.Locale;
15+
import java.util.concurrent.TimeUnit;
16+
import org.junit.jupiter.api.Test;
17+
18+
class StackTraceComponentProviderTest {
19+
@Test
20+
void endToEnd() {
21+
String yaml =
22+
"file_format: 1.0-rc.1\n"
23+
+ "tracer_provider:\n"
24+
+ " processors:\n"
25+
+ " - experimental_stacktrace: \n"
26+
+ " min_duration: 100\n"
27+
+ " filter: io.opentelemetry.contrib.stacktrace.StackTraceSpanProcessorTest$YesPredicate\n";
28+
29+
OpenTelemetrySdk openTelemetrySdk =
30+
DeclarativeConfiguration.parseAndCreate(
31+
new ByteArrayInputStream(yaml.getBytes(StandardCharsets.UTF_8)));
32+
33+
assertThat(openTelemetrySdk.getSdkTracerProvider().toString())
34+
.contains(
35+
String.format(
36+
Locale.ROOT,
37+
"StackTraceSpanProcessor{minSpanDurationNanos=%d, "
38+
+ "filterPredicate=io.opentelemetry.contrib.stacktrace.StackTraceSpanProcessorTest$YesPredicate",
39+
TimeUnit.MILLISECONDS.toNanos(100)));
40+
}
41+
}

0 commit comments

Comments
 (0)