Skip to content

Add content type to additional data spans#388

Merged
shashank11p merged 5 commits intomainfrom
addContentTypeToAdditionalDataSpans
Oct 17, 2023
Merged

Add content type to additional data spans#388
shashank11p merged 5 commits intomainfrom
addContentTypeToAdditionalDataSpans

Conversation

@shashank11p
Copy link
Copy Markdown
Contributor

In case of capturing request/response bodies in additional data spans, we only have the body. Also adding the content type header in those spans along with body.

@shashank11p
Copy link
Copy Markdown
Contributor Author

Have manually tested this change as well.

// Also add content type if present
if (span.getClass().getName().equals("io.opentelemetry.sdk.trace.SdkSpan")) {
try {
Method getAttribute =
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Needed to use reflection because this part of code will be running in the application class loader. And that will not have the sdk libraries which has this SdkSpan class.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Can we store content type in context along with parent span? Rather than retrieving with reflection from span.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We can but we will need that change in all the framework instrumentations that we want to support. This was a one place change for this for all parent frameworks

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What method is this instrumentation on?

Also how many framework instrumentation points do we support streaming bodies for?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

What method is this instrumentation on?

This is instrumented on the read method in java.io.InputStream

Also how many framework instrumentation points do we support streaming bodies for?

We have 4 client instrumentations and all support streaming.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ok, my concern is with overhead, will let you take call on which approach to go. If we go with reflection, should we at least cache the Method object because that wouldn't change, will it? If that's not an expensive operation then nvm.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, added the method to static block during instantiation. Will be called only once.

SpanBuilder spanBuilder =
TRACER
.spanBuilder(HypertraceSemanticAttributes.ADDITIONAL_DATA_SPAN_NAME)
.setParent(Context.root().with(span))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Why is this Context.root() instead of Context.current()?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Because if the span has ended, then the current may not actually be the parent of this additional-data.
It could be inside the scope of another span, but we want this additional-data with response body to be present under the span which we are passing down from the VirtualStore

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Which span has ended?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

So if we had a root span -> parent span (which has the inputstream).
Now, the parent span is ended, but the inputstream.read() is not yet called, but the inputstream is passed down, and another span is created, and then the input stream is read. Then the current span where input stream is read is not the actual span under which we want to create the additional data span. So that may the reason. We would want it like:

root span:
  parent span(ended):
    additional span:
  new span(calls inputstream.read()):

I wasn't involved when this code was written, so I'm also trying to think and justify this.

SpanBuilder spanBuilder =
TRACER
.spanBuilder(HypertraceSemanticAttributes.ADDITIONAL_DATA_SPAN_NAME)
.setParent(Context.root().with(span))
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Which span has ended?

// Also add content type if present
if (span.getClass().getName().equals("io.opentelemetry.sdk.trace.SdkSpan")) {
try {
Method getAttribute =
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Ok, my concern is with overhead, will let you take call on which approach to go. If we go with reflection, should we at least cache the Method object because that wouldn't change, will it? If that's not an expensive operation then nvm.

@shashank11p shashank11p merged commit ce9ed38 into main Oct 17, 2023
@shashank11p shashank11p deleted the addContentTypeToAdditionalDataSpans branch October 17, 2023 18:27
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.

2 participants