-
Notifications
You must be signed in to change notification settings - Fork 24.9k
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
Adds minimal traceparent header support to Elasticsearch #74210
Changes from 9 commits
0064cf4
64e20bd
ff74038
864d61b
2ab60f0
e3bb235
dc069c0
3771370
d3007fa
70807dd
4544fc4
dff91d1
05b1f2e
188a6de
9bc7a36
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
package org.elasticsearch.common.logging; | ||
|
||
import org.apache.logging.log4j.core.LogEvent; | ||
import org.apache.logging.log4j.core.config.plugins.Plugin; | ||
import org.apache.logging.log4j.core.pattern.ConverterKeys; | ||
import org.apache.logging.log4j.core.pattern.LogEventPatternConverter; | ||
import org.apache.logging.log4j.core.pattern.PatternConverter; | ||
import org.elasticsearch.tasks.Task; | ||
|
||
import java.util.Objects; | ||
|
||
/** | ||
* Pattern converter to format the trace id provided in the traceparent header into JSON fields <code>trace.id</code>. | ||
*/ | ||
@Plugin(category = PatternConverter.CATEGORY, name = "TraceIdConverter") | ||
@ConverterKeys({"trace_id"}) | ||
public final class TraceIdConverter extends LogEventPatternConverter { | ||
/** | ||
* Called by log4j2 to initialize this converter. | ||
*/ | ||
public static TraceIdConverter newInstance(@SuppressWarnings("unused") final String[] options) { | ||
return new TraceIdConverter(); | ||
} | ||
|
||
public TraceIdConverter() { | ||
super("trace_id", "trace_id"); | ||
} | ||
|
||
public static String getTraceId() { | ||
return HeaderWarning.THREAD_CONTEXT.stream() | ||
.map(t -> t.<String>getTransient(Task.TRACE_ID)) | ||
.filter(Objects::nonNull) | ||
.findFirst() | ||
.orElse(null); | ||
} | ||
|
||
/** | ||
* Formats the trace.id into json fields. | ||
* | ||
* @param event - a log event is ignored in this method as it uses the clusterId value | ||
* from <code>NodeAndClusterIdStateListener</code> to format | ||
*/ | ||
@Override | ||
public void format(LogEvent event, StringBuilder toAppendTo) { | ||
String traceId = getTraceId(); | ||
if (traceId != null) { | ||
toAppendTo.append(traceId); | ||
} | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -574,7 +574,7 @@ protected Node(final Environment initialEnvironment, | |
final Transport transport = networkModule.getTransportSupplier().get(); | ||
Set<String> taskHeaders = Stream.concat( | ||
pluginsService.filterPlugins(ActionPlugin.class).stream().flatMap(p -> p.getTaskHeaders().stream()), | ||
Stream.of(Task.X_OPAQUE_ID) | ||
Stream.of(Task.X_OPAQUE_ID, Task.TRACE_PARENT) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this make sure the header gets propagated to other downstream ES nodes? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Afaik this makes sure the headers go over the transport wire to other nodes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Even though it would technically render the
That is because ES is not creating spans currently and thus there's no parent. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed I personally prefer not zeroing out and treat ES as pass-through for now given this piece of information is no longer used. |
||
).collect(Collectors.toSet()); | ||
final TransportService transportService = newTransportService(settings, transport, threadPool, | ||
networkModule.getTransportInterceptor(), localNodeFactory, settingsModule.getClusterSettings(), taskHeaders); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,6 +29,7 @@ | |
import org.elasticsearch.http.HttpServerTransport; | ||
import org.elasticsearch.indices.breaker.CircuitBreakerService; | ||
import org.elasticsearch.rest.RestHandler.Route; | ||
import org.elasticsearch.tasks.Task; | ||
import org.elasticsearch.usage.UsageService; | ||
|
||
import java.io.ByteArrayOutputStream; | ||
|
@@ -344,6 +345,12 @@ private void tryAllHandlers(final RestRequest request, final RestChannel channel | |
BytesRestResponse. | ||
createSimpleErrorResponse(channel, BAD_REQUEST, "multiple values for single-valued header [" + name + "].")); | ||
return; | ||
} else if (name.equals(Task.TRACE_PARENT)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you think we could extract the whole headers copy to a separate method? |
||
String traceparent = distinctHeaderValues.get(0); | ||
if (traceparent.length() >= 55) { | ||
threadContext.putTransient(Task.TRACE_ID, traceparent.substring(3, 35)); | ||
Mpdreamz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
threadContext.putHeader(name, traceparent); | ||
} else { | ||
threadContext.putHeader(name, String.join(",", distinctHeaderValues)); | ||
} | ||
|
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 also need for TRACE_ID ?
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 don't think so as
TRACE_ID
a transient header. It's not getting in our out of a single node. It's just used for log correlation.