-
Notifications
You must be signed in to change notification settings - Fork 545
Runtime and threadlocal context #209
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
Merged
reyang
merged 41 commits into
open-telemetry:master
from
satac2:runtime_and_threadlocal_context
Jul 28, 2020
Merged
Changes from all commits
Commits
Show all changes
41 commits
Select commit
Hold shift + click to select a range
4128a69
added context header with dummy methods
satac2 cba6d5f
Build and CMake files
satac2 b2e876e
auto formatted
satac2 a7480c8
changed variable name from attributes to values
satac2 96cd32f
Update api/include/opentelemetry/context/context.h
satac2 5f0634b
changed to follow the spec and added context_value type
satac2 5d77daf
Merge branch 'context_api_dummy_methods' of github.com:satac2/opentel…
satac2 68a1a70
removed tests for this PR
satac2 5e68574
removed line
satac2 16a492e
removed unnecessary include
satac2 497eb67
changed a function to pass by reference
satac2 479dead
formatted
satac2 2a78c48
Added tests.
satac2 f51748f
avoiding ABI compatibility issues
satac2 7d73219
Merge branch 'master' into context_api_dummy_methods
maxgolov 3f85aa5
added throw capture
satac2 0ec83e8
Merge branch 'context_api_dummy_methods' of github.com:satac2/opentel…
satac2 21ea872
minor exception syntax error
satac2 f016689
Merge pull request #13 from satac2/context_api_dummy_methods
satac2 1f5e5fd
added runtime and threadlocal contexts
satac2 bbf9559
add comparison operator to context api
satac2 c8b7ed6
added stack for local storage of context objects
satac2 8d8b91f
removed old context.h
satac2 4b78ac8
changed runtime context interface to match
satac2 d3cea59
Merge remote-tracking branch 'origin/master' into runtime_and_threadl…
satac2 25bec5e
Merge remote-tracking branch 'origin/master' into runtime_and_threadl…
satac2 d77e445
formatted and added some size checks to prevent seg faults, also adde…
satac2 0583e3c
added tests
satac2 e02fadb
add a context_config file to choose which implementation the runtime …
satac2 c06edc5
readding string_view_test
satac2 fc42d91
threadlocalcontext is once again a derived class of RuntimeContext an…
satac2 ce78585
protected virtual members
satac2 02dbbdf
reset string_view_test
satac2 c1ebc16
Merge branch 'master' into runtime_and_threadlocal_context
reyang 5a5df6e
added destructor that detaches the context to the Token
satac2 a2c81b3
Merge branch 'runtime_and_threadlocal_context' of github.com:satac2/o…
satac2 1d7549f
minor changes and switch from RuntimeContext accepting a ptr
satac2 090fbe7
fixed nits
satac2 2ba7e02
added const to Top
satac2 2fe8935
Merge branch 'master' into runtime_and_threadlocal_context
reyang 6b2ff4c
Merge branch 'master' into runtime_and_threadlocal_context
reyang File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| #pragma once | ||
|
|
||
| #include "opentelemetry/context/context.h" | ||
|
|
||
| OPENTELEMETRY_BEGIN_NAMESPACE | ||
| namespace context | ||
| { | ||
| // Provides a wrapper for propagating the context object globally. In order | ||
| // to use either the threadlocal_context.h file must be included or another | ||
| // implementation which must be derived from the RuntimeContext can be | ||
| // provided. | ||
| class RuntimeContext | ||
| { | ||
| public: | ||
| class Token | ||
| { | ||
| public: | ||
| bool operator==(const Context &other) noexcept { return context_ == other; } | ||
|
|
||
| ~Token() noexcept { Detach(*this); } | ||
|
|
||
| private: | ||
| friend class RuntimeContext; | ||
|
|
||
| // A constructor that sets the token's Context object to the | ||
| // one that was passed in. | ||
| Token(Context context) noexcept : context_(context){}; | ||
|
|
||
| Token() noexcept = default; | ||
|
|
||
| Context context_; | ||
| }; | ||
|
|
||
| // Return the current context. | ||
| static Context GetCurrent() noexcept { return context_handler_->InternalGetCurrent(); } | ||
|
|
||
| // Sets the current 'Context' object. Returns a token | ||
| // that can be used to reset to the previous Context. | ||
| static Token Attach(Context context) noexcept | ||
| { | ||
| return context_handler_->InternalAttach(context); | ||
| } | ||
|
|
||
| // Resets the context to a previous value stored in the | ||
| // passed in token. Returns true if successful, false otherwise | ||
| static bool Detach(Token &token) noexcept { return context_handler_->InternalDetach(token); } | ||
|
|
||
| static RuntimeContext *context_handler_; | ||
|
|
||
| protected: | ||
| // Provides a token with the passed in context | ||
| Token CreateToken(Context context) noexcept { return Token(context); } | ||
|
|
||
| virtual Context InternalGetCurrent() noexcept = 0; | ||
|
|
||
| virtual Token InternalAttach(Context context) noexcept = 0; | ||
|
|
||
| virtual bool InternalDetach(Token &token) noexcept = 0; | ||
| }; | ||
| } // namespace context | ||
| OPENTELEMETRY_END_NAMESPACE | ||
116 changes: 116 additions & 0 deletions
116
api/include/opentelemetry/context/threadlocal_context.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| #pragma once | ||
|
|
||
| #include "opentelemetry/context/context.h" | ||
| #include "opentelemetry/context/runtime_context.h" | ||
|
|
||
| OPENTELEMETRY_BEGIN_NAMESPACE | ||
| namespace context | ||
| { | ||
|
|
||
| // The ThreadLocalContext class is a derived class from RuntimeContext and | ||
| // provides a wrapper for propogating context through cpp thread locally. | ||
| // This file must be included to use the RuntimeContext class if another | ||
| // implementation has not been registered. | ||
pyohannes marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| class ThreadLocalContext : public RuntimeContext | ||
| { | ||
| public: | ||
| ThreadLocalContext() noexcept = default; | ||
|
|
||
| // Return the current context. | ||
| Context InternalGetCurrent() noexcept override { return stack_.Top(); } | ||
|
|
||
| // Resets the context to a previous value stored in the | ||
| // passed in token. Returns true if successful, false otherwise | ||
| bool InternalDetach(Token &token) noexcept override | ||
| { | ||
| if (!(token == stack_.Top())) | ||
| { | ||
| return false; | ||
| } | ||
| stack_.Pop(); | ||
| return true; | ||
| } | ||
|
|
||
| // Sets the current 'Context' object. Returns a token | ||
| // that can be used to reset to the previous Context. | ||
| Token InternalAttach(Context context) noexcept override | ||
| { | ||
| stack_.Push(context); | ||
| Token old_context = CreateToken(context); | ||
| return old_context; | ||
| } | ||
|
|
||
| private: | ||
| // A nested class to store the attached contexts in a stack. | ||
| class Stack | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's mark all
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Marked as noexcept and const. |
||
| { | ||
| friend class ThreadLocalContext; | ||
|
|
||
| Stack() noexcept : size_(0), capacity_(0), base_(nullptr){}; | ||
|
|
||
| // Pops the top Context off the stack and returns it. | ||
| Context Pop() noexcept | ||
| { | ||
| if (size_ <= 0) | ||
| { | ||
| return Context(); | ||
| } | ||
| int index = size_ - 1; | ||
| size_--; | ||
| return base_[index]; | ||
| } | ||
|
|
||
| // Returns the Context at the top of the stack. | ||
| Context Top() const noexcept | ||
| { | ||
| if (size_ <= 0) | ||
| { | ||
| return Context(); | ||
| } | ||
| return base_[size_ - 1]; | ||
| } | ||
|
|
||
| // Pushes the passed in context pointer to the top of the stack | ||
| // and resizes if necessary. | ||
| void Push(Context context) noexcept | ||
| { | ||
| size_++; | ||
| if (size_ > capacity_) | ||
| { | ||
| Resize(size_ * 2); | ||
| } | ||
| base_[size_ - 1] = context; | ||
| } | ||
|
|
||
| // Reallocates the storage array to the pass in new capacity size. | ||
| void Resize(int new_capacity) noexcept | ||
| { | ||
| int old_size = size_ - 1; | ||
| if (new_capacity == 0) | ||
| { | ||
| new_capacity = 2; | ||
| } | ||
| Context *temp = new Context[new_capacity]; | ||
| if (base_ != nullptr) | ||
| { | ||
| std::copy(base_, base_ + old_size, temp); | ||
| delete[] base_; | ||
| } | ||
| base_ = temp; | ||
| } | ||
|
|
||
| ~Stack() noexcept { delete[] base_; } | ||
|
|
||
| size_t size_; | ||
| size_t capacity_; | ||
| Context *base_; | ||
| }; | ||
|
|
||
| static thread_local Stack stack_; | ||
| }; | ||
| thread_local ThreadLocalContext::Stack ThreadLocalContext::stack_ = ThreadLocalContext::Stack(); | ||
pyohannes marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| // Registers the ThreadLocalContext as the context handler for the RuntimeContext | ||
| RuntimeContext *RuntimeContext::context_handler_ = new ThreadLocalContext(); | ||
| } // namespace context | ||
| OPENTELEMETRY_END_NAMESPACE | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| #include "opentelemetry/context/context.h" | ||
| #include "opentelemetry/context/threadlocal_context.h" | ||
|
|
||
| #include <gtest/gtest.h> | ||
|
|
||
| using namespace opentelemetry; | ||
|
|
||
| // Tests that GetCurrent returns the current context | ||
| TEST(RuntimeContextTest, GetCurrent) | ||
| { | ||
| std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}}; | ||
| context::Context test_context = context::Context(map_test); | ||
| context::RuntimeContext::Token old_context = context::RuntimeContext::Attach(test_context); | ||
| EXPECT_TRUE(context::RuntimeContext::GetCurrent() == test_context); | ||
| context::RuntimeContext::Detach(old_context); | ||
| } | ||
|
|
||
| // Tests that detach resets the context to the previous context | ||
| TEST(RuntimeContextTest, Detach) | ||
| { | ||
| std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}}; | ||
| context::Context test_context = context::Context(map_test); | ||
| context::Context foo_context = context::Context(map_test); | ||
|
|
||
| context::RuntimeContext::Token test_context_token = context::RuntimeContext::Attach(test_context); | ||
| context::RuntimeContext::Token foo_context_token = context::RuntimeContext::Attach(foo_context); | ||
|
|
||
| context::RuntimeContext::Detach(foo_context_token); | ||
| EXPECT_TRUE(context::RuntimeContext::GetCurrent() == test_context); | ||
| context::RuntimeContext::Detach(test_context_token); | ||
| } | ||
|
|
||
| // Tests that detach returns false when the wrong context is provided | ||
| TEST(RuntimeContextTest, DetachWrongContext) | ||
| { | ||
| std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}}; | ||
| context::Context test_context = context::Context(map_test); | ||
| context::Context foo_context = context::Context(map_test); | ||
| context::RuntimeContext::Token test_context_token = context::RuntimeContext::Attach(test_context); | ||
| context::RuntimeContext::Token foo_context_token = context::RuntimeContext::Attach(foo_context); | ||
| EXPECT_FALSE(context::RuntimeContext::Detach(test_context_token)); | ||
| context::RuntimeContext::Detach(foo_context_token); | ||
| context::RuntimeContext::Detach(test_context_token); | ||
| } | ||
|
|
||
| // Tests that the ThreadLocalContext can handle three attached contexts | ||
| TEST(RuntimeContextTest, ThreeAttachDetach) | ||
| { | ||
| std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}}; | ||
| context::Context test_context = context::Context(map_test); | ||
| context::Context foo_context = context::Context(map_test); | ||
| context::Context other_context = context::Context(map_test); | ||
| context::RuntimeContext::Token test_context_token = context::RuntimeContext::Attach(test_context); | ||
| context::RuntimeContext::Token foo_context_token = context::RuntimeContext::Attach(foo_context); | ||
| context::RuntimeContext::Token other_context_token = | ||
| context::RuntimeContext::Attach(other_context); | ||
|
|
||
| EXPECT_TRUE(context::RuntimeContext::Detach(other_context_token)); | ||
| EXPECT_TRUE(context::RuntimeContext::Detach(foo_context_token)); | ||
| EXPECT_TRUE(context::RuntimeContext::Detach(test_context_token)); | ||
| } | ||
pyohannes marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to have a dtor for Token which calls Detach?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That make sense, seems like it will add an element of safety so the context can't get stuck after a token has gone out of scope. I will add it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.