From 278707f265eca03b048262088368bb45b887f3ed Mon Sep 17 00:00:00 2001 From: owentou Date: Fri, 17 Dec 2021 16:39:50 +0800 Subject: [PATCH] + Add log level for internal log of sdk + Fix document for internal log of sdk + Fix crash problem when any provider is destroyed after internal log handle. Signed-off-by: owentou --- CHANGELOG.md | 1 + docs/public/sdk/GettingStarted.rst | 24 +-- .../sdk/common/global_log_handler.h | 180 +++++++++--------- sdk/test/common/BUILD | 13 ++ sdk/test/common/CMakeLists.txt | 12 +- sdk/test/common/global_log_handle_test.cc | 57 ++++++ 6 files changed, 187 insertions(+), 100 deletions(-) create mode 100644 sdk/test/common/global_log_handle_test.cc diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e5f88f9c4..ade957c314 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Increment the: * [EXPORTER] Bugfix: Jaeger exporter: extend supported attributes types ([#1106](https://github.com/open-telemetry/opentelemetry-cpp/pull/1106)) * [EXPORTER] Fix otlp generates null span ids ([#1106](https://github.com/open-telemetry/opentelemetry-cpp/pull/1106)) +* [SDK] Add LogLevel to internal_log ([#1138](https://github.com/open-telemetry/opentelemetry-cpp/issues/1138)) ## [1.1.0] 2021-11-19 diff --git a/docs/public/sdk/GettingStarted.rst b/docs/public/sdk/GettingStarted.rst index dc982fc391..6e7b6f0916 100644 --- a/docs/public/sdk/GettingStarted.rst +++ b/docs/public/sdk/GettingStarted.rst @@ -195,27 +195,29 @@ and it can be changed at compile time. .. code:: cpp - OTEL_INTERNAL_LOG_ERROR - (" Connection failed. Error string " << error_str << " Error Num: " << errorno); - OTEL_INTERNAL_LOG_ERROR - (" Connection failed." , {{"error message: " : error_str},{"error number": errorno}}); - OTEL_INTERNAL_LOG_DEBUG - (" Connection Established Successfully. Headers:", {{"url", url},{"content-length", len}, {"content-type", type}}); + OTEL_INTERNAL_LOG_ERROR(" Connection failed. Error string " << error_str << " Error Num: " << errorno); + opentelemetry::sdk::common::AttributeMap error_attributes = { + {"url", url}, {"content-length", len}, {"content-type", type}}; + OTEL_INTERNAL_LOG_ERROR(" Connection failed." , error_attributes); + opentelemetry::sdk::common::AttributeMap http_attributes = { + {"url", url}, {"content-length", len}, {"content-type", type}}; + OTEL_INTERNAL_LOG_DEBUG(" Connection Established Successfully. Headers:", http_attributes); -The custom log handler can be defined by inheriting from `sdk::common::internal_log::LogHandler` class. +The custom log handler can be defined by inheriting from `opentelemetry::sdk::common::internal_log::LogHandler` class. .. code:: cpp - class CustomLogHandler : public sdk::common::internal_log::LogHandler + class CustomLogHandler : public opentelemetry::sdk::common::internal_log::LogHandler { - void Handle(Loglevel level, + void Handle(opentelemetry::sdk::common::internal_log::LogLevel level, const char \*file, int line, const char \*msg, - const sdk::common::AttributeMap &attributes) + const opentelemetry::sdk::common::AttributeMap &attributes) noexcept override { // add implementation here } }; - sdk::common::internal_log::GlobalLogHandler::SetLogHandler(CustomLogHandler()); \ No newline at end of file + opentelemetry::sdk::common::internal_log::GlobalLogHandler::SetLogHandler(CustomLogHandler()); + opentelemetry::sdk::common::internal_log::GlobalLogHandler::SetLogLevel(opentelemetry::sdk::common::internal_log::LogLevel::Debug); \ No newline at end of file diff --git a/sdk/include/opentelemetry/sdk/common/global_log_handler.h b/sdk/include/opentelemetry/sdk/common/global_log_handler.h index 0ef5d54c46..37f6901934 100644 --- a/sdk/include/opentelemetry/sdk/common/global_log_handler.h +++ b/sdk/include/opentelemetry/sdk/common/global_log_handler.h @@ -5,20 +5,12 @@ #include #include +#include #include "opentelemetry/nostd/shared_ptr.h" #include "opentelemetry/sdk/common/attribute_utils.h" #include "opentelemetry/version.h" -#define OTEL_INTERNAL_LOG_LEVEL_ERROR 0 -#define OTEL_INTERNAL_LOG_LEVEL_WARN 1 -#define OTEL_INTERNAL_LOG_LEVEL_INFO 2 -#define OTEL_INTERNAL_LOG_LEVEL_DEBUG 3 // to be disabled in release - -#ifndef OTEL_INTERNAL_LOG_LEVEL -# define OTEL_INTERNAL_LOG_LEVEL OTEL_INTERNAL_LOG_LEVEL_WARN // ERROR and WARN -#endif - OPENTELEMETRY_BEGIN_NAMESPACE namespace sdk { @@ -54,6 +46,8 @@ inline std::string LevelToString(LogLevel level) class LogHandler { public: + virtual ~LogHandler() = default; + virtual void Handle(LogLevel level, const char *file, int line, @@ -108,26 +102,43 @@ class GlobalLogHandler /** * Returns the singleton LogHandler. * - * By default, a default LogHandler is returned. This will never return a - * nullptr LogHandler. + * By default, a default LogHandler is returned. */ - static nostd::shared_ptr GetLogHandler() noexcept + static const nostd::shared_ptr &GetLogHandler() noexcept { - return nostd::shared_ptr(GetHandler()); + return GetHandlerAndLevel().first; } /** * Changes the singleton LogHandler. - * This should be called once at the start of application before creating TracerProvider + * This should be called once at the start of application before creating any Provider * instance. */ - static void SetLogHandler(nostd::shared_ptr eh) noexcept { GetHandler() = eh; } + static void SetLogHandler(nostd::shared_ptr eh) noexcept + { + GetHandlerAndLevel().first = eh; + } + + /** + * Returns the singleton log level. + * + * By default, a default log level is returned. + */ + static LogLevel GetLogLevel() noexcept { return GetHandlerAndLevel().second; } + + /** + * Changes the singleton Log level. + * This should be called once at the start of application before creating any Provider + * instance. + */ + static void SetLogLevel(LogLevel level) noexcept { GetHandlerAndLevel().second = level; } private: - static nostd::shared_ptr &GetHandler() noexcept + static std::pair, LogLevel> &GetHandlerAndLevel() noexcept { - static nostd::shared_ptr handler(new DefaultLogHandler); - return handler; + static std::pair, LogLevel> handler_and_level{ + nostd::shared_ptr(new DefaultLogHandler), LogLevel::Warning}; + return handler_and_level; } }; @@ -136,74 +147,71 @@ class GlobalLogHandler } // namespace sdk OPENTELEMETRY_END_NAMESPACE -#define OTEL_INTERNAL_LOG_DISPATCH(level, message, attributes) \ - do \ - { \ - using namespace opentelemetry::sdk::common::internal_log; \ - std::stringstream tmp_stream; \ - tmp_stream << message; \ - GlobalLogHandler::GetLogHandler()->Handle(level, __FILE__, __LINE__, tmp_stream.str().c_str(), \ - attributes); \ - } while (0) +/** + * We can not decide the destroying order of signaltons. + * Which means, the destructors of other singletons (GlobalLogHandler,TracerProvider and etc.) + * may be called after destroying of global LogHandler and use OTEL_INTERNAL_LOG_* in it.We can do + * nothing but ignore the log in this situation. + */ +#define OTEL_INTERNAL_LOG_DISPATCH(level, message, attributes) \ + do \ + { \ + using opentelemetry::sdk::common::internal_log::GlobalLogHandler; \ + using opentelemetry::sdk::common::internal_log::LogHandler; \ + if (level > GlobalLogHandler::GetLogLevel()) \ + { \ + break; \ + } \ + const opentelemetry::nostd::shared_ptr &log_handler = \ + GlobalLogHandler::GetLogHandler(); \ + if (!log_handler) \ + { \ + break; \ + } \ + std::stringstream tmp_stream; \ + tmp_stream << message; \ + log_handler->Handle(level, __FILE__, __LINE__, tmp_stream.str().c_str(), attributes); \ + } while (false); #define OTEL_INTERNAL_LOG_GET_3RD_ARG(arg1, arg2, arg3, ...) arg3 -#if OTEL_INTERNAL_LOG_LEVEL >= OTEL_INTERNAL_LOG_LEVEL_ERROR -# define OTEL_INTERNAL_LOG_ERROR_1_ARGS(message) \ - OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Error, message, \ - {}) -# define OTEL_INTERNAL_LOG_ERROR_2_ARGS(message, attributes) \ - OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Error, message, \ - attributes) -# define OTEL_INTERNAL_LOG_ERROR_MACRO(...) \ - OTEL_INTERNAL_LOG_GET_3RD_ARG(__VA_ARGS__, OTEL_INTERNAL_LOG_ERROR_2_ARGS, \ - OTEL_INTERNAL_LOG_ERROR_1_ARGS) -# define OTEL_INTERNAL_LOG_ERROR(...) OTEL_INTERNAL_LOG_ERROR_MACRO(__VA_ARGS__)(__VA_ARGS__) -#else -# define OTEL_INTERNAL_LOG_ERROR(...) -#endif - -#if OTEL_INTERNAL_LOG_LEVEL >= OTEL_INTERNAL_LOG_LEVEL_WARN -# define OTEL_INTERNAL_LOG_WARN_1_ARGS(message) \ - OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Warning, \ - message, {}) -# define OTEL_INTERNAL_LOG_WARN_2_ARGS(message, attributes) \ - OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Warning, \ - message, attributes) -# define OTEL_INTERNAL_LOG_WARN_MACRO(...) \ - OTEL_INTERNAL_LOG_GET_3RD_ARG(__VA_ARGS__, OTEL_INTERNAL_LOG_WARN_2_ARGS, \ - OTEL_INTERNAL_LOG_WARN_1_ARGS) -# define OTEL_INTERNAL_LOG_WARN(...) OTEL_INTERNAL_LOG_WARN_MACRO(__VA_ARGS__)(__VA_ARGS__) -#else -# define OTEL_INTERNAL_LOG_ERROR(...) -#endif - -#if OTEL_INTERNAL_LOG_LEVEL >= OTEL_INTERNAL_LOG_LEVEL_DEBUG -# define OTEL_INTERNAL_LOG_DEBUG_1_ARGS(message) \ - OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Debug, message, \ - {}) -# define OTEL_INTERNAL_LOG_DEBUG_2_ARGS(message, attributes) \ - OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_logg::LogLevel::Debug, \ - message, attributes) -# define OTEL_INTERNAL_LOG_DEBUG_MACRO(...) \ - OTEL_INTERNAL_LOG_GET_3RD_ARG(__VA_ARGS__, OTEL_INTERNAL_LOG_DEBUG_2_ARGS, \ - OTEL_INTERNAL_LOG_DEBUG_1_ARGS) -# define OTEL_INTERNAL_LOG_DEBUG(...) OTEL_INTERNAL_LOG_DEBUG_MACRO(__VA_ARGS__)(__VA_ARGS__) -#else -# define OTEL_INTERNAL_LOG_DEBUG(...) -#endif - -#if OTEL_INTERNAL_LOG_LEVEL >= OTEL_INTERNAL_LOG_LEVEL_INFO -# define OTEL_INTERNAL_LOG_INFO_1_ARGS(message) \ - OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_logger::LogLevel::Info, \ - message, {}) -# define OTEL_INTERNAL_LOG_INFO_2_ARGS(message, attributes) \ - OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_logger::LogLevel::Info, \ - message, attributes) -# define OTEL_INTERNAL_LOG_INFO_MACRO(...) \ - OTEL_INTERNAL_LOG_GET_3RD_ARG(__VA_ARGS__, OTEL_INTERNAL_LOG_ERROR_2_ARGS, \ - OTEL_INTERNAL_LOG_ERROR_1_ARGS) -# define OTEL_INTERNAL_LOG_INFO(...) OTEL_INTERNAL_LOG_INFO_MACRO(__VA_ARGS__)(__VA_ARGS__) -#else -# define OTEL_INTERNAL_LOG_INFO(...) -#endif +#define OTEL_INTERNAL_LOG_ERROR_1_ARGS(message) \ + OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Error, message, {}) +#define OTEL_INTERNAL_LOG_ERROR_2_ARGS(message, attributes) \ + OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Error, message, \ + attributes) +#define OTEL_INTERNAL_LOG_ERROR_MACRO(...) \ + OTEL_INTERNAL_LOG_GET_3RD_ARG(__VA_ARGS__, OTEL_INTERNAL_LOG_ERROR_2_ARGS, \ + OTEL_INTERNAL_LOG_ERROR_1_ARGS) +#define OTEL_INTERNAL_LOG_ERROR(...) OTEL_INTERNAL_LOG_ERROR_MACRO(__VA_ARGS__)(__VA_ARGS__) + +#define OTEL_INTERNAL_LOG_WARN_1_ARGS(message) \ + OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Warning, message, \ + {}) +#define OTEL_INTERNAL_LOG_WARN_2_ARGS(message, attributes) \ + OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Warning, message, \ + attributes) +#define OTEL_INTERNAL_LOG_WARN_MACRO(...) \ + OTEL_INTERNAL_LOG_GET_3RD_ARG(__VA_ARGS__, OTEL_INTERNAL_LOG_WARN_2_ARGS, \ + OTEL_INTERNAL_LOG_WARN_1_ARGS) +#define OTEL_INTERNAL_LOG_WARN(...) OTEL_INTERNAL_LOG_WARN_MACRO(__VA_ARGS__)(__VA_ARGS__) + +#define OTEL_INTERNAL_LOG_DEBUG_1_ARGS(message) \ + OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Debug, message, {}) +#define OTEL_INTERNAL_LOG_DEBUG_2_ARGS(message, attributes) \ + OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Debug, message, \ + attributes) +#define OTEL_INTERNAL_LOG_DEBUG_MACRO(...) \ + OTEL_INTERNAL_LOG_GET_3RD_ARG(__VA_ARGS__, OTEL_INTERNAL_LOG_DEBUG_2_ARGS, \ + OTEL_INTERNAL_LOG_DEBUG_1_ARGS) +#define OTEL_INTERNAL_LOG_DEBUG(...) OTEL_INTERNAL_LOG_DEBUG_MACRO(__VA_ARGS__)(__VA_ARGS__) + +#define OTEL_INTERNAL_LOG_INFO_1_ARGS(message) \ + OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Info, message, {}) +#define OTEL_INTERNAL_LOG_INFO_2_ARGS(message, attributes) \ + OTEL_INTERNAL_LOG_DISPATCH(opentelemetry::sdk::common::internal_log::LogLevel::Info, message, \ + attributes) +#define OTEL_INTERNAL_LOG_INFO_MACRO(...) \ + OTEL_INTERNAL_LOG_GET_3RD_ARG(__VA_ARGS__, OTEL_INTERNAL_LOG_ERROR_2_ARGS, \ + OTEL_INTERNAL_LOG_ERROR_1_ARGS) +#define OTEL_INTERNAL_LOG_INFO(...) OTEL_INTERNAL_LOG_INFO_MACRO(__VA_ARGS__)(__VA_ARGS__) diff --git a/sdk/test/common/BUILD b/sdk/test/common/BUILD index 14cfd0c67d..57a84339fd 100644 --- a/sdk/test/common/BUILD +++ b/sdk/test/common/BUILD @@ -114,3 +114,16 @@ cc_test( "@com_google_googletest//:gtest_main", ], ) + +cc_test( + name = "global_log_handle_test", + srcs = [ + "global_log_handle_test.cc", + ], + tags = ["test"], + deps = [ + "//api", + "//sdk:headers", + "@com_google_googletest//:gtest_main", + ], +) diff --git a/sdk/test/common/CMakeLists.txt b/sdk/test/common/CMakeLists.txt index 2782402f12..40a195804e 100644 --- a/sdk/test/common/CMakeLists.txt +++ b/sdk/test/common/CMakeLists.txt @@ -1,6 +1,12 @@ -foreach(testname - random_test fast_random_number_generator_test atomic_unique_ptr_test - circular_buffer_range_test circular_buffer_test attribute_utils_test) +foreach( + testname + random_test + fast_random_number_generator_test + atomic_unique_ptr_test + circular_buffer_range_test + circular_buffer_test + attribute_utils_test + global_log_handle_test) add_executable(${testname} "${testname}.cc") target_link_libraries( diff --git a/sdk/test/common/global_log_handle_test.cc b/sdk/test/common/global_log_handle_test.cc new file mode 100644 index 0000000000..9c24b0234e --- /dev/null +++ b/sdk/test/common/global_log_handle_test.cc @@ -0,0 +1,57 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#include "opentelemetry/sdk/common/global_log_handler.h" + +#include + +#include + +class CustomLogHandler : public opentelemetry::sdk::common::internal_log::LogHandler +{ +public: + void Handle(opentelemetry::sdk::common::internal_log::LogLevel level, + const char *, + int, + const char *msg, + const opentelemetry::sdk::common::AttributeMap &) noexcept override + { + if (level == opentelemetry::sdk::common::internal_log::LogLevel::Debug) + { + EXPECT_EQ(0, strncmp(msg, "Debug message", 13)); + } + else if (level == opentelemetry::sdk::common::internal_log::LogLevel::Error) + { + EXPECT_EQ(0, strncmp(msg, "Error message", 13)); + } + ++count; + } + + size_t count = 0; +}; + +TEST(GlobalLogHandleTest, CustomLogHandler) +{ + using opentelemetry::sdk::common::internal_log::LogHandler; + auto backup_log_handle = + opentelemetry::sdk::common::internal_log::GlobalLogHandler::GetLogHandler(); + auto backup_log_level = opentelemetry::sdk::common::internal_log::GlobalLogHandler::GetLogLevel(); + + auto custom_log_handler = opentelemetry::nostd::shared_ptr(new CustomLogHandler{}); + opentelemetry::sdk::common::internal_log::GlobalLogHandler::SetLogHandler(custom_log_handler); + auto before_count = static_cast(custom_log_handler.get())->count; + opentelemetry::sdk::common::AttributeMap attributes = { + {"url", "https://opentelemetry.io/"}, {"content-length", 0}, {"content-type", "text/html"}}; + OTEL_INTERNAL_LOG_ERROR("Error message"); + OTEL_INTERNAL_LOG_DEBUG("Debug message. Headers:", attributes); + EXPECT_EQ(before_count + 1, static_cast(custom_log_handler.get())->count); + + opentelemetry::sdk::common::internal_log::GlobalLogHandler::SetLogLevel( + opentelemetry::sdk::common::internal_log::LogLevel::Debug); + OTEL_INTERNAL_LOG_ERROR("Error message"); + OTEL_INTERNAL_LOG_DEBUG("Debug message. Headers:", attributes); + EXPECT_EQ(before_count + 3, static_cast(custom_log_handler.get())->count); + + opentelemetry::sdk::common::internal_log::GlobalLogHandler::SetLogHandler(backup_log_handle); + opentelemetry::sdk::common::internal_log::GlobalLogHandler::SetLogLevel(backup_log_level); +}