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

Add response headers #365

Merged
merged 13 commits into from
Mar 25, 2020
Merged

Conversation

dyladan
Copy link
Member

@dyladan dyladan commented Dec 3, 2019

spec/21-http_response_header_format.md Outdated Show resolved Hide resolved
spec/21-http_response_header_format.md Outdated Show resolved Hide resolved
spec/21-http_response_header_format.md Show resolved Hide resolved
@dyladan dyladan mentioned this pull request Dec 17, 2019

* `version`
* `trace-id`
* `parent-id`

Choose a reason for hiding this comment

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

I think using "parent" in a response is rather confusing. Is it referring to the span that initiated the request (and is likely receiving the response), or the span that is sending the response?

Depending on the answer, it should probably be renamed to something else.

Copy link
Member Author

Choose a reason for hiding this comment

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

It is actually neither. The motivational use case for this was the web browser initial page load. The page load happens before the instrumentation js is loaded, so the initial request is sent without a traceparent header. The first instrumented service can then create a "fake" span which it assigns to be it's parent and returns the id of the fake span to the client. The client then uses that id when it creates the span for the page load. So it is the id that is actually assigned to the parent span, making parent-id a decent name IMO.

Copy link

Choose a reason for hiding this comment

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

I just wanted to chime in that we use response headers at SolarWinds (historically based on X-Trace headers used in Tracelytics, TraceView, and now AppOptics), and our response header includes a trace ID and event ID from the span that wrote the response in the header. So for us "parent" may not strictly be true (it's actually the child), but we can work with any name.

Copy link

Choose a reason for hiding this comment

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

Basically, for us, the response header communicates a happened-before relationship between the end of the responding span and the end of the caller span, and also confirms the successful communication of the callee's response, as well as the caller's trace ID, between caller and callee.

Copy link
Member

Choose a reason for hiding this comment

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

@cce I think you're describing a substantially different use case.

  • "parent" makes sense to communicate back to the browser the ID it should use for its span (because for some reason it could not have created that ID before sending the request to the server)
  • @cce's case is to communicate back the server-side event ID

Choose a reason for hiding this comment

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

parent doesnt make sense. parent passed to a server is the parent of the server span. the span id generated is more often the child of the caller. returning something named parent in the response is confusing and not intuitive. focusing on what you know. ex the span id that serviced the request, is more sensible if this is included at all.

also bear in mind response header processing at all cant be mandatory. this isnt mentioned explicitly. if you do decide to do this it is making this not implementable without significant rewrites of code.

Copy link
Member Author

@dyladan dyladan Feb 11, 2020

Choose a reason for hiding this comment

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

@adriancole @cce I think the issue may be that the name of the field does not fully convey it's intended semantic. Given the situation where service foo calls service bar, if bar returns a parent-id to foo, it is not saying "this is my span id", but rather "this is the span ID that you, my parent, should use."

The motivating use case is a situation like a browser where the initial request may not contain a span id, but the called service needs to use some id as its "parent," so it generates its own id but also generates an id that it uses as its parent. This parent id is then sent back up the wire to the calling service so that it can either use that id as its own span id, or it can at least link that id to its span.

Would changing the field name to something like suggested-parent-id, assumed-parent-id, requested-span-id or similar be more useful in conveying this semantic?

Copy link
Member Author

Choose a reason for hiding this comment

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

Here is a more visual explanation of the use case:

image

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 rename this to proposed-parent-id (it's not like this string is sent over the wire, a longer name does not hurt).

I would also prefer that the spec clearly states that in case of the caller already providing well-formed traceparent header, the proposed-parent-id should be omitted.

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Member

@justinfoote justinfoote left a comment

Choose a reason for hiding this comment

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

Overall, I love this PR. It matches what we discussed in Seattle, it has some great examples, it has good parity with the request header spec, and I love that you went back and updated the request header spec to add the word request.

I added some minor formatting comments, which you can take or leave.

Thanks for doing the legwork on this one, Dan!

spec/21-http_response_header_format.md Outdated Show resolved Hide resolved
spec/21-http_response_header_format.md Outdated Show resolved Hide resolved
spec/21-http_response_header_format.md Outdated Show resolved Hide resolved
spec/21-http_response_header_format.md Outdated Show resolved Hide resolved
The following `version-format` definition is used for version `00`.

``` abnf
version-format = [trace-id] "-" [parent-id] "-" [trace-flags]
Copy link
Member

Choose a reason for hiding this comment

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

Making fields optional while keeping the same format as traceparent carry potential issues. Some may decide to use the same optionality for traceparent (even though it's not allowed by spec) and break interoperability. Mostly because the same code may be used to parse and generate both headers.

This said, it will be great to confirm that all the scenario listed below in this proposal:

  1. Would actually significantly benefit from fields optionality.
  2. Define a clear logic on how to decide which parts to return.
  3. Would not need more properties than listed in traceresponse and will ACTUALLY need the arbitrary tracestate on response instead.

@codefromthecrypt
Copy link

codefromthecrypt commented Feb 12, 2020 via email

Copy link
Contributor

@danielkhan danielkhan left a comment

Choose a reason for hiding this comment

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

Great work @dyladan!

``` abnf
version-format = [trace-id] "-" [proposed-parent-id] "-" [trace-flags]
trace-id = 32HEXDIGLC ; 16 bytes array identifier. All zeroes forbidden
proposed-parent-id = 16HEXDIGLC ; 8 bytes array identifier. All zeroes forbidden
Copy link
Member

Choose a reason for hiding this comment

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

nit: may want to fix whitespace/alignment


#### proposed-parent-id

This is the ID of the calling request as known by the callee (in some tracing systems, this is known as the `span-id`, where a `span` is the execution of a client request). It is represented as an 8-byte array, for example, `00f067aa0ba902b7`. All bytes as zero (`0000000000000000`) is considered an invalid value.
Copy link
Member

@yurishkuro yurishkuro Mar 25, 2020

Choose a reason for hiding this comment

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

Suggested change
This is the ID of the calling request as known by the callee (in some tracing systems, this is known as the `span-id`, where a `span` is the execution of a client request). It is represented as an 8-byte array, for example, `00f067aa0ba902b7`. All bytes as zero (`0000000000000000`) is considered an invalid value.
This is the ID of the calling request proposed by the callee back to the caller in cases when the caller did not send the `traceparent` header (in some tracing systems, this ID is known as the `span-id`, where a `span` is the execution of a client request). It is represented as an 8-byte array, for example, `00f067aa0ba902b7`. All bytes as zero (`0000000000000000`) is considered an invalid value.

@yurishkuro
Copy link
Member

Extra use case: when server creates a different trace (e.g. a cloud service), it may want to return its trace ID to allow the client to correlate with it.

@danielkhan danielkhan merged commit 4db5ee1 into w3c:master Mar 25, 2020
@yurishkuro
Copy link
Member

Merged as the current proposal. Open issues:

  • how to represent two distinct use cases: reporting server's trace/span ID vs. proposing span ID for the client
  • how to deal with optionality, especially given different use cases (maybe use dictionary)

@codefromthecrypt
Copy link

codefromthecrypt commented Mar 25, 2020

@yurishkuro let me get this right. you are literally going to expect people to speculatively generate parent IDs when creating a root span, which effectively means root spans won't have a null parent anymore? Then, add some middleware to push this back (more overhead), also speculatively as there's no way to know if the caller actually would use it. you are ok doing this without clearing this with with basically all OSS implementations except Otel which expect a root span to have no parent?

@dyladan
Copy link
Member Author

dyladan commented Mar 26, 2020

@adriancole the working group decided on the call to merge this as a starting place today. In no way is it meant to be considered final and nothing is unchangeable. Also, note that the response header is an entirely optional part of the trace. If there is some material change you'd like to see feel free to join the call tomorrow or Friday (not sure what timezone you're in but the call is 2PM-5PM US East), file an issue, or open a PR.

@dyladan dyladan deleted the add-response-headers branch March 26, 2020 00:05
@codefromthecrypt
Copy link

@dyladan I raised protest to this before you merged it and you merged it anyway without answering to that. what good would raising an issue be if you will just merge things anyway?

#365 (comment)

@yurishkuro
Copy link
Member

expect people to speculatively generate parent IDs when creating a root span, which effectively means root spans won't have a null parent anymore

I expect this to be at minimum configurable in the SDK, and perhaps even triggered by something in the request. It's an odd use case with which I don't have any experience.

@codefromthecrypt
Copy link

In attempts to give a constructive way out, as this was merged IMHO by mistake.

Revert all text about proposed-parent-id, then re-introduce a PR with it, or better yet keep out until better studied and far more distinct stakeholders have a use case to pay for its complexity.

In normal OSS, you reduce change to what can be merged, and strip out stuff that isn't ready to be merged. That can work here, also even if retroactively.

@codefromthecrypt
Copy link

I also opened this, as I was surprised to find tracestate is a rare thing we are required to not allow unless accompanied by traceparent #401

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants