why upgrade? anything wrong? Try to fix the problem about opentelemetry::v1::ext::http::client::curl::HttpOperation::Send(), I have updated the pr info.
413 lines
15 KiB
Diff
413 lines
15 KiB
Diff
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
|
index f4fa0649..a64e74bc 100644
|
|
--- a/CMakeLists.txt
|
|
+++ b/CMakeLists.txt
|
|
@@ -118,9 +118,8 @@ option(WITH_GSL
|
|
|
|
option(WITH_ABSEIL "Whether to use Abseil for C++latest features" OFF)
|
|
|
|
+set(OPENTELEMETRY_INSTALL_default ON)
|
|
if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
|
|
- set(OPENTELEMETRY_INSTALL_default ON)
|
|
-else()
|
|
set(OPENTELEMETRY_INSTALL_default OFF)
|
|
endif()
|
|
option(OPENTELEMETRY_INSTALL "Whether to install opentelemetry targets"
|
|
diff --git a/api/include/opentelemetry/common/threadlocal.h b/api/include/opentelemetry/common/threadlocal.h
|
|
new file mode 100644
|
|
index 00000000..23a39e14
|
|
--- /dev/null
|
|
+++ b/api/include/opentelemetry/common/threadlocal.h
|
|
@@ -0,0 +1,123 @@
|
|
+// Copyright The OpenTelemetry Authors
|
|
+// SPDX-License-Identifier: Apache-2.0
|
|
+
|
|
+#pragma once
|
|
+
|
|
+#include "opentelemetry/version.h"
|
|
+
|
|
+//
|
|
+// GCC can be told that a certain branch is not likely to be taken (for
|
|
+// instance, a CHECK failure), and use that information in static analysis.
|
|
+// Giving it this information can help it optimize for the common case in
|
|
+// the absence of better information (ie. -fprofile-arcs).
|
|
+//
|
|
+#define LIKELY(expr) __builtin_expect(!!(expr), 1)
|
|
+#define UNLIKELY(expr) __builtin_expect(!!(expr), 0)
|
|
+
|
|
+// Block-scoped static thread local implementation.
|
|
+//
|
|
+// Usage is similar to a C++11 thread_local. The BLOCK_STATIC_THREAD_LOCAL_TELEMTRY macro
|
|
+// defines a thread-local pointer to the specified type, which is lazily
|
|
+// instantiated by any thread entering the block for the first time. The
|
|
+// constructor for the type T is invoked at macro execution time, as expected,
|
|
+// and its destructor is invoked when the corresponding thread's Runnable
|
|
+// returns, or when the thread exits.
|
|
+//
|
|
+// Inspired by Poco <http://pocoproject.org/docs/Poco.ThreadLocal.html>,
|
|
+// Andrew Tomazos <http://stackoverflow.com/questions/12049684/>, and
|
|
+// the C++11 thread_local API.
|
|
+//
|
|
+// Example usage:
|
|
+//
|
|
+// // Invokes a 3-arg constructor on SomeClass:
|
|
+// BLOCK_STATIC_THREAD_LOCAL_TELEMTRY(SomeClass, instance, arg1, arg2, arg3);
|
|
+// instance->DoSomething();
|
|
+//
|
|
+#define BLOCK_STATIC_THREAD_LOCAL_TELEMTRY(T, t, ...) \
|
|
+ static __thread T *t; \
|
|
+ do \
|
|
+ { \
|
|
+ if (UNLIKELY(t == nullptr)) \
|
|
+ { \
|
|
+ t = new T(__VA_ARGS__); \
|
|
+ internal_threadlocal::AddDestructor(internal_threadlocal::Destroy<T>, t); \
|
|
+ } \
|
|
+ } while (false)
|
|
+
|
|
+// Class-scoped static thread local implementation.
|
|
+//
|
|
+// Very similar in implementation to the above block-scoped version, but
|
|
+// requires a bit more syntax and vigilance to use properly.
|
|
+//
|
|
+// DECLARE_STATIC_THREAD_LOCAL_TELEMETRY(Type, instance_var_) must be placed in the
|
|
+// class header, as usual for variable declarations.
|
|
+//
|
|
+// Because these variables are static, they must also be defined in the impl
|
|
+// file with DEFINE_STATIC_THREAD_LOCAL_TELEMETRY(Type, Classname, instance_var_),
|
|
+// which is very much like defining any static member, i.e. int Foo::member_.
|
|
+//
|
|
+// Finally, each thread must initialize the instance before using it by calling
|
|
+// INIT_STATIC_THREAD_LOCAL_TELEMETRY(Type, instance_var_, ...). This is a cheap
|
|
+// call, and may be invoked at the top of any method which may reference a
|
|
+// thread-local variable.
|
|
+//
|
|
+// Due to all of these requirements, you should probably declare TLS members
|
|
+// as private.
|
|
+//
|
|
+// Example usage:
|
|
+//
|
|
+// // foo.h
|
|
+// #include "kudu/utils/file.h"
|
|
+// class Foo {
|
|
+// public:
|
|
+// void DoSomething(std::string s);
|
|
+// private:
|
|
+// DECLARE_STATIC_THREAD_LOCAL_TELEMETRY(utils::File, file_);
|
|
+// };
|
|
+//
|
|
+// // foo.cc
|
|
+// #include "kudu/foo.h"
|
|
+// DEFINE_STATIC_THREAD_LOCAL_TELEMETRY(utils::File, Foo, file_);
|
|
+// void Foo::WriteToFile(std::string s) {
|
|
+// // Call constructor if necessary.
|
|
+// INIT_STATIC_THREAD_LOCAL_TELEMETRY(utils::File, file_, "/tmp/file_location.txt");
|
|
+// file_->Write(s);
|
|
+// }
|
|
+
|
|
+// Goes in the class declaration (usually in a header file).
|
|
+// dtor must be destructed _after_ t, so it gets defined first.
|
|
+// Uses a mangled variable name for dtor since it must also be a member of the
|
|
+// class.
|
|
+#define DECLARE_STATIC_THREAD_LOCAL_TELEMETRY(T, t) static __thread T *t
|
|
+
|
|
+// You must also define the instance in the .cc file.
|
|
+#define DEFINE_STATIC_THREAD_LOCAL_TELEMETRY(T, Class, t) __thread T *Class::t
|
|
+
|
|
+// Must be invoked at least once by each thread that will access t.
|
|
+#define INIT_STATIC_THREAD_LOCAL_TELEMETRY(T, t, ...) \
|
|
+ do \
|
|
+ { \
|
|
+ if (UNLIKELY(t == nullptr)) \
|
|
+ { \
|
|
+ t = new T(__VA_ARGS__); \
|
|
+ internal_threadlocal::AddDestructor(internal_threadlocal::Destroy<T>, t); \
|
|
+ } \
|
|
+ } while (false)
|
|
+
|
|
+// Internal implementation below.
|
|
+OPENTELEMETRY_BEGIN_NAMESPACE
|
|
+namespace internal_threadlocal
|
|
+{
|
|
+
|
|
+// Add a destructor to the list.
|
|
+void AddDestructor(void (*destructor)(void *), void *arg);
|
|
+
|
|
+// Destroy the passed object of type T.
|
|
+template <class T>
|
|
+static void Destroy(void *t)
|
|
+{
|
|
+ // With tcmalloc, this should be pretty cheap (same thread as new).
|
|
+ delete reinterpret_cast<T *>(t);
|
|
+}
|
|
+} // namespace internal_threadlocal
|
|
+OPENTELEMETRY_END_NAMESPACE
|
|
\ No newline at end of file
|
|
diff --git a/api/include/opentelemetry/context/runtime_context.h b/api/include/opentelemetry/context/runtime_context.h
|
|
index bec96a9a..2349a29c 100644
|
|
--- a/api/include/opentelemetry/context/runtime_context.h
|
|
+++ b/api/include/opentelemetry/context/runtime_context.h
|
|
@@ -5,6 +5,7 @@
|
|
|
|
#include "opentelemetry/common/macros.h"
|
|
#include "opentelemetry/context/context.h"
|
|
+#include "opentelemetry/common/threadlocal.h"
|
|
|
|
OPENTELEMETRY_BEGIN_NAMESPACE
|
|
namespace context
|
|
@@ -189,7 +190,7 @@ class ThreadLocalContextStorage : public RuntimeContextStorage
|
|
ThreadLocalContextStorage() noexcept = default;
|
|
|
|
// Return the current context.
|
|
- Context GetCurrent() noexcept override { return GetStack().Top(); }
|
|
+ Context GetCurrent() noexcept override { return GetStack()->Top(); }
|
|
|
|
// Resets the context to the value previous to the passed in token. This will
|
|
// also detach all child contexts of the passed in token.
|
|
@@ -197,23 +198,23 @@ class ThreadLocalContextStorage : public RuntimeContextStorage
|
|
bool Detach(Token &token) noexcept override
|
|
{
|
|
// In most cases, the context to be detached is on the top of the stack.
|
|
- if (token == GetStack().Top())
|
|
+ if (token == GetStack()->Top())
|
|
{
|
|
- GetStack().Pop();
|
|
+ GetStack()->Pop();
|
|
return true;
|
|
}
|
|
|
|
- if (!GetStack().Contains(token))
|
|
+ if (!GetStack()->Contains(token))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
- while (!(token == GetStack().Top()))
|
|
+ while (!(token == GetStack()->Top()))
|
|
{
|
|
- GetStack().Pop();
|
|
+ GetStack()->Pop();
|
|
}
|
|
|
|
- GetStack().Pop();
|
|
+ GetStack()->Pop();
|
|
|
|
return true;
|
|
}
|
|
@@ -222,14 +223,14 @@ class ThreadLocalContextStorage : public RuntimeContextStorage
|
|
// that can be used to reset to the previous Context.
|
|
nostd::unique_ptr<Token> Attach(const Context &context) noexcept override
|
|
{
|
|
- GetStack().Push(context);
|
|
+ GetStack()->Push(context);
|
|
return CreateToken(context);
|
|
}
|
|
|
|
-private:
|
|
// A nested class to store the attached contexts in a stack.
|
|
class Stack
|
|
{
|
|
+ public:
|
|
friend class ThreadLocalContextStorage;
|
|
|
|
Stack() noexcept : size_(0), capacity_(0), base_(nullptr) {}
|
|
@@ -316,9 +317,10 @@ class ThreadLocalContextStorage : public RuntimeContextStorage
|
|
Context *base_;
|
|
};
|
|
|
|
- OPENTELEMETRY_API_SINGLETON Stack &GetStack()
|
|
+ OPENTELEMETRY_API_SINGLETON Stack *GetStack()
|
|
{
|
|
- static thread_local Stack stack_ = Stack();
|
|
+ // static thread_local Stack stack_ = Stack();
|
|
+ BLOCK_STATIC_THREAD_LOCAL_TELEMTRY(ThreadLocalContextStorage::Stack, stack_);
|
|
return stack_;
|
|
}
|
|
};
|
|
diff --git a/sdk/CMakeLists.txt b/sdk/CMakeLists.txt
|
|
index 2e8f3bb6..224e6463 100644
|
|
--- a/sdk/CMakeLists.txt
|
|
+++ b/sdk/CMakeLists.txt
|
|
@@ -1,7 +1,7 @@
|
|
# Copyright The OpenTelemetry Authors
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
-add_library(opentelemetry_sdk INTERFACE)
|
|
+add_library(opentelemetry_sdk INTERFACE ../api/include/opentelemetry/common/threadlocal.h)
|
|
target_include_directories(
|
|
opentelemetry_sdk
|
|
INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
|
|
diff --git a/sdk/src/common/CMakeLists.txt b/sdk/src/common/CMakeLists.txt
|
|
index b23a93e8..1cc0e0f2 100644
|
|
--- a/sdk/src/common/CMakeLists.txt
|
|
+++ b/sdk/src/common/CMakeLists.txt
|
|
@@ -1,7 +1,7 @@
|
|
# Copyright The OpenTelemetry Authors
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
-set(COMMON_SRCS random.cc core.cc global_log_handler.cc env_variables.cc)
|
|
+set(COMMON_SRCS random.cc core.cc global_log_handler.cc env_variables.cc threadlocal.cc)
|
|
if(WIN32)
|
|
list(APPEND COMMON_SRCS platform/fork_windows.cc)
|
|
else()
|
|
diff --git a/sdk/src/common/random.cc b/sdk/src/common/random.cc
|
|
index 77b88cfa..dc71f9c1 100644
|
|
--- a/sdk/src/common/random.cc
|
|
+++ b/sdk/src/common/random.cc
|
|
@@ -3,6 +3,7 @@
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
#include "src/common/random.h"
|
|
+#include "opentelemetry/common/threadlocal.h"
|
|
#include "src/common/platform/fork.h"
|
|
|
|
#include <cstring>
|
|
@@ -29,33 +30,37 @@ class TlsRandomNumberGenerator
|
|
platform::AtFork(nullptr, nullptr, OnFork);
|
|
}
|
|
|
|
- static FastRandomNumberGenerator &engine() noexcept { return engine_; }
|
|
+ static FastRandomNumberGenerator *engine() noexcept { return engine_; }
|
|
|
|
private:
|
|
- static thread_local FastRandomNumberGenerator engine_;
|
|
+ // static thread_local FastRandomNumberGenerator engine_;
|
|
+ DECLARE_STATIC_THREAD_LOCAL_TELEMETRY(FastRandomNumberGenerator, engine_);
|
|
|
|
static void OnFork() noexcept { Seed(); }
|
|
|
|
static void Seed() noexcept
|
|
{
|
|
+ INIT_STATIC_THREAD_LOCAL_TELEMETRY(FastRandomNumberGenerator, engine_);
|
|
std::random_device random_device;
|
|
std::seed_seq seed_seq{random_device(), random_device(), random_device(), random_device()};
|
|
- engine_.seed(seed_seq);
|
|
+ engine_->seed(seed_seq);
|
|
}
|
|
};
|
|
|
|
-thread_local FastRandomNumberGenerator TlsRandomNumberGenerator::engine_{};
|
|
+// thread_local FastRandomNumberGenerator TlsRandomNumberGenerator::engine_{};
|
|
+DEFINE_STATIC_THREAD_LOCAL_TELEMETRY(FastRandomNumberGenerator, TlsRandomNumberGenerator, engine_);
|
|
} // namespace
|
|
|
|
-FastRandomNumberGenerator &Random::GetRandomNumberGenerator() noexcept
|
|
+FastRandomNumberGenerator *Random::GetRandomNumberGenerator() noexcept
|
|
{
|
|
- static thread_local TlsRandomNumberGenerator random_number_generator{};
|
|
+ // static thread_local TlsRandomNumberGenerator random_number_generator{};
|
|
+ BLOCK_STATIC_THREAD_LOCAL_TELEMTRY(TlsRandomNumberGenerator, random_number_generator);
|
|
return TlsRandomNumberGenerator::engine();
|
|
}
|
|
|
|
uint64_t Random::GenerateRandom64() noexcept
|
|
{
|
|
- return GetRandomNumberGenerator()();
|
|
+ return GetRandomNumberGenerator()->operator()();
|
|
}
|
|
|
|
void Random::GenerateRandomBuffer(opentelemetry::nostd::span<uint8_t> buffer) noexcept
|
|
diff --git a/sdk/src/common/random.h b/sdk/src/common/random.h
|
|
index ecd6dabc..1aaa2204 100644
|
|
--- a/sdk/src/common/random.h
|
|
+++ b/sdk/src/common/random.h
|
|
@@ -34,7 +34,7 @@ class Random
|
|
/**
|
|
* @return a seeded thread-local random number generator.
|
|
*/
|
|
- static FastRandomNumberGenerator &GetRandomNumberGenerator() noexcept;
|
|
+ static FastRandomNumberGenerator *GetRandomNumberGenerator() noexcept;
|
|
};
|
|
} // namespace common
|
|
} // namespace sdk
|
|
diff --git a/sdk/src/common/threadlocal.cc b/sdk/src/common/threadlocal.cc
|
|
new file mode 100644
|
|
index 00000000..ec2038b4
|
|
--- /dev/null
|
|
+++ b/sdk/src/common/threadlocal.cc
|
|
@@ -0,0 +1,83 @@
|
|
+// Copyright The OpenTelemetry Authors
|
|
+// SPDX-License-Identifier: Apache-2.0
|
|
+
|
|
+#include <opentelemetry/common/threadlocal.h>
|
|
+#include "opentelemetry/sdk/common/global_log_handler.h"
|
|
+
|
|
+#include <pthread.h>
|
|
+#include <memory>
|
|
+#include <mutex>
|
|
+#include <ostream>
|
|
+#include <sstream>
|
|
+
|
|
+OPENTELEMETRY_BEGIN_NAMESPACE
|
|
+namespace internal_threadlocal
|
|
+{
|
|
+
|
|
+// One key used by the entire process to attach destructors on thread exit.
|
|
+static pthread_key_t destructors_key;
|
|
+
|
|
+static std::once_flag once_init;
|
|
+
|
|
+namespace
|
|
+{
|
|
+// List of destructors for all thread locals instantiated on a given thread.
|
|
+struct PerThreadDestructorList
|
|
+{
|
|
+ void (*destructor)(void *);
|
|
+ void *arg;
|
|
+ PerThreadDestructorList *next;
|
|
+};
|
|
+
|
|
+} // anonymous namespace
|
|
+
|
|
+// Call all the destructors associated with all THREAD_LOCAL instances in this thread.
|
|
+static void InvokeDestructors(void *t)
|
|
+{
|
|
+ auto *d = reinterpret_cast<PerThreadDestructorList *>(t);
|
|
+ while (d != nullptr)
|
|
+ {
|
|
+ d->destructor(d->arg);
|
|
+ PerThreadDestructorList *next = d->next;
|
|
+ delete d;
|
|
+ d = next;
|
|
+ }
|
|
+}
|
|
+
|
|
+// This key must be initialized only once.
|
|
+static void CreateKey()
|
|
+{
|
|
+ int ret = pthread_key_create(&destructors_key, &InvokeDestructors);
|
|
+ // Linux supports up to 1024 keys, we will use only one for all thread locals.
|
|
+ if (ret != 0)
|
|
+ {
|
|
+ std::stringstream ss;
|
|
+ ss << "[thread local] pthread_key_create() failed, cannot add destructor to thread: "
|
|
+ << "error " << ret;
|
|
+ OTEL_INTERNAL_LOG_ERROR(ss.str());
|
|
+ }
|
|
+}
|
|
+
|
|
+// Adds a destructor to the list.
|
|
+void AddDestructor(void (*destructor)(void *), void *arg)
|
|
+{
|
|
+ std::call_once(once_init, &CreateKey);
|
|
+
|
|
+ // Returns NULL if nothing is set yet.
|
|
+ std::unique_ptr<PerThreadDestructorList> p(new PerThreadDestructorList());
|
|
+ p->destructor = destructor;
|
|
+ p->arg = arg;
|
|
+ p->next = reinterpret_cast<PerThreadDestructorList *>(pthread_getspecific(destructors_key));
|
|
+ int ret = pthread_setspecific(destructors_key, p.release());
|
|
+ // The only time this check should fail is if we are out of memory, or if
|
|
+ // somehow key creation failed, which should be caught by the above CHECK.
|
|
+ if (ret != 0)
|
|
+ {
|
|
+ std::stringstream ss;
|
|
+ ss << "[thread local] pthread_setspecific() failed, cannot update destructor list: "
|
|
+ << "error " << ret;
|
|
+ OTEL_INTERNAL_LOG_ERROR(ss.str());
|
|
+ }
|
|
+}
|
|
+} // namespace internal_threadlocal
|
|
+OPENTELEMETRY_END_NAMESPACE
|
|
\ No newline at end of file
|