Skip to content

Commit c3a0784

Browse files
authored
Adds support for tracing runnable scenarios (#9187)
Signed-off-by: Gagan Juneja <[email protected]>
1 parent ab8e306 commit c3a0784

File tree

11 files changed

+234
-6
lines changed

11 files changed

+234
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5454
- [Refactor] MediaTypeParser to MediaTypeParserRegistry ([#8636](https://github.com/opensearch-project/OpenSearch/pull/8636))
5555
- Make MultiBucketConsumerService thread safe to use across slices during search ([#9047](https://github.com/opensearch-project/OpenSearch/pull/9047))
5656
- Removed blocking wait in TransportGetSnapshotsAction which was exhausting generic threadpool ([#8377](https://github.com/opensearch-project/OpenSearch/pull/8377))
57+
- Adds support for tracing runnable scenarios ([#8831](https://github.com/opensearch-project/OpenSearch/pull/8831))
5758

5859
### Deprecated
5960

libs/telemetry/src/main/java/org/opensearch/telemetry/tracing/DefaultTracer.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,17 @@ public DefaultTracer(TracingTelemetry tracingTelemetry, TracerContextStorage<Str
3737

3838
@Override
3939
public SpanScope startSpan(String spanName) {
40-
Span span = createSpan(spanName, getCurrentSpan());
40+
return startSpan(spanName, null);
41+
}
42+
43+
@Override
44+
public SpanScope startSpan(String spanName, SpanContext parentSpan) {
45+
Span span = null;
46+
if (parentSpan != null) {
47+
span = createSpan(spanName, parentSpan.getSpan());
48+
} else {
49+
span = createSpan(spanName, getCurrentSpanInternal());
50+
}
4151
setCurrentSpanInContext(span);
4252
addDefaultAttributes(span);
4353
return new DefaultSpanScope(span, (scopeSpan) -> endSpan(scopeSpan));
@@ -48,11 +58,15 @@ public void close() throws IOException {
4858
((Closeable) tracingTelemetry).close();
4959
}
5060

51-
// Visible for testing
52-
Span getCurrentSpan() {
61+
private Span getCurrentSpanInternal() {
5362
return tracerContextStorage.get(TracerContextStorage.CURRENT_SPAN);
5463
}
5564

65+
public SpanContext getCurrentSpan() {
66+
final Span currentSpan = tracerContextStorage.get(TracerContextStorage.CURRENT_SPAN);
67+
return (currentSpan == null) ? null : new SpanContext(currentSpan);
68+
}
69+
5670
private void endSpan(Span span) {
5771
if (span != null) {
5872
span.endSpan();
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.telemetry.tracing;
10+
11+
/**
12+
* Wrapped Span will be exposed to the code outside of tracing package for sharing the {@link Span} without having access to
13+
* its properties.
14+
*/
15+
public final class SpanContext {
16+
private final Span span;
17+
18+
/**
19+
* Constructor.
20+
* @param span span to be wrapped.
21+
*/
22+
public SpanContext(Span span) {
23+
this.span = span;
24+
}
25+
26+
Span getSpan() {
27+
return span;
28+
}
29+
}

libs/telemetry/src/main/java/org/opensearch/telemetry/tracing/Tracer.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,17 @@ public interface Tracer extends Closeable {
2626
*/
2727
SpanScope startSpan(String spanName);
2828

29+
/**
30+
* Started the {@link Span} with the given name and parent.
31+
* @param spanName span name.
32+
* @param parentSpan parent span.
33+
* @return scope of the span, must be closed with explicit close or with try-with-resource
34+
*/
35+
SpanScope startSpan(String spanName, SpanContext parentSpan);
36+
37+
/**
38+
* Returns the current span.
39+
* @return current wrapped span.
40+
*/
41+
SpanContext getCurrentSpan();
2942
}

libs/telemetry/src/main/java/org/opensearch/telemetry/tracing/noop/NoopTracer.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import org.opensearch.telemetry.tracing.SpanScope;
1212
import org.opensearch.telemetry.tracing.Tracer;
13+
import org.opensearch.telemetry.tracing.SpanContext;
1314

1415
/**
1516
* No-op implementation of Tracer
@@ -30,6 +31,16 @@ public SpanScope startSpan(String spanName) {
3031
return SpanScope.NO_OP;
3132
}
3233

34+
@Override
35+
public SpanContext getCurrentSpan() {
36+
return null;
37+
}
38+
39+
@Override
40+
public SpanScope startSpan(String spanName, SpanContext parentSpan) {
41+
return SpanScope.NO_OP;
42+
}
43+
3344
@Override
3445
public void close() {
3546

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.telemetry.tracing.runnable;
10+
11+
import org.opensearch.telemetry.tracing.SpanContext;
12+
import org.opensearch.telemetry.tracing.SpanScope;
13+
import org.opensearch.telemetry.tracing.Tracer;
14+
15+
/**
16+
* Wraps the runnable and add instrumentation to trace the {@link Runnable}
17+
*/
18+
public class TraceableRunnable implements Runnable {
19+
private final Runnable runnable;
20+
private final SpanContext parent;
21+
private final Tracer tracer;
22+
private final String spanName;
23+
24+
/**
25+
* Constructor.
26+
* @param tracer tracer
27+
* @param spanName spanName
28+
* @param parent parent Span.
29+
* @param runnable runnable.
30+
*/
31+
public TraceableRunnable(Tracer tracer, String spanName, SpanContext parent, Runnable runnable) {
32+
this.tracer = tracer;
33+
this.spanName = spanName;
34+
this.parent = parent;
35+
this.runnable = runnable;
36+
}
37+
38+
@Override
39+
public void run() {
40+
try (SpanScope spanScope = tracer.startSpan(spanName, parent)) {
41+
runnable.run();
42+
}
43+
}
44+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
/**
10+
* Contains tracing related classes
11+
*/
12+
package org.opensearch.telemetry.tracing.runnable;

libs/telemetry/src/test/java/org/opensearch/telemetry/tracing/DefaultTracerTests.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
package org.opensearch.telemetry.tracing;
1010

1111
import org.junit.Assert;
12+
import org.opensearch.common.settings.Settings;
13+
import org.opensearch.common.util.concurrent.ThreadContext;
1214
import org.opensearch.test.OpenSearchTestCase;
1315

1416
import java.io.IOException;
17+
import org.opensearch.test.telemetry.tracing.MockTracingTelemetry;
1518

1619
import static org.mockito.Mockito.mock;
1720
import static org.mockito.Mockito.when;
@@ -40,7 +43,37 @@ public void testCreateSpan() {
4043

4144
defaultTracer.startSpan("span_name");
4245

43-
Assert.assertEquals("span_name", defaultTracer.getCurrentSpan().getSpanName());
46+
Assert.assertEquals("span_name", defaultTracer.getCurrentSpan().getSpan().getSpanName());
47+
}
48+
49+
public void testCreateSpanWithParent() {
50+
TracingTelemetry tracingTelemetry = new MockTracingTelemetry();
51+
DefaultTracer defaultTracer = new DefaultTracer(
52+
tracingTelemetry,
53+
new ThreadContextBasedTracerContextStorage(new ThreadContext(Settings.EMPTY), tracingTelemetry)
54+
);
55+
56+
defaultTracer.startSpan("span_name", null);
57+
58+
SpanContext parentSpan = defaultTracer.getCurrentSpan();
59+
60+
defaultTracer.startSpan("span_name_1", parentSpan);
61+
62+
Assert.assertEquals("span_name_1", defaultTracer.getCurrentSpan().getSpan().getSpanName());
63+
Assert.assertEquals(parentSpan.getSpan(), defaultTracer.getCurrentSpan().getSpan().getParentSpan());
64+
}
65+
66+
public void testCreateSpanWithNullParent() {
67+
TracingTelemetry tracingTelemetry = new MockTracingTelemetry();
68+
DefaultTracer defaultTracer = new DefaultTracer(
69+
tracingTelemetry,
70+
new ThreadContextBasedTracerContextStorage(new ThreadContext(Settings.EMPTY), tracingTelemetry)
71+
);
72+
73+
defaultTracer.startSpan("span_name", null);
74+
75+
Assert.assertEquals("span_name", defaultTracer.getCurrentSpan().getSpan().getSpanName());
76+
Assert.assertEquals(null, defaultTracer.getCurrentSpan().getSpan().getParentSpan());
4477
}
4578

4679
public void testEndSpanByClosingScope() {
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* The OpenSearch Contributors require contributions made to
5+
* this file be licensed under the Apache-2.0 license or a
6+
* compatible open source license.
7+
*/
8+
9+
package org.opensearch.telemetry.tracing;
10+
11+
import java.util.concurrent.atomic.AtomicBoolean;
12+
import java.util.concurrent.atomic.AtomicReference;
13+
import org.opensearch.common.settings.Settings;
14+
import org.opensearch.common.util.concurrent.ThreadContext;
15+
import org.opensearch.telemetry.tracing.runnable.TraceableRunnable;
16+
import org.opensearch.test.OpenSearchTestCase;
17+
import org.opensearch.test.telemetry.tracing.MockTracingTelemetry;
18+
19+
public class TraceableRunnableTests extends OpenSearchTestCase {
20+
21+
private final ThreadContextBasedTracerContextStorage contextStorage = new ThreadContextBasedTracerContextStorage(
22+
new ThreadContext(Settings.EMPTY),
23+
new MockTracingTelemetry()
24+
);
25+
26+
public void testRunnableWithNullParent() throws Exception {
27+
String spanName = "testRunnable";
28+
DefaultTracer defaultTracer = new DefaultTracer(new MockTracingTelemetry(), contextStorage);
29+
final AtomicBoolean isRunnableCompleted = new AtomicBoolean(false);
30+
TraceableRunnable traceableRunnable = new TraceableRunnable(
31+
defaultTracer,
32+
spanName,
33+
null,
34+
() -> { isRunnableCompleted.set(true); }
35+
);
36+
traceableRunnable.run();
37+
assertTrue(isRunnableCompleted.get());
38+
assertEquals(spanName, defaultTracer.getCurrentSpan().getSpan().getSpanName());
39+
assertEquals(null, defaultTracer.getCurrentSpan().getSpan().getParentSpan());
40+
}
41+
42+
public void testRunnableWithParent() throws Exception {
43+
String spanName = "testRunnable";
44+
String parentSpanName = "parentSpan";
45+
DefaultTracer defaultTracer = new DefaultTracer(new MockTracingTelemetry(), contextStorage);
46+
defaultTracer.startSpan(parentSpanName);
47+
SpanContext parentSpan = defaultTracer.getCurrentSpan();
48+
AtomicReference<SpanContext> currrntSpan = new AtomicReference<>(new SpanContext(null));
49+
final AtomicBoolean isRunnableCompleted = new AtomicBoolean(false);
50+
TraceableRunnable traceableRunnable = new TraceableRunnable(defaultTracer, spanName, parentSpan, () -> {
51+
isRunnableCompleted.set(true);
52+
currrntSpan.set(defaultTracer.getCurrentSpan());
53+
});
54+
traceableRunnable.run();
55+
assertTrue(isRunnableCompleted.get());
56+
assertEquals(spanName, currrntSpan.get().getSpan().getSpanName());
57+
assertEquals(parentSpan.getSpan(), currrntSpan.get().getSpan().getParentSpan());
58+
assertEquals(parentSpan.getSpan(), defaultTracer.getCurrentSpan().getSpan());
59+
}
60+
}

server/src/main/java/org/opensearch/telemetry/tracing/WrappedTracer.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,19 @@ public WrappedTracer(TelemetrySettings telemetrySettings, Tracer defaultTracer)
3636

3737
@Override
3838
public SpanScope startSpan(String spanName) {
39+
return startSpan(spanName, null);
40+
}
41+
42+
@Override
43+
public SpanContext getCurrentSpan() {
44+
Tracer delegateTracer = getDelegateTracer();
45+
return delegateTracer.getCurrentSpan();
46+
}
47+
48+
@Override
49+
public SpanScope startSpan(String spanName, SpanContext parentSpan) {
3950
Tracer delegateTracer = getDelegateTracer();
40-
return delegateTracer.startSpan(spanName);
51+
return delegateTracer.startSpan(spanName, parentSpan);
4152
}
4253

4354
@Override

0 commit comments

Comments
 (0)