Skip to content

Commit

Permalink
+ Add log level for internal log of sdk
Browse files Browse the repository at this point in the history
+ Fix document for internal log of sdk
+ Fix crash problem when any provider is destroyed after internal log handle.

Signed-off-by: owentou <[email protected]>
  • Loading branch information
owent committed Dec 20, 2021
1 parent 7b9132c commit 278707f
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 100 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Increment the:

* [EXPORTER] Bugfix: Jaeger exporter: extend supported attributes types ([#1106](https:/open-telemetry/opentelemetry-cpp/pull/1106))
* [EXPORTER] Fix otlp generates null span ids ([#1106](https:/open-telemetry/opentelemetry-cpp/pull/1106))
* [SDK] Add LogLevel to internal_log ([#1138](https:/open-telemetry/opentelemetry-cpp/issues/1138))

## [1.1.0] 2021-11-19

Expand Down
24 changes: 13 additions & 11 deletions docs/public/sdk/GettingStarted.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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());
opentelemetry::sdk::common::internal_log::GlobalLogHandler::SetLogHandler(CustomLogHandler());
opentelemetry::sdk::common::internal_log::GlobalLogHandler::SetLogLevel(opentelemetry::sdk::common::internal_log::LogLevel::Debug);
180 changes: 94 additions & 86 deletions sdk/include/opentelemetry/sdk/common/global_log_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,12 @@

#include <iostream>
#include <sstream>
#include <utility>

#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
{
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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<LogHandler> GetLogHandler() noexcept
static const nostd::shared_ptr<LogHandler> &GetLogHandler() noexcept
{
return nostd::shared_ptr<LogHandler>(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<LogHandler> eh) noexcept { GetHandler() = eh; }
static void SetLogHandler(nostd::shared_ptr<LogHandler> 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<LogHandler> &GetHandler() noexcept
static std::pair<nostd::shared_ptr<LogHandler>, LogLevel> &GetHandlerAndLevel() noexcept
{
static nostd::shared_ptr<LogHandler> handler(new DefaultLogHandler);
return handler;
static std::pair<nostd::shared_ptr<LogHandler>, LogLevel> handler_and_level{
nostd::shared_ptr<LogHandler>(new DefaultLogHandler), LogLevel::Warning};
return handler_and_level;
}
};

Expand All @@ -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<LogHandler> &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__)
13 changes: 13 additions & 0 deletions sdk/test/common/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -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",
],
)
12 changes: 9 additions & 3 deletions sdk/test/common/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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(
Expand Down
57 changes: 57 additions & 0 deletions sdk/test/common/global_log_handle_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#include "opentelemetry/sdk/common/global_log_handler.h"

#include <gtest/gtest.h>

#include <cstring>

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<LogHandler>(new CustomLogHandler{});
opentelemetry::sdk::common::internal_log::GlobalLogHandler::SetLogHandler(custom_log_handler);
auto before_count = static_cast<CustomLogHandler *>(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<CustomLogHandler *>(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<CustomLogHandler *>(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);
}

0 comments on commit 278707f

Please sign in to comment.