-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
integrate and implement open telemetry tracing #18534
integrate and implement open telemetry tracing #18534
Conversation
119f1c7
to
49d6041
Compare
f070e75
to
3fd2443
Compare
@highker could we get a first pass on this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed the first commit
presto-main/src/main/java/com/facebook/presto/tracing/OpenTelemetryTracer.java
Outdated
Show resolved
Hide resolved
@Override | ||
public void endTrace(String annotation) | ||
{ | ||
addPoint(annotation); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to take care of any unfinished Span?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you help me understanding the closing logic of opentelemetry here? Thank you
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am looking into this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tanjialiang Addressed by ending any unended spans at the time of ending trace.
presto-main/src/main/java/com/facebook/presto/tracing/OpenTelemetryTracer.java
Outdated
Show resolved
Hide resolved
presto-main/src/main/java/com/facebook/presto/tracing/OpenTelemetryTracerProvider.java
Outdated
Show resolved
Hide resolved
presto-main/src/main/java/com/facebook/presto/tracing/OpenTelemetryTracer.java
Outdated
Show resolved
Hide resolved
a2a2097
to
e932e63
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
high-level comments only
presto-main/src/main/java/com/facebook/presto/server/ServerMainModule.java
Outdated
Show resolved
Hide resolved
presto-spi/src/main/java/com/facebook/presto/spi/tracing/TracerProvider.java
Outdated
Show resolved
Hide resolved
presto-main/src/main/java/com/facebook/presto/tracing/TracingConfig.java
Show resolved
Hide resolved
5173a23
to
35a6292
Compare
936cf9e
to
ee19b16
Compare
Hey @highker, I want to try to get my changes pushed through by the end of next week if possible. If there's anything in this PR that still needs further discussion or you still want revised, I'm happy to remove it from this PR and address it as a new one for the future if that works. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please squash all commits into one.
I have one major comment in the end. Please check that one first.
public static final String PRESTO_W3C_PROPAGATION = "traceparent"; | ||
public static final String PRESTO_B3_SINGLE_HEADER_PROPAGATION = "b3"; | ||
public static final String PRESTO_BAGGAGE_HEADER = "baggage"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remove these headers to presto-open-telemetry. Check my other comment
stringProperty( | ||
CONTEXT_PROPAGATOR, | ||
"Context propagator for Open Telemetry tracing. w3c, b3_single_header, or b3_multiple_header", | ||
tracingConfig.getContextPropagator(), | ||
false), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use the header instead of session property to control the flags?
String tunnelTraceId = trimEmptyToNull(servletRequest.getHeader(PRESTO_TRACE_TOKEN)); | ||
String contextPropagator = sessionPropertyManager | ||
.map(manager -> manager.decodeSystemPropertyValue(CONTEXT_PROPAGATOR, null, String.class)) | ||
.orElse(TracingConfig.ContextPropagator.B3_SINGLE_HEADER); | ||
String propagatedContext = getPropagatedContext(contextPropagator, servletRequest); | ||
String baggage = servletRequest.getHeader(PRESTO_BAGGAGE_HEADER); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's refactor the code a bit so we don't have to use session property or the header explicitly. Check my other comment
* @param servletRequest http request with headers | ||
* @return header value extracted from http request based on context propagator | ||
*/ | ||
private static String getPropagatedContext(String contextPropagator, HttpServletRequest servletRequest) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this to presto-open-telemetry
module. Check my other comment
{ | ||
private final String tracerType; | ||
private final boolean systemTracingEnabled; | ||
private @Nullable TracerProvider tracerProvider; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit
@Nullable
private TracerProvider tracerProvider;
|
||
public TracerProvider getTracerProvider() | ||
{ | ||
return tracerProvider; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check non null
OpenTelemetry openTelemetry = OpenTelemetrySdk.builder() | ||
.setTracerProvider(sdkTracerProvider) | ||
.setPropagators(ContextPropagators.create(OpenTelemetryBuilder.getPropagatorInstance(contextPropagator))) | ||
.buildAndRegisterGlobal(); | ||
|
||
return openTelemetry; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
directly return instead of creating openTelemetry
public interface TracerProvider | ||
{ | ||
String getName(); | ||
|
||
String getTracerType(); | ||
/** | ||
* | ||
* @return A @Tracer that should be kept throughout the whole duration of tracing. | ||
*/ | ||
Tracer getNewTracer(); | ||
Tracer getNewTracer(String traceToken, String contextPropagator, String propagatedContext, String baggage); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Major] this is my major comment.
Similar to many other "handle" classes in our codebase, let's create a handle interface in com.facebook.presto.spi.tracing
:
public interface TracerHandle
{
}
Change the signature of getNewTracer
to
Tracer getNewTracer(TracerHandle handle);
Create a new method of TracerProvider
:
/**
* The method returns a function to take a set of HTTP headers and generate the tracer handle
*/
Function<Set<String>, TracerHandle> getHandleGenerator();
In your OpenTelemetry implementation, you should have
public class OpenTelemetryTracerHandle
implements TracerHandle
{
private final String traceToken;
private final String contextPropagator;
private final String propagatedContext;
private final String baggage;
...
}
In your OpenTelemetryTracerProvider
, you should have
@Override
public Tracer getNewTracer(TracerHandle handle)
{
OpenTelemetryTracerHandle tracerHandle = (TracerHandle) handle;
return new OpenTelemetryTracer(tracerHandle.getXXX, ...);
}
In your getHandleGenerator
implementation, move all the logics you have in presto-main here so we can hide all those headers and specialized extraction methods.
@@ -115,4 +116,9 @@ default Iterable<HistoryBasedPlanStatisticsProvider> getHistoryBasedPlanStatisti | |||
{ | |||
return emptyList(); | |||
} | |||
|
|||
default Iterable<TracerProvider> getTracerProviders() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add javadoc
String getName(); | ||
|
||
String getTracerType(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add javadoc
d171ea9
to
1e44c8f
Compare
@highker Trace handle implementation done |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
awesome change! All nits. Otherwise, good to go
@@ -211,19 +211,33 @@ else if (nameParts.size() == 2) { | |||
|
|||
this.sessionFunctions = parseSessionFunctionHeader(servletRequest); | |||
this.sessionPropertyManager = requireNonNull(sessionPropertyManager, "sessionPropertyManager is null"); | |||
String tunnelTraceId = trimEmptyToNull(servletRequest.getHeader(PRESTO_TRACE_TOKEN)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know it's a bit anti pattern; but in order to keep the logic so we don't pollute the traceToken
below. Check my comment below.
|
||
// If tunnel trace token is null, we expose the Presto tracing id. | ||
// Otherwise we preserve the ability of trace token tunneling but | ||
// still trace Presto internally for aggregation purposes. | ||
traceToken = Optional.ofNullable(tunnelTraceId == null ? this.tracer.get().getTracerId() : tunnelTraceId); | ||
traceToken = Optional.ofNullable(this.tracer.get().getTracerId()); | ||
} | ||
else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a new branch here: else if (trimEmptyToNull(servletRequest.getHeader(PRESTO_TRACE_TOKEN)) != null)
or something like that. And inside the body, we can either create a SimpleTracerProvider and get the token or directly assign traceToken from PRESTO_TRACE_TOKEN
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated trace token to replicate similar logic as before
|
||
private static Map<String, String> getRequestHeaderMap(HttpServletRequest servletRequest) | ||
{ | ||
Map<String, String> headerMap = new HashMap<>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use immutableMap builder
} | ||
} | ||
|
||
private static Map<String, String> getRequestHeaderMap(HttpServletRequest servletRequest) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: it's not critical but good to follow:
we don't usually name a function or var with word "Map"; instead, we use getRequestHeaders
. Same for the variable headerMap
--> headers
. And everything else in the PR.
@@ -211,19 +211,33 @@ else if (nameParts.size() == 2) { | |||
|
|||
this.sessionFunctions = parseSessionFunctionHeader(servletRequest); | |||
this.sessionPropertyManager = requireNonNull(sessionPropertyManager, "sessionPropertyManager is null"); | |||
String tunnelTraceId = trimEmptyToNull(servletRequest.getHeader(PRESTO_TRACE_TOKEN)); | |||
|
|||
Map<String, String> requestHeaderMap = getRequestHeaderMap(servletRequest); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: requestHeaders
if (headers.containsKey(PRESTO_B3_SINGLE_HEADER_PROPAGATION)) { | ||
return "b3_single_header"; | ||
} | ||
else if (headers.containsKey(PRESTO_W3C_PROPAGATION)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove else
; it's redundant
CONTEXT_PROPAGATOR_ERROR, | ||
"Only b3 single header context propagation mode is currently supported."); | ||
} | ||
else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove else
; it's redundant
if (contextPropagator.equals(TracingConfig.ContextPropagator.B3_SINGLE_HEADER)) { | ||
return headers.get(PRESTO_B3_SINGLE_HEADER_PROPAGATION); | ||
} | ||
else if (contextPropagator.equals(TracingConfig.ContextPropagator.W3C)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove else; it's redundant
@@ -113,6 +113,7 @@ | |||
QUERY_PLANNING_TIMEOUT(0x0001_0027, INTERNAL_ERROR), | |||
NATIVE_EXECUTION_TASK_ERROR(0x0001_0028, INTERNAL_ERROR), | |||
UNSUPPORTED_ANALYZER_TYPE(0x0001_0029, INTERNAL_ERROR), | |||
CONTEXT_PROPAGATOR_ERROR(0x0001_002A, INTERNAL_ERROR), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is not a generic error; check my other comment
throw new PrestoException( | ||
CONTEXT_PROPAGATOR_ERROR, | ||
"Only b3 single header context propagation mode is currently supported."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
two options:
- you can create your own error code class within the module with a brand new base code; check any other implementation of
ErrorCodeSupplier
; or - you can just throw runtime error or put generic code to be a catch-all to save the effort, which is not recommended but fine
@highker Addressed nits, and made one further change for open telemetry baggage propagation. Put it in new commit so it's easier to see and will squash if it looks good. |
Thanks. Please squash all commits into one. |
11edf44
to
19a4184
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
more nits; otherwise LGTM
@@ -211,19 +212,39 @@ else if (nameParts.size() == 2) { | |||
|
|||
this.sessionFunctions = parseSessionFunctionHeader(servletRequest); | |||
this.sessionPropertyManager = requireNonNull(sessionPropertyManager, "sessionPropertyManager is null"); | |||
String tunnelTraceId = trimEmptyToNull(servletRequest.getHeader(PRESTO_TRACE_TOKEN)); | |||
|
|||
ImmutableMap<String, String> requestHeaders = getRequestHeaders(servletRequest); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: ImmutableMap<String, String> -> Map<String, String>
traceToken = Optional.ofNullable(tunnelTraceId == null ? this.tracer.get().getTracerId() : tunnelTraceId); | ||
String tunnelTraceId = trimEmptyToNull(servletRequest.getHeader(PRESTO_TRACE_TOKEN)); | ||
if (tunnelTraceId != null) { | ||
traceToken = Optional.ofNullable(tunnelTraceId); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Optional.of(tunnelTraceId)
it's not null already
traceToken = Optional.ofNullable(tunnelTraceId); | ||
} | ||
|
||
private static ImmutableMap<String, String> getRequestHeaders(HttpServletRequest servletRequest) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: ImmutableMap<String, String> -> Map<String, String>
public static class ContextPropagator | ||
{ | ||
public static final String W3C = "w3c"; | ||
public static final String B3_SINGLE_HEADER = "b3_single_header"; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
comment not addressed? https://github.com/prestodb/presto/pull/18534/files#r1035527320
|
||
OpenTelemetryErrorCode(int code, ErrorType type) | ||
{ | ||
errorCode = new ErrorCode(code, name(), type); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this.openTelemetry = OpenTelemetryBuilder.build(contextPropagator); | ||
this.currentContextPropagator = contextPropagator; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not expert in open telemetry but are we sure the logic is correct by modifying static variables?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it should be fine. If we have a different context propagator, we need to rebuild the open telemetry instance for all tracers that may exist.
d227668
to
6ad17a0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One last nit
public static final String OTEL = "otel"; | ||
} | ||
|
||
public static class ContextPropagator |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we delete this class from this file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
support simple tracer in new open telemetry implementation bump okhttp3 version to 4.5.0 use system val if client val not set add support for context extraction from b3 propagation and overall interface revert back to okhttp3 version 3.9.0 for this PR implement W3C baggage header extraction tracer handle implementation, remove context propagator from system property, general refactor address nits and open telemetry baggage updates
6ad17a0
to
54c6530
Compare
@highker Thanks for the helpful reviews and merge! |
Test plan -