forked from open-telemetry/opentelemetry-cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from satac2/context_api_content
Context api content
- Loading branch information
Showing
5 changed files
with
324 additions
and
36 deletions.
There are no files selected for viewing
This file contains 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 |
---|---|---|
@@ -1,61 +1,219 @@ | ||
#pragma once | ||
|
||
|
||
#include <map> | ||
#include <string> | ||
#include <mutex> | ||
|
||
#include "opentelemetry/version.h" | ||
|
||
OPENTELEMETRY_BEGIN_NAMESPACE | ||
namespace context | ||
{ | ||
|
||
std::mutex context_id_mutex; | ||
|
||
/*The context class provides a context identifier*/ | ||
class Context{ | ||
|
||
private: | ||
|
||
/*The identifier itself*/ | ||
std::map<int, int> ctx_map_; | ||
|
||
/*Used to track that last ContextKey identifier and create the next one */ | ||
static int last_key_identifier_; | ||
|
||
/* Context: A constructor that accepts a key/value map*/ | ||
Context(std::map<int,int> ctx_map){ | ||
ctx_map_ = ctx_map; | ||
} | ||
|
||
public: | ||
|
||
/*The ContextKey class is used to obscure access from the | ||
* user to the context map. The identifier is used as a key | ||
* to the context map. | ||
*/ | ||
class ContextKey{ | ||
private: | ||
friend class Context; | ||
|
||
std::string key_name_; | ||
|
||
int identifier_; | ||
|
||
|
||
/* GetIdentifier: returns the identifier*/ | ||
int GetIdentifier(){ | ||
return identifier_; | ||
} | ||
|
||
/* ContextKey: constructs a new ContextKey with the | ||
* passed in name and identifier. | ||
*/ | ||
ContextKey(std::string key_name, int identifier){ | ||
key_name_ = key_name; | ||
identifier_ = identifier; | ||
} | ||
|
||
public: | ||
|
||
/* ContextKey: 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){ | ||
key_name_ = key_name; | ||
|
||
context_id_mutex.lock(); | ||
|
||
Context::last_key_identifier_++; | ||
|
||
identifier_ = Context::last_key_identifier_; | ||
|
||
context_id_mutex.unlock(); | ||
} | ||
|
||
}; | ||
|
||
|
||
/* Context: contructor, creates a context object with no key/value pairs | ||
*/ | ||
Context(){ | ||
ctx_map_ = std::map<int,int> {}; | ||
|
||
} | ||
|
||
/* Context: contructor, creates a context object from a map | ||
* of keys and identifiers | ||
*/ | ||
Context(ContextKey key, int value){ | ||
ctx_map_[key.GetIdentifier()] = value; | ||
} | ||
|
||
|
||
/* WriteValue: 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){ | ||
std::map<int, int> temp_map = ctx_map_; | ||
|
||
temp_map[key.GetIdentifier()] = value; | ||
|
||
return Context(temp_map); | ||
} | ||
|
||
|
||
/* GetValue: Returns the value associated with the passed in key | ||
*/ | ||
int GetValue(ContextKey key){ | ||
return ctx_map_[key.GetIdentifier()]; | ||
} | ||
|
||
/* CreateKey: Returns a ContextKey that has the passed in name and the | ||
* next available identifier.*/ | ||
ContextKey CreateKey(std::string key_name){ | ||
int id; | ||
|
||
context_id_mutex.lock(); | ||
|
||
last_key_identifier_++; | ||
|
||
id = last_key_identifier_; | ||
|
||
context_id_mutex.unlock(); | ||
|
||
return ContextKey(key_name,id); | ||
} | ||
|
||
|
||
}; | ||
|
||
|
||
|
||
/* The token class provides an identifier that is used by | ||
* the attach and detach methods to keep track of context | ||
* objects.*/ | ||
|
||
class Token{ | ||
private: | ||
|
||
Context ctx_; | ||
|
||
public: | ||
|
||
/* Token: A constructor that sets the token's Context object to the | ||
* one that was passed in. | ||
*/ | ||
Token(Context &ctx){ | ||
ctx_ = ctx; | ||
} | ||
|
||
/* GetContext: Returns the stored context object */ | ||
Context GetContext(){ | ||
return ctx_; | ||
} | ||
|
||
}; | ||
|
||
|
||
/* The RuntimeContext class provides a wrapper for | ||
* propogating context through cpp*/ | ||
class RuntimeContext { | ||
private: | ||
|
||
static thread_local Context context_; | ||
|
||
public: | ||
|
||
|
||
/*The context class provides a context identifier*/ | ||
class Context{ | ||
private: | ||
/*The identifier itself*/ | ||
std::map<std::string, int> ctx_; | ||
RuntimeContext(){ | ||
context_ = Context(); | ||
} | ||
|
||
public: | ||
/* Context: contructor, creates a context object from a map | ||
* of keys and identifiers | ||
*/ | ||
Context(std::map<std::string, int> ctx); | ||
|
||
}; | ||
/* RuntimeContext: A constructor that will set the context as | ||
* the passed in context. | ||
*/ | ||
RuntimeContext(Context &context){ | ||
context_ = context; | ||
} | ||
|
||
/* The token class provides an identifier that is used by | ||
* the RuntimeContext attach and detach methods to keep track of context | ||
* objects.*/ | ||
class Token{ | ||
Token(); | ||
}; | ||
/* attach: Sets the current 'Context' object. Returns a token | ||
* that can be used to reset to the previous Context. | ||
*/ | ||
Token Attach(Context &context){ | ||
|
||
Token old_context_token = Token(context_); | ||
|
||
/* The RuntimeContext class provides a wrapper for | ||
* propogating context through cpp*/ | ||
class RuntimeContext { | ||
public: | ||
context_ = context; | ||
|
||
/* RuntimeContext: A constructor that will set the current | ||
* context to the threading local. | ||
*/ | ||
RuntimeContext(); | ||
return old_context_token; | ||
} | ||
|
||
/* attach: Sets the current 'Context' object. Returns a token | ||
* that can be used to reset to the previous Context. | ||
*/ | ||
static Token Attach(Context context); | ||
|
||
/* GetCurrent: Return the current context. | ||
*/ | ||
static Context GetCurrent(){ | ||
Context context = context_; | ||
return context_; | ||
} | ||
|
||
/* get_current: Return the current context. | ||
*/ | ||
static Context GetCurrent(); | ||
|
||
|
||
/* detach: Resets the context to a previous value. | ||
*/ | ||
static void Detach(Token token); | ||
/* Detach: Resets the context to a previous value stored in the | ||
* passed in token. | ||
*/ | ||
void Detach(Token &token){ | ||
context_ = token.GetContext(); | ||
} | ||
|
||
}; | ||
|
||
thread_local Context RuntimeContext::context_ = Context(); | ||
int Context::last_key_identifier_ = 0; | ||
|
||
}; | ||
|
||
} | ||
OPENTELEMETRY_END_NAMESPACE |
This file contains 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 |
---|---|---|
@@ -1,4 +1,5 @@ | ||
add_subdirectory(core) | ||
add_subdirectory(context) | ||
add_subdirectory(plugin) | ||
add_subdirectory(nostd) | ||
add_subdirectory(trace) |
This file contains 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,25 @@ | ||
load("//bazel:otel_cc_benchmark.bzl", "otel_cc_benchmark") | ||
|
||
cc_test( | ||
name = "context_test", | ||
srcs = [ | ||
"context_test.cc", | ||
], | ||
deps = [ | ||
"//api", | ||
"@com_google_googletest//:gtest_main", | ||
], | ||
) | ||
|
||
cc_test( | ||
name = "runtimeContext_test", | ||
srcs = [ | ||
"runtimeContext_test.cc", | ||
], | ||
copts = ["-Wall","-std=c++17"], | ||
deps = [ | ||
"//api", | ||
"@com_google_googletest//:gtest_main", | ||
], | ||
) | ||
|
This file contains 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,45 @@ | ||
#include "opentelemetry/context/context.h" | ||
|
||
#include <gtest/gtest.h> | ||
|
||
using namespace opentelemetry::context; | ||
|
||
/* Tests whether the original context objects changes | ||
* when you write to it. | ||
*/ | ||
TEST(Context_test, is_context_immutable) | ||
{ | ||
|
||
Context test_context = Context(); | ||
|
||
Context::ContextKey test_key = test_context.CreateKey("test_key"); | ||
|
||
EXPECT_EQ(test_context.GetValue(test_key), NULL); | ||
|
||
Context new_test_context = test_context.WriteValue(test_key,7); | ||
|
||
EXPECT_EQ(new_test_context.GetValue(test_key), 7); | ||
|
||
EXPECT_EQ(test_context.GetValue(test_key), NULL); | ||
} | ||
|
||
/* Tests whether the new Context Objects inherits the keys and values | ||
* of the original context object | ||
*/ | ||
TEST(Context_test, context_write_new_object) | ||
{ | ||
|
||
|
||
Context::ContextKey test_key = Context::ContextKey("test_key"); | ||
|
||
Context test_context = Context(test_key, 7); | ||
|
||
Context::ContextKey foo_key = test_context.CreateKey("foo_key"); | ||
|
||
Context new_test_context = test_context.WriteValue(foo_key,1); | ||
|
||
EXPECT_EQ(new_test_context.GetValue(test_key), 7); | ||
|
||
EXPECT_EQ(new_test_context.GetValue(foo_key), 1); | ||
} | ||
|
This file contains 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,59 @@ | ||
#include "opentelemetry/context/context.h" | ||
|
||
#include <gtest/gtest.h> | ||
|
||
using namespace opentelemetry::context; | ||
|
||
|
||
/* Tests whether the runtimeContext object properly returns the current context | ||
*/ | ||
TEST(runtimeContext_test, get_current_context) | ||
{ | ||
|
||
Context::ContextKey test_key = Context::ContextKey("test_key"); | ||
Context test_context = Context(test_key, 7); | ||
|
||
RuntimeContext test_runtime = RuntimeContext(test_context); | ||
|
||
EXPECT_EQ(test_runtime.GetCurrent().GetValue(test_key), | ||
test_context.GetValue(test_key)); | ||
|
||
} | ||
|
||
|
||
|
||
|
||
/* Tests whether the runtimeContext object properly attaches and detaches | ||
* the context object. | ||
*/ | ||
TEST(runtimeContext_test, attach_detach_context) | ||
{ | ||
|
||
Context::ContextKey test_key = Context::ContextKey("test_key"); | ||
Context test_context = Context(test_key, 7); | ||
|
||
RuntimeContext test_runtime = RuntimeContext(test_context); | ||
|
||
Context::ContextKey foo_key = Context::ContextKey("foo_key"); | ||
Context foo_context = Context(foo_key, 5); | ||
|
||
EXPECT_EQ(test_runtime.GetCurrent().GetValue(test_key), | ||
test_context.GetValue(test_key)); | ||
EXPECT_NE(test_runtime.GetCurrent().GetValue(foo_key), | ||
foo_context.GetValue(foo_key)); | ||
|
||
Token test_token = test_runtime.Attach(foo_context); | ||
|
||
EXPECT_NE(test_runtime.GetCurrent().GetValue(test_key), | ||
test_context.GetValue(test_key)); | ||
EXPECT_EQ(test_runtime.GetCurrent().GetValue(foo_key), | ||
foo_context.GetValue(foo_key)); | ||
|
||
test_runtime.Detach(test_token); | ||
|
||
EXPECT_EQ(test_runtime.GetCurrent().GetValue(test_key), | ||
test_context.GetValue(test_key)); | ||
EXPECT_NE(test_runtime.GetCurrent().GetValue(foo_key), | ||
foo_context.GetValue(foo_key)); | ||
} | ||
|