-
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
Conversation
String[] tokens = traceparent.split("-"); | ||
if (tokens.length == 4) { |
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.
Just as a suggestion: you could validate the length of the header. If it has the expected minimum length, use java.lang.String#substring(int, int)
with the known offsets for the trace id and parent id.
server/src/main/java/org/elasticsearch/rest/RestController.java
Outdated
Show resolved
Hide resolved
@@ -570,7 +570,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 comment
The 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 comment
The 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 comment
The reason will be displayed to describe this comment to others. Learn more.
Even though it would technically render the traceparent
header invalid, we may want to zero out the parent-id
part of the header when sending to downstream nodes.
Kibana
|
traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
|
v
ES Node1
|
traceparent: 00-0af7651916cd43dd8448eb211c80319c-0000000000000000-01
|
v
ES Node 2
That is because ES is not creating spans currently and thus there's no parent.
Based on the outcome of this discussion (#74210 (comment)), we don't need that part of the traceparent
header anyway.
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.
Removed transaction.id
.
I personally prefer not zeroing out and treat ES as pass-through for now given this piece of information is no longer used.
This makes Elasticsearch accept `traceparent` header and makes sure its available as variable in log4j. By default ECS logger includes it.
Pinging @elastic/es-core-infra (Team:Core/Infra) |
99c90de
to
e3bb235
Compare
server/src/main/java/org/elasticsearch/common/util/concurrent/ThreadContext.java
Outdated
Show resolved
Hide resolved
…ThreadContext.java Co-authored-by: Rory Hunter <pugnascotia@users.noreply.github.com>
server/src/main/java/org/elasticsearch/common/util/concurrent/ThreadContext.java
Outdated
Show resolved
Hide resolved
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.
looks good!
can we also add testing in JsonLoggerTests
?
I am not sure what is the difference for trace_parent
and trace_id
?
@@ -344,6 +345,17 @@ 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 comment
The 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?
ThreadContextStruct threadContextStruct = | ||
DEFAULT_CONTEXT.putHeaders(Map.of(Task.X_OPAQUE_ID, context.requestHeaders.get(Task.X_OPAQUE_ID))); | ||
|
||
if (context.requestHeaders.containsKey(Task.X_OPAQUE_ID) || context.requestHeaders.containsKey(Task.TRACE_PARENT)) { |
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.
…ThreadContext.java Co-authored-by: Felix Barnsteiner <felixbarny@users.noreply.github.com>
ThreadContextStruct threadContextStruct = | ||
DEFAULT_CONTEXT.putHeaders(Map.of(Task.X_OPAQUE_ID, context.requestHeaders.get(Task.X_OPAQUE_ID))); | ||
|
||
if (context.requestHeaders.containsKey(Task.X_OPAQUE_ID) || context.requestHeaders.containsKey(Task.TRACE_PARENT)) { |
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.
server/src/main/java/org/elasticsearch/rest/RestController.java
Outdated
Show resolved
Hide resolved
Will do! 😸
|
Co-authored-by: Felix Barnsteiner <felixbarny@users.noreply.github.com>
server/src/main/java/org/elasticsearch/rest/RestController.java
Outdated
Show resolved
Hide resolved
…ticsearch into Mpdreamz-feature/trace-header
@pgomulka will the |
@felixbarny the sample log line for ES8 will be
and the corresponding plain text log line emitted at the same time
This change is intended to be in v8, right? |
@pgomulka I skimmed over the diffs, looked reasonable and nothing stood out. |
IINM, @mshustov was hoping to get the @pgomulka in 8.x, will the default log format be ECS JSON for Elasticsearch? If so, I think it makes sense to do the same in Kibana. WDYT @mshustov? |
yes. I started talking to the ES team. I will open an issue a bit later.
Kibana does support ECS JSON format in v8.0, but I've never heard it's going to be the default in Elasticseasrch as of the next major release. @pgomulka Is there an appropriate issue in the Elasticsearch repo? I didn't manage to find one.
@pgomulka Kibana and Elasticsearch must align on this behavior. Is the Elasticsearch team going to attach tracing information to the Plain-test logs? |
the default will be ECS JSON format in v8.0. ES will emit .json log files (in ECS) for server, slow logs, deprecated logs. These log files contain additional 'meta data' fields like node ids, cluster names, x-opaque-id and now trace.id. The purpose of the plaintext (.log) server logs is to be human readable and it only contains the basic fields (timestamp, class, thread, message). Note that only server logs will be in plaintext. All other logs are only in json. here is an issue #46119 you should expect these logs to be generated by ESv8
@albertzaharovits do you know if we plan to have audit logs in ECS? Do we want trace.id there as well? |
This adds just enough support for the traceparent header to be useful in es8. Since Elasticsearch already logs in ECS format extending it with support for transaction.id and trace.id is a quick win. This allows us to surface server/deprecation slow logs from an instrumented application using the Trace Logs feature. Parsing `traceparent` in http layer and populating tasks with `trace_id` which is preserved in thread context.
A new trace.id header is added by elastic#74210. It is handled almost the same way as x-opaque-id. Specifically, it gets passed into default thread context. This means the existing assertion should expect it in addition to x-opaque-id.
A new trace.id header is added by #74210. It is handled almost the same way as x-opaque-id. Specifically, it gets passed into default thread context. This means the existing assertion should expect it in addition to x-opaque-id.
A new trace.id header is added by elastic#74210. It is handled almost the same way as x-opaque-id. Specifically, it gets passed into default thread context. This means the existing assertion should expect it in addition to x-opaque-id.
A new trace.id header is added by #74210. It is handled almost the same way as x-opaque-id. Specifically, it gets passed into default thread context. This means the existing assertion should expect it in addition to x-opaque-id.
since #74210 ES is emitting trace.id into its logs, but it did not emit it into audit logs. This commit adds trace.id into audit logging.
since elastic#74210 ES is emitting trace.id into its logs, but it did not emit it into audit logs. This commit adds trace.id into audit logging.
since elastic#74210 ES is emitting trace.id into its logs, but it did not emit it into audit logs. This commit adds trace.id into audit logging.
This adds just enough support for the
traceparent
header to be useful inmaster
.Since Elasticsearch already logs in ECS format extending it with support for
transaction.id
andtrace.id
is a quick win.This allows us to surface server/deprecation slow logs from an instrumented application using the
Trace Logs
feature.This forwards to Logs UI with a filter on
trace.id
The parsing of the header itself is naive. I am hoping Elasticsearch in the future can take a dependency on the Java Agent OOTB (https://github.com/elastic/apm-agent-java) which ships with high performance parsing and validation routines. Which could then act as a jumping off point to manually instrument Elasticsearch.
We can work on incrementally adding value 🥳
NOTE: this needs #74211 to prevent clashes with Filebeat/ECS defaults