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

Extends TextMapGetter with GetAll() method, implement usage in W3CBaggagePropagator #6852

Conversation

jamesmoessis
Copy link
Contributor

@jamesmoessis jamesmoessis commented Nov 7, 2024

Implements proposed spec changes in open-telemetry/opentelemetry-specification#433 and #6837

  • Adds getList() method to TextMapGetter, with default method
  • Changes W3CBaggagePropagator to handle multiple headers for baggage, using new getList() method.
  • Includes tests.

The vast majority of HTTP server implementation are able to return multiple header values, including the commonly used HttpServletRequest. I have published this branch to my local maven and demonstrated it's usage in the Spring Web MVC instrumentation module, which uses the HttpServletRequest interface. See here: open-telemetry/opentelemetry-java-instrumentation#12581

@jamesmoessis jamesmoessis requested a review from a team as a code owner November 7, 2024 05:33
Copy link

codecov bot commented Nov 7, 2024

Codecov Report

Attention: Patch coverage is 90.90909% with 2 lines in your changes missing coverage. Please review.

Project coverage is 90.11%. Comparing base (7829f53) to head (c95cec8).
Report is 14 commits behind head on main.

Files with missing lines Patch % Lines
.../api/baggage/propagation/W3CBaggagePropagator.java 88.88% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main    #6852      +/-   ##
============================================
- Coverage     90.23%   90.11%   -0.13%     
- Complexity     6594     6603       +9     
============================================
  Files           729      730       +1     
  Lines         19800    19850      +50     
  Branches       1947     1957      +10     
============================================
+ Hits          17867    17888      +21     
- Misses         1341     1369      +28     
- Partials        592      593       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

* @return the first value of the given propagation {@code key} as a singleton list, or returns an
* empty list.
*/
default List<String> getList(@Nullable C carrier, String key) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps using List<String> isn't the best option. Maybe Iterable<String> as used in keys or Iterator<String> would work better? When using List<String> and carrier is HttpServletRequest where getHeaders returns Enumeration you'd have to copy the enumeration to list with Collections.list(carrier.getHeaders(key)). When using Iterator<String> you could skip copying the enumeration to list with

Enumeration<String> enumeration = carrier.getHeaders(key);
return new Iterator<String>() {
  @Override
  public boolean hasNext() {
    return enumeration.hasMoreElements();
  }

  @Override
  public String next() {
    return enumeration.nextElement();
  }
};

Copy link
Contributor Author

@jamesmoessis jamesmoessis Nov 10, 2024

Choose a reason for hiding this comment

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

Yes I agree Iterator<String> is a better choice given the use of Enumeration in HttpServletRequest. I had just copied @jack-berg's implementation from #6837. Will update once we get alignment with Jack.

In terms of the name of the new method, getList also would no longer make sense. Possible names could be getIterator or getAllValues, let me know preference.

Copy link
Member

Choose a reason for hiding this comment

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

Hmm... iterator is easier / less allocation for some TextMapGetter implementations, but (slighty) worse ergonomics for callers.

Given this, I think iterator is the better choice since we expect most (all?) propagator instances to be maintained by opentelemetry, and its fine for us to have slightly more burden to improve performance.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Cool, I've changed it to Iterator. I've also renamed the method to getAll()

* @return the first value of the given propagation {@code key} as a singleton list, or returns an
* empty list.
*/
default List<String> getList(@Nullable C carrier, String key) {
Copy link
Member

Choose a reason for hiding this comment

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

It might be necessary for us to add this in an experimental fashion, rather than jumping straight to the stable API.

For example, we could have an ExtendedTextMapGetter interface in opentelemetry-api-incubator or in an internal package of opentelemetry-context. Then, W3CBaggagePropagator could check if (getter instanceOf ExtendedTextMapGetter) and adjust its behavior accordingly.

If we do this, I think it would have to go in opentelemetry-context instead of opentelemetry-api-incubator since W3CBaggagePropagator doesn't have access to opentelemetry-api-incubator.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes sense to me

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, this is done - please take a look

@jamesmoessis jamesmoessis force-pushed the propagator-extract-multiple-headers branch from b3f4af6 to 6f13bfb Compare November 15, 2024 03:13
Copy link
Member

@jack-berg jack-berg left a comment

Choose a reason for hiding this comment

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

I think this looks great.

@jamesmoessis jamesmoessis changed the title Add optional method getList() to TextMapGetter, implement usage in W3CBaggagePropagator Extends TextMapGetter with GetAll() method, implement usage in W3CBaggagePropagator Nov 18, 2024
…using new getList() method on the TextMapGetter. Includes tests.
…etter, as per review.

Also changes the return type of the method to Iterator<String> as per review, and renames the method to getAll(). Tests are also adjusted
…context.internal.propagation package into context.propagation.internal package
@jamesmoessis jamesmoessis force-pushed the propagator-extract-multiple-headers branch from 3cd5429 to 28c8491 Compare November 26, 2024 00:19
@jamesmoessis
Copy link
Contributor Author

@jack-berg FYI - just made some slight changes. I realised I needed to check for get() returning null in the default getAll otherwise it returns an iterator of Iterator.of(null) instead of an empty iterator.

I've also added tests to verify this behaviour, and a couple more baggage tests (the build was complaining the coverage wasn't quite there, so I covered the remanining lines)

jack-berg added a commit to open-telemetry/opentelemetry-specification that referenced this pull request Nov 28, 2024
…ey (#4295)

Fixes #433

Discussed in 11/5/24 Spec SIG, and prototyped in Java and Go.

## Changes

Adds `GetAll` method to Getter, allowing for the retrieval of multiple
keys for the same value. For example, an HTTP request may have multiple
`baggage` headers.

As written in the changes, the implementation of `GetAll` is strictly
optional. This is for two reasons:
1. Backwards compatibility with existing types/interfaces
2. Carriers do not necessarily support returning multiple values for a
single key

## Links to Prototypes

This includes implementations of `GetAll()` in Java and Go, as well as
using the method in the W3C Baggage Propagators (multiple baggage
headers are allowed, [spec
reference](https://www.w3.org/TR/baggage/#baggage-http-header-format)).

- Java: open-telemetry/opentelemetry-java#6852
- Go: open-telemetry/opentelemetry-go#5973

* [x] Links to the prototypes (when adding or changing features)
* [x]
[`CHANGELOG.md`](https://github.com/open-telemetry/opentelemetry-specification/blob/main/CHANGELOG.md)
file updated for non-trivial changes

---------

Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
Co-authored-by: jack-berg <34418638+jack-berg@users.noreply.github.com>
Co-authored-by: Robert Pająk <pellared@hotmail.com>
Copy link
Member

@jack-berg jack-berg left a comment

Choose a reason for hiding this comment

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

Two additional minor comments. Will get this in before Friday's 1.45.0 release.

@jack-berg jack-berg merged commit b07dab3 into open-telemetry:main Dec 5, 2024
25 checks passed
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.

3 participants