Skip to content

Commit d40f63e

Browse files
committed
1 parent c42469e commit d40f63e

File tree

21 files changed

+201
-57
lines changed

21 files changed

+201
-57
lines changed

hadoop-common-project/hadoop-common/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -406,6 +406,11 @@
406406
<artifactId>junit-platform-launcher</artifactId>
407407
<scope>test</scope>
408408
</dependency>
409+
<dependency>
410+
<groupId>io.opentelemetry</groupId>
411+
<artifactId>opentelemetry-api</artifactId>
412+
<version>${opentelemetry.version}</version>
413+
</dependency>
409414
</dependencies>
410415

411416
<build>

hadoop-common-project/hadoop-common/src/main/conf/hadoop-env.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,3 +432,13 @@ export HADOOP_OS_TYPE=${HADOOP_OS_TYPE:-$(uname -s)}
432432
# By default, Hadoop uses jsvc which needs to know to launch a
433433
# server jvm.
434434
# export HADOOP_REGISTRYDNS_SECURE_EXTRA_OPTS="-jvm server"
435+
436+
###
437+
# Opentelemetry Trace Exporters Configuration
438+
###
439+
# export OPENTELEMETRY_JAVAAGENT_PATH="$(find $HADOOP_HOME/share/hadoop/tools/lib/ -name opentelemetry-javaagent*)"
440+
# export HADOOP_TRACE_OPTS="-javaagent:$OPENTELEMETRY_JAVAAGENT_PATH -Dotel.traces.exporter=jaeger -Dotel.metrics.exporter=none"
441+
# export HDFS_NAMENODE_OPTS="$HDFS_NAMENODE_OPTS $HADOOP_TRACE_OPTS -Dotel.resource.attributes=service.name=hdfs-namenode"
442+
# export HDFS_DATANODE_OPTS="$HDFS_DATANODE_OPTS $HADOOP_TRACE_OPTS -Dotel.resource.attributes=service.name=hdfs-datanode"
443+
# export HDFS_SECONDARYNAMENODE_OPTS="$HDFS_SECONDARYNAMENODE_OPTS $HADOOP_TRACE_OPTS -Dotel.resource.attributes=service.name=hdfs-secondarynamenode"
444+
# export HADOOP_CLIENT_OPTS="$HADOOP_CLIENT_OPTS $HADOOP_TRACE_OPTS -Dotel.resource.attributes=service.name=hadoop-client"

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FsShell.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ private TableListing createOptionTableListing() {
301301
public int run(String[] argv) {
302302
// initialize FsShell
303303
init();
304-
Tracer tracer = new Tracer.Builder("FsShell").
304+
Tracer tracer = new Tracer.Builder().
305305
conf(TraceUtils.wrapHadoopConf(SHELL_HTRACE_PREFIX, getConf())).
306306
build();
307307
int exitCode = -1;

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/FsTracer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public final class FsTracer {
3838

3939
public static synchronized Tracer get(Configuration conf) {
4040
if (instance == null) {
41-
instance = new Tracer.Builder("FSClient").
41+
instance = new Tracer.Builder().
4242
conf(TraceUtils.wrapHadoopConf(CommonConfigurationKeys.
4343
FS_CLIENT_HTRACE_PREFIX, conf)).
4444
build();

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Server.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2948,15 +2948,15 @@ private void processRpcRequest(RpcRequestHeaderProto header,
29482948
Span span = null;
29492949
if (header.hasTraceInfo()) {
29502950
RPCTraceInfoProto traceInfoProto = header.getTraceInfo();
2951-
if (traceInfoProto.hasSpanContext()) {
2951+
if (traceInfoProto.getOpenSpanContextMap() != null) {
29522952
if (tracer == null) {
29532953
setTracer(Tracer.curThreadTracer());
29542954
}
29552955
if (tracer != null) {
29562956
// If the incoming RPC included tracing info, always continue the
29572957
// trace
2958-
SpanContext spanCtx = TraceUtils.byteStringToSpanContext(
2959-
traceInfoProto.getSpanContext());
2958+
SpanContext spanCtx = TraceUtils.mapToSpanContext(
2959+
traceInfoProto.getOpenSpanContextMap());
29602960
if (spanCtx != null) {
29612961
span = tracer.newSpan(
29622962
RpcClientUtil.toTraceName(rpcRequest.toString()), spanCtx);

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/tracing/Span.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,63 @@
1717
*/
1818
package org.apache.hadoop.tracing;
1919

20+
import io.opentelemetry.context.Scope;
21+
2022
import java.io.Closeable;
2123

24+
/***
25+
* This class is a wrapper class on top of opentelemetry Span class
26+
* avoiding direct dependency on opentelemetry API.
27+
*/
2228
public class Span implements Closeable {
29+
private io.opentelemetry.api.trace.Span openSpan;
2330

2431
public Span() {
2532
}
2633

34+
public Span(io.opentelemetry.api.trace.Span openSpan){
35+
this.openSpan = openSpan;
36+
}
37+
2738
public Span addKVAnnotation(String key, String value) {
39+
if(openSpan != null){
40+
openSpan.setAttribute(key, value);
41+
}
2842
return this;
2943
}
3044

3145
public Span addTimelineAnnotation(String msg) {
46+
if(openSpan != null){
47+
openSpan.addEvent(msg);
48+
}
3249
return this;
3350
}
3451

3552
public SpanContext getContext() {
53+
if(openSpan != null){
54+
return new SpanContext(openSpan.getSpanContext());
55+
}
3656
return null;
3757
}
3858

3959
public void finish() {
60+
close();
4061
}
4162

4263
public void close() {
64+
if(openSpan != null){
65+
openSpan.end();
66+
}
67+
}
68+
69+
/***
70+
* This method activates the current span on the current thread
71+
* @return the scope for the current span
72+
*/
73+
public Scope makeCurrent() {
74+
if(openSpan != null){
75+
return openSpan.makeCurrent();
76+
}
77+
return null;
4378
}
4479
}

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/tracing/SpanContext.java

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,74 @@
1818
package org.apache.hadoop.tracing;
1919

2020
import java.io.Closeable;
21+
import java.util.HashMap;
22+
import java.util.Map;
23+
24+
import io.opentelemetry.api.trace.TraceFlags;
25+
import io.opentelemetry.api.trace.TraceState;
26+
import io.opentelemetry.api.trace.TraceStateBuilder;
27+
import org.slf4j.Logger;
28+
import org.slf4j.LoggerFactory;
2129

2230
/**
2331
* Wrapper class for SpanContext to avoid using OpenTracing/OpenTelemetry
2432
* SpanContext class directly for better separation.
2533
*/
2634
public class SpanContext implements Closeable {
27-
public SpanContext() {
35+
public static final Logger LOG = LoggerFactory.getLogger(SpanContext.class.getName());
36+
37+
private static final String TRACE_ID = "TRACE_ID";
38+
private static final String SPAN_ID = "SPAN_ID";
39+
private static final String TRACE_FLAGS = "TRACE_FLAGS";
40+
41+
private io.opentelemetry.api.trace.SpanContext openSpanContext;
42+
43+
public SpanContext(io.opentelemetry.api.trace.SpanContext openSpanContext) {
44+
this.openSpanContext = openSpanContext;
2845
}
2946

3047
public void close() {
3148
}
49+
50+
public Map<String, String> getKVSpanContext(){
51+
if(openSpanContext != null){
52+
//TODO: may we should move this to Proto
53+
Map<String, String> kvMap = new HashMap<>();
54+
kvMap.put(TRACE_ID, openSpanContext.getTraceId());
55+
kvMap.put(SPAN_ID, openSpanContext.getSpanId());
56+
kvMap.put(TRACE_FLAGS, openSpanContext.getTraceFlags().asHex());
57+
kvMap.putAll(openSpanContext.getTraceState().asMap());
58+
return kvMap;
59+
}
60+
return null;
61+
}
62+
63+
static SpanContext buildFromKVMap(Map<String, String> kvMap){
64+
try{
65+
String traceId = kvMap.get(TRACE_ID);
66+
String spanId = kvMap.get(SPAN_ID);
67+
String traceFlagsHex = kvMap.get(TRACE_FLAGS);
68+
if(traceId == null || spanId == null || traceFlagsHex == null){
69+
return null;
70+
}
71+
TraceFlags traceFlags = TraceFlags.fromHex(traceFlagsHex, 0);
72+
TraceStateBuilder traceStateBuilder = TraceState.builder();
73+
for(Map.Entry<String, String> keyValue: kvMap.entrySet()){
74+
if(keyValue.getKey().equals(TRACE_ID) || keyValue.getKey().equals(SPAN_ID) || keyValue.getKey().equals(TRACE_FLAGS)){
75+
continue;
76+
}
77+
traceStateBuilder.put(keyValue.getKey(), keyValue.getValue());
78+
}
79+
TraceState traceState = traceStateBuilder.build();
80+
io.opentelemetry.api.trace.SpanContext spanContext = io.opentelemetry.api.trace.SpanContext.createFromRemoteParent(traceId, spanId, traceFlags, traceState );
81+
return new SpanContext(spanContext);
82+
} catch (Exception e){
83+
LOG.error("Error in processing remote context :", e);
84+
return null;
85+
}
86+
}
87+
88+
public io.opentelemetry.api.trace.SpanContext getOpenSpanContext() {
89+
return openSpanContext;
90+
}
3291
}

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/tracing/TraceScope.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,33 @@
1717
*/
1818
package org.apache.hadoop.tracing;
1919

20+
import io.opentelemetry.context.Scope;
21+
2022
import java.io.Closeable;
2123

2224
public class TraceScope implements Closeable {
2325
Span span;
2426

27+
Scope openScope;
28+
2529
public TraceScope(Span span) {
2630
this.span = span;
31+
if(span != null){
32+
this.openScope = span.makeCurrent();
33+
}
2734
}
2835

2936
// Add tag to the span
3037
public void addKVAnnotation(String key, String value) {
38+
span.addKVAnnotation(key, value);
3139
}
3240

3341
public void addKVAnnotation(String key, Number value) {
42+
span.addKVAnnotation(key, value.toString());
3443
}
3544

3645
public void addTimelineAnnotation(String msg) {
46+
span.addTimelineAnnotation(msg);
3747
}
3848

3949
public Span span() {
@@ -51,6 +61,9 @@ public void detach() {
5161
}
5262

5363
public void close() {
64+
if(openScope != null){
65+
openScope.close();
66+
}
5467
if (span != null) {
5568
span.close();
5669
}

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/tracing/TraceUtils.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,18 @@
1919

2020
import org.apache.hadoop.classification.InterfaceAudience;
2121
import org.apache.hadoop.conf.Configuration;
22-
import org.apache.hadoop.thirdparty.protobuf.ByteString;
22+
import org.slf4j.Logger;
23+
import org.slf4j.LoggerFactory;
24+
25+
import java.util.Map;
2326

2427
/**
2528
* This class provides utility functions for tracing.
2629
*/
2730
@InterfaceAudience.Private
2831
public class TraceUtils {
32+
public static final Logger LOG = LoggerFactory.getLogger(TraceUtils.class.getName());
33+
2934
static final String DEFAULT_HADOOP_TRACE_PREFIX = "hadoop.htrace.";
3035

3136
public static TraceConfiguration wrapHadoopConf(final String prefix,
@@ -37,11 +42,14 @@ public static Tracer createAndRegisterTracer(String name) {
3742
return null;
3843
}
3944

40-
public static SpanContext byteStringToSpanContext(ByteString byteString) {
41-
return null;
45+
public static SpanContext mapToSpanContext(Map<String, String> kvMap) {
46+
return SpanContext.buildFromKVMap(kvMap);
4247
}
4348

44-
public static ByteString spanContextToByteString(SpanContext context) {
45-
return null;
49+
public static Map<String, String> spanContextToMap(SpanContext context) {
50+
if (context == null) {
51+
return null;
52+
}
53+
return context.getKVSpanContext();
4654
}
4755
}

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/tracing/Tracer.java

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,26 @@
1717
*/
1818
package org.apache.hadoop.tracing;
1919

20+
import io.opentelemetry.api.GlobalOpenTelemetry;
21+
import io.opentelemetry.context.Context;
22+
import org.slf4j.Logger;
23+
import org.slf4j.LoggerFactory;
24+
2025
/**
2126
* No-Op Tracer (for now) to remove HTrace without changing too many files.
2227
*/
2328
public class Tracer {
29+
public static final Logger LOG = LoggerFactory.getLogger(Tracer.class.getName());
30+
private static final String INSTRUMENTATION_NAME = "io.opentelemetry.contrib.hadoop";
31+
2432
// Singleton
25-
private static final Tracer globalTracer = null;
26-
private final NullTraceScope nullTraceScope;
27-
private final String name;
33+
private static Tracer globalTracer = null;
34+
io.opentelemetry.api.trace.Tracer OTelTracer = GlobalOpenTelemetry.getTracer(INSTRUMENTATION_NAME);
2835

2936
public final static String SPAN_RECEIVER_CLASSES_KEY =
3037
"span.receiver.classes";
3138

32-
public Tracer(String name) {
33-
this.name = name;
34-
nullTraceScope = NullTraceScope.INSTANCE;
35-
}
39+
private Tracer() {}
3640

3741
// Keeping this function at the moment for HTrace compatiblity,
3842
// in fact all threads share a single global tracer for OpenTracing.
@@ -45,53 +49,51 @@ public static Tracer curThreadTracer() {
4549
* @return org.apache.hadoop.tracing.Span
4650
*/
4751
public static Span getCurrentSpan() {
48-
return null;
52+
io.opentelemetry.api.trace.Span span = io.opentelemetry.api.trace.Span.current();
53+
return span.getSpanContext().isValid()? new Span(span): null;
4954
}
5055

5156
public TraceScope newScope(String description) {
52-
return nullTraceScope;
57+
Span span = new Span(OTelTracer.spanBuilder(description).startSpan());
58+
return new TraceScope(span);
5359
}
5460

5561
public Span newSpan(String description, SpanContext spanCtx) {
56-
return new Span();
62+
io.opentelemetry.api.trace.Span parentSpan = io.opentelemetry.api.trace.Span.wrap(spanCtx.getOpenSpanContext());
63+
io.opentelemetry.api.trace.Span span = OTelTracer.spanBuilder(description).setParent(Context.current().with(parentSpan)).startSpan();
64+
return new Span(span);
5765
}
5866

5967
public TraceScope newScope(String description, SpanContext spanCtx) {
60-
return nullTraceScope;
68+
if(spanCtx == null){
69+
return new TraceScope(new Span(io.opentelemetry.api.trace.Span.getInvalid()));
70+
}
71+
return new TraceScope(newSpan(description, spanCtx));
6172
}
6273

6374
public TraceScope newScope(String description, SpanContext spanCtx,
6475
boolean finishSpanOnClose) {
65-
return nullTraceScope;
76+
return new TraceScope(newSpan(description, spanCtx));
6677
}
6778

6879
public TraceScope activateSpan(Span span) {
69-
return nullTraceScope;
80+
return new TraceScope(span);
7081
}
7182

7283
public void close() {
7384
}
7485

75-
public String getName() {
76-
return name;
77-
}
78-
7986
public static class Builder {
80-
static Tracer globalTracer;
81-
private String name;
87+
static Tracer globalTracer = new Tracer();
8288

83-
public Builder(final String name) {
84-
this.name = name;
89+
public Builder() {
8590
}
8691

8792
public Builder conf(TraceConfiguration conf) {
8893
return this;
8994
}
9095

91-
public Tracer build() {
92-
if (globalTracer == null) {
93-
globalTracer = new Tracer(name);
94-
}
96+
public synchronized Tracer build() {
9597
return globalTracer;
9698
}
9799
}

0 commit comments

Comments
 (0)