Skip to content
Merged
Show file tree
Hide file tree
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 Jul 6, 2020
cba6d5f
Build and CMake files
satac2 Jul 6, 2020
b2e876e
auto formatted
satac2 Jul 6, 2020
a7480c8
changed variable name from attributes to values
satac2 Jul 9, 2020
96cd32f
Update api/include/opentelemetry/context/context.h
satac2 Jul 9, 2020
5f0634b
changed to follow the spec and added context_value type
satac2 Jul 13, 2020
5d77daf
Merge branch 'context_api_dummy_methods' of github.com:satac2/opentel…
satac2 Jul 13, 2020
68a1a70
removed tests for this PR
satac2 Jul 13, 2020
5e68574
removed line
satac2 Jul 13, 2020
16a492e
removed unnecessary include
satac2 Jul 13, 2020
497eb67
changed a function to pass by reference
satac2 Jul 13, 2020
479dead
formatted
satac2 Jul 13, 2020
2a78c48
Added tests.
satac2 Jul 13, 2020
f51748f
avoiding ABI compatibility issues
satac2 Jul 13, 2020
7d73219
Merge branch 'master' into context_api_dummy_methods
maxgolov Jul 13, 2020
3f85aa5
added throw capture
satac2 Jul 14, 2020
0ec83e8
Merge branch 'context_api_dummy_methods' of github.com:satac2/opentel…
satac2 Jul 14, 2020
21ea872
minor exception syntax error
satac2 Jul 14, 2020
f016689
Merge pull request #13 from satac2/context_api_dummy_methods
satac2 Jul 14, 2020
1f5e5fd
added runtime and threadlocal contexts
satac2 Jul 14, 2020
bbf9559
add comparison operator to context api
satac2 Jul 14, 2020
c8b7ed6
added stack for local storage of context objects
satac2 Jul 16, 2020
8d8b91f
removed old context.h
satac2 Jul 16, 2020
4b78ac8
changed runtime context interface to match
satac2 Jul 16, 2020
d3cea59
Merge remote-tracking branch 'origin/master' into runtime_and_threadl…
satac2 Jul 22, 2020
25bec5e
Merge remote-tracking branch 'origin/master' into runtime_and_threadl…
satac2 Jul 22, 2020
d77e445
formatted and added some size checks to prevent seg faults, also adde…
satac2 Jul 22, 2020
0583e3c
added tests
satac2 Jul 22, 2020
e02fadb
add a context_config file to choose which implementation the runtime …
satac2 Jul 23, 2020
c06edc5
readding string_view_test
satac2 Jul 23, 2020
fc42d91
threadlocalcontext is once again a derived class of RuntimeContext an…
satac2 Jul 23, 2020
ce78585
protected virtual members
satac2 Jul 23, 2020
02dbbdf
reset string_view_test
satac2 Jul 23, 2020
c1ebc16
Merge branch 'master' into runtime_and_threadlocal_context
reyang Jul 23, 2020
5a5df6e
added destructor that detaches the context to the Token
satac2 Jul 24, 2020
a2c81b3
Merge branch 'runtime_and_threadlocal_context' of github.com:satac2/o…
satac2 Jul 24, 2020
1d7549f
minor changes and switch from RuntimeContext accepting a ptr
satac2 Jul 25, 2020
090fbe7
fixed nits
satac2 Jul 28, 2020
2ba7e02
added const to Top
satac2 Jul 28, 2020
2fe8935
Merge branch 'master' into runtime_and_threadlocal_context
reyang Jul 28, 2020
6b2ff4c
Merge branch 'master' into runtime_and_threadlocal_context
reyang Jul 28, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions api/include/opentelemetry/context/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class Context
{

public:
Context() = default;
// Creates a context object from a map of keys and identifiers, this will
// hold a shared_ptr to the head of the DataList linked list
template <class T>
Expand Down Expand Up @@ -89,9 +90,9 @@ class Context
return false;
}

private:
Context() = default;
bool operator==(const Context &other) { return (head_ == other.head_); }

private:
// A linked list to contain the keys and values of this context node
class DataList
{
Expand Down
61 changes: 61 additions & 0 deletions api/include/opentelemetry/context/runtime_context.h
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
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.

Would it make sense to have a dtor for Token which calls Detach?

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.

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.

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.

Added.

{
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 api/include/opentelemetry/context/threadlocal_context.h
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.
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
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.

Let's mark all Stack methods as noexcept. Top can be const too.

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.

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();

// Registers the ThreadLocalContext as the context handler for the RuntimeContext
RuntimeContext *RuntimeContext::context_handler_ = new ThreadLocalContext();
} // namespace context
OPENTELEMETRY_END_NAMESPACE
11 changes: 11 additions & 0 deletions api/test/context/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,14 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)

cc_test(
name = "runtime_context_test",
srcs = [
"runtime_context_test.cc",
],
deps = [
"//api",
"@com_google_googletest//:gtest_main",
],
)
19 changes: 19 additions & 0 deletions api/test/context/context_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,22 @@ TEST(ContextTest, ContextHasKey)
EXPECT_TRUE(context_test.HasKey("test_key"));
EXPECT_FALSE(context_test.HasKey("foo_key"));
}

// Tests that a copied context returns true when compared
TEST(ContextTest, ContextCopyCompare)
{
std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}};
context::Context context_test = context::Context(map_test);
context::Context copied_test = context_test;
EXPECT_TRUE(context_test == copied_test);
}

// Tests that two differently constructed contexts return false when compared
TEST(ContextTest, ContextDiffCompare)
{
std::map<std::string, context::ContextValue> map_test = {{"test_key", (int64_t)123}};
std::map<std::string, context::ContextValue> map_foo = {{"foo_key", (int64_t)123}};
context::Context context_test = context::Context(map_test);
context::Context foo_test = context::Context(map_foo);
EXPECT_FALSE(context_test == foo_test);
}
61 changes: 61 additions & 0 deletions api/test/context/runtime_context_test.cc
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));
}