Skip to content

Conversation

sfc-gh-sili
Copy link
Contributor

@sfc-gh-sili sfc-gh-sili commented Jul 23, 2025

Description

This PR provides a solution to propagate context values across batching. This is particularly useful in scenarios where context carries important metadata—such as authentication tokens.

New API

A new API has been added to support this functionality:

mergeCtx func(ctx1 context.Context, ctx2 context.Context) context.Context

By supplying a custom mergeCtx function, users can control how context values are preserved or combined—for example, by selectively copying specific keys, merging metadata, or keeping the larger value.

Note: context.Context returned from the above function should not override Value() function.

Default Behavior
If mergeCtx is not provided (i.e., left as nil), the batching system defaults to a conservative behavior: no context values are retained from the original incoming contexts. Users who need context propagation must explicitly opt in by defining and supplying a mergeCtx function.

Link to tracking issue

#13320

Testing

  • batch_context_test.go checks the mergeCtx does not interfere with span link
  • partition_batcher_test.go checks mergeCtx=nil works properly

Documentation

Copy link

codecov bot commented Jul 23, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.50%. Comparing base (6716056) to head (ea7d236).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #13460      +/-   ##
==========================================
- Coverage   92.52%   92.50%   -0.03%     
==========================================
  Files         630      630              
  Lines       35535    35542       +7     
==========================================
- Hits        32878    32877       -1     
- Misses       2113     2119       +6     
- Partials      544      546       +2     

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@sfc-gh-sili sfc-gh-sili marked this pull request as ready for review July 23, 2025 01:25
@sfc-gh-sili sfc-gh-sili requested review from a team, bogdandrutu and dmitryax as code owners July 23, 2025 01:25
@sfc-gh-sili sfc-gh-sili changed the title [exporterhelper][queuebatcher] Context value propagation during batching - approach #2 - Draft [exporterhelper][queuebatcher] Context value propagation during batching - approach #2 Jul 23, 2025
Copy link
Contributor

@jmacd jmacd left a comment

Choose a reason for hiding this comment

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

This appears to be a good low-level interface allowing future customization. Would you develop this feature into an extension interface, or a configurable feature in the exporterhelper settings, somehow?

In the scenario I remember wanting this feature, we would copy all the partition metadata key:values as context keys for the batch. Maybe that's overly simple, but I would expect users to get something in a .yaml they can configure to make an access token both the partition key and an export key (the way include_metadata does for receivers).

@github-actions github-actions bot requested a review from bogdandrutu July 24, 2025 00:48
@sfc-gh-sili
Copy link
Contributor Author

sfc-gh-sili commented Jul 24, 2025

@jmacd

Would you develop this feature into an extension interface, or a configurable feature in the exporterhelper settings, somehow?

Thanks! I’ve just updated the PR so that mergeCtx is now exposed as queue_batch.Settings.MergeCtx and configurable for users. IIUC, queue_batch.Settings will be exposed with exporterhelper, so I am hoping that this approach will the most common use case.
I’m not too familiar with extension interfaces, but I am happy to hear your perspective if you think extension interface seems a good fit.

@sfc-gh-sili sfc-gh-sili requested a review from jmacd July 24, 2025 20:17
Copy link
Contributor

@jmacd jmacd left a comment

Choose a reason for hiding this comment

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

This looks good. It would help me understand this a bit more to work through an example. I believe we are aiming to complete the replacement of batchprocessor implied by #8122, and it means implementing the metadata_keys feature one way or another. I see that this PR is half of what we need. I think I want to see an option in the config that replaces metadata_keys, basically.

The reason I mention extension interfaces (see also #13263), is that probably metadata_keys functionality can be implemented as a "PartitionerExtension", it would have the legacy configuration from the batch processor https://github.com/open-telemetry/opentelemetry-collector/blob/main/processor/batchprocessor/README.md#batching-and-client-metadata and be configured as in

extensions:
  batchpartitioner:
    metadata_keys:
    - tenant_id
    metadata_cardinality_limit: 10

and in the exporter batcher:

exporters:
  otlp:
    sending_queue:
      batch:
        // ...
        partitioner: batchpartitioner # refers to extension

In the exporterhelper setup code, you'll inspect for a partitioner setting and probe the Host for the extension. The extension will provide a MergeCtx interface.

ItemsSizer request.Sizer[T]
BytesSizer request.Sizer[T]
Partitioner Partitioner[T]
MergeCtx func(context.Context, context.Context) context.Context
Copy link
Contributor

Choose a reason for hiding this comment

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

Interesting -- I agree this is a good place for programmable configuration. I expect there is a default implementation that mostly just works for most exporters.

Copy link
Contributor Author

@sfc-gh-sili sfc-gh-sili Jul 25, 2025

Choose a reason for hiding this comment

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

I am leaning towards the most conservative default behavior — dropping everything — which also aligns with the current behavior. I’d love to hear your thoughts on this.

Copy link
Contributor

Choose a reason for hiding this comment

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

OK. I assume that without the batcher, context otherwise passes through the exporterhelper path so that extensions like https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/headerssetterextension work.

@sfc-gh-sili sfc-gh-sili requested a review from jmacd July 24, 2025 20:55
@sfc-gh-sili
Copy link
Contributor Author

@jmacd Thanks for the input — this helps clarify a lot of things. I do think there’s still more to figure out around how to expose both partitionKey and MergeContext, especially since their APIs probably should belong in the same layer. Just to share some of the reasoning that led to the current shape:

When I designed the partitioning and merge context, I started with the assumption that users might want to pull arbitrary data out of the pdata or context — not just metadata. Under this assumption,MergeContext becomes difficult to expresse in YAML and is much more flexible to define in code, either in exporterhelper.settings or like you suggested in extensions. However, on the partitioning side, using extensions interface might be limiting since (unless I’m mistaken) extensions don’t have access to pdata. That makes exporterhelper.settings the most natural fit for now, allowing flexible definition for both MergeContext and partitionKey.

Of course, this is all based on the assumption that users will want to work with more than just metadata. From use cases I’ve seen, the assumptions holds true, as people are interested in:

  1. Using pdata resource attribute fields as partition key during partitioning
  2. Reading timestamp written into the context by a processor
  3. Reading database ID also written into the context by a processor (extracted from pdata).

So I am yet not confident that metadata is unique enough to be the default behavior. That said, you likely have more insight into these patterns, so if you have suggestions for a better approach, I’m open to hearing them.

@sfc-gh-sili sfc-gh-sili force-pushed the sili-partition-2 branch 4 times, most recently from 244c305 to 0b80e40 Compare August 5, 2025 23:30
qb.currentBatch.done = append(qb.currentBatch.done, done)
qb.currentBatch.ctx = contextWithMergedLinks(qb.currentBatch.ctx, ctx)

mergedCtx := context.Background()
Copy link
Contributor

Choose a reason for hiding this comment

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

Can't understand the check failure. 👎

ItemsSizer request.Sizer[T]
BytesSizer request.Sizer[T]
Partitioner Partitioner[T]
MergeCtx func(context.Context, context.Context) context.Context
Copy link
Contributor

Choose a reason for hiding this comment

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

OK. I assume that without the batcher, context otherwise passes through the exporterhelper path so that extensions like https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/extension/headerssetterextension work.

@dmitryax
Copy link
Member

dmitryax commented Aug 6, 2025

LGTM @sfc-gh-sili please resolve the CI failures

@sfc-gh-sili sfc-gh-sili changed the title [exporterhelper][queuebatcher] Context value propagation during batching - approach #2 [HOLD][exporterhelper][queuebatcher] Context value propagation during batching - approach #2 Aug 6, 2025
@sfc-gh-sili sfc-gh-sili force-pushed the sili-partition-2 branch 4 times, most recently from c8ead13 to e754f81 Compare August 8, 2025 22:29
@sfc-gh-sili sfc-gh-sili changed the title [HOLD][exporterhelper][queuebatcher] Context value propagation during batching - approach #2 [exporterhelper][queuebatcher] Context value propagation during batching - approach #2 Aug 9, 2025
@sfc-gh-sili
Copy link
Contributor Author

sfc-gh-sili commented Aug 9, 2025

After some offline discussions, I propose we aim at providing the following in OTLP exporter

  1. Support specifying partition key as a list of metadata keys
  2. By default, always preserve metadata that were used as part of the partition key in context
  3. For metadata that were not used as part of the partition key, provide a yaml interface similar to what is described in [exporter][queuebatch] Support merging and splitting context with batching #13320

All these features should be configurable with a yaml file so OTLP exporter can be used out-of-the-box. In alignment with this goal, we will make a couple of adjustments to the programmatic API

  1. MergeCtx() (this PR)
  2. Remove ctx from MergeSplit API, so it's explicit MergeCtx and MergeSplit handles context and request data respectively.
  3. Update Partitioner API so it would support using any data type as paritition key. (Currently only supports string type).

Thanks @jmacd and @bogdandrutu for the great input!

@dmitryax dmitryax added this pull request to the merge queue Aug 11, 2025
Merged via the queue into open-telemetry:main with commit c0b49d4 Aug 11, 2025
57 checks passed
@lahsivjar
Copy link
Member

@sfc-gh-sili Shouldn't MergeCtx be exposed in QueueBatchSettings?

@lahsivjar
Copy link
Member

@sfc-gh-sili I have created #13742 PR to expose the MergeCtx to be used with exporterhelper's options. PTAL whenever you have time.

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.

5 participants