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

NH-24786 x-trace-options custom-* kvs, bugfix, and lots more tests #85

Merged
merged 45 commits into from
Dec 5, 2022

Conversation

tammy-baylis-swi
Copy link
Contributor

Second attempt after closing #79 without merging.

There are a few small src code changes in this PR, while the rest is adding/updating/restructuring unit and integration tests.

Code changes:

  1. custom-* KVs in extracted x-trace-options headers are written to entry spans as attributes
  2. custom-* are only ignored if there is no value, e.g. custom-key-but-no-value; (different from NH-24786 xtraceoptions custom kvs #79 which ignored if too many = signs)
  3. TriggeredTrace: true is written to entry spans as attribute if triggered-trace; is in x-trace-options.
  4. Fixes the propagator extract method so it still extracts x-trace-options-signature even if no x-trace-options header.
  5. Fixes the XTraceOptions struct so it still inits with x-trace-options-signature value even if no x-trace-options value given.

Manual test traces in this updated doc: https://swicloud.atlassian.net/wiki/spaces/NIT/pages/3294199981/2022-11-16+x-trace-options+set+custom-

Integration test changes:

  1. Renamed test_scenario_6.py to test_unsigned_tt.py.
  2. Added test_signed_tt.py.
  3. test_unsigned_tt.py and test_signed_tt.py(hopefully) test scenarios 6-12 in the Trigger Trace Request/Response Matrix, plus the basic indented cases under Handling and Response.
  4. Also updated test_scenario_8.py to test the custom-* and TriggeredTrace: true setting for when traceparent and tracestate are used for regular sampling, but any KVs in x-trace-options should still be written in entry span attributes.

Unit test changes:

  1. Update propagator and XTraceOptions unit tests to accommodate updates and bugfixes.
  2. Added a lot more Sampler unit tests! A new subdir tests/unit/test_sampler/ contains test_sampler_calculate_attributes.py which is dedicated to testing calculate_attributes, while the rest of the methods are tested in test_sampler.py.
  3. tests/unit/test_sampler/fixture/ has fixtures/mocks shared by the Sampler tests.

Does not include tests for: the Req/Resp matrix's invalid values, unexpected usage, input validation. Those are for future PRs because this one is already out of hand sorry.

Please let me know what you think! 😃 I hope my summary makes sense but this is a long one, so let me know if you'd like to huddle-review anything.

@tammy-baylis-swi tammy-baylis-swi marked this pull request as ready for review November 30, 2022 00:37
Copy link
Contributor

@cheempz cheempz left a comment

Choose a reason for hiding this comment

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

Really awesome enhancement of the integration and unit testing @tammy-baylis-swi! I look a closer look at the integration tests and just skimmed the unit tests, mainly because the integration rules hinge on the far from clear x-trace-options (aka trigger trace) specification -- which this review helped highlight (and so yes, made some more tweaks on the spec ;p).

Feel free to address the logic around setting the x-trace-options-response header in a subsequent PR.

# while value can contain more equals signs
if len(option_kv) > 1:
self.custom_kvs[option_key] = "=".join(
okv.strip() for okv in option_kv[1:]
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor curiosity: just realized in line 53 it is option_kv = option.split("=", 2) which allows splitting beyond the first equal sign. Any reason why it can't be option_kv = option.split("=", 1) which should ensure further equal signs in the option value would not be split out, so is there still the need to rejoin split items here? e.g.

a = 'custom-something=value_thing=4'
>>> a.split('=',2)
['custom-something', 'value_thing', '4']
>>> a.split('=',1)
['custom-something', 'value_thing=4']

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No reason, yes it can be simplified! Addressed in 1ee0466, which will be in another PR.

assert span_server.attributes["TriggeredTrace"] == True
assert "this-will-be-ignored" not in span_server.attributes

# Check root span tracestate has `sw` and `xtrace_options_response` keys
Copy link
Contributor

Choose a reason for hiding this comment

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

Very OCD nit: should be Check client span tracestate... instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes! Addressing in b75c652

2. Some traceparent and tracestate are injected into service's outgoing request
(done by OTel TraceContextTextMapPropagator).
3. No x-trace-options-response header is calculated because the extracted
x-trace-options does not include trigger-trace.
Copy link
Contributor

Choose a reason for hiding this comment

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

I realized the spec was quite unclear on this, so tweaked it more. But if an x-trace-options header was given, we should set an x-trace-options-response (which would indicate that "trigger trace was not requested" in this particular scenario).

Even though these x-trace-options* headers are primarily for trigger tracing, in effect they are (perhaps a bit over?)designed to be a generic way to pass "options" to influence the tracing behaviour, whether it is sampling (trigger trace) or setting specific attributes (custom-*) on a resulting trace. So request header x-trace-options should be matched with response header x-trace-options-response to tell the user what happened.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in b75c652 (in another PR)

spans = self.memory_exporter.get_finished_spans()
assert len(spans) == 0

def test_signed_missing_xtraceoptions_header(self):
Copy link
Contributor

Choose a reason for hiding this comment

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

This would be the scenario where x-trace-options-response response header should not be injected.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed in b75c652 and tested in e60aa96 (in #88)

@tammy-baylis-swi
Copy link
Contributor Author

Thanks @cheempz !

Feel free to address the logic around setting the x-trace-options-response header in a subsequent PR.

I will take you up on this offer since there are more PRs floating about anyway 😄 . Merging this one.

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

Successfully merging this pull request may close these issues.

2 participants