Skip to content
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

Updating Trace Context headers implementation #1024

Merged
merged 21 commits into from
Feb 14, 2020

Conversation

eyalkoren
Copy link
Contributor

@eyalkoren eyalkoren commented Feb 6, 2020

What does this PR do?

Implementing

Implementing elastic/apm#71. Since this logic touches LOTs of plugins for both server and client sides of the tracing, it starts with a refactor that adds new APIs so that all plugins are indifferent to the logic of headers additions/reads/removal.

Checklist

  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Author's Checklist

Related issues

Closes #923

Use cases

Screenshots

@eyalkoren eyalkoren requested a review from felixbarny February 6, 2020 09:34
}
byte[] buffer = headerSetter.getFixedLengthByteArray(TRACE_PARENT_BINARY_HEADER_NAME, BINARY_FORMAT_EXPECTED_LENGTH);
if (buffer == null || buffer.length != BINARY_FORMAT_EXPECTED_LENGTH) {
logger.warn("Header setter {} failed to provide a byte buffer with the proper length. Allocating a buffer for each header.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a chance that this will be logged very frequently. Do any of the existing implementations return null?

Copy link
Contributor Author

@eyalkoren eyalkoren Feb 9, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a single implementation (Kafka) that returns null if the current assumption (of same thread setting and serializing the headers) becomes invalid. If and when that happens, I don't mind the first user encountering it will get lots of errors. I made it so that distributed tracing will continue to work, but will start allocating more than before, so it can be easily overlooked if not logged clearly.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codecov-io
Copy link

Codecov Report

❗ No coverage uploaded for pull request base (master@83d5248). Click here to learn what that means.
The diff coverage is 58.62%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master    #1024   +/-   ##
=========================================
  Coverage          ?   61.69%           
  Complexity        ?       85           
=========================================
  Files             ?      288           
  Lines             ?    11298           
  Branches          ?     1499           
=========================================
  Hits              ?     6970           
  Misses            ?     3881           
  Partials          ?      447
Impacted Files Coverage Δ Complexity Δ
...va/co/elastic/apm/agent/impl/ElasticApmTracer.java 68.75% <ø> (ø) 0 <0> (?)
...java/co/elastic/apm/agent/bci/ElasticApmAgent.java 72.72% <75%> (ø) 0 <0> (?)
...astic/apm/agent/jdbc/StatementInstrumentation.java 30.14% <8.69%> (ø) 0 <0> (?)
...client/AbstractAsyncHttpClientInstrumentation.java 44.26% <87.5%> (ø) 0 <0> (?)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 83d5248...2bf09df. Read the comment docs.

Improvements
- MethodHandles are not @nullable
- Both getFirstHeader and getAllHeaders method handles are used in HeadersExtractorBridge
Allows for internal iteration which can be more efficient
- No forced Iterator allocations
- No conversion from Header to String/byte[] necessary
- Consumer is stateless and can be re-used, due to state method argument
Copy link
Member

@felixbarny felixbarny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made some suggestions in eyalkoren#1

See also the messages of the individual commits.

@robgil
Copy link

robgil commented Feb 9, 2020

Codecov Report

Merging #1024 into master will not change coverage by %.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff            @@
##             master    #1024   +/-   ##
=========================================
  Coverage     62.30%   62.30%           
  Complexity       85       85           
=========================================
  Files           290      290           
  Lines         11375    11375           
  Branches       1514     1514           
=========================================
  Hits           7087     7087           
  Misses         3840     3840           
  Partials        448      448           

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update d724774...c284fc4. Read the comment docs.

@eyalkoren eyalkoren changed the title [WIP] Updating Trace Context headers implementation Updating Trace Context headers implementation Feb 10, 2020
@eyalkoren eyalkoren requested a review from felixbarny February 10, 2020 04:56
}
byte[] buffer = headerSetter.getFixedLengthByteArray(TRACE_PARENT_BINARY_HEADER_NAME, BINARY_FORMAT_EXPECTED_LENGTH);
if (buffer == null || buffer.length != BINARY_FORMAT_EXPECTED_LENGTH) {
logger.warn("Header setter {} failed to provide a byte buffer with the proper length. Allocating a buffer for each header.",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


private HeadersExtractorBridge() {
public static Extractor of(@Nullable Object headerExtractor, Object headersExtractor) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not work, unfortunately. There can be multiple implementations passed to the API. Even for the same technology, the headerExtractor will be specific to a particular instance of a request object.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course 🤦‍♂
I can make it ThreadLocal, or cache per extractor. Since it's our API implementation, I want to make sure it is in accordance to the rest of the stuff we do

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's just allocate in this case. There will be allocations anyway for a capturing lambda (like request::getHeaders) and the header iterator. Allocations are fine and inevitable in the public API.

@felixbarny felixbarny merged commit 9528d35 into elastic:master Feb 14, 2020
@eyalkoren eyalkoren deleted the tracestate-implementation branch August 3, 2020 13:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support tracecontext header
4 participants