Skip to content

Commit d0b463d

Browse files
authored
Refactor ExtendedTracer, ExtendedSpanBuilder to reflect incubating API conventions (#6497)
1 parent 7364687 commit d0b463d

File tree

7 files changed

+295
-572
lines changed

7 files changed

+295
-572
lines changed

api/incubator/README.md

+7-167
Original file line numberDiff line numberDiff line change
@@ -35,170 +35,10 @@ Features:
3535

3636
See [ExtendedContextPropagatorsUsageTest](./src/test/java/io/opentelemetry/api/incubator/propagation/ExtendedContextPropagatorsUsageTest.java).
3737

38-
## ExtendedTracer
39-
40-
Utility methods to make it easier to use the OpenTelemetry tracer.
41-
42-
Here are some examples how the utility methods can help reduce boilerplate code.
43-
44-
TODO: translate examples to test to ensure no java compilation issues.
45-
46-
### Tracing a function
47-
48-
Before:
49-
50-
<!-- markdownlint-disable -->
51-
```java
52-
Span span = tracer.spanBuilder("reset_checkout").startSpan();
53-
String transactionId;
54-
try (Scope scope = span.makeCurrent()) {
55-
transactionId = resetCheckout(cartId);
56-
} catch (Throwable e) {
57-
span.setStatus(StatusCode.ERROR);
58-
span.recordException(e);
59-
throw e; // or throw new RuntimeException(e) - depending on your error handling strategy
60-
} finally {
61-
span.end();
62-
}
63-
```
64-
<!-- markdownlint-enable -->
65-
66-
After:
67-
68-
```java
69-
import io.opentelemetry.extension.incubator.trace.ExtendedTracer;
70-
71-
ExtendedTracer extendedTracer = ExtendedTracer.create(tracer);
72-
String transactionId = extendedTracer.spanBuilder("reset_checkout").startAndCall(() -> resetCheckout(cartId));
73-
```
74-
75-
If you want to set attributes on the span, you can use the `startAndCall` method on the span builder:
76-
77-
```java
78-
import io.opentelemetry.extension.incubator.trace.ExtendedTracer;
79-
80-
ExtendedTracer extendedTracer = ExtendedTracer.create(tracer);
81-
String transactionId = extendedTracer.spanBuilder("reset_checkout")
82-
.setAttribute("foo", "bar")
83-
.startAndCall(() -> resetCheckout(cartId));
84-
```
85-
86-
Note:
87-
88-
- Use `startAndRun` instead of `startAndCall` if the function returns `void` (both on the tracer and span builder).
89-
- Exceptions are re-thrown without modification - see [Exception handling](#exception-handling)
90-
for more details.
91-
92-
### Trace context propagation
93-
94-
Before:
95-
96-
```java
97-
Map<String, String> propagationHeaders = new HashMap<>();
98-
openTelemetry
99-
.getPropagators()
100-
.getTextMapPropagator()
101-
.inject(
102-
Context.current(),
103-
propagationHeaders,
104-
(map, key, value) -> {
105-
if (map != null) {
106-
map.put(key, value);
107-
}
108-
});
109-
110-
// add propagationHeaders to request headers and call checkout service
111-
```
112-
113-
<!-- markdownlint-disable -->
114-
```java
115-
// in checkout service: get request headers into a Map<String, String> requestHeaders
116-
Map<String, String> requestHeaders = new HashMap<>();
117-
String cartId = "cartId";
118-
119-
SpanBuilder spanBuilder = tracer.spanBuilder("checkout_cart");
120-
121-
TextMapGetter<Map<String, String>> TEXT_MAP_GETTER =
122-
new TextMapGetter<Map<String, String>>() {
123-
@Override
124-
public Set<String> keys(Map<String, String> carrier) {
125-
return carrier.keySet();
126-
}
127-
128-
@Override
129-
@Nullable
130-
public String get(@Nullable Map<String, String> carrier, String key) {
131-
return carrier == null ? null : carrier.get(key);
132-
}
133-
};
134-
135-
Map<String, String> normalizedTransport =
136-
requestHeaders.entrySet().stream()
137-
.collect(
138-
Collectors.toMap(
139-
entry -> entry.getKey().toLowerCase(Locale.ROOT), Map.Entry::getValue));
140-
Context newContext = openTelemetry
141-
.getPropagators()
142-
.getTextMapPropagator()
143-
.extract(Context.current(), normalizedTransport, TEXT_MAP_GETTER);
144-
String transactionId;
145-
try (Scope ignore = newContext.makeCurrent()) {
146-
Span span = spanBuilder.setSpanKind(SERVER).startSpan();
147-
try (Scope scope = span.makeCurrent()) {
148-
transactionId = processCheckout(cartId);
149-
} catch (Throwable e) {
150-
span.setStatus(StatusCode.ERROR);
151-
span.recordException(e);
152-
throw e; // or throw new RuntimeException(e) - depending on your error handling strategy
153-
} finally {
154-
span.end();
155-
}
156-
}
157-
```
158-
<!-- markdownlint-enable -->
159-
160-
After:
161-
162-
```java
163-
import io.opentelemetry.extension.incubator.propagation.ExtendedContextPropagators;
164-
165-
Map<String, String> propagationHeaders =
166-
ExtendedContextPropagators.getTextMapPropagationContext(openTelemetry.getPropagators());
167-
// add propagationHeaders to request headers and call checkout service
168-
```
169-
170-
```java
171-
import io.opentelemetry.api.trace.SpanKind;
172-
import io.opentelemetry.extension.incubator.trace.ExtendedTracer;
173-
174-
// in checkout service: get request headers into a Map<String, String> requestHeaders
175-
Map<String, String> requestHeaders = new HashMap<>();
176-
String cartId = "cartId";
177-
178-
ExtendedTracer extendedTracer = ExtendedTracer.create(tracer);
179-
String transactionId = extendedTracer.spanBuilder("checkout_cart")
180-
.setSpanKind(SpanKind.SERVER)
181-
.setParentFrom(openTelemetry.getPropagators(), requestHeaders)
182-
.startAndCall(() -> processCheckout(cartId));
183-
```
184-
185-
### Exception handling
186-
187-
`ExtendedTracer` re-throws exceptions without modification. This means you can
188-
catch exceptions around `ExtendedTracer` calls and handle them as you would without `ExtendedTracer`.
189-
190-
When an exception is encountered during an `ExtendedTracer` call, the span is marked as error and
191-
the exception is recorded.
192-
193-
If you want to customize this behaviour, e.g. to only record the exception, because you are
194-
able to recover from the error, you can call the overloaded method of `startAndCall` or
195-
`startAndRun` that takes an exception handler:
196-
197-
```java
198-
import io.opentelemetry.api.trace.Span;
199-
import io.opentelemetry.extension.incubator.trace.ExtendedTracer;
200-
201-
ExtendedTracer extendedTracer = ExtendedTracer.create(tracer);
202-
String transactionId = extendedTracer.spanBuilder("checkout_cart")
203-
.startAndCall(() -> processCheckout(cartId), Span::recordException);
204-
```
38+
## Extended Trace APIs
39+
40+
Features:
41+
42+
* Utility methods to reduce boilerplace using span API, including extracting context, and wrapping runnables / callables with spans
43+
44+
See [ExtendedTraceApiUsageTest](./src/test/java/io/opentelemetry/api/incubator/trace/ExtendedTraceApiUsageTest.java).

api/incubator/src/main/java/io/opentelemetry/api/incubator/trace/ExtendedSpanBuilder.java

+9-146
Original file line numberDiff line numberDiff line change
@@ -6,106 +6,14 @@
66
package io.opentelemetry.api.incubator.trace;
77

88
import io.opentelemetry.api.OpenTelemetry;
9-
import io.opentelemetry.api.common.AttributeKey;
10-
import io.opentelemetry.api.common.Attributes;
11-
import io.opentelemetry.api.incubator.propagation.ExtendedContextPropagators;
129
import io.opentelemetry.api.trace.Span;
1310
import io.opentelemetry.api.trace.SpanBuilder;
14-
import io.opentelemetry.api.trace.SpanContext;
15-
import io.opentelemetry.api.trace.SpanKind;
16-
import io.opentelemetry.api.trace.StatusCode;
17-
import io.opentelemetry.context.Context;
18-
import io.opentelemetry.context.Scope;
1911
import io.opentelemetry.context.propagation.ContextPropagators;
20-
import java.time.Instant;
2112
import java.util.Map;
22-
import java.util.concurrent.TimeUnit;
2313
import java.util.function.BiConsumer;
2414

25-
public final class ExtendedSpanBuilder implements SpanBuilder {
26-
private final SpanBuilder delegate;
27-
28-
ExtendedSpanBuilder(SpanBuilder delegate) {
29-
this.delegate = delegate;
30-
}
31-
32-
@Override
33-
public ExtendedSpanBuilder setParent(Context context) {
34-
delegate.setParent(context);
35-
return this;
36-
}
37-
38-
@Override
39-
public ExtendedSpanBuilder setNoParent() {
40-
delegate.setNoParent();
41-
return this;
42-
}
43-
44-
@Override
45-
public ExtendedSpanBuilder addLink(SpanContext spanContext) {
46-
delegate.addLink(spanContext);
47-
return this;
48-
}
49-
50-
@Override
51-
public ExtendedSpanBuilder addLink(SpanContext spanContext, Attributes attributes) {
52-
delegate.addLink(spanContext, attributes);
53-
return this;
54-
}
55-
56-
@Override
57-
public ExtendedSpanBuilder setAttribute(String key, String value) {
58-
delegate.setAttribute(key, value);
59-
return this;
60-
}
61-
62-
@Override
63-
public ExtendedSpanBuilder setAttribute(String key, long value) {
64-
delegate.setAttribute(key, value);
65-
return this;
66-
}
67-
68-
@Override
69-
public ExtendedSpanBuilder setAttribute(String key, double value) {
70-
delegate.setAttribute(key, value);
71-
return this;
72-
}
73-
74-
@Override
75-
public ExtendedSpanBuilder setAttribute(String key, boolean value) {
76-
delegate.setAttribute(key, value);
77-
return this;
78-
}
79-
80-
@Override
81-
public <T> ExtendedSpanBuilder setAttribute(AttributeKey<T> key, T value) {
82-
delegate.setAttribute(key, value);
83-
return this;
84-
}
85-
86-
@Override
87-
public ExtendedSpanBuilder setAllAttributes(Attributes attributes) {
88-
delegate.setAllAttributes(attributes);
89-
return this;
90-
}
91-
92-
@Override
93-
public ExtendedSpanBuilder setSpanKind(SpanKind spanKind) {
94-
delegate.setSpanKind(spanKind);
95-
return this;
96-
}
97-
98-
@Override
99-
public ExtendedSpanBuilder setStartTimestamp(long startTimestamp, TimeUnit unit) {
100-
delegate.setStartTimestamp(startTimestamp, unit);
101-
return this;
102-
}
103-
104-
@Override
105-
public ExtendedSpanBuilder setStartTimestamp(Instant startTimestamp) {
106-
delegate.setStartTimestamp(startTimestamp);
107-
return this;
108-
}
15+
/** Extended {@link SpanBuilder} with experimental APIs. */
16+
public interface ExtendedSpanBuilder extends SpanBuilder {
10917

11018
/**
11119
* Extract a span context from the given carrier and set it as parent of the span for {@link
@@ -124,16 +32,7 @@ public ExtendedSpanBuilder setStartTimestamp(Instant startTimestamp) {
12432
* @param propagators provide the propagators from {@link OpenTelemetry#getPropagators()}
12533
* @param carrier the string map where to extract the span context from
12634
*/
127-
public ExtendedSpanBuilder setParentFrom(
128-
ContextPropagators propagators, Map<String, String> carrier) {
129-
setParent(ExtendedContextPropagators.extractTextMapPropagationContext(carrier, propagators));
130-
return this;
131-
}
132-
133-
@Override
134-
public Span startSpan() {
135-
return delegate.startSpan();
136-
}
35+
ExtendedSpanBuilder setParentFrom(ContextPropagators propagators, Map<String, String> carrier);
13736

13837
/**
13938
* Runs the given {@link SpanCallable} inside of the span created by the given {@link
@@ -147,9 +46,7 @@ public Span startSpan() {
14746
* @param <E> the type of the exception
14847
* @return the result of the {@link SpanCallable}
14948
*/
150-
public <T, E extends Throwable> T startAndCall(SpanCallable<T, E> spanCallable) throws E {
151-
return startAndCall(spanCallable, ExtendedSpanBuilder::setSpanError);
152-
}
49+
<T, E extends Throwable> T startAndCall(SpanCallable<T, E> spanCallable) throws E;
15350

15451
/**
15552
* Runs the given {@link SpanCallable} inside of the span created by the given {@link
@@ -165,20 +62,8 @@ public <T, E extends Throwable> T startAndCall(SpanCallable<T, E> spanCallable)
16562
* @param <E> the type of the exception
16663
* @return the result of the {@link SpanCallable}
16764
*/
168-
public <T, E extends Throwable> T startAndCall(
169-
SpanCallable<T, E> spanCallable, BiConsumer<Span, Throwable> handleException) throws E {
170-
Span span = startSpan();
171-
172-
//noinspection unused
173-
try (Scope unused = span.makeCurrent()) {
174-
return spanCallable.callInSpan();
175-
} catch (Throwable e) {
176-
handleException.accept(span, e);
177-
throw e;
178-
} finally {
179-
span.end();
180-
}
181-
}
65+
<T, E extends Throwable> T startAndCall(
66+
SpanCallable<T, E> spanCallable, BiConsumer<Span, Throwable> handleException) throws E;
18267

18368
/**
18469
* Runs the given {@link SpanRunnable} inside of the span created by the given {@link
@@ -190,10 +75,7 @@ public <T, E extends Throwable> T startAndCall(
19075
* @param runnable the {@link SpanRunnable} to run
19176
* @param <E> the type of the exception
19277
*/
193-
@SuppressWarnings("NullAway")
194-
public <E extends Throwable> void startAndRun(SpanRunnable<E> runnable) throws E {
195-
startAndRun(runnable, ExtendedSpanBuilder::setSpanError);
196-
}
78+
<E extends Throwable> void startAndRun(SpanRunnable<E> runnable) throws E;
19779

19880
/**
19981
* Runs the given {@link SpanRunnable} inside of the span created by the given {@link
@@ -206,25 +88,6 @@ public <E extends Throwable> void startAndRun(SpanRunnable<E> runnable) throws E
20688
* @param runnable the {@link SpanRunnable} to run
20789
* @param <E> the type of the exception
20890
*/
209-
@SuppressWarnings("NullAway")
210-
public <E extends Throwable> void startAndRun(
211-
SpanRunnable<E> runnable, BiConsumer<Span, Throwable> handleException) throws E {
212-
startAndCall(
213-
() -> {
214-
runnable.runInSpan();
215-
return null;
216-
},
217-
handleException);
218-
}
219-
220-
/**
221-
* Marks a span as error. This is the default exception handler.
222-
*
223-
* @param span the span
224-
* @param exception the exception that caused the error
225-
*/
226-
private static void setSpanError(Span span, Throwable exception) {
227-
span.setStatus(StatusCode.ERROR);
228-
span.recordException(exception);
229-
}
91+
<E extends Throwable> void startAndRun(
92+
SpanRunnable<E> runnable, BiConsumer<Span, Throwable> handleException) throws E;
23093
}

0 commit comments

Comments
 (0)