Skip to content

Conversation

@aknott
Copy link
Contributor

@aknott aknott commented Oct 20, 2025

Fixes #3034

I'd like to implement a custom RuntimeContextStorage and need to store some additional data in a subclass of Token. Based on previous discussions in #3034, it seemed like people were OK with making this constructor public, so I'm doing that here.

Changes

  • Moves Token constructor from private to protected
  • Makes context_ protected, so subclasses can access it.
  • Makes Token destructor virtual

For significant contributions please make sure you have completed the following items:

  • CHANGELOG.md updated for non-trivial changes
  • Unit tests have been added
  • Changes in public API reviewed

@aknott aknott requested a review from a team as a code owner October 20, 2025 23:39
@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Oct 20, 2025

CLA Signed

The committers listed above are authorized under a signed CLA.

  • ✅ login: marcalff / name: Marc Alff (e5b561c)

@marcalff marcalff added the pr:waiting-on-cla Waiting on CLA label Oct 20, 2025
@codecov
Copy link

codecov bot commented Oct 21, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.00%. Comparing base (33029bc) to head (e5b561c).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #3708      +/-   ##
==========================================
- Coverage   90.01%   90.00%   -0.01%     
==========================================
  Files         225      225              
  Lines        7105     7105              
==========================================
- Hits         6395     6394       -1     
- Misses        710      711       +1     
Files with missing lines Coverage Δ
...pi/include/opentelemetry/context/runtime_context.h 92.14% <ø> (ø)

... and 1 file with indirect coverage changes

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

@marcalff marcalff removed the pr:waiting-on-cla Waiting on CLA label Oct 21, 2025
Copy link
Member

@marcalff marcalff left a comment

Choose a reason for hiding this comment

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

LGTM, thanks for the fix.

@marcalff marcalff changed the title Make Request Context Token constructor public [API] Make Request Context Token constructor public Oct 21, 2025
@marcalff
Copy link
Member

@lalitb @ThomsonTan @esigo

Please review.

This looks good to me, but given how this touches the very core of the instrumentation API (runtime context), better be safe than sorry.

@lalitb
Copy link
Member

lalitb commented Oct 21, 2025

Not ABI-breaking, but the change looks unnecessary and could introduce design issues by increasing visibility. If additional data needs to be associated, it can be handled externally (e.g., std::unordered_map<const Token*, MyData>) or through a wrapper. Better to keep Token private and opaque.

@marcalff
Copy link
Member

Not ABI-breaking, but the change looks unnecessary and could introduce design issues by increasing visibility. If additional data needs to be associated, it can be handled externally (e.g., std::unordered_map<const Token*, MyData>) or through a wrapper. Better to keep Token private and opaque.

How would this work ?

The whole point is to inherit form Token, to trigger custom code in the destructor, invoked when the unique_ptr gets out of scope.

With a separate map, when would the map be maintained ?

@marcalff
Copy link
Member

Note that Token itself is still private and opaque, what is needed is to subclass it in a custom runtime context.

@lalitb
Copy link
Member

lalitb commented Oct 23, 2025

The whole point is to inherit form Token, to trigger custom code in the destructor, invoked when the unique_ptr gets out of scope.

Maybe I am missing something - what's the use-case of inheriting from Token.

@aknott
Copy link
Contributor Author

aknott commented Oct 23, 2025

I'm specifically trying to integrate folly::RequestContext as the underlying storage for context. Ideally this is done by attaching the folly::ShallowCopyRequestContextScopeGuard within a derived Token class. When that goes out of scope, folly::RequestContext handles restoring previous context automatically.

@Reneg973
Copy link
Contributor

At least the destructor should be virtual then.
And, if it's a custom token, the Token's == operator may not be good enough, so == may also get virtual?

@marcalff marcalff added the discuss To discuss in SIG meeting label Oct 27, 2025
@marcalff
Copy link
Member

@lalitb

Let's discuss the details in the next opentelemetry-cpp SIG meeting:

  • how to implement a custom runtime context
  • how to add custom data with a token, and retrieve it during Token destruction or ::Detach().

@lalitb
Copy link
Member

lalitb commented Oct 27, 2025

@lalitb

Let's discuss the details in the next opentelemetry-cpp SIG meeting:

  • how to implement a custom runtime context

  • how to add custom data with a token, and retrieve it during Token destruction or ::Detach().

@marcalff will try to join the meeting bit late. To summarise my concern

  • would good to be conservative in making constructs publicly visible unless not doing so breaks the basic functionality.
  • if we can't create custom storage runtime without this fix, the change is fine.
  • I am not sure if we should allow the token to be inherited, and so add custom data added. Would review the use case more thoroughly today, and reply back.

@lalitb
Copy link
Member

lalitb commented Oct 29, 2025

Can we keep

Token(const Context &context) : context_(context) {}

as protected as well ?

Copy link
Member

@lalitb lalitb left a comment

Choose a reason for hiding this comment

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

LGTM, I think there are workaround by storing guards in RuntimeContextStorage, but the change achieves better RAII pattern.

@ThomsonTan
Copy link
Contributor

Instead of making it public, is protected sufficient to make Token constructible in your subclass of Token, which then can be used in the subclass of RuntimeContextStorage? This way, we still don't expose the Token class to public.

Copy link
Member

@marcalff marcalff left a comment

Choose a reason for hiding this comment

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

Looks ok, with the following changes:

  • The constructor of Token should be protected, not public
  • The destructor of Token should be virtual

@Reneg973
Copy link
Contributor

Looks ok, with the following changes:

  • The constructor of Token should be protected, not public
  • The destructor of Token should be virtual

And, as the virtual destructor implies, the custom token may have its own state, it may also require a custom ==. Therefore

  • make operator== virtual

@marcalff
Copy link
Member

And, as the virtual destructor implies, the custom token may have its own state, it may also require a custom ==. Therefore

* make operator== virtual

@Reneg973

Thanks for the comments.

In this case, the CustomToken subclass is used to keep state that precisely is not stored into the Context, otherwise the plain Token class should be used in the first place.

The operator== is to compare with a Context, not a token in general, so I don't think this equality operator should be virtual (but it is possible I missed something).

Of course it would be better to see an actual implementation of a CustomToken and a CustomRuntimeContextStorage to grasp all what is needed here, I think what is missing the most is an example custom runtime context to validate we have all the missing pieces here, as well as show a template implementation to use, but we don't have that at the moment.

@Reneg973
Copy link
Contributor

In this case, the CustomToken subclass is used to keep state that precisely is not stored into the Context

Yes, you're right. Somehow I've overseen that it's not an equality operator. In this case the operator is a bit abused ;).
If a token 'is a' context, something like using Token = Context; would be easier

@aknott aknott requested a review from marcalff November 6, 2025 05:23
Copy link
Member

@marcalff marcalff left a comment

Choose a reason for hiding this comment

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

LGTM

@ThomsonTan ThomsonTan merged commit 4ba23ba into open-telemetry:main Nov 7, 2025
67 checks passed
malkia added a commit to malkia/opentelemetry-cpp that referenced this pull request Nov 9, 2025
[API] Make Request Context Token constructor public (open-telemetry#3708)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

discuss To discuss in SIG meeting

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RuntimeContext::Attach returns a unique_ptr to a Token, but can not use a subclass

6 participants