Skip to content

[WIP] Context API - #99

Closed
satac2 wants to merge 37 commits into
open-telemetry:masterfrom
satac2:context_api
Closed

satac2 wants to merge 37 commits into
open-telemetry:masterfrom
satac2:context_api

Conversation

@satac2

@satac2 satac2 commented Jun 8, 2020

Copy link
Copy Markdown
Contributor

If you could take a look at the class declarations and see if I am on the right track for the context api, that would be great, thanks.

@linux-foundation-easycla

linux-foundation-easycla Bot commented Jun 8, 2020

Copy link
Copy Markdown

CLA Check
The committers are authorized under a signed CLA.

Comment thread api/include/opentelemetry/context/context.h Outdated
/* Context: contructor, creates a context object from a map
* of keys and identifiers
*/
Context(std::map<std::string, int> ctx);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All the public APIs need to be ABI compatible - which means they are not supposed to expose dependency on STL traits/layout.

Comment thread api/include/opentelemetry/context/context.h Outdated
Comment thread api/include/opentelemetry/context/context.h Outdated
@reyang reyang changed the title Context api [WIP] @reyang [WIP] Context API Jun 8, 2020
@reyang

reyang commented Jun 8, 2020

Copy link
Copy Markdown
Member

Welcome to your first PR @satac2, please clear the CLA steps as required by the CI / CNCF.


context_id_mutex.lock();

Context::last_key_identifier_++;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Instead of maintaining a counter and introducing a contention, consider using the address of the underlying object to uniquely identify the key.

Context(std::map<int,int> ctx_map){
ctx_map_ = ctx_map;
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Need to format the code.

/* Contructor, creates a context object from a map
* of keys and identifiers
*/
Context(ContextKey key, int value){

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This ctor would only take 1 key-value pair?

/* Accepts a new key/value pair and then returns a new
* context that contains both the original pairs and the new pair.
*/
Context WriteValue(ContextKey key, int value){

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I guess the value should a nostd::variant type instead of an int?

}

/* A constructor that will set the context as the passed in context. */
RuntimeContext(Context &context){

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

According to the spec these will be global/static function so no ctor needed here?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

My current thinking:

  • Provide RuntimeContext as an interface, providing static methods for Attach/Detach/GetCurrent.
  • Implement ThreadLocalContext, providing biding for TLS (thread local storage).
  • By default the static methods from RuntimeContext will use ThreadLocalContext, and there is a way for the user to implement/specify their own context binding.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'm a little confused what you mean by this, should the ThreadLocalContext be a derived class of RuntimeContext?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm a little confused what you mean by this, should the ThreadLocalContext be a derived class of RuntimeContext?

Yes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

How would it be different than RuntimeContext, should the RuntimeContext just have a static context and the ThreadLocal have a static thread_local context?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think RuntimeContext is the abstraction layer (which doesn't have understanding about TLS).

/* Constructs a new ContextKey with the passed in name and
* identifier.
*/
ContextKey(std::string key_name, int identifier){

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We don't use std::string , only nostd::string_view in API

/* Consructs a new ContextKey with the passed in name and increments
* the identifier then assigns it to be the key's identifier.
*/
ContextKey(std::string key_name){

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please use nostd::string_view

* user to the context map. The identifier is used as a key
* to the context map.
*/
class ContextKey{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I'd suggest to use this class as a foundation for key-value iterable:
https://github.com/open-telemetry/opentelemetry-cpp/blob/master/api/include/opentelemetry/trace/key_value_iterable.h

You can entirely avoid using std::map in API. We do not require std::map


private:

static thread_local Context context_;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not 100% sure this static would always work in certain DLL loading scenarios, where two different DLLs consume OT API surface, esp. lazy loading / delay-loading. May want to spell out the limitations somewhere in the class documentation..

https://devblogs.microsoft.com/oldnewthing/20101122-00/?p=12233

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Agreed. Rather use this singleton style (adding thread_local). That's what we use here.


std::mutex context_id_mutex;

/*The context class provides a context identifier */

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please use // style comments and add a full stop. :)

/* Consructs a new ContextKey with the passed in name and increments
* the identifier then assigns it to be the key's identifier.
*/
ContextKey(std::string key_name){

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please mark this constructor explicit.

Comment thread api/test/context/BUILD Outdated
cc_test(
name = "runtimeContext_test",
srcs = [
"runtimeContext_test.cc",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please use lowercase + underscores, i.e. runtime_context_test (also on L15) to be consistent with the rest of the files.

Comment thread api/test/context/BUILD Outdated
srcs = [
"runtimeContext_test.cc",
],
copts = ["-Wall","-std=c++17"],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please remove these copts.

@g-easy

g-easy commented Jun 11, 2020

Copy link
Copy Markdown
Contributor

More general context questions:

  1. Should the actual TLS part be a pointer, and allocate the per-thread context when it's accessed by Attach/GetCurrent?

  2. However we end up resolving the std::map question: how can we attach/detach faster than doing a full copy of the map?

@reyang

reyang commented Jun 11, 2020

Copy link
Copy Markdown
Member
  1. However we end up resolving the std::map question: how can we attach/detach faster than doing a full copy of the map?

https://www.python.org/dev/peps/pep-0550/#implementation 😄

@g-easy

g-easy commented Jun 11, 2020

Copy link
Copy Markdown
Contributor

And refcount the context objects that form chains?

@g-easy

g-easy commented Jun 12, 2020

Copy link
Copy Markdown
Contributor

Can we have a no-op Context API and move the implementation into the SDK, so that other SDKs can make different performance tradeoffs in how this is implemented?

@reyang

reyang commented Jun 12, 2020

Copy link
Copy Markdown
Member

Can we have a no-op Context API and move the implementation into the SDK, so that other SDKs can make different performance trade-offs in how this is implemented?

Probably not, the OpenTelemetry API package has to give a default implementation that flows the incoming traceid/spanid/tracestate/flags to the outgoing request, thus the actual implementation cannot be in the SDK.
However we need to make sure that other SDKs / components can replace the context implementation.

@satac2 satac2 closed this Jul 6, 2020
GerHobbelt pushed a commit to GerHobbelt/opentelemetry-cpp that referenced this pull request Jun 17, 2025
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