Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add log level for internal log of sdk #1147

Merged
merged 4 commits into from
Jan 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ Increment the:

## [Unreleased]

## [1.1.1] 2021-12-20
* [SDK] Add LogLevel to internal_log ([#1147](https:/open-telemetry/opentelemetry-cpp/pull/1147))

## [1.1.1] 2021-12-

* [SDK] Rename OTEL_CPP_GET_ATTR macro, and define it using fully qualified attr function ([#1140](https:/open-telemetry/opentelemetry-cpp/pull/1140))
* [SDK] Default resource attributes and attributes in OTEL_RESOURCE_ATTRIBUTES are missing when using Otlp*LogExporter ([#1082](https:/open-telemetry/opentelemetry-cpp/pull/1082))
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);
96 changes: 66 additions & 30 deletions sdk/include/opentelemetry/sdk/common/global_log_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

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

#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/sdk/common/attribute_utils.h"
Expand All @@ -13,10 +14,10 @@
#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

#define OTEL_INTERNAL_LOG_LEVEL_DEBUG 3
#ifndef OTEL_INTERNAL_LOG_LEVEL
# define OTEL_INTERNAL_LOG_LEVEL OTEL_INTERNAL_LOG_LEVEL_WARN // ERROR and WARN
// DEBUG by default, we can change log level on runtime
# define OTEL_INTERNAL_LOG_LEVEL OTEL_INTERNAL_LOG_LEVEL_DEBUG
#endif

OPENTELEMETRY_BEGIN_NAMESPACE
Expand Down Expand Up @@ -54,6 +55,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 +111,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,15 +156,31 @@ 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

Expand Down Expand Up @@ -182,9 +218,9 @@ OPENTELEMETRY_END_NAMESPACE
# 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_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)
Expand All @@ -194,12 +230,12 @@ OPENTELEMETRY_END_NAMESPACE
#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_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)
Expand Down
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);
}