From 65ebdb1e613a031aafe737a6721f0da3c71ebf0a Mon Sep 17 00:00:00 2001 From: WenTao Ou Date: Sun, 29 Jan 2023 01:29:36 +0800 Subject: [PATCH] Update logs sdk and api to follow specification (#1884) --- CHANGELOG.md | 1 + .../opentelemetry/common/key_value_iterable.h | 27 + api/include/opentelemetry/logs/event_logger.h | 94 +++ .../logs/event_logger_provider.h | 36 + api/include/opentelemetry/logs/logger.h | 708 ++++++------------ .../opentelemetry/logs/logger_provider.h | 44 +- .../opentelemetry/logs/logger_type_traits.h | 196 +++++ api/include/opentelemetry/logs/noop.h | 47 +- api/include/opentelemetry/logs/provider.h | 29 + api/test/logs/logger_test.cc | 106 ++- api/test/logs/provider_test.cc | 72 +- .../common/logs_foo_library/foo_library.cc | 8 +- .../opentelemetry/exporters/etw/etw_logger.h | 39 +- exporters/etw/test/etw_logger_test.cc | 10 +- exporters/ostream/test/ostream_log_test.cc | 4 +- .../otlp_grpc_log_record_exporter_test.cc | 9 +- .../otlp_http_log_record_exporter_test.cc | 168 +++-- .../opentelemetry/sdk/logs/event_logger.h | 52 ++ .../sdk/logs/event_logger_provider.h | 37 + .../sdk/logs/event_logger_provider_factory.h | 32 + sdk/include/opentelemetry/sdk/logs/logger.h | 5 +- .../opentelemetry/sdk/logs/logger_provider.h | 24 +- sdk/src/logs/CMakeLists.txt | 3 + sdk/src/logs/event_logger.cc | 56 ++ sdk/src/logs/event_logger_provider.cc | 41 + sdk/src/logs/event_logger_provider_factory.cc | 24 + sdk/src/logs/logger.cc | 46 +- sdk/src/logs/logger_provider.cc | 18 +- sdk/test/logs/BUILD | 1 + sdk/test/logs/CMakeLists.txt | 5 +- sdk/test/logs/logger_provider_sdk_test.cc | 34 +- sdk/test/logs/logger_sdk_test.cc | 137 +++- 32 files changed, 1346 insertions(+), 767 deletions(-) create mode 100644 api/include/opentelemetry/logs/event_logger.h create mode 100644 api/include/opentelemetry/logs/event_logger_provider.h create mode 100644 api/include/opentelemetry/logs/logger_type_traits.h create mode 100644 sdk/include/opentelemetry/sdk/logs/event_logger.h create mode 100644 sdk/include/opentelemetry/sdk/logs/event_logger_provider.h create mode 100644 sdk/include/opentelemetry/sdk/logs/event_logger_provider_factory.h create mode 100644 sdk/src/logs/event_logger.cc create mode 100644 sdk/src/logs/event_logger_provider.cc create mode 100644 sdk/src/logs/event_logger_provider_factory.cc diff --git a/CHANGELOG.md b/CHANGELOG.md index b2c3707cb7..7ab9ad72f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Increment the: ## [Unreleased] +* [LOGS] Add `include_trace_context` and `EventLogger` [#1884](https://github.com/open-telemetry/opentelemetry-cpp/pull/1884) * [METRICS] Change BatchLogRecordProcessorFactory::Create to static method * [BUILD] Fix OTELCPP_MAINTAINER_MODE [#1844](https://github.com/open-telemetry/opentelemetry-cpp/pull/1844) * [BUILD] Fix compatibility when using clang and libc++, upgrade GTest and diff --git a/api/include/opentelemetry/common/key_value_iterable.h b/api/include/opentelemetry/common/key_value_iterable.h index f187f75b86..732d361e7b 100644 --- a/api/include/opentelemetry/common/key_value_iterable.h +++ b/api/include/opentelemetry/common/key_value_iterable.h @@ -32,5 +32,32 @@ class KeyValueIterable */ virtual size_t size() const noexcept = 0; }; + +/** + * Supports internal iteration over a collection of key-value pairs. + */ +class NoopKeyValueIterable : public KeyValueIterable +{ +public: + ~NoopKeyValueIterable() override = default; + + /** + * Iterate over key-value pairs + * @param callback a callback to invoke for each key-value. If the callback returns false, + * the iteration is aborted. + * @return true if every key-value pair was iterated over + */ + bool ForEachKeyValue( + nostd::function_ref) const noexcept override + { + return true; + } + + /** + * @return the number of key-value pairs + */ + size_t size() const noexcept override { return 0; } +}; + } // namespace common OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/logs/event_logger.h b/api/include/opentelemetry/logs/event_logger.h new file mode 100644 index 0000000000..654c6f6c69 --- /dev/null +++ b/api/include/opentelemetry/logs/event_logger.h @@ -0,0 +1,94 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include +# include +# include + +# include "opentelemetry/common/macros.h" +# include "opentelemetry/logs/log_record.h" +# include "opentelemetry/logs/logger.h" +# include "opentelemetry/logs/logger_type_traits.h" +# include "opentelemetry/logs/severity.h" +# include "opentelemetry/nostd/shared_ptr.h" +# include "opentelemetry/nostd/string_view.h" +# include "opentelemetry/nostd/unique_ptr.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace logs +{ +/** + * Handles event log record creation. + **/ +class EventLogger +{ +public: + virtual ~EventLogger() = default; + + /* Returns the name of the logger */ + virtual const nostd::string_view GetName() noexcept = 0; + + /* Returns the delegate logger of this event logger */ + virtual nostd::shared_ptr GetDelegateLogger() noexcept = 0; + + /** + * Emit a event Log Record object + * + * @param event_name Event name + * @param log_record Log record + */ + virtual void EmitEvent(nostd::string_view event_name, + nostd::unique_ptr &&log_record) noexcept = 0; + + /** + * Emit a event Log Record object with arguments + * + * @param event_name Event name + * @tparam args Arguments which can be used to set data of log record by type. + * Severity -> severity, severity_text + * string_view -> body + * AttributeValue -> body + * SpanContext -> span_id,tace_id and trace_flags + * SpanId -> span_id + * TraceId -> tace_id + * TraceFlags -> trace_flags + * SystemTimestamp -> timestamp + * system_clock::time_point -> timestamp + * KeyValueIterable -> attributes + * Key value iterable container -> attributes + * span> -> attributes(return type of MakeAttributes) + */ + template + void EmitEvent(nostd::string_view event_name, ArgumentType &&... args) + { + nostd::shared_ptr delegate_logger = GetDelegateLogger(); + if (!delegate_logger) + { + return; + } + nostd::unique_ptr log_record = delegate_logger->CreateLogRecord(); + if (!log_record) + { + return; + } + + IgnoreTraitResult( + detail::LogRecordSetterTrait::type>::template Set( + log_record.get(), std::forward(args))...); + + EmitEvent(event_name, std::move(log_record)); + } + +private: + template + void IgnoreTraitResult(ValueType &&...) + {} +}; +} // namespace logs +OPENTELEMETRY_END_NAMESPACE + +#endif diff --git a/api/include/opentelemetry/logs/event_logger_provider.h b/api/include/opentelemetry/logs/event_logger_provider.h new file mode 100644 index 0000000000..8692222c10 --- /dev/null +++ b/api/include/opentelemetry/logs/event_logger_provider.h @@ -0,0 +1,36 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include "opentelemetry/common/key_value_iterable.h" +# include "opentelemetry/common/key_value_iterable_view.h" +# include "opentelemetry/logs/event_logger.h" +# include "opentelemetry/logs/logger.h" +# include "opentelemetry/nostd/shared_ptr.h" +# include "opentelemetry/nostd/string_view.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace logs +{ +/** + * Creates new EventLogger instances. + */ +class EventLoggerProvider +{ +public: + virtual ~EventLoggerProvider() = default; + + /** + * Creates a named EventLogger instance. + * + */ + + virtual nostd::shared_ptr CreateEventLogger( + nostd::shared_ptr delegate_logger, + nostd::string_view event_domain) noexcept = 0; +}; +} // namespace logs +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/api/include/opentelemetry/logs/logger.h b/api/include/opentelemetry/logs/logger.h index a8342e3f71..e62fbe1156 100644 --- a/api/include/opentelemetry/logs/logger.h +++ b/api/include/opentelemetry/logs/logger.h @@ -14,6 +14,7 @@ # include "opentelemetry/common/macros.h" # include "opentelemetry/common/timestamp.h" # include "opentelemetry/logs/log_record.h" +# include "opentelemetry/logs/logger_type_traits.h" # include "opentelemetry/logs/severity.h" # include "opentelemetry/nostd/shared_ptr.h" # include "opentelemetry/nostd/span.h" @@ -35,578 +36,289 @@ namespace logs class Logger { public: - virtual ~Logger() = default; - - /* Returns the name of the logger */ - virtual const nostd::string_view GetName() noexcept = 0; - - /** - * Create a Log Record object - * - * @return nostd::unique_ptr - */ - virtual nostd::unique_ptr CreateLogRecord() noexcept = 0; - - /** - * Emit a Log Record object - * - * @param log_record - */ - virtual void EmitLogRecord(nostd::unique_ptr &&log_record) noexcept = 0; - /** - * Emit a Log Record object with custom span context + * Utility function to help to make a attribute view from initializer_list * - * @param log_record + * @param attributes + * @return nostd::span> */ - virtual void EmitLogRecord(nostd::unique_ptr &&log_record, - const trace::SpanContext &trace_context) + inline static nostd::span> + MakeAttributes(std::initializer_list> + attributes) noexcept { - if (!log_record) - { - return; - } - - log_record->SetSpanId(trace_context.span_id()); - log_record->SetTraceId(trace_context.trace_id()); - log_record->SetTraceFlags(trace_context.trace_flags()); - - EmitLogRecord(std::move(log_record)); + return nostd::span>{ + attributes.begin(), attributes.end()}; } /** + * Utility function to help to make a attribute view from a span * - * @param severity the severity level of the log event. - * @param message the string message of the log (perhaps support std::fmt or fmt-lib format). - * @param attributes the attributes, stored as a 2D list of key/value pairs, that are associated - * with the log event. - * @param trace_id the trace id associated with the log event. - * @param span_id the span id associate with the log event. - * @param trace_flags the trace flags associated with the log event. - * @param timestamp the timestamp the log record was created. - * @throws No exceptions under any circumstances. + * @param attributes + * @return nostd::span> */ - virtual void Log(Severity severity, - nostd::string_view body, - const common::KeyValueIterable &attributes, - trace::TraceId trace_id, - trace::SpanId span_id, - trace::TraceFlags trace_flags, - common::SystemTimestamp timestamp) noexcept + inline static nostd::span> + MakeAttributes( + nostd::span> attributes) noexcept { - nostd::unique_ptr log_record = CreateLogRecord(); - if (!log_record) - { - return; - } - - log_record->SetSeverity(severity); - log_record->SetBody(body); - log_record->SetTimestamp(timestamp); - - if (trace_id.IsValid()) - { - log_record->SetTraceId(trace_id); - log_record->SetTraceFlags(trace_flags); - } - - if (span_id.IsValid()) - { - log_record->SetSpanId(span_id); - } - - attributes.ForEachKeyValue( - [&log_record](nostd::string_view key, common::AttributeValue value) noexcept { - log_record->SetAttribute(key, value); - return true; - }); - - EmitLogRecord(std::move(log_record)); + return attributes; } /** + * Utility function to help to make a attribute view from a KeyValueIterable * - * @param severity the severity level of the log event. - * @param message the string message of the log (perhaps support std::fmt or fmt-lib format). - * @param attributes the attributes, stored as a 2D list of key/value pairs, that are associated - * with the log event. - * @param timestamp the timestamp the log record was created. - * @throws No exceptions under any circumstances. + * @param attributes + * @return common::KeyValueIterable */ - virtual void Log(Severity severity, - nostd::string_view body, - const common::KeyValueIterable &attributes, - common::SystemTimestamp timestamp) noexcept + inline static const common::KeyValueIterable &MakeAttributes( + const common::KeyValueIterable &attributes) noexcept { - nostd::unique_ptr log_record = CreateLogRecord(); - if (!log_record) - { - return; - } - - log_record->SetSeverity(severity); - log_record->SetBody(body); - log_record->SetTimestamp(timestamp); - - attributes.ForEachKeyValue( - [&log_record](nostd::string_view key, common::AttributeValue value) noexcept { - log_record->SetAttribute(key, value); - return true; - }); - - EmitLogRecord(std::move(log_record)); + return attributes; } - /*** Overloaded methods for KeyValueIterables ***/ /** - * The secondary base Log(...) method that all other Log(...) overloaded methods except the one - * above will eventually call, in order to create a log record. + * Utility function to help to make a attribute view from a key-value iterable object + * + * @param attributes + * @return nostd::span> */ - template ::value> * = nullptr> - void Log(Severity severity, - nostd::string_view body, - const T &attributes, - trace::TraceId trace_id, - trace::SpanId span_id, - trace::TraceFlags trace_flags, - common::SystemTimestamp timestamp) noexcept + template < + class ArgumentType, + nostd::enable_if_t::value> * = nullptr> + inline static common::KeyValueIterableView MakeAttributes( + const ArgumentType &arg) noexcept { - Log(severity, body, common::KeyValueIterableView(attributes), trace_id, span_id, trace_flags, - timestamp); + return common::KeyValueIterableView(arg); } - template ::value> * = nullptr> - void Log(Severity severity, - nostd::string_view body, - const T &attributes, - common::SystemTimestamp timestamp) noexcept - { - Log(severity, body, common::KeyValueIterableView(attributes), timestamp); - } - - void Log(Severity severity, - nostd::string_view body, - std::initializer_list> attributes, - trace::TraceId trace_id, - trace::SpanId span_id, - trace::TraceFlags trace_flags, - common::SystemTimestamp timestamp) noexcept - { - return this->Log(severity, body, - nostd::span>{ - attributes.begin(), attributes.end()}, - trace_id, span_id, trace_flags, timestamp); - } - - /** Wrapper methods that the user could call for convenience when logging **/ - - /** - * Writes a log. - * @param severity The severity of the log - * @param message The message to log - */ - void Log(Severity severity, nostd::string_view message) noexcept - { - this->Log(severity, message, - nostd::span>{}, - std::chrono::system_clock::now()); - } + virtual ~Logger() = default; - /** - * Writes a log. - * @param severity The severity of the log - * @param attributes The attributes of the log as a key/value object - */ - template ::value> * = nullptr> - void Log(Severity severity, const T &attributes) noexcept - { - this->Log(severity, "", attributes, std::chrono::system_clock::now()); - } + /* Returns the name of the logger */ + virtual const nostd::string_view GetName() noexcept = 0; /** - * Writes a log. - * @param severity The severity of the log - * @param message The message to log - * @param attributes The attributes of the log as a key/value object + * Create a Log Record object + * + * @return nostd::unique_ptr */ - template ::value> * = nullptr> - void Log(Severity severity, nostd::string_view message, const T &attributes) noexcept - { - this->Log(severity, message, attributes, std::chrono::system_clock::now()); - } + virtual nostd::unique_ptr CreateLogRecord() noexcept = 0; /** - * Writes a log. - * @param severity The severity of the log - * @param attributes The attributes of the log as an initializer list + * Emit a Log Record object + * + * @param log_record */ - void Log(Severity severity, - std::initializer_list> - attributes) noexcept - { - this->Log(severity, "", attributes, std::chrono::system_clock::now()); - } + virtual void EmitLogRecord(nostd::unique_ptr &&log_record) noexcept = 0; /** - * Writes a log. - * @param severity The severity of the log - * @param message The message to log - * @param attributes The attributes of the log as an initializer list - */ - void Log(Severity severity, - nostd::string_view message, - std::initializer_list> - attributes) noexcept + * Emit a Log Record object with arguments + * + * @param log_record Log record + * @tparam args Arguments which can be used to set data of log record by type. + * Severity -> severity, severity_text + * string_view -> body + * AttributeValue -> body + * SpanContext -> span_id,tace_id and trace_flags + * SpanId -> span_id + * TraceId -> tace_id + * TraceFlags -> trace_flags + * SystemTimestamp -> timestamp + * system_clock::time_point -> timestamp + * KeyValueIterable -> attributes + * Key value iterable container -> attributes + * span> -> attributes(return type of MakeAttributes) + */ + template + void EmitLogRecord(nostd::unique_ptr &&log_record, ArgumentType &&... args) { - this->Log(severity, message, attributes, std::chrono::system_clock::now()); - } + if (!log_record) + { + return; + } - /** - * Writes a log. - * @param severity The severity of the log - * @param attributes The attributes, stored as a 2D list of key/value pairs, that are associated - * with the log event - */ - void Log(Severity severity, const common::KeyValueIterable &attributes) noexcept - { - this->Log(severity, "", attributes, std::chrono::system_clock::now()); - } + IgnoreTraitResult( + detail::LogRecordSetterTrait::type>::template Set( + log_record.get(), std::forward(args))...); - /** - * Writes a log. - * @param severity The severity of the log - * @param message The message to log - * @param attributes The attributes, stored as a 2D list of key/value pairs, that are associated - * with the log event - */ - void Log(Severity severity, - nostd::string_view message, - const common::KeyValueIterable &attributes) noexcept - { - this->Log(severity, message, attributes, std::chrono::system_clock::now()); + EmitLogRecord(std::move(log_record)); } - /** Trace severity overloads **/ - /** - * Writes a log with a severity of trace. - * @param message The message to log - */ - void Trace(nostd::string_view message) noexcept { this->Log(Severity::kTrace, message); } - - /** - * Writes a log with a severity of trace. - * @param attributes The attributes of the log as a key/value object - */ - template ::value> * = nullptr> - void Trace(const T &attributes) noexcept + * Emit a Log Record object with arguments + * + * @tparam args Arguments which can be used to set data of log record by type. + * Severity -> severity, severity_text + * string_view -> body + * AttributeValue -> body + * SpanContext -> span_id,tace_id and trace_flags + * SpanId -> span_id + * TraceId -> tace_id + * TraceFlags -> trace_flags + * SystemTimestamp -> timestamp + * system_clock::time_point -> timestamp + * KeyValueIterable -> attributes + * Key value iterable container -> attributes + * span> -> attributes(return type of MakeAttributes) + */ + template + void EmitLogRecord(ArgumentType &&... args) { - this->Log(Severity::kTrace, attributes); - } + nostd::unique_ptr log_record = CreateLogRecord(); + if (!log_record) + { + return; + } - /** - * Writes a log with a severity of trace. - * @param message The message of the log - * @param attributes The attributes of the log as a key/value object - */ - template ::value> * = nullptr> - void Trace(nostd::string_view message, const T &attributes) noexcept - { - this->Log(Severity::kTrace, message, attributes); + EmitLogRecord(std::move(log_record), std::forward(args)...); } /** * Writes a log with a severity of trace. - * @param attributes The attributes of the log as an initializer list + * @tparam args Arguments which can be used to set data of log record by type. + * string_view -> body + * AttributeValue -> body + * SpanContext -> span_id,tace_id and trace_flags + * SpanId -> span_id + * TraceId -> tace_id + * TraceFlags -> trace_flags + * SystemTimestamp -> timestamp + * system_clock::time_point -> timestamp + * KeyValueIterable -> attributes + * Key value iterable container -> attributes + * span> -> attributes(return type of MakeAttributes) */ - void Trace(std::initializer_list> - attributes) noexcept + template + void Trace(ArgumentType &&... args) noexcept { - this->Log(Severity::kTrace, attributes); - } - - /** - * Writes a log with a severity of trace. - * @param message The message of the log - * @param attributes The attributes of the log as an initializer list - */ - void Trace(nostd::string_view message, - std::initializer_list> - attributes) noexcept - { - this->Log(Severity::kTrace, message, attributes); - } - - /** Debug severity overloads **/ - - /** - * Writes a log with a severity of debug. - * @param message The message to log - */ - void Debug(nostd::string_view message) noexcept { this->Log(Severity::kDebug, message); } - - /** - * Writes a log with a severity of debug. - * @param attributes The attributes of the log as a key/value object - */ - template ::value> * = nullptr> - void Debug(const T &attributes) noexcept - { - this->Log(Severity::kDebug, attributes); - } - - /** - * Writes a log with a severity of debug. - * @param message The message of the log - * @param attributes The attributes of the log as a key/value object - */ - template ::value> * = nullptr> - void Debug(nostd::string_view message, const T &attributes) noexcept - { - this->Log(Severity::kDebug, message, attributes); + static_assert( + !detail::LogRecordHasType::type...>::value, + "Severity is already set."); + this->EmitLogRecord(Severity::kTrace, std::forward(args)...); } /** * Writes a log with a severity of debug. - * @param attributes The attributes of the log as an initializer list - */ - void Debug(std::initializer_list> - attributes) noexcept - { - this->Log(Severity::kDebug, attributes); - } - - /** - * Writes a log with a severity of debug. - * @param message The message of the log - * @param attributes The attributes of the log as an initializer list - */ - void Debug(nostd::string_view message, - std::initializer_list> - attributes) noexcept - { - this->Log(Severity::kDebug, message, attributes); - } - - /** Info severity overloads **/ - - /** - * Writes a log with a severity of info. - * @param message The message to log - */ - void Info(nostd::string_view message) noexcept { this->Log(Severity::kInfo, message); } - - /** - * Writes a log with a severity of info. - * @param attributes The attributes of the log as a key/value object - */ - template ::value> * = nullptr> - void Info(const T &attributes) noexcept - { - this->Log(Severity::kInfo, attributes); - } - - /** - * Writes a log with a severity of info. - * @param message The message of the log - * @param attributes The attributes of the log as a key/value object - */ - template ::value> * = nullptr> - void Info(nostd::string_view message, const T &attributes) noexcept - { - this->Log(Severity::kInfo, message, attributes); - } - - /** - * Writes a log with a severity of info. - * @param attributes The attributes of the log as an initializer list + * @tparam args Arguments which can be used to set data of log record by type. + * string_view -> body + * AttributeValue -> body + * SpanContext -> span_id,tace_id and trace_flags + * SpanId -> span_id + * TraceId -> tace_id + * TraceFlags -> trace_flags + * SystemTimestamp -> timestamp + * system_clock::time_point -> timestamp + * KeyValueIterable -> attributes + * Key value iterable container -> attributes + * span> -> attributes(return type of MakeAttributes) */ - void Info(std::initializer_list> - attributes) noexcept + template + void Debug(ArgumentType &&... args) noexcept { - this->Log(Severity::kInfo, attributes); + static_assert( + !detail::LogRecordHasType::type...>::value, + "Severity is already set."); + this->EmitLogRecord(Severity::kDebug, std::forward(args)...); } /** * Writes a log with a severity of info. - * @param message The message of the log - * @param attributes The attributes of the log as an initializer list + * @tparam args Arguments which can be used to set data of log record by type. + * string_view -> body + * AttributeValue -> body + * SpanContext -> span_id,tace_id and trace_flags + * SpanId -> span_id + * TraceId -> tace_id + * TraceFlags -> trace_flags + * SystemTimestamp -> timestamp + * system_clock::time_point -> timestamp + * KeyValueIterable -> attributes + * Key value iterable container -> attributes + * span> -> attributes(return type of MakeAttributes) */ - void Info(nostd::string_view message, - std::initializer_list> - attributes) noexcept + template + void Info(ArgumentType &&... args) noexcept { - this->Log(Severity::kInfo, message, attributes); + static_assert( + !detail::LogRecordHasType::type...>::value, + "Severity is already set."); + this->EmitLogRecord(Severity::kInfo, std::forward(args)...); } - /** Warn severity overloads **/ - - /** - * Writes a log with a severity of warn. - * @param message The message to log - */ - void Warn(nostd::string_view message) noexcept { this->Log(Severity::kWarn, message); } - /** * Writes a log with a severity of warn. - * @param attributes The attributes of the log as a key/value object + * @tparam args Arguments which can be used to set data of log record by type. + * string_view -> body + * AttributeValue -> body + * SpanContext -> span_id,tace_id and trace_flags + * SpanId -> span_id + * TraceId -> tace_id + * TraceFlags -> trace_flags + * SystemTimestamp -> timestamp + * system_clock::time_point -> timestamp + * KeyValueIterable -> attributes + * Key value iterable container -> attributes + * span> -> attributes(return type of MakeAttributes) */ - template ::value> * = nullptr> - void Warn(const T &attributes) noexcept + template + void Warn(ArgumentType &&... args) noexcept { - this->Log(Severity::kWarn, attributes); + static_assert( + !detail::LogRecordHasType::type...>::value, + "Severity is already set."); + this->EmitLogRecord(Severity::kWarn, std::forward(args)...); } - /** - * Writes a log with a severity of warn. - * @param message The message of the log - * @param attributes The attributes of the log as a key/value object - */ - template ::value> * = nullptr> - void Warn(nostd::string_view message, const T &attributes) noexcept - { - this->Log(Severity::kWarn, message, attributes); - } - - /** - * Writes a log with a severity of warn. - * @param attributes The attributes of the log as an initializer list - */ - void Warn(std::initializer_list> - attributes) noexcept - { - this->Log(Severity::kWarn, attributes); - } - - /** - * Writes a log with a severity of warn. - * @param message The message of the log - * @param attributes The attributes of the log as an initializer list - */ - void Warn(nostd::string_view message, - std::initializer_list> - attributes) noexcept - { - this->Log(Severity::kWarn, message, attributes); - } - - /** Error severity overloads **/ - - /** - * Writes a log with a severity of error. - * @param message The message to log - */ - void Error(nostd::string_view message) noexcept { this->Log(Severity::kError, message); } - /** * Writes a log with a severity of error. - * @param attributes The attributes of the log as a key/value object + * @tparam args Arguments which can be used to set data of log record by type. + * string_view -> body + * AttributeValue -> body + * SpanContext -> span_id,tace_id and trace_flags + * SpanId -> span_id + * TraceId -> tace_id + * TraceFlags -> trace_flags + * SystemTimestamp -> timestamp + * system_clock::time_point -> timestamp + * KeyValueIterable -> attributes + * Key value iterable container -> attributes + * span> -> attributes(return type of MakeAttributes) */ - template ::value> * = nullptr> - void Error(const T &attributes) noexcept + template + void Error(ArgumentType &&... args) noexcept { - this->Log(Severity::kError, attributes); + static_assert( + !detail::LogRecordHasType::type...>::value, + "Severity is already set."); + this->EmitLogRecord(Severity::kError, std::forward(args)...); } - /** - * Writes a log with a severity of error. - * @param message The message of the log - * @param attributes The attributes of the log as a key/value object - */ - template ::value> * = nullptr> - void Error(nostd::string_view message, const T &attributes) noexcept - { - this->Log(Severity::kError, message, attributes); - } - - /** - * Writes a log with a severity of error. - * @param attributes The attributes of the log as an initializer list - */ - void Error(std::initializer_list> - attributes) noexcept - { - this->Log(Severity::kError, attributes); - } - - /** - * Writes a log with a severity of error. - * @param message The message of the log - * @param attributes The attributes of the log as an initializer list - */ - void Error(nostd::string_view message, - std::initializer_list> - attributes) noexcept - { - this->Log(Severity::kError, message, attributes); - } - - /** Fatal severity overloads **/ - - /** - * Writes a log with a severity of fatal. - * @param message The message to log - */ - void Fatal(nostd::string_view message) noexcept { this->Log(Severity::kFatal, message); } - /** * Writes a log with a severity of fatal. - * @param attributes The attributes of the log as a key/value object - */ - template ::value> * = nullptr> - void Fatal(const T &attributes) noexcept - { - this->Log(Severity::kFatal, attributes); - } - - /** - * Writes a log with a severity of fatal. - * @param message The message of the log - * @param attributes The attributes of the log as a key/value object - */ - template ::value> * = nullptr> - void Fatal(nostd::string_view message, const T &attributes) noexcept - { - this->Log(Severity::kFatal, message, attributes); - } - - /** - * Writes a log with a severity of fatal. - * @param attributes The attributes of the log as an initializer list - */ - void Fatal(std::initializer_list> - attributes) noexcept - { - this->Log(Severity::kFatal, attributes); - } - - /** - * Writes a log with a severity of fatal. - * @param message The message of the log - * @param attributes The attributes of the log as an initializer list - */ - void Fatal(nostd::string_view message, - std::initializer_list> - attributes) noexcept - { - this->Log(Severity::kFatal, message, attributes); - } + * @tparam args Arguments which can be used to set data of log record by type. + * string_view -> body + * AttributeValue -> body + * SpanContext -> span_id,tace_id and trace_flags + * SpanId -> span_id + * TraceId -> tace_id + * TraceFlags -> trace_flags + * SystemTimestamp -> timestamp + * system_clock::time_point -> timestamp + * KeyValueIterable -> attributes + * Key value iterable container -> attributes + * span> -> attributes(return type of MakeAttributes) + */ + template + void Fatal(ArgumentType &&... args) noexcept + { + static_assert( + !detail::LogRecordHasType::type...>::value, + "Severity is already set."); + this->EmitLogRecord(Severity::kFatal, std::forward(args)...); + } + +private: + template + void IgnoreTraitResult(ValueType &&...) + {} }; } // namespace logs OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/logs/logger_provider.h b/api/include/opentelemetry/logs/logger_provider.h index 5f1795c8ea..7fb56f4964 100644 --- a/api/include/opentelemetry/logs/logger_provider.h +++ b/api/include/opentelemetry/logs/logger_provider.h @@ -4,6 +4,8 @@ #pragma once #ifdef ENABLE_LOGS_PREVIEW +# include "opentelemetry/common/key_value_iterable.h" +# include "opentelemetry/common/key_value_iterable_view.h" # include "opentelemetry/logs/logger.h" # include "opentelemetry/nostd/shared_ptr.h" # include "opentelemetry/nostd/string_view.h" @@ -30,17 +32,39 @@ class LoggerProvider * */ - virtual nostd::shared_ptr GetLogger(nostd::string_view logger_name, - nostd::string_view options, - nostd::string_view library_name, - nostd::string_view library_version = "", - nostd::string_view schema_url = "") = 0; + virtual nostd::shared_ptr GetLogger( + nostd::string_view logger_name, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "", + bool include_trace_context = true, + const common::KeyValueIterable &attributes = common::NoopKeyValueIterable()) = 0; - virtual nostd::shared_ptr GetLogger(nostd::string_view logger_name, - nostd::span args, - nostd::string_view library_name, - nostd::string_view library_version = "", - nostd::string_view schema_url = "") = 0; + nostd::shared_ptr GetLogger( + nostd::string_view logger_name, + nostd::string_view library_name, + nostd::string_view library_version, + nostd::string_view schema_url, + bool include_trace_context, + std::initializer_list> attributes) + { + return GetLogger(logger_name, library_name, library_version, schema_url, include_trace_context, + nostd::span>{ + attributes.begin(), attributes.end()}); + } + + template ::value> * = nullptr> + nostd::shared_ptr GetLogger(nostd::string_view logger_name, + nostd::string_view library_name, + nostd::string_view library_version, + nostd::string_view schema_url, + bool include_trace_context, + const T &attributes) + { + return GetLogger(logger_name, library_name, library_version, schema_url, include_trace_context, + common::KeyValueIterableView(attributes)); + } }; } // namespace logs OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/logs/logger_type_traits.h b/api/include/opentelemetry/logs/logger_type_traits.h new file mode 100644 index 0000000000..805d07736c --- /dev/null +++ b/api/include/opentelemetry/logs/logger_type_traits.h @@ -0,0 +1,196 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include +# include +# include +# include + +# include "opentelemetry/common/attribute_value.h" +# include "opentelemetry/common/key_value_iterable.h" +# include "opentelemetry/common/key_value_iterable_view.h" +# include "opentelemetry/common/macros.h" +# include "opentelemetry/common/timestamp.h" +# include "opentelemetry/logs/log_record.h" +# include "opentelemetry/logs/severity.h" +# include "opentelemetry/nostd/shared_ptr.h" +# include "opentelemetry/nostd/span.h" +# include "opentelemetry/nostd/string_view.h" +# include "opentelemetry/nostd/type_traits.h" +# include "opentelemetry/nostd/unique_ptr.h" +# include "opentelemetry/trace/span_context.h" +# include "opentelemetry/trace/span_id.h" +# include "opentelemetry/trace/trace_flags.h" +# include "opentelemetry/trace/trace_id.h" +# include "opentelemetry/version.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace logs +{ +namespace detail +{ +template +struct LogRecordSetterTrait; + +template <> +struct LogRecordSetterTrait +{ + template + inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept + { + log_record->SetSeverity(std::forward(arg)); + + return log_record; + } +}; + +template <> +struct LogRecordSetterTrait +{ + template + inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept + { + log_record->SetSpanId(arg.span_id()); + log_record->SetTraceId(arg.trace_id()); + log_record->SetTraceFlags(arg.trace_flags()); + + return log_record; + } +}; + +template <> +struct LogRecordSetterTrait +{ + template + inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept + { + log_record->SetSpanId(std::forward(arg)); + + return log_record; + } +}; + +template <> +struct LogRecordSetterTrait +{ + template + inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept + { + log_record->SetTraceId(std::forward(arg)); + + return log_record; + } +}; + +template <> +struct LogRecordSetterTrait +{ + template + inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept + { + log_record->SetTraceFlags(std::forward(arg)); + + return log_record; + } +}; + +template <> +struct LogRecordSetterTrait +{ + template + inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept + { + log_record->SetTimestamp(std::forward(arg)); + + return log_record; + } +}; + +template <> +struct LogRecordSetterTrait +{ + template + inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept + { + log_record->SetTimestamp(common::SystemTimestamp(std::forward(arg))); + + return log_record; + } +}; + +template <> +struct LogRecordSetterTrait +{ + template + inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept + { + arg.ForEachKeyValue( + [&log_record](nostd::string_view key, common::AttributeValue value) noexcept { + log_record->SetAttribute(key, value); + return true; + }); + + return log_record; + } +}; + +template +struct LogRecordSetterTrait +{ + template ::value || + std::is_convertible::value, + void> * = nullptr> + inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept + { + log_record->SetBody(std::forward(arg)); + + return log_record; + } + + template ::value, bool> + * = nullptr> + inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept + { + return LogRecordSetterTrait::template Set( + log_record, std::forward(arg)); + } + + template ::value, int> * = + nullptr> + inline static LogRecord *Set(LogRecord *log_record, ArgumentType &&arg) noexcept + { + for (auto &argv : arg) + { + log_record->SetAttribute(argv.first, argv.second); + } + + return log_record; + } +}; + +template +struct LogRecordHasType; + +template +struct LogRecordHasType : public std::false_type +{}; + +template +struct LogRecordHasType + : public std::conditional::value, + std::true_type, + LogRecordHasType>::type +{}; + +} // namespace detail + +} // namespace logs +OPENTELEMETRY_END_NAMESPACE + +#endif diff --git a/api/include/opentelemetry/logs/noop.h b/api/include/opentelemetry/logs/noop.h index d8941510da..5061003274 100644 --- a/api/include/opentelemetry/logs/noop.h +++ b/api/include/opentelemetry/logs/noop.h @@ -15,6 +15,7 @@ # include "opentelemetry/common/key_value_iterable.h" # include "opentelemetry/common/timestamp.h" # include "opentelemetry/context/runtime_context.h" +# include "opentelemetry/logs/event_logger_provider.h" # include "opentelemetry/logs/logger.h" # include "opentelemetry/logs/logger_provider.h" # include "opentelemetry/logs/severity.h" @@ -60,26 +61,54 @@ class NoopLoggerProvider final : public opentelemetry::logs::LoggerProvider {} nostd::shared_ptr GetLogger(nostd::string_view /* logger_name */, - nostd::string_view /* options */, nostd::string_view /* library_name */, nostd::string_view /* library_version */, - nostd::string_view /* schema_url */) override + nostd::string_view /* schema_url */, + bool /* include_trace_context */, + const common::KeyValueIterable & /* attributes */) override { return logger_; } - nostd::shared_ptr GetLogger(nostd::string_view /* logger_name */, - nostd::span /* args */, - nostd::string_view /* library_name */, - nostd::string_view /* library_version */, - nostd::string_view /* schema_url */) override +private: + nostd::shared_ptr logger_; +}; + +class NoopEventLogger final : public EventLogger +{ +public: + NoopEventLogger() : logger_{nostd::shared_ptr(new NoopLogger())} {} + + const nostd::string_view GetName() noexcept override { return "noop event logger"; } + + nostd::shared_ptr GetDelegateLogger() noexcept override { return logger_; } + + void EmitEvent(nostd::string_view, nostd::unique_ptr &&) noexcept override {} + +private: + nostd::shared_ptr logger_; +}; + +/** + * No-op implementation of a EventLoggerProvider. + */ +class NoopEventLoggerProvider final : public EventLoggerProvider +{ +public: + NoopEventLoggerProvider() : event_logger_{nostd::shared_ptr(new NoopEventLogger())} + {} + + nostd::shared_ptr CreateEventLogger( + nostd::shared_ptr /*delegate_logger*/, + nostd::string_view /*event_domain*/) noexcept override { - return logger_; + return event_logger_; } private: - nostd::shared_ptr logger_; + nostd::shared_ptr event_logger_; }; + } // namespace logs OPENTELEMETRY_END_NAMESPACE #endif diff --git a/api/include/opentelemetry/logs/provider.h b/api/include/opentelemetry/logs/provider.h index 6f4b76fbd7..ed6fe86baa 100644 --- a/api/include/opentelemetry/logs/provider.h +++ b/api/include/opentelemetry/logs/provider.h @@ -8,6 +8,7 @@ # include "opentelemetry/common/macros.h" # include "opentelemetry/common/spin_lock_mutex.h" +# include "opentelemetry/logs/event_logger_provider.h" # include "opentelemetry/logs/logger_provider.h" # include "opentelemetry/logs/noop.h" # include "opentelemetry/nostd/shared_ptr.h" @@ -42,6 +43,27 @@ class Provider GetProvider() = tp; } + /** + * Returns the singleton EventLoggerProvider. + * + * By default, a no-op EventLoggerProvider is returned. This will never return a + * nullptr EventLoggerProvider. + */ + static nostd::shared_ptr GetEventLoggerProvider() noexcept + { + std::lock_guard guard(GetLock()); + return nostd::shared_ptr(GetEventProvider()); + } + + /** + * Changes the singleton EventLoggerProvider. + */ + static void SetEventLoggerProvider(nostd::shared_ptr tp) noexcept + { + std::lock_guard guard(GetLock()); + GetEventProvider() = tp; + } + private: OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr &GetProvider() noexcept { @@ -49,6 +71,13 @@ class Provider return provider; } + OPENTELEMETRY_API_SINGLETON static nostd::shared_ptr + &GetEventProvider() noexcept + { + static nostd::shared_ptr provider(new NoopEventLoggerProvider); + return provider; + } + OPENTELEMETRY_API_SINGLETON static common::SpinLockMutex &GetLock() noexcept { static common::SpinLockMutex lock; diff --git a/api/test/logs/logger_test.cc b/api/test/logs/logger_test.cc index 48e9c375d3..ab364cdfb5 100644 --- a/api/test/logs/logger_test.cc +++ b/api/test/logs/logger_test.cc @@ -5,6 +5,7 @@ # include # include +# include # include "opentelemetry/common/timestamp.h" # include "opentelemetry/logs/logger.h" @@ -27,7 +28,7 @@ TEST(Logger, GetLoggerDefault) { auto lp = Provider::GetLoggerProvider(); const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"}; - auto logger = lp->GetLogger("TestLogger", "", "opentelelemtry_library", "", schema_url); + auto logger = lp->GetLogger("TestLogger", "opentelelemtry_library", "", schema_url); auto name = logger->GetName(); EXPECT_NE(nullptr, logger); EXPECT_EQ(name, "noop logger"); @@ -38,65 +39,98 @@ TEST(Logger, GetNoopLoggerNameWithArgs) { auto lp = Provider::GetLoggerProvider(); - // GetLogger(name, list(args)) - std::array sv{"string"}; - span args{sv}; const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"}; - lp->GetLogger("NoopLoggerWithArgs", args, "opentelelemtry_library", "", schema_url); + lp->GetLogger("NoopLoggerWithArgs", "opentelelemtry_library", "", schema_url); - // GetLogger(name, string options) - lp->GetLogger("NoopLoggerWithOptions", "options", "opentelelemtry_library", "", schema_url); + lp->GetLogger("NoopLoggerWithOptions", "opentelelemtry_library", "", schema_url); } -// Test the Log() overloads +// Test the EmitLogRecord() overloads TEST(Logger, LogMethodOverloads) { auto lp = Provider::GetLoggerProvider(); const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"}; - auto logger = lp->GetLogger("TestLogger", "", "opentelelemtry_library", "", schema_url); + auto logger = lp->GetLogger("TestLogger", "opentelelemtry_library", "", schema_url); // Create a map to test the logs with std::map m = {{"key1", "value1"}}; - // Log overloads - logger->Log(Severity::kTrace, "Test log message"); - logger->Log(Severity::kInfo, "Test log message"); - logger->Log(Severity::kDebug, m); - logger->Log(Severity::kWarn, "Logging a map", m); - logger->Log(Severity::kError, {{"key1", "value 1"}, {"key2", 2}}); - logger->Log(Severity::kFatal, "Logging an initializer list", {{"key1", "value 1"}, {"key2", 2}}); + // EmitLogRecord overloads + logger->EmitLogRecord(Severity::kTrace, "Test log message"); + logger->EmitLogRecord(Severity::kInfo, "Test log message"); + logger->EmitLogRecord(Severity::kDebug, m); + logger->EmitLogRecord(Severity::kWarn, "Logging a map", m); + logger->EmitLogRecord(Severity::kError, + Logger::MakeAttributes({{"key1", "value 1"}, {"key2", 2}})); + logger->EmitLogRecord(Severity::kFatal, "Logging an initializer list", + Logger::MakeAttributes({{"key1", "value 1"}, {"key2", 2}})); + logger->EmitLogRecord(Severity::kDebug, Logger::MakeAttributes(m)); + logger->EmitLogRecord(Severity::kDebug, + common::KeyValueIterableView>(m)); + std::pair array[] = {{"key1", "value1"}}; + logger->EmitLogRecord(Severity::kDebug, Logger::MakeAttributes(array)); + std::vector> vec = {{"key1", "value1"}}; + logger->EmitLogRecord(Severity::kDebug, Logger::MakeAttributes(vec)); // Severity methods logger->Trace("Test log message"); logger->Trace("Test log message", m); - logger->Trace("Test log message", {{"key1", "value 1"}, {"key2", 2}}); + logger->Trace("Test log message", Logger::MakeAttributes({{"key1", "value 1"}, {"key2", 2}})); logger->Trace(m); - logger->Trace({{"key1", "value 1"}, {"key2", 2}}); + logger->Trace(Logger::MakeAttributes({{"key1", "value 1"}, {"key2", 2}})); logger->Debug("Test log message"); logger->Debug("Test log message", m); - logger->Debug("Test log message", {{"key1", "value 1"}, {"key2", 2}}); + logger->Debug("Test log message", Logger::MakeAttributes({{"key1", "value 1"}, {"key2", 2}})); logger->Debug(m); - logger->Debug({{"key1", "value 1"}, {"key2", 2}}); + logger->Debug(Logger::MakeAttributes({{"key1", "value 1"}, {"key2", 2}})); logger->Info("Test log message"); logger->Info("Test log message", m); - logger->Info("Test log message", {{"key1", "value 1"}, {"key2", 2}}); + logger->Info("Test log message", Logger::MakeAttributes({{"key1", "value 1"}, {"key2", 2}})); logger->Info(m); - logger->Info({{"key1", "value 1"}, {"key2", 2}}); + logger->Info(Logger::MakeAttributes({{"key1", "value 1"}, {"key2", 2}})); logger->Warn("Test log message"); logger->Warn("Test log message", m); - logger->Warn("Test log message", {{"key1", "value 1"}, {"key2", 2}}); + logger->Warn("Test log message", Logger::MakeAttributes({{"key1", "value 1"}, {"key2", 2}})); logger->Warn(m); - logger->Warn({{"key1", "value 1"}, {"key2", 2}}); + logger->Warn(Logger::MakeAttributes({{"key1", "value 1"}, {"key2", 2}})); logger->Error("Test log message"); logger->Error("Test log message", m); - logger->Error("Test log message", {{"key1", "value 1"}, {"key2", 2}}); + logger->Error("Test log message", Logger::MakeAttributes({{"key1", "value 1"}, {"key2", 2}})); logger->Error(m); - logger->Error({{"key1", "value 1"}, {"key2", 2}}); + logger->Error(Logger::MakeAttributes({{"key1", "value 1"}, {"key2", 2}})); logger->Fatal("Test log message"); logger->Fatal("Test log message", m); - logger->Fatal("Test log message", {{"key1", "value 1"}, {"key2", 2}}); + logger->Fatal("Test log message", Logger::MakeAttributes({{"key1", "value 1"}, {"key2", 2}})); logger->Fatal(m); - logger->Fatal({{"key1", "value 1"}, {"key2", 2}}); + logger->Fatal(Logger::MakeAttributes({{"key1", "value 1"}, {"key2", 2}})); +} + +TEST(Logger, EventLogMethodOverloads) +{ + auto lp = Provider::GetLoggerProvider(); + const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"}; + auto logger = lp->GetLogger("TestLogger", "opentelelemtry_library", "", schema_url); + + auto elp = Provider::GetEventLoggerProvider(); + auto event_logger = elp->CreateEventLogger(logger, "otel-cpp.test"); + + std::map m = {{"key1", "value1"}}; + + event_logger->EmitEvent("event name", Severity::kTrace, "Test log message"); + event_logger->EmitEvent("event name", Severity::kInfo, "Test log message"); + event_logger->EmitEvent("event name", Severity::kDebug, m); + event_logger->EmitEvent("event name", Severity::kWarn, "Logging a map", m); + event_logger->EmitEvent("event name", Severity::kError, + Logger::MakeAttributes({{"key1", "value 1"}, {"key2", 2}})); + event_logger->EmitEvent("event name", Severity::kFatal, "Logging an initializer list", + Logger::MakeAttributes({{"key1", "value 1"}, {"key2", 2}})); + event_logger->EmitEvent("event name", Severity::kDebug, Logger::MakeAttributes(m)); + event_logger->EmitEvent("event name", Severity::kDebug, + common::KeyValueIterableView>(m)); + std::pair array[] = {{"key1", "value1"}}; + event_logger->EmitEvent("event name", Severity::kDebug, Logger::MakeAttributes(array)); + std::vector> vec = {{"key1", "value1"}}; + event_logger->EmitEvent("event name", Severity::kDebug, Logger::MakeAttributes(vec)); } // Define a basic Logger class @@ -118,19 +152,11 @@ class TestLogger : public Logger class TestProvider : public LoggerProvider { nostd::shared_ptr GetLogger(nostd::string_view /* logger_name */, - nostd::string_view /* options */, - nostd::string_view /* library_name */, - nostd::string_view /* library_version */, - nostd::string_view /* schema_url */) override - { - return shared_ptr(new TestLogger()); - } - - nostd::shared_ptr GetLogger(nostd::string_view /* logger_name */, - nostd::span /* args */, nostd::string_view /* library_name */, nostd::string_view /* library_version */, - nostd::string_view /* schema_url */) override + nostd::string_view /* schema_url */, + bool /* include_trace_context */, + const common::KeyValueIterable & /* attributes */) override { return shared_ptr(new TestLogger()); } @@ -146,7 +172,7 @@ TEST(Logger, PushLoggerImplementation) // Check that the implementation was pushed by calling TestLogger's GetName() nostd::string_view schema_url{"https://opentelemetry.io/schemas/1.11.0"}; - auto logger = lp->GetLogger("TestLogger", "", "opentelelemtry_library", "", schema_url); + auto logger = lp->GetLogger("TestLogger", "opentelelemtry_library", "", schema_url); ASSERT_EQ("test logger", logger->GetName()); } #endif diff --git a/api/test/logs/provider_test.cc b/api/test/logs/provider_test.cc index 1dd60d0b87..0d607f1d01 100644 --- a/api/test/logs/provider_test.cc +++ b/api/test/logs/provider_test.cc @@ -9,6 +9,8 @@ # include "opentelemetry/logs/provider.h" # include "opentelemetry/nostd/shared_ptr.h" +using opentelemetry::logs::EventLogger; +using opentelemetry::logs::EventLoggerProvider; using opentelemetry::logs::Logger; using opentelemetry::logs::LoggerProvider; using opentelemetry::logs::Provider; @@ -17,20 +19,13 @@ namespace nostd = opentelemetry::nostd; class TestProvider : public LoggerProvider { - nostd::shared_ptr GetLogger(nostd::string_view /* logger_name */, - nostd::string_view /* options */, - nostd::string_view /* library_name */, - nostd::string_view /* library_version */, - nostd::string_view /* schema_url */) override - { - return shared_ptr(nullptr); - } - - nostd::shared_ptr GetLogger(nostd::string_view /* logger_name */, - nostd::span /* args */, - nostd::string_view /* library_name */, - nostd::string_view /* library_version */, - nostd::string_view /* schema_url */) override + nostd::shared_ptr GetLogger( + nostd::string_view /* logger_name */, + nostd::string_view /* library_name */, + nostd::string_view /* library_version */, + nostd::string_view /* schema_url */, + bool /* include_trace_context */, + const opentelemetry::common::KeyValueIterable & /* attributes */) override { return shared_ptr(nullptr); } @@ -64,14 +59,55 @@ TEST(Provider, GetLogger) auto tf = shared_ptr(new TestProvider()); // tests GetLogger(name, version, schema) const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; - auto logger = tf->GetLogger("logger1", "", "opentelelemtry_library", "", schema_url); + auto logger = tf->GetLogger("logger1", "opentelelemtry_library", "", schema_url); EXPECT_EQ(nullptr, logger); // tests GetLogger(name, arguments) - std::array sv{"string"}; - nostd::span args{sv}; - auto logger2 = tf->GetLogger("logger2", args, "opentelelemtry_library", "", schema_url); + auto logger2 = tf->GetLogger("logger2", "opentelelemtry_library", "", schema_url); EXPECT_EQ(nullptr, logger2); } + +class TestEventLoggerProvider : public EventLoggerProvider +{ +public: + nostd::shared_ptr CreateEventLogger( + nostd::shared_ptr /*delegate_logger*/, + nostd::string_view /*event_domain*/) noexcept override + { + return nostd::shared_ptr(nullptr); + } +}; + +TEST(Provider, GetEventLoggerProviderDefault) +{ + auto tf = Provider::GetEventLoggerProvider(); + EXPECT_NE(nullptr, tf); +} + +TEST(Provider, SetEventLoggerProvider) +{ + auto tf = nostd::shared_ptr(new TestEventLoggerProvider()); + Provider::SetEventLoggerProvider(tf); + ASSERT_EQ(tf, Provider::GetEventLoggerProvider()); +} + +TEST(Provider, MultipleEventLoggerProviders) +{ + auto tf = nostd::shared_ptr(new TestEventLoggerProvider()); + Provider::SetEventLoggerProvider(tf); + auto tf2 = nostd::shared_ptr(new TestEventLoggerProvider()); + Provider::SetEventLoggerProvider(tf2); + + ASSERT_NE(Provider::GetEventLoggerProvider(), tf); +} + +TEST(Provider, CreateEventLogger) +{ + auto tf = nostd::shared_ptr(new TestEventLoggerProvider()); + auto logger = tf->CreateEventLogger(nostd::shared_ptr(nullptr), "domain"); + + EXPECT_EQ(nullptr, logger); +} + #endif diff --git a/examples/common/logs_foo_library/foo_library.cc b/examples/common/logs_foo_library/foo_library.cc index 9e41584067..e952220108 100644 --- a/examples/common/logs_foo_library/foo_library.cc +++ b/examples/common/logs_foo_library/foo_library.cc @@ -22,7 +22,7 @@ nostd::shared_ptr get_tracer() nostd::shared_ptr get_logger() { auto provider = logs::Provider::GetLoggerProvider(); - return provider->GetLogger("foo_library_logger", "", "foo_library"); + return provider->GetLogger("foo_library_logger", "foo_library"); } } // namespace @@ -32,8 +32,8 @@ void foo_library() auto scoped_span = trace::Scope(get_tracer()->StartSpan("foo_library")); auto ctx = span->GetContext(); auto logger = get_logger(); - logger->Log(opentelemetry::logs::Severity::kDebug, "body", {}, ctx.trace_id(), ctx.span_id(), - ctx.trace_flags(), - opentelemetry::common::SystemTimestamp(std::chrono::system_clock::now())); + logger->EmitLogRecord(opentelemetry::logs::Severity::kDebug, "body", ctx.trace_id(), + ctx.span_id(), ctx.trace_flags(), + opentelemetry::common::SystemTimestamp(std::chrono::system_clock::now())); } #endif diff --git a/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h b/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h index d72fe64edb..8019c36105 100644 --- a/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h +++ b/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h @@ -317,44 +317,17 @@ class LoggerProvider : public opentelemetry::logs::LoggerProvider nostd::shared_ptr GetLogger( nostd::string_view logger_name, - nostd::string_view options, nostd::string_view library_name, - nostd::string_view version = "", - nostd::string_view schema_url = "") override + nostd::string_view version = "", + nostd::string_view schema_url = "", + bool include_trace_context = true, + const common::KeyValueIterable &attributes = common::NoopKeyValueIterable()) override { - UNREFERENCED_PARAMETER(options); - UNREFERENCED_PARAMETER(library_name); - UNREFERENCED_PARAMETER(version); - UNREFERENCED_PARAMETER(schema_url); - ETWProvider::EventFormat evtFmt = config_.encoding; - return nostd::shared_ptr{ - new (std::nothrow) etw::Logger(*this, logger_name, evtFmt)}; - } - - /** - * @brief Obtain ETW Tracer. - * @param name ProviderId (instrumentation name) - Name or GUID - * @param args Additional arguments that controls `codec` of the provider. - * Possible values are: - * - "ETW" - 'classic' Trace Logging Dynamic manifest ETW events. - * - "MSGPACK" - MessagePack-encoded binary payload ETW events. - * - "XML" - XML events (reserved for future use) - * @param library_name Library name - * @param version Library version - * @param schema_url schema URL - * @return - */ - nostd::shared_ptr GetLogger( - nostd::string_view logger_name, - nostd::span args, - nostd::string_view library_name, - nostd::string_view version = "", - nostd::string_view schema_url = "") override - { - UNREFERENCED_PARAMETER(args); UNREFERENCED_PARAMETER(library_name); UNREFERENCED_PARAMETER(version); UNREFERENCED_PARAMETER(schema_url); + UNREFERENCED_PARAMETER(include_trace_context); + UNREFERENCED_PARAMETER(attributes); ETWProvider::EventFormat evtFmt = config_.encoding; return nostd::shared_ptr{ new (std::nothrow) etw::Logger(*this, logger_name, evtFmt)}; diff --git a/exporters/etw/test/etw_logger_test.cc b/exporters/etw/test/etw_logger_test.cc index 7d9040b553..fba15581a3 100644 --- a/exporters/etw/test/etw_logger_test.cc +++ b/exporters/etw/test/etw_logger_test.cc @@ -49,9 +49,10 @@ TEST(ETWLogger, LoggerCheckWithBody) exporter::etw::LoggerProvider lp; const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; - auto logger = lp.GetLogger(providerName, "", schema_url); + auto logger = lp.GetLogger(providerName, schema_url); Properties attribs = {{"attrib1", 1}, {"attrib2", 2}}; - EXPECT_NO_THROW(logger->Log(opentelemetry::logs::Severity::kDebug, "This is test log body")); + EXPECT_NO_THROW( + logger->EmitLogRecord(opentelemetry::logs::Severity::kDebug, "This is test log body")); } /** @@ -91,10 +92,11 @@ TEST(ETWLogger, LoggerCheckWithAttributes) exporter::etw::LoggerProvider lp; const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; - auto logger = lp.GetLogger(providerName, "", schema_url); + auto logger = lp.GetLogger(providerName, schema_url); // Log attributes Properties attribs = {{"attrib1", 1}, {"attrib2", 2}}; - EXPECT_NO_THROW(logger->Log(opentelemetry::logs::Severity::kDebug, attribs)); + EXPECT_NO_THROW(logger->EmitLogRecord(opentelemetry::logs::Severity::kDebug, + Logger::MakeAttributes(attribs))); } # endif // _WIN32 diff --git a/exporters/ostream/test/ostream_log_test.cc b/exporters/ostream/test/ostream_log_test.cc index e247f06038..5896c6e42d 100644 --- a/exporters/ostream/test/ostream_log_test.cc +++ b/exporters/ostream/test/ostream_log_test.cc @@ -291,7 +291,7 @@ TEST(OStreamLogRecordExporter, IntegrationTest) logs_api::Provider::SetLoggerProvider(provider); const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"}; auto logger = logs_api::Provider::GetLoggerProvider()->GetLogger( - "Logger", "", "opentelelemtry_library", "", schema_url); + "Logger", "opentelelemtry_library", "", schema_url); // Back up cout's streambuf std::streambuf *original = std::cout.rdbuf(); @@ -302,7 +302,7 @@ TEST(OStreamLogRecordExporter, IntegrationTest) // Write a log to ostream exporter common::SystemTimestamp now(std::chrono::system_clock::now()); - logger->Log(logs_api::Severity::kDebug, "Hello", {}, {}, {}, {}, now); + logger->EmitLogRecord(logs_api::Severity::kDebug, "Hello", now); // Restore cout's original streambuf std::cout.rdbuf(original); diff --git a/exporters/otlp/test/otlp_grpc_log_record_exporter_test.cc b/exporters/otlp/test/otlp_grpc_log_record_exporter_test.cc index f87b5bf2d7..e606224133 100644 --- a/exporters/otlp/test/otlp_grpc_log_record_exporter_test.cc +++ b/exporters/otlp/test/otlp_grpc_log_record_exporter_test.cc @@ -136,7 +136,7 @@ TEST_F(OtlpGrpcLogRecordExporterTestPeer, ExportIntegrationTest) opentelemetry::trace::SpanId span_id{span_id_bin}; const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"}; - auto logger = provider->GetLogger("test", "", "opentelelemtry_library", "", schema_url); + auto logger = provider->GetLogger("test", "opentelelemtry_library", "", schema_url); std::unordered_map attributes; attributes["service.name"] = "unit_test_service"; attributes["tenant.id"] = "test_user"; @@ -153,9 +153,10 @@ TEST_F(OtlpGrpcLogRecordExporterTestPeer, ExportIntegrationTest) attributes["vec_uint64_value"] = attribute_storage_uint64_value; attributes["vec_double_value"] = attribute_storage_double_value; attributes["vec_string_value"] = attribute_storage_string_value; - logger->Log(opentelemetry::logs::Severity::kInfo, "Log message", attributes, trace_id, span_id, - opentelemetry::trace::TraceFlags{opentelemetry::trace::TraceFlags::kIsSampled}, - std::chrono::system_clock::now()); + logger->EmitLogRecord( + opentelemetry::logs::Severity::kInfo, "Log message", attributes, trace_id, span_id, + opentelemetry::trace::TraceFlags{opentelemetry::trace::TraceFlags::kIsSampled}, + std::chrono::system_clock::now()); } } // namespace otlp diff --git a/exporters/otlp/test/otlp_http_log_record_exporter_test.cc b/exporters/otlp/test/otlp_http_log_record_exporter_test.cc index c3fc69231a..627a2d5f0e 100644 --- a/exporters/otlp/test/otlp_http_log_record_exporter_test.cc +++ b/exporters/otlp/test/otlp_http_log_record_exporter_test.cc @@ -129,7 +129,7 @@ class OtlpHttpLogRecordExporterTestPeer : public ::testing::Test opentelemetry::trace::SpanId span_id{span_id_bin}; const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; - auto logger = provider->GetLogger("test", "", "opentelelemtry_library", "", schema_url); + auto logger = provider->GetLogger("test", "opentelelemtry_library", "", schema_url); trace_id.ToLowerBase16(MakeSpan(trace_id_hex)); report_trace_id.assign(trace_id_hex, sizeof(trace_id_hex)); @@ -165,25 +165,27 @@ class OtlpHttpLogRecordExporterTestPeer : public ::testing::Test response.Finish(*callback.get()); }); - logger->Log(opentelemetry::logs::Severity::kInfo, "Log message", - {{"service.name", "unit_test_service"}, - {"tenant.id", "test_user"}, - {"bool_value", true}, - {"int32_value", static_cast(1)}, - {"uint32_value", static_cast(2)}, - {"int64_value", static_cast(0x1100000000LL)}, - {"uint64_value", static_cast(0x1200000000ULL)}, - {"double_value", static_cast(3.1)}, - {"vec_bool_value", attribute_storage_bool_value}, - {"vec_int32_value", attribute_storage_int32_value}, - {"vec_uint32_value", attribute_storage_uint32_value}, - {"vec_int64_value", attribute_storage_int64_value}, - {"vec_uint64_value", attribute_storage_uint64_value}, - {"vec_double_value", attribute_storage_double_value}, - {"vec_string_value", attribute_storage_string_value}}, - trace_id, span_id, - opentelemetry::trace::TraceFlags{opentelemetry::trace::TraceFlags::kIsSampled}, - std::chrono::system_clock::now()); + logger->EmitLogRecord( + opentelemetry::logs::Severity::kInfo, "Log message", + opentelemetry::logs::Logger::MakeAttributes( + {{"service.name", "unit_test_service"}, + {"tenant.id", "test_user"}, + {"bool_value", true}, + {"int32_value", static_cast(1)}, + {"uint32_value", static_cast(2)}, + {"int64_value", static_cast(0x1100000000LL)}, + {"uint64_value", static_cast(0x1200000000ULL)}, + {"double_value", static_cast(3.1)}, + {"vec_bool_value", attribute_storage_bool_value}, + {"vec_int32_value", attribute_storage_int32_value}, + {"vec_uint32_value", attribute_storage_uint32_value}, + {"vec_int64_value", attribute_storage_int64_value}, + {"vec_uint64_value", attribute_storage_uint64_value}, + {"vec_double_value", attribute_storage_double_value}, + {"vec_string_value", attribute_storage_string_value}}), + trace_id, span_id, + opentelemetry::trace::TraceFlags{opentelemetry::trace::TraceFlags::kIsSampled}, + std::chrono::system_clock::now()); provider->ForceFlush(); } @@ -226,7 +228,7 @@ class OtlpHttpLogRecordExporterTestPeer : public ::testing::Test opentelemetry::trace::SpanId span_id{span_id_bin}; const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; - auto logger = provider->GetLogger("test", "", "opentelelemtry_library", "1.2.0", schema_url); + auto logger = provider->GetLogger("test", "opentelelemtry_library", "1.2.0", schema_url); trace_id.ToLowerBase16(MakeSpan(trace_id_hex)); report_trace_id.assign(trace_id_hex, sizeof(trace_id_hex)); @@ -274,25 +276,27 @@ class OtlpHttpLogRecordExporterTestPeer : public ::testing::Test async_finish.detach(); }); - logger->Log(opentelemetry::logs::Severity::kInfo, "Log message", - {{"service.name", "unit_test_service"}, - {"tenant.id", "test_user"}, - {"bool_value", true}, - {"int32_value", static_cast(1)}, - {"uint32_value", static_cast(2)}, - {"int64_value", static_cast(0x1100000000LL)}, - {"uint64_value", static_cast(0x1200000000ULL)}, - {"double_value", static_cast(3.1)}, - {"vec_bool_value", attribute_storage_bool_value}, - {"vec_int32_value", attribute_storage_int32_value}, - {"vec_uint32_value", attribute_storage_uint32_value}, - {"vec_int64_value", attribute_storage_int64_value}, - {"vec_uint64_value", attribute_storage_uint64_value}, - {"vec_double_value", attribute_storage_double_value}, - {"vec_string_value", attribute_storage_string_value}}, - trace_id, span_id, - opentelemetry::trace::TraceFlags{opentelemetry::trace::TraceFlags::kIsSampled}, - std::chrono::system_clock::now()); + logger->EmitLogRecord( + opentelemetry::logs::Severity::kInfo, "Log message", + opentelemetry::logs::Logger::MakeAttributes( + {{"service.name", "unit_test_service"}, + {"tenant.id", "test_user"}, + {"bool_value", true}, + {"int32_value", static_cast(1)}, + {"uint32_value", static_cast(2)}, + {"int64_value", static_cast(0x1100000000LL)}, + {"uint64_value", static_cast(0x1200000000ULL)}, + {"double_value", static_cast(3.1)}, + {"vec_bool_value", attribute_storage_bool_value}, + {"vec_int32_value", attribute_storage_int32_value}, + {"vec_uint32_value", attribute_storage_uint32_value}, + {"vec_int64_value", attribute_storage_int64_value}, + {"vec_uint64_value", attribute_storage_uint64_value}, + {"vec_double_value", attribute_storage_double_value}, + {"vec_string_value", attribute_storage_string_value}}), + trace_id, span_id, + opentelemetry::trace::TraceFlags{opentelemetry::trace::TraceFlags::kIsSampled}, + std::chrono::system_clock::now()); provider->ForceFlush(); } @@ -332,7 +336,7 @@ class OtlpHttpLogRecordExporterTestPeer : public ::testing::Test opentelemetry::trace::SpanId span_id{span_id_bin}; const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; - auto logger = provider->GetLogger("test", "", "opentelelemtry_library", "1.2.0", schema_url); + auto logger = provider->GetLogger("test", "opentelelemtry_library", "1.2.0", schema_url); report_trace_id.assign(reinterpret_cast(trace_id_bin), sizeof(trace_id_bin)); report_span_id.assign(reinterpret_cast(span_id_bin), sizeof(span_id_bin)); @@ -372,25 +376,27 @@ class OtlpHttpLogRecordExporterTestPeer : public ::testing::Test response.Finish(*callback.get()); }); - logger->Log(opentelemetry::logs::Severity::kInfo, "Log message", - {{"service.name", "unit_test_service"}, - {"tenant.id", "test_user"}, - {"bool_value", true}, - {"int32_value", static_cast(1)}, - {"uint32_value", static_cast(2)}, - {"int64_value", static_cast(0x1100000000LL)}, - {"uint64_value", static_cast(0x1200000000ULL)}, - {"double_value", static_cast(3.1)}, - {"vec_bool_value", attribute_storage_bool_value}, - {"vec_int32_value", attribute_storage_int32_value}, - {"vec_uint32_value", attribute_storage_uint32_value}, - {"vec_int64_value", attribute_storage_int64_value}, - {"vec_uint64_value", attribute_storage_uint64_value}, - {"vec_double_value", attribute_storage_double_value}, - {"vec_string_value", attribute_storage_string_value}}, - trace_id, span_id, - opentelemetry::trace::TraceFlags{opentelemetry::trace::TraceFlags::kIsSampled}, - std::chrono::system_clock::now()); + logger->EmitLogRecord( + opentelemetry::logs::Severity::kInfo, "Log message", + opentelemetry::logs::Logger::MakeAttributes( + {{"service.name", "unit_test_service"}, + {"tenant.id", "test_user"}, + {"bool_value", true}, + {"int32_value", static_cast(1)}, + {"uint32_value", static_cast(2)}, + {"int64_value", static_cast(0x1100000000LL)}, + {"uint64_value", static_cast(0x1200000000ULL)}, + {"double_value", static_cast(3.1)}, + {"vec_bool_value", attribute_storage_bool_value}, + {"vec_int32_value", attribute_storage_int32_value}, + {"vec_uint32_value", attribute_storage_uint32_value}, + {"vec_int64_value", attribute_storage_int64_value}, + {"vec_uint64_value", attribute_storage_uint64_value}, + {"vec_double_value", attribute_storage_double_value}, + {"vec_string_value", attribute_storage_string_value}}), + trace_id, span_id, + opentelemetry::trace::TraceFlags{opentelemetry::trace::TraceFlags::kIsSampled}, + std::chrono::system_clock::now()); provider->ForceFlush(); } @@ -431,7 +437,7 @@ class OtlpHttpLogRecordExporterTestPeer : public ::testing::Test opentelemetry::trace::SpanId span_id{span_id_bin}; const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; - auto logger = provider->GetLogger("test", "", "opentelelemtry_library", "", schema_url); + auto logger = provider->GetLogger("test", "opentelelemtry_library", "", schema_url); report_trace_id.assign(reinterpret_cast(trace_id_bin), sizeof(trace_id_bin)); report_span_id.assign(reinterpret_cast(span_id_bin), sizeof(span_id_bin)); @@ -471,25 +477,27 @@ class OtlpHttpLogRecordExporterTestPeer : public ::testing::Test async_finish.detach(); }); - logger->Log(opentelemetry::logs::Severity::kInfo, "Log message", - {{"service.name", "unit_test_service"}, - {"tenant.id", "test_user"}, - {"bool_value", true}, - {"int32_value", static_cast(1)}, - {"uint32_value", static_cast(2)}, - {"int64_value", static_cast(0x1100000000LL)}, - {"uint64_value", static_cast(0x1200000000ULL)}, - {"double_value", static_cast(3.1)}, - {"vec_bool_value", attribute_storage_bool_value}, - {"vec_int32_value", attribute_storage_int32_value}, - {"vec_uint32_value", attribute_storage_uint32_value}, - {"vec_int64_value", attribute_storage_int64_value}, - {"vec_uint64_value", attribute_storage_uint64_value}, - {"vec_double_value", attribute_storage_double_value}, - {"vec_string_value", attribute_storage_string_value}}, - trace_id, span_id, - opentelemetry::trace::TraceFlags{opentelemetry::trace::TraceFlags::kIsSampled}, - std::chrono::system_clock::now()); + logger->EmitLogRecord( + opentelemetry::logs::Severity::kInfo, "Log message", + opentelemetry::logs::Logger::MakeAttributes( + {{"service.name", "unit_test_service"}, + {"tenant.id", "test_user"}, + {"bool_value", true}, + {"int32_value", static_cast(1)}, + {"uint32_value", static_cast(2)}, + {"int64_value", static_cast(0x1100000000LL)}, + {"uint64_value", static_cast(0x1200000000ULL)}, + {"double_value", static_cast(3.1)}, + {"vec_bool_value", attribute_storage_bool_value}, + {"vec_int32_value", attribute_storage_int32_value}, + {"vec_uint32_value", attribute_storage_uint32_value}, + {"vec_int64_value", attribute_storage_int64_value}, + {"vec_uint64_value", attribute_storage_uint64_value}, + {"vec_double_value", attribute_storage_double_value}, + {"vec_string_value", attribute_storage_string_value}}), + trace_id, span_id, + opentelemetry::trace::TraceFlags{opentelemetry::trace::TraceFlags::kIsSampled}, + std::chrono::system_clock::now()); provider->ForceFlush(); } diff --git a/sdk/include/opentelemetry/sdk/logs/event_logger.h b/sdk/include/opentelemetry/sdk/logs/event_logger.h new file mode 100644 index 0000000000..85ad924766 --- /dev/null +++ b/sdk/include/opentelemetry/sdk/logs/event_logger.h @@ -0,0 +1,52 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include +# include + +# include "opentelemetry/common/macros.h" +# include "opentelemetry/logs/event_logger.h" +# include "opentelemetry/logs/logger.h" +# include "opentelemetry/nostd/unique_ptr.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace logs +{ + +class EventLogger final : public opentelemetry::logs::EventLogger +{ +public: + /** + * Initialize a new Eventlogger. + * @param delegate_logger The delegate logger instance + * @param event_domain Event domain + */ + explicit EventLogger(nostd::shared_ptr delegate_logger, + nostd::string_view event_domain) noexcept; + + /** + * Returns the name of this logger. + */ + const opentelemetry::nostd::string_view GetName() noexcept override; + + nostd::shared_ptr GetDelegateLogger() noexcept override; + + using opentelemetry::logs::EventLogger::EmitEvent; + + void EmitEvent(nostd::string_view event_name, + nostd::unique_ptr &&log_record) noexcept override; + +private: + nostd::shared_ptr delegate_logger_; + std::string event_domain_; +}; + +} // namespace logs +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/sdk/include/opentelemetry/sdk/logs/event_logger_provider.h b/sdk/include/opentelemetry/sdk/logs/event_logger_provider.h new file mode 100644 index 0000000000..ba12d94600 --- /dev/null +++ b/sdk/include/opentelemetry/sdk/logs/event_logger_provider.h @@ -0,0 +1,37 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0/ + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include "opentelemetry/logs/event_logger_provider.h" +# include "opentelemetry/logs/logger.h" +# include "opentelemetry/nostd/shared_ptr.h" +# include "opentelemetry/sdk/logs/logger.h" + +// Define the maximum number of loggers that are allowed to be registered to the loggerprovider. +// TODO: Add link to logging spec once this is added to it +# define MAX_LOGGER_COUNT 100 + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace logs +{ +class Logger; + +class EventLoggerProvider final : public opentelemetry::logs::EventLoggerProvider +{ +public: + EventLoggerProvider() noexcept; + + ~EventLoggerProvider() override; + + nostd::shared_ptr CreateEventLogger( + nostd::shared_ptr delegate_logger, + nostd::string_view event_domain) noexcept override; +}; +} // namespace logs +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/sdk/include/opentelemetry/sdk/logs/event_logger_provider_factory.h b/sdk/include/opentelemetry/sdk/logs/event_logger_provider_factory.h new file mode 100644 index 0000000000..06aa1c4f2e --- /dev/null +++ b/sdk/include/opentelemetry/sdk/logs/event_logger_provider_factory.h @@ -0,0 +1,32 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0/ + +#pragma once + +#ifdef ENABLE_LOGS_PREVIEW + +# include "opentelemetry/logs/event_logger_provider.h" +# include "opentelemetry/nostd/shared_ptr.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace logs +{ + +/** + * Factory class for EventLoggerProvider. + */ +class EventLoggerProviderFactory +{ +public: + /** + * Create a EventLoggerProvider. + */ + static std::unique_ptr Create(); +}; + +} // namespace logs +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif /* ENABLE_LOGS_PREVIEW */ diff --git a/sdk/include/opentelemetry/sdk/logs/logger.h b/sdk/include/opentelemetry/sdk/logs/logger.h index d290df98c3..ece83a8b57 100644 --- a/sdk/include/opentelemetry/sdk/logs/logger.h +++ b/sdk/include/opentelemetry/sdk/logs/logger.h @@ -33,7 +33,8 @@ class Logger final : public opentelemetry::logs::Logger opentelemetry::nostd::string_view name, std::shared_ptr context, std::unique_ptr instrumentation_scope = - instrumentationscope::InstrumentationScope::Create("")) noexcept; + instrumentationscope::InstrumentationScope::Create(""), + bool include_trace_context = true) noexcept; /** * Returns the name of this logger. @@ -66,6 +67,8 @@ class Logger final : public opentelemetry::logs::Logger // logger-context. std::unique_ptr instrumentation_scope_; std::shared_ptr context_; + + bool include_trace_context_; }; } // namespace logs diff --git a/sdk/include/opentelemetry/sdk/logs/logger_provider.h b/sdk/include/opentelemetry/sdk/logs/logger_provider.h index fd38532752..c1efd71753 100644 --- a/sdk/include/opentelemetry/sdk/logs/logger_provider.h +++ b/sdk/include/opentelemetry/sdk/logs/logger_provider.h @@ -67,34 +67,18 @@ class LoggerProvider final : public opentelemetry::logs::LoggerProvider * Creates a logger with the given name, and returns a shared pointer to it. * If a logger with that name already exists, return a shared pointer to it * @param logger_name The name of the logger to be created. - * @param options The options for the logger. TODO: Once the logging spec defines it, - * give a list of options that the logger supports. * @param library_name The version of the library. * @param library_version The version of the library. * @param schema_url The schema URL. */ nostd::shared_ptr GetLogger( nostd::string_view logger_name, - nostd::string_view options, nostd::string_view library_name, nostd::string_view library_version = "", - nostd::string_view schema_url = "") noexcept override; - /** - * Creates a logger with the given name, and returns a shared pointer to it. - * If a logger with that name already exists, return a shared pointer to it - * @param name The name of the logger to be created. - * @param args The arguments for the logger. TODO: Once the logging spec defines it, - * give a list of arguments that the logger supports. - * @param library_name The version of the library. - * @param library_version The version of the library. - * @param schema_url The schema URL. - */ - nostd::shared_ptr GetLogger( - nostd::string_view logger_name, - nostd::span args, - nostd::string_view library_name, - nostd::string_view library_version = "", - nostd::string_view schema_url = "") noexcept override; + nostd::string_view schema_url = "", + bool include_trace_context = true, + const opentelemetry::common::KeyValueIterable &attributes = + opentelemetry::common::NoopKeyValueIterable()) noexcept override; /** * Add the processor that is stored internally in the logger provider. diff --git a/sdk/src/logs/CMakeLists.txt b/sdk/src/logs/CMakeLists.txt index ff43c4d92b..36fa2f004e 100644 --- a/sdk/src/logs/CMakeLists.txt +++ b/sdk/src/logs/CMakeLists.txt @@ -3,6 +3,9 @@ add_library( logger_provider.cc logger_provider_factory.cc logger.cc + event_logger_provider.cc + event_logger_provider_factory.cc + event_logger.cc simple_log_record_processor.cc simple_log_record_processor_factory.cc batch_log_record_processor.cc diff --git a/sdk/src/logs/event_logger.cc b/sdk/src/logs/event_logger.cc new file mode 100644 index 0000000000..2106ecb233 --- /dev/null +++ b/sdk/src/logs/event_logger.cc @@ -0,0 +1,56 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifdef ENABLE_LOGS_PREVIEW +# include "opentelemetry/sdk/logs/event_logger.h" +# include "opentelemetry/sdk_config.h" +# include "opentelemetry/trace/provider.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace logs +{ +namespace nostd = opentelemetry::nostd; + +EventLogger::EventLogger(nostd::shared_ptr delegate_logger, + nostd::string_view event_domain) noexcept + : delegate_logger_(delegate_logger), event_domain_(event_domain) +{} + +const nostd::string_view EventLogger::GetName() noexcept +{ + if (delegate_logger_) + { + return delegate_logger_->GetName(); + } + + return {}; +} + +nostd::shared_ptr EventLogger::GetDelegateLogger() noexcept +{ + return delegate_logger_; +} + +void EventLogger::EmitEvent(nostd::string_view event_name, + nostd::unique_ptr &&log_record) noexcept +{ + if (!delegate_logger_ || !log_record) + { + return; + } + + if (!event_domain_.empty() && !event_name.empty()) + { + log_record->SetAttribute("event.domain", event_domain_); + log_record->SetAttribute("event.name", event_name); + } + + delegate_logger_->EmitLogRecord(std::move(log_record)); +} + +} // namespace logs +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/sdk/src/logs/event_logger_provider.cc b/sdk/src/logs/event_logger_provider.cc new file mode 100644 index 0000000000..2352fca59b --- /dev/null +++ b/sdk/src/logs/event_logger_provider.cc @@ -0,0 +1,41 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifdef ENABLE_LOGS_PREVIEW + +# include "opentelemetry/sdk/logs/event_logger_provider.h" +# include "opentelemetry/sdk/common/global_log_handler.h" +# include "opentelemetry/sdk/logs/event_logger.h" + +# include +# include +# include +# include +# include + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace logs +{ +namespace nostd = opentelemetry::nostd; + +EventLoggerProvider::EventLoggerProvider() noexcept +{ + OTEL_INTERNAL_LOG_DEBUG("[EventLoggerProvider] EventLoggerProvider created."); +} + +EventLoggerProvider::~EventLoggerProvider() {} + +nostd::shared_ptr EventLoggerProvider::CreateEventLogger( + nostd::shared_ptr delegate_logger, + nostd::string_view event_domain) noexcept +{ + return nostd::shared_ptr{ + new EventLogger(delegate_logger, event_domain)}; +} + +} // namespace logs +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/sdk/src/logs/event_logger_provider_factory.cc b/sdk/src/logs/event_logger_provider_factory.cc new file mode 100644 index 0000000000..966f33228a --- /dev/null +++ b/sdk/src/logs/event_logger_provider_factory.cc @@ -0,0 +1,24 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifdef ENABLE_LOGS_PREVIEW + +# include "opentelemetry/sdk/logs/event_logger_provider_factory.h" +# include "opentelemetry/sdk/logs/event_logger_provider.h" +# include "opentelemetry/sdk/resource/resource.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace logs +{ + +std::unique_ptr EventLoggerProviderFactory::Create() +{ + return std::unique_ptr(new EventLoggerProvider()); +} + +} // namespace logs +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/sdk/src/logs/logger.cc b/sdk/src/logs/logger.cc index a955d7a1ae..5fc58cf0ad 100644 --- a/sdk/src/logs/logger.cc +++ b/sdk/src/logs/logger.cc @@ -3,6 +3,7 @@ #ifdef ENABLE_LOGS_PREVIEW # include "opentelemetry/sdk/logs/logger.h" +# include "opentelemetry/context/runtime_context.h" # include "opentelemetry/sdk_config.h" # include "opentelemetry/trace/provider.h" @@ -15,13 +16,14 @@ namespace trace_api = opentelemetry::trace; namespace nostd = opentelemetry::nostd; namespace common = opentelemetry::common; -Logger::Logger( - nostd::string_view name, - std::shared_ptr context, - std::unique_ptr instrumentation_scope) noexcept +Logger::Logger(nostd::string_view name, + std::shared_ptr context, + std::unique_ptr instrumentation_scope, + bool include_trace_context) noexcept : logger_name_(std::string(name)), instrumentation_scope_(std::move(instrumentation_scope)), - context_(context) + context_(context), + include_trace_context_(include_trace_context) {} const nostd::string_view Logger::GetName() noexcept @@ -37,8 +39,38 @@ nostd::unique_ptr Logger::CreateLogRecord() noex return nullptr; } - return nostd::unique_ptr( - context_->GetProcessor().MakeRecordable().release()); + auto recordable = context_->GetProcessor().MakeRecordable(); + if (include_trace_context_ && + opentelemetry::context::RuntimeContext::GetCurrent().HasKey(opentelemetry::trace::kSpanKey)) + { + opentelemetry::context::ContextValue context_value = + opentelemetry::context::RuntimeContext::GetCurrent().GetValue( + opentelemetry::trace::kSpanKey); + if (nostd::holds_alternative>(context_value)) + { + nostd::shared_ptr &data = + nostd::get>(context_value); + if (data) + { + recordable->SetTraceId(data->GetContext().trace_id()); + recordable->SetTraceFlags(data->GetContext().trace_flags()); + recordable->SetSpanId(data->GetContext().span_id()); + } + } + else if (nostd::holds_alternative>(context_value)) + { + nostd::shared_ptr &data = + nostd::get>(context_value); + if (data) + { + recordable->SetTraceId(data->trace_id()); + recordable->SetTraceFlags(data->trace_flags()); + recordable->SetSpanId(data->span_id()); + } + } + } + + return nostd::unique_ptr(recordable.release()); } void Logger::EmitLogRecord(nostd::unique_ptr &&log_record) noexcept diff --git a/sdk/src/logs/logger_provider.cc b/sdk/src/logs/logger_provider.cc index 3000aa8230..b262d0df44 100644 --- a/sdk/src/logs/logger_provider.cc +++ b/sdk/src/logs/logger_provider.cc @@ -58,10 +58,11 @@ LoggerProvider::~LoggerProvider() nostd::shared_ptr LoggerProvider::GetLogger( nostd::string_view logger_name, - nostd::string_view /* options */, nostd::string_view library_name, nostd::string_view library_version, - nostd::string_view schema_url) noexcept + nostd::string_view schema_url, + bool include_trace_context, + const opentelemetry::common::KeyValueIterable & /*attributes*/) noexcept { // Ensure only one thread can read/write from the map of loggers std::lock_guard lock_guard{lock_}; @@ -102,22 +103,13 @@ nostd::shared_ptr LoggerProvider::GetLogger( lib = instrumentationscope::InstrumentationScope::Create(library_name, library_version, schema_url); } + // TODO: attributes should be added into InstrumentationScope once it implement attributes. loggers_.push_back(std::shared_ptr( - new Logger(logger_name, context_, std::move(lib)))); + new Logger(logger_name, context_, std::move(lib), include_trace_context))); return nostd::shared_ptr{loggers_.back()}; } -nostd::shared_ptr LoggerProvider::GetLogger( - nostd::string_view logger_name, - nostd::span /* args */, - nostd::string_view library_name, - nostd::string_view library_version, - nostd::string_view schema_url) noexcept -{ - return GetLogger(logger_name, "", library_name, library_version, schema_url); -} - void LoggerProvider::AddProcessor(std::unique_ptr processor) noexcept { context_->AddProcessor(std::move(processor)); diff --git a/sdk/test/logs/BUILD b/sdk/test/logs/BUILD index edf3a9a8d3..ccb75e0f86 100644 --- a/sdk/test/logs/BUILD +++ b/sdk/test/logs/BUILD @@ -25,6 +25,7 @@ cc_test( ], deps = [ "//sdk/src/logs", + "//sdk/src/trace", "@com_google_googletest//:gtest_main", ], ) diff --git a/sdk/test/logs/CMakeLists.txt b/sdk/test/logs/CMakeLists.txt index 23d2a89f21..c25eff62d2 100644 --- a/sdk/test/logs/CMakeLists.txt +++ b/sdk/test/logs/CMakeLists.txt @@ -2,8 +2,9 @@ foreach(testname logger_provider_sdk_test logger_sdk_test log_record_test simple_log_record_processor_test batch_log_record_processor_test) add_executable(${testname} "${testname}.cc") - target_link_libraries(${testname} ${GTEST_BOTH_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} opentelemetry_logs) + target_link_libraries( + ${testname} ${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} + opentelemetry_logs opentelemetry_trace) gtest_add_tests( TARGET ${testname} TEST_PREFIX logs. diff --git a/sdk/test/logs/logger_provider_sdk_test.cc b/sdk/test/logs/logger_provider_sdk_test.cc index 9339560377..db5772ebf5 100644 --- a/sdk/test/logs/logger_provider_sdk_test.cc +++ b/sdk/test/logs/logger_provider_sdk_test.cc @@ -4,9 +4,12 @@ #ifdef ENABLE_LOGS_PREVIEW # include +# include + # include "opentelemetry/logs/provider.h" # include "opentelemetry/nostd/shared_ptr.h" # include "opentelemetry/nostd/string_view.h" +# include "opentelemetry/sdk/logs/event_logger_provider_factory.h" # include "opentelemetry/sdk/logs/logger.h" # include "opentelemetry/sdk/logs/logger_provider.h" # include "opentelemetry/sdk/logs/recordable.h" @@ -33,8 +36,8 @@ TEST(LoggerProviderSDK, LoggerProviderGetLoggerSimple) auto lp = std::shared_ptr(new LoggerProvider()); nostd::string_view schema_url{"https://opentelemetry.io/schemas/1.11.0"}; - auto logger1 = lp->GetLogger("logger1", "", "opentelelemtry_library", "", schema_url); - auto logger2 = lp->GetLogger("logger2", "", "", "", schema_url); + auto logger1 = lp->GetLogger("logger1", "opentelelemtry_library", "", schema_url); + auto logger2 = lp->GetLogger("logger2", "", "", schema_url); // Check that the logger is not nullptr ASSERT_NE(logger1, nullptr); @@ -54,7 +57,7 @@ TEST(LoggerProviderSDK, LoggerProviderGetLoggerSimple) ASSERT_NE(logger1, logger2); // Check that two loggers with the same name are the same instance - auto logger3 = lp->GetLogger("logger1", "", "opentelelemtry_library", "", schema_url); + auto logger3 = lp->GetLogger("logger1", "opentelelemtry_library", "", schema_url); ASSERT_EQ(logger1, logger3); auto sdk_logger3 = static_cast(logger3.get()); ASSERT_EQ(sdk_logger3->GetInstrumentationScope(), sdk_logger1->GetInstrumentationScope()); @@ -68,15 +71,30 @@ TEST(LoggerProviderSDK, LoggerProviderLoggerArguments) auto lp = std::shared_ptr(new LoggerProvider()); nostd::string_view schema_url{"https://opentelemetry.io/schemas/1.11.0"}; - auto logger1 = lp->GetLogger("logger1", "", "opentelelemtry_library", "", schema_url); + auto logger1 = lp->GetLogger("logger1", "opentelelemtry_library", "", schema_url); - // Check GetLogger(logger_name, args) - std::array sv{"string"}; - nostd::span args{sv}; - auto logger2 = lp->GetLogger("logger2", args, "opentelelemtry_library", "", schema_url); + auto logger2 = lp->GetLogger("logger2", "opentelelemtry_library", "", schema_url); auto sdk_logger1 = static_cast(logger1.get()); auto sdk_logger2 = static_cast(logger2.get()); ASSERT_EQ(sdk_logger2->GetInstrumentationScope(), sdk_logger1->GetInstrumentationScope()); + + auto logger3 = lp->GetLogger("logger3", "opentelelemtry_library", "", schema_url, true, + {{"scope_key1", "scope_value"}, {"scope_key1", 2}}); + + std::unordered_map scope_attributes = {{"scope_key", "scope_value"}}; + auto logger4 = + lp->GetLogger("logger4", "opentelelemtry_library", "", schema_url, true, scope_attributes); +} + +TEST(LoggerProviderSDK, EventLoggerProviderFactory) +{ + auto elp = opentelemetry::sdk::logs::EventLoggerProviderFactory::Create(); + auto lp = std::shared_ptr(new LoggerProvider()); + + nostd::string_view schema_url{"https://opentelemetry.io/schemas/1.11.0"}; + auto logger1 = lp->GetLogger("logger1", "opentelelemtry_library", "", schema_url); + + auto event_logger = elp->CreateEventLogger(logger1, "otel-cpp.test"); } class DummyLogRecordable final : public opentelemetry::sdk::logs::Recordable diff --git a/sdk/test/logs/logger_sdk_test.cc b/sdk/test/logs/logger_sdk_test.cc index b6b597a887..848d9f19df 100644 --- a/sdk/test/logs/logger_sdk_test.cc +++ b/sdk/test/logs/logger_sdk_test.cc @@ -7,8 +7,12 @@ # include "opentelemetry/nostd/string_view.h" # include "opentelemetry/nostd/variant.h" +# include "opentelemetry/sdk/logs/event_logger.h" +# include "opentelemetry/sdk/logs/event_logger_provider.h" # include "opentelemetry/sdk/logs/logger.h" # include "opentelemetry/sdk/logs/recordable.h" +# include "opentelemetry/sdk/trace/tracer_provider_factory.h" +# include "opentelemetry/trace/scope.h" # include @@ -18,13 +22,13 @@ namespace nostd = opentelemetry::nostd; TEST(LoggerSDK, LogToNullProcessor) { - // Confirm Logger::Log() does not have undefined behavior + // Confirm Logger::EmitLogRecord() does not have undefined behavior // even when there is no processor set // since it calls Processor::OnEmit() auto lp = std::shared_ptr(new LoggerProvider()); const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"}; - auto logger = lp->GetLogger("logger", "", "opentelelemtry_library", "", schema_url); + auto logger = lp->GetLogger("logger", "opentelelemtry_library", "", schema_url); auto sdk_logger = static_cast(logger.get()); ASSERT_EQ(sdk_logger->GetInstrumentationScope().GetName(), "opentelelemtry_library"); @@ -64,15 +68,50 @@ class MockLogRecordable final : public opentelemetry::sdk::logs::Recordable void SetBody(const std::string &message) noexcept { body_ = message; } - void SetTraceId(const opentelemetry::trace::TraceId &) noexcept override {} + void SetTraceId(const opentelemetry::trace::TraceId &trace_id) noexcept override + { + trace_id_ = trace_id; + } + inline const opentelemetry::trace::TraceId &GetTraceId() const noexcept { return trace_id_; } - void SetSpanId(const opentelemetry::trace::SpanId &) noexcept override {} + void SetSpanId(const opentelemetry::trace::SpanId &span_id) noexcept override + { + span_id_ = span_id; + } - void SetTraceFlags(const opentelemetry::trace::TraceFlags &) noexcept override {} + inline const opentelemetry::trace::SpanId &GetSpanId() const noexcept { return span_id_; } - void SetAttribute(nostd::string_view, - const opentelemetry::common::AttributeValue &) noexcept override - {} + void SetTraceFlags(const opentelemetry::trace::TraceFlags &trace_flags) noexcept override + { + trace_flags_ = trace_flags; + } + + inline const opentelemetry::trace::TraceFlags &GetTraceFlags() const noexcept + { + return trace_flags_; + } + + void SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept override + { + if (!nostd::holds_alternative(value)) + { + return; + } + + if (key == "event.domain") + { + event_domain_ = static_cast(nostd::get(value)); + } + else if (key == "event.name") + { + event_name_ = static_cast(nostd::get(value)); + } + } + + inline const std::string &GetEventName() const noexcept { return event_name_; } + + inline const std::string &GetEventDomain() const noexcept { return event_domain_; } void SetResource(const opentelemetry::sdk::resource::Resource &) noexcept override {} @@ -80,9 +119,25 @@ class MockLogRecordable final : public opentelemetry::sdk::logs::Recordable const opentelemetry::sdk::instrumentationscope::InstrumentationScope &) noexcept override {} + void CopyFrom(const MockLogRecordable &other) + { + severity_ = other.severity_; + body_ = other.body_; + trace_id_ = other.trace_id_; + span_id_ = other.span_id_; + trace_flags_ = other.trace_flags_; + event_name_ = other.event_name_; + event_domain_ = other.event_domain_; + } + private: opentelemetry::logs::Severity severity_ = opentelemetry::logs::Severity::kInvalid; std::string body_; + opentelemetry::trace::TraceId trace_id_; + opentelemetry::trace::SpanId span_id_; + opentelemetry::trace::TraceFlags trace_flags_; + std::string event_name_; + std::string event_domain_; }; class MockProcessor final : public LogRecordProcessor @@ -111,8 +166,7 @@ class MockProcessor final : public LogRecordProcessor // Copy over the received log record's severity, name, and body fields over to the recordable // passed in the constructor - record_received_->SetSeverity(copy->GetSeverity()); - record_received_->SetBody(copy->GetBody()); + record_received_->CopyFrom(*copy); } bool ForceFlush(std::chrono::microseconds /* timeout */) noexcept override { return true; } @@ -124,15 +178,24 @@ TEST(LoggerSDK, LogToAProcessor) // Create an API LoggerProvider and logger auto api_lp = std::shared_ptr(new LoggerProvider()); const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"}; - auto logger = api_lp->GetLogger("logger", "", "opentelelemtry_library", "", schema_url); + auto logger = api_lp->GetLogger("logger", "opentelelemtry_library", "", schema_url, true); // Cast the API LoggerProvider to an SDK Logger Provider and assert that it is still the same // LoggerProvider by checking that getting a logger with the same name as the previously defined // logger is the same instance auto lp = static_cast(api_lp.get()); - auto logger2 = lp->GetLogger("logger", "", "opentelelemtry_library", "", schema_url); + auto logger2 = lp->GetLogger("logger", "opentelelemtry_library", "", schema_url, true); ASSERT_EQ(logger, logger2); + nostd::shared_ptr include_span; + { + std::vector> span_processors; + auto trace_provider = + opentelemetry::sdk::trace::TracerProviderFactory::Create(std::move(span_processors)); + include_span = trace_provider->GetTracer("logger")->StartSpan("test_logger"); + } + opentelemetry::trace::Scope trace_scope{include_span}; + auto sdk_logger = static_cast(logger.get()); ASSERT_EQ(sdk_logger->GetInstrumentationScope().GetName(), "opentelelemtry_library"); ASSERT_EQ(sdk_logger->GetInstrumentationScope().GetVersion(), ""); @@ -142,10 +205,56 @@ TEST(LoggerSDK, LogToAProcessor) lp->AddProcessor(std::unique_ptr( new MockProcessor(shared_recordable))); - // Check that the recordable created by the Log() statement is set properly - logger->Log(logs_api::Severity::kWarn, "Log Message"); + // Check that the recordable created by the EmitLogRecord() statement is set properly + logger->EmitLogRecord(logs_api::Severity::kWarn, "Log Message"); ASSERT_EQ(shared_recordable->GetSeverity(), logs_api::Severity::kWarn); ASSERT_EQ(shared_recordable->GetBody(), "Log Message"); + ASSERT_EQ(shared_recordable->GetTraceFlags().flags(), + include_span->GetContext().trace_flags().flags()); + char trace_id_in_logger[opentelemetry::trace::TraceId::kSize * 2]; + char trace_id_in_span[opentelemetry::trace::TraceId::kSize * 2]; + char span_id_in_logger[opentelemetry::trace::SpanId::kSize * 2]; + char span_id_in_span[opentelemetry::trace::SpanId::kSize * 2]; + shared_recordable->GetTraceId().ToLowerBase16(trace_id_in_logger); + include_span->GetContext().trace_id().ToLowerBase16(trace_id_in_span); + shared_recordable->GetSpanId().ToLowerBase16(span_id_in_logger); + include_span->GetContext().span_id().ToLowerBase16(span_id_in_span); + std::string trace_id_text_in_logger{trace_id_in_logger, sizeof(trace_id_in_logger)}; + std::string trace_id_text_in_span{trace_id_in_span, sizeof(trace_id_in_span)}; + std::string span_id_text_in_logger{span_id_in_logger, sizeof(span_id_in_logger)}; + std::string span_id_text_in_span{span_id_in_span, sizeof(span_id_in_span)}; + ASSERT_EQ(trace_id_text_in_logger, trace_id_text_in_span); + ASSERT_EQ(span_id_text_in_logger, span_id_text_in_span); } + +TEST(LoggerSDK, EventLog) +{ + // Create an API LoggerProvider and logger + auto api_lp = std::shared_ptr(new LoggerProvider()); + const std::string schema_url{"https://opentelemetry.io/schemas/1.11.0"}; + auto logger = api_lp->GetLogger("logger", "opentelelemtry_library", "", schema_url, false); + + auto api_elp = std::shared_ptr(new EventLoggerProvider()); + auto event_logger = api_elp->CreateEventLogger(logger, "otel-cpp.event_domain"); + + auto sdk_logger = static_cast(logger.get()); + ASSERT_EQ(sdk_logger->GetInstrumentationScope().GetName(), "opentelelemtry_library"); + ASSERT_EQ(sdk_logger->GetInstrumentationScope().GetVersion(), ""); + ASSERT_EQ(sdk_logger->GetInstrumentationScope().GetSchemaURL(), schema_url); + // Set a processor for the LoggerProvider + auto shared_recordable = std::shared_ptr(new MockLogRecordable()); + auto sdk_lp = static_cast(api_lp.get()); + sdk_lp->AddProcessor(std::unique_ptr( + new MockProcessor(shared_recordable))); + + // Check that the recordable created by the EmitEvent() statement is set properly + event_logger->EmitEvent("otel-cpp.event_name", logs_api::Severity::kWarn, "Event Log Message"); + + ASSERT_EQ(shared_recordable->GetSeverity(), logs_api::Severity::kWarn); + ASSERT_EQ(shared_recordable->GetBody(), "Event Log Message"); + ASSERT_EQ(shared_recordable->GetEventName(), "otel-cpp.event_name"); + ASSERT_EQ(shared_recordable->GetEventDomain(), "otel-cpp.event_domain"); +} + #endif