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 TraceState #57

Merged
merged 9 commits into from
Jul 1, 2019
Merged

Conversation

mayurkale22
Copy link
Member

Specs: https://w3c.github.io/trace-context/#tracestate-field

Originates from #31 (comment)

This would be easier to interact with by using an actual object than can then be serialized to a string by some formatter/encoder. Of course this could be done with a getter and a corresponding _traceState private property to hold the object, but then every vendor will have to replicate this logic.

@mayurkale22 mayurkale22 added Discussion Issue or PR that needs/is extended discussion. API labels Jun 24, 2019
@mayurkale22 mayurkale22 added this to the API complete milestone Jun 24, 2019
@mayurkale22 mayurkale22 requested a review from rochdev June 24, 2019 22:42
@bg451
Copy link
Member

bg451 commented Jun 25, 2019

Are there existing use cases where a vendor checks the tracestate size and truncates kv pairs until it's under the size limit? I don't think I've seen a vendor use tracestate/baggage that way yet, but might be worth creating an issue to add that functionality.

@mayurkale22
Copy link
Member Author

Are there existing use cases where a vendor checks the tracestate size and truncates kv pairs until it's under the size limit? I don't think I've seen a vendor use tracestate/baggage that way yet, but might be worth creating an issue to add that functionality.

Good question, but I haven't heard about these use cases. I would suggest to open an issue in specification repo.

import * as types from '@opentelemetry/types';

// TODO validate maximum number of items
// const maximumTraceStateItems = 32;
Copy link
Member

Choose a reason for hiding this comment

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

Why would this be limited? What if a vendor needs more than the limit?

Copy link
Member Author

Choose a reason for hiding this comment

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

This limit is enforced by the specs, "There can be a maximum of 32 list-members in a list.".

Copy link
Member

Choose a reason for hiding this comment

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

I think it should be fine for now as 32 is somewhat high for this. It may be worth it however to start a discussion about the reasoning for the limit. Since there is already a maximum length for the whole state, it doesn't really make sense to add such an additional limit.

Copy link
Contributor

Choose a reason for hiding this comment

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

@rochdev one vendor can only have one key-value pair.
Here is an explanation of how entries are added and replaced: https://github.com/w3c/trace-context/blob/master/spec/20-http_header_format.md#relationship-between-the-headers


const maximumTraceStateLength = 512;
export interface InternalTraceState {
[key: string]: string;
Copy link
Member

Choose a reason for hiding this comment

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

Why is this limited to strings? We store other types in the trace state.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think this is easier for serialization/deserialization and this is how other languages are keeping it. What are the types do you use/prefer in the trace state?

Copy link
Member

Choose a reason for hiding this comment

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

The problem is if other types of object are stored and manipulated during the lifetime of the local trace, then conversion will constantly be needed. This is generally a concern for anywhere that accepts only string values, but in this case it may be fine since the trace state properties are usually not altered after they are set.

Copy link
Member

Choose a reason for hiding this comment

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

Actually, if this is only used at propagation time to another service, my above concern doesn't exist. This is especially true if there is a single trace state by vendor.

agg.push(`${key}=${state.get(key)}`);
return agg;
}, [])
.join(',');
Copy link
Member

Choose a reason for hiding this comment

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

This format is very difficult to work with, especially for trace states with nested objects. Why not simply rely on JSON?

Copy link
Member

Choose a reason for hiding this comment

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

Looks like this is enforced by W3C TraceContext. We should investigate how to properly support the , and = characters, and also nested objects.

Copy link
Contributor

@danielkhan danielkhan Jun 30, 2019

Choose a reason for hiding this comment

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

Value is opaque string up to 256 characters printable ASCII [[!RFC0020]] characters 
(i.e., the range 0x20 to 0x7E) except comma , and =. Note that this also excludes tabs,
newlines, carriage returns, etc.

What will go into value needs to be specified in OpenTelemetry. This is not a general purpose list for user-provided baggage.

[key: string]: string;
}

export class TraceState implements types.TraceState {
Copy link
Member

Choose a reason for hiding this comment

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

Where will this be stored? It also looks like this conflicts with DistributedContext as this is the equivalent of one of the class described in open-telemetry/opentelemetry-specification#140?

@mayurkale22
Copy link
Member Author

I think I addressed all of the comments by updating the PR and adding TODOs. PTAL

this.internalState.set(name, value);
}

serialize(): string {
Copy link
Contributor

Choose a reason for hiding this comment

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

We had talked today in the SIG about doing some kind of encoding/decoding of values. E.g. using URL encoding for the unsupported characters. Is there any kind of encoding format for this specified in the spec?

Copy link
Member

Choose a reason for hiding this comment

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

There isn't in the w3c spec nor the opentelem spec. I think as an instrumentation library we should only attempt to validate the user's input and provide a stern warning (but not exception) that the input is invalid. I wouldn't want to automatically encode the input when it goes over the wire in case they aren't using an opentelem library downstream. I feel like if the user wants to include non spec conforming data and have it accessible downstream, we can recommend using URL encoding.

Copy link
Member

Choose a reason for hiding this comment

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

This is pushing unnecessary complexity on the user. I understand if W3C don't want to enforce a specific format, but I think OpenTelemetry should standardize this.

Copy link
Member

Choose a reason for hiding this comment

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

+1 on OpenTelem standardizing on it. For what it's worth I'm not super stoked on using tracestate to propagate baggage to begin with, definitely interested in seeing how the new w3c correlation context turns out.

Copy link
Contributor

Choose a reason for hiding this comment

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

The intent of tracestate is to encode tracing system specific information and it's up to the tracing system how this is encoded. Some vendors use base64 to send some json, some simply have information like a tenant id in plain text.
At some point Opentelemetry needs to come up with what should be put in there and was there is quite some overlap between the w3c group and this project it will definitely be compliant.

The intent is NOT to make it available to the user to use it for baggage. As @bg451 said, this will be up to another spec.

Copy link
Member

Choose a reason for hiding this comment

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

With your above explanation that each vendor should have a single entry, it makes sense to not require a specific format. However, if there is a entry reserved for OpenTelemetry itself, then we should define the format of that entry.

- Give more descriptive name than `s` to variable.
- Private properties prefixed with an underscore for JavaScript users.
- Private methods prefixed with an underscore for JavaScript users.
@danielkhan
Copy link
Contributor

Are there existing use cases where a vendor checks the tracestate size and truncates kv pairs until it's under the size limit? I don't think I've seen a vendor use tracestate/baggage that way yet, but might be worth creating an issue to add that functionality.

@bg451 - the reason why this limit was added is to prevent users from abusing tracestate for baggage of arbitrary length. This is a requirement that came from cloud vendors.

This rule allows a cloud vendor to truncate tracestate back to a reasonable size if needed.

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.

I'm sure that we will have to add a bit more work - especially for dealing with limits - but this is a good start.

@mayurkale22 mayurkale22 merged commit 7b629d6 into open-telemetry:master Jul 1, 2019
@mayurkale22 mayurkale22 deleted the trace_state branch July 1, 2019 18:53
vmarchaud pushed a commit to vmarchaud/opentelemetry-js that referenced this pull request Jul 1, 2019
* Add TraceState

* Fix review comments

* Minor Fix, add TODOs

* Use Map to preserve ordering

* Add underscore for private methods & rename variable

- Give more descriptive name than `s` to variable.
- Private properties prefixed with an underscore for JavaScript users.
- Private methods prefixed with an underscore for JavaScript users.

* Remove TEST_ONLY methods

* Add comment about TraceState class

* Add unset method
@rochdev
Copy link
Member

rochdev commented Jul 2, 2019

This rule allows a cloud vendor to truncate tracestate back to a reasonable size if needed.

What happens if one vendor, or a combination of vendors, breaks the rule? Will this break the state for every vendor?

@danielkhan
Copy link
Contributor

This rule allows a cloud vendor to truncate tracestate back to a reasonable size if needed.

What happens if one vendor, or a combination of vendors, breaks the rule? Will this break the state for every vendor?

Here is the spec:

In situation when tracestate needs to be truncated due to size limitations, platform of tracing vendor MUST truncate whole entries. Entries larger than 128 characters long SHOULD be removed first. Then entries SHOULD be removed starting from the end of tracestate. Note, other truncation strategies like safe list entries, blocked list entries or size-based truncation MAY be used, but highly discouraged. Those strategies will decrease interoperability of various tracing vendors.

So the rule describes a procedure of how to deal with entries that are too long.
If this rule wouldn't be in place, the state could break for other vendors if one violates the size limits and another system just starts throwing away entries until the size requirements are met again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Discussion Issue or PR that needs/is extended discussion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants