From 8785f642d08046e604f316a4102f755896341055 Mon Sep 17 00:00:00 2001 From: owent <admin@owent.net> Date: Tue, 29 Nov 2022 14:19:03 +0800 Subject: [PATCH] Remove `EmitEvent` to follow https://github.com/open-telemetry/opentelemetry-specification/pull/2941 Signed-off-by: owent <admin@owent.net> Fix `-Werror=suggest-override` and style Signed-off-by: owent <admin@owent.net> Fix ostream_log_test Signed-off-by: owent <admin@owent.net> Fix ostream print_value for `AttributeValue` Signed-off-by: owent <admin@owent.net> New Recordable of logs Signed-off-by: owent <admin@owent.net> Restore .vscode/launch.json Signed-off-by: owent <admin@owent.net> Fix warning. Signed-off-by: owent <admin@owent.net> Fix warnings in maintainer mode and ETW exporter Signed-off-by: owent <admin@owent.net> Add CHANGELOG Signed-off-by: owent <admin@owent.net> Allow to move 'nostd::unique_ptr<T>' into `nostd::shared_ptr<T>` Signed-off-by: owent <admin@owent.net> Do not use `std/type_traits.h` any more. Maybe we should remove this file later. Signed-off-by: owent <admin@owent.net> Allow to add rvalue into `CircularBuffer` Signed-off-by: owent <admin@owent.net> Finish new `LogRecord` for exporters. Signed-off-by: owent <admin@owent.net> Finish unit tests in API and SDK. Exporters are still work in progress. Signed-off-by: owent <admin@owent.net> New `LogRecord` and `Recordable` implementations. Signed-off-by: WenTao Ou <admin@owent.net> Restore `nostd::unique_ptr` to `std::unique_ptr` in sdk and exporters. Signed-off-by: WenTao Ou <admin@owent.net> Fix feedback of comments and useless headers Signed-off-by: WenTao Ou <admin@owent.net> Optimize if branch in `ReadWriteLogRecord::GetResource` . Signed-off-by: owent <admin@owent.net> --- .vscode/launch.json | 44 +-- CHANGELOG.md | 2 + .../common/key_value_iterable_view.h | 8 + api/include/opentelemetry/logs/log_record.h | 81 +++++ api/include/opentelemetry/logs/logger.h | 217 ++++++------- api/include/opentelemetry/logs/noop.h | 21 +- api/include/opentelemetry/nostd/shared_ptr.h | 15 + api/test/logs/logger_test.cc | 39 +-- exporters/elasticsearch/BUILD | 1 + exporters/elasticsearch/CMakeLists.txt | 2 +- .../elasticsearch/es_log_record_exporter.h | 3 +- .../elasticsearch/es_log_recordable.h | 194 +++--------- .../src/es_log_record_exporter.cc | 2 +- .../elasticsearch/src/es_log_recordable.cc | 296 ++++++++++++++++++ .../test/es_log_record_exporter_test.cc | 1 - .../opentelemetry/exporters/etw/etw_logger.h | 148 ++++++--- .../exporters/ostream/common_utils.h | 47 +++ .../exporters/ostream/log_record_exporter.h | 5 +- exporters/ostream/src/log_record_exporter.cc | 45 ++- exporters/ostream/test/ostream_log_test.cc | 118 +++---- .../exporters/otlp/otlp_log_recordable.h | 73 ++--- .../otlp/otlp_populate_attribute_utils.h | 10 + .../exporters/otlp/otlp_recordable_utils.h | 6 +- .../otlp/src/otlp_grpc_log_record_exporter.cc | 3 +- .../otlp/src/otlp_http_log_record_exporter.cc | 3 +- exporters/otlp/src/otlp_log_recordable.cc | 195 ++++++------ .../otlp/src/otlp_populate_attribute_utils.cc | 123 +++++--- exporters/otlp/src/otlp_recordable_utils.cc | 4 +- .../otlp_grpc_log_record_exporter_test.cc | 1 - .../otlp_http_log_record_exporter_test.cc | 1 - .../otlp/test/otlp_log_recordable_test.cc | 149 ++++----- .../sdk/common/circular_buffer.h | 8 + .../logs/batch_log_record_processor_factory.h | 2 + sdk/include/opentelemetry/sdk/logs/exporter.h | 3 +- .../opentelemetry/sdk/logs/log_record.h | 200 ------------ sdk/include/opentelemetry/sdk/logs/logger.h | 42 +-- .../opentelemetry/sdk/logs/logger_context.h | 2 + .../sdk/logs/logger_context_factory.h | 2 + .../opentelemetry/sdk/logs/multi_recordable.h | 55 ++-- .../opentelemetry/sdk/logs/processor.h | 5 +- .../sdk/logs/read_write_log_record.h | 191 +++++++++++ .../sdk/logs/readable_log_record.h | 121 +++++++ .../opentelemetry/sdk/logs/recordable.h | 63 +--- .../sdk/logs/simple_log_record_processor.h | 1 + .../simple_log_record_processor_factory.h | 2 + sdk/src/logs/CMakeLists.txt | 4 +- sdk/src/logs/batch_log_record_processor.cc | 2 +- sdk/src/logs/logger.cc | 84 +---- sdk/src/logs/logger_provider.cc | 2 +- sdk/src/logs/multi_log_record_processor.cc | 2 +- sdk/src/logs/multi_recordable.cc | 79 +++-- sdk/src/logs/read_write_log_record.cc | 174 ++++++++++ sdk/src/logs/readable_log_record.cc | 51 +++ .../logs/batch_log_record_processor_test.cc | 99 ++++-- sdk/test/logs/log_record_test.cc | 28 +- sdk/test/logs/logger_provider_sdk_test.cc | 32 +- sdk/test/logs/logger_sdk_test.cc | 79 ++++- .../logs/simple_log_record_processor_test.cc | 64 +++- 58 files changed, 2048 insertions(+), 1206 deletions(-) create mode 100644 api/include/opentelemetry/logs/log_record.h create mode 100644 exporters/elasticsearch/src/es_log_recordable.cc delete mode 100644 sdk/include/opentelemetry/sdk/logs/log_record.h create mode 100644 sdk/include/opentelemetry/sdk/logs/read_write_log_record.h create mode 100644 sdk/include/opentelemetry/sdk/logs/readable_log_record.h create mode 100644 sdk/src/logs/read_write_log_record.cc create mode 100644 sdk/src/logs/readable_log_record.cc diff --git a/.vscode/launch.json b/.vscode/launch.json index e9a256a518..3532ca4d2a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,24 +1,24 @@ { - "version": "0.2.0", - "configurations": [ - { - "name": "Debug on Windows", - "type": "cppvsdbg", - "request": "launch", - "program": "${workspaceFolder}/build/<path-to-bin-file>", - "args": [], - "stopAtEntry": false, - "cwd": "${workspaceFolder}", - "environment": [], - "externalConsole": false - }, - { - "name": "Debug on Linux", - "type": "gdb", - "request": "launch", - "target": "${workspaceFolder}/bazel-bin/<path to the bin file>", - "cwd": "${workspaceRoot}", - "valuesFormatting": "parseText" - } - ] + "version": "0.2.0", + "configurations": [ + { + "name": "Debug on Windows", + "type": "cppvsdbg", + "request": "launch", + "program": "${workspaceFolder}/build/<path-to-bin-file>", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false + }, + { + "name": "Debug on Linux", + "type": "gdb", + "request": "launch", + "target": "${workspaceFolder}/bazel-bin/<path to the bin file>", + "cwd": "${workspaceRoot}", + "valuesFormatting": "parseText" + } + ] } diff --git a/CHANGELOG.md b/CHANGELOG.md index fbe24799dd..3b2e3bb0dc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -69,6 +69,8 @@ exporters [#1828](https://github.com/open-telemetry/opentelemetry-cpp/pull/1828) * [BUILD] Add CMake OTELCPP_PROTO_PATH [#1730](https://github.com/open-telemetry/opentelemetry-cpp/pull/1730) * [SEMANTIC CONVENTIONS] Upgrade to version 1.15.0 [#1761](https://github.com/open-telemetry/opentelemetry-cpp/pull/1761) +* [LOGS SDK] New LogRecord and logs::Recordable implementations. + [#1766](https://github.com/open-telemetry/opentelemetry-cpp/pull/1766) Deprecation notes: diff --git a/api/include/opentelemetry/common/key_value_iterable_view.h b/api/include/opentelemetry/common/key_value_iterable_view.h index 2a0cbbc445..e688ec253f 100644 --- a/api/include/opentelemetry/common/key_value_iterable_view.h +++ b/api/include/opentelemetry/common/key_value_iterable_view.h @@ -8,6 +8,7 @@ #include <utility> #include "opentelemetry/common/key_value_iterable.h" +#include "opentelemetry/nostd/type_traits.h" #include "opentelemetry/nostd/utility.h" #include "opentelemetry/version.h" @@ -73,5 +74,12 @@ class KeyValueIterableView final : public KeyValueIterable private: const T *container_; }; + +template <class T, nostd::enable_if_t<detail::is_key_value_iterable<T>::value> * = nullptr> +KeyValueIterableView<T> MakeKeyValueIterableView(const T &container) noexcept +{ + return KeyValueIterableView<T>(container); +} + } // namespace common OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/logs/log_record.h b/api/include/opentelemetry/logs/log_record.h new file mode 100644 index 0000000000..7fb51c2d99 --- /dev/null +++ b/api/include/opentelemetry/logs/log_record.h @@ -0,0 +1,81 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include "opentelemetry/common/attribute_value.h" +# include "opentelemetry/common/key_value_iterable.h" +# include "opentelemetry/common/timestamp.h" +# include "opentelemetry/logs/severity.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 +{ +/** + * Maintains a representation of a log in a format that can be processed by a recorder. + * + * This class is thread-compatible. + */ +class LogRecord +{ +public: + virtual ~LogRecord() = default; + + /** + * Set the timestamp for this log. + * @param timestamp the timestamp to set + */ + virtual void SetTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept = 0; + + /** + * Set the observed timestamp for this log. + * @param timestamp the timestamp to set + */ + virtual void SetObservedTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept = 0; + + /** + * Set the severity for this log. + * @param severity the severity of the event + */ + virtual void SetSeverity(opentelemetry::logs::Severity severity) noexcept = 0; + + /** + * Set body field for this log. + * @param message the body to set + */ + virtual void SetBody(const opentelemetry::common::AttributeValue &message) noexcept = 0; + + /** + * Set an attribute of a log. + * @param key the name of the attribute + * @param value the attribute value + */ + virtual void SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept = 0; + + /** + * Set the trace id for this log. + * @param trace_id the trace id to set + */ + virtual void SetTraceId(const opentelemetry::trace::TraceId &trace_id) noexcept = 0; + + /** + * Set the span id for this log. + * @param span_id the span id to set + */ + virtual void SetSpanId(const opentelemetry::trace::SpanId &span_id) noexcept = 0; + + /** + * Inject trace_flags for this log. + * @param trace_flags the trace flags to set + */ + virtual void SetTraceFlags(const opentelemetry::trace::TraceFlags &trace_flags) 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 32c3974a1f..a8342e3f71 100644 --- a/api/include/opentelemetry/logs/logger.h +++ b/api/include/opentelemetry/logs/logger.h @@ -13,11 +13,14 @@ # 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" @@ -38,8 +41,40 @@ class Logger virtual const nostd::string_view GetName() noexcept = 0; /** - * Each of the following overloaded Log(...) methods - * creates a log message with the specific parameters passed. + * Create a Log Record object + * + * @return nostd::unique_ptr<LogRecord> + */ + virtual nostd::unique_ptr<LogRecord> CreateLogRecord() noexcept = 0; + + /** + * Emit a Log Record object + * + * @param log_record + */ + virtual void EmitLogRecord(nostd::unique_ptr<LogRecord> &&log_record) noexcept = 0; + + /** + * Emit a Log Record object with custom span context + * + * @param log_record + */ + virtual void EmitLogRecord(nostd::unique_ptr<LogRecord> &&log_record, + const trace::SpanContext &trace_context) + { + 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)); + } + + /** * * @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). @@ -51,45 +86,75 @@ class Logger * @param timestamp the timestamp the log record was created. * @throws No exceptions under any circumstances. */ - - /** - * The base Log(...) method that all other Log(...) overloaded methods will eventually call, - * in order to create a log record. - */ 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 = 0; + common::SystemTimestamp timestamp) noexcept + { + nostd::unique_ptr<LogRecord> 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)); + } /** - * Each of the following overloaded Log(...) methods - * creates a log message with the specific parameters passed. * * @param severity the severity level of the log event. - * @param name the name 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. */ - OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") virtual void Log(Severity severity, - OPENTELEMETRY_MAYBE_UNUSED nostd::string_view name, nostd::string_view body, const common::KeyValueIterable &attributes, - trace::TraceId trace_id, - trace::SpanId span_id, - trace::TraceFlags trace_flags, common::SystemTimestamp timestamp) noexcept { - Log(severity, body, attributes, trace_id, span_id, trace_flags, timestamp); + nostd::unique_ptr<LogRecord> 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)); } /*** Overloaded methods for KeyValueIterables ***/ @@ -113,18 +178,12 @@ class Logger template <class T, nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> - OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") void Log(Severity severity, - nostd::string_view name, nostd::string_view body, const T &attributes, - trace::TraceId trace_id, - trace::SpanId span_id, - trace::TraceFlags trace_flags, common::SystemTimestamp timestamp) noexcept { - Log(severity, name, body, common::KeyValueIterableView<T>(attributes), trace_id, span_id, - trace_flags, timestamp); + Log(severity, body, common::KeyValueIterableView<T>(attributes), timestamp); } void Log(Severity severity, @@ -141,22 +200,6 @@ class Logger trace_id, span_id, trace_flags, timestamp); } - OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") - void Log(Severity severity, - nostd::string_view name, - nostd::string_view body, - std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes, - trace::TraceId trace_id, - trace::SpanId span_id, - trace::TraceFlags trace_flags, - common::SystemTimestamp timestamp) noexcept - { - return this->Log(severity, name, body, - nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{ - attributes.begin(), attributes.end()}, - trace_id, span_id, trace_flags, timestamp); - } - /** Wrapper methods that the user could call for convenience when logging **/ /** @@ -166,13 +209,9 @@ class Logger */ void Log(Severity severity, nostd::string_view message) noexcept { - this->Log(severity, message, {}, {}, {}, {}, std::chrono::system_clock::now()); - } - - OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") - void Log(Severity severity, nostd::string_view name, nostd::string_view message) noexcept - { - this->Log(severity, name, message, {}, {}, {}, {}, std::chrono::system_clock::now()); + this->Log(severity, message, + nostd::span<const std::pair<nostd::string_view, common::AttributeValue>>{}, + std::chrono::system_clock::now()); } /** @@ -184,7 +223,7 @@ class Logger nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> void Log(Severity severity, const T &attributes) noexcept { - this->Log(severity, "", attributes, {}, {}, {}, std::chrono::system_clock::now()); + this->Log(severity, "", attributes, std::chrono::system_clock::now()); } /** @@ -197,7 +236,7 @@ class Logger nostd::enable_if_t<common::detail::is_key_value_iterable<T>::value> * = nullptr> void Log(Severity severity, nostd::string_view message, const T &attributes) noexcept { - this->Log(severity, message, attributes, {}, {}, {}, std::chrono::system_clock::now()); + this->Log(severity, message, attributes, std::chrono::system_clock::now()); } /** @@ -209,7 +248,7 @@ class Logger std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes) noexcept { - this->Log(severity, "", attributes, {}, {}, {}, std::chrono::system_clock::now()); + this->Log(severity, "", attributes, std::chrono::system_clock::now()); } /** @@ -223,7 +262,7 @@ class Logger std::initializer_list<std::pair<nostd::string_view, common::AttributeValue>> attributes) noexcept { - this->Log(severity, message, attributes, {}, {}, {}, std::chrono::system_clock::now()); + this->Log(severity, message, attributes, std::chrono::system_clock::now()); } /** @@ -234,7 +273,7 @@ class Logger */ void Log(Severity severity, const common::KeyValueIterable &attributes) noexcept { - this->Log(severity, "", attributes, {}, {}, {}, std::chrono::system_clock::now()); + this->Log(severity, "", attributes, std::chrono::system_clock::now()); } /** @@ -248,7 +287,7 @@ class Logger nostd::string_view message, const common::KeyValueIterable &attributes) noexcept { - this->Log(severity, message, attributes, {}, {}, {}, std::chrono::system_clock::now()); + this->Log(severity, message, attributes, std::chrono::system_clock::now()); } /** Trace severity overloads **/ @@ -259,17 +298,6 @@ class Logger */ void Trace(nostd::string_view message) noexcept { this->Log(Severity::kTrace, message); } - /** - * Writes a log with a severity of trace. - * @param name The name of the log - * @param message The message to log - */ - OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") - void Trace(nostd::string_view name, nostd::string_view message) noexcept - { - this->Log(Severity::kTrace, name, message); - } - /** * Writes a log with a severity of trace. * @param attributes The attributes of the log as a key/value object @@ -323,17 +351,6 @@ class Logger */ void Debug(nostd::string_view message) noexcept { this->Log(Severity::kDebug, message); } - /** - * Writes a log with a severity of debug. - * @param name The name of the log - * @param message The message to log - */ - OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") - void Debug(nostd::string_view name, nostd::string_view message) noexcept - { - this->Log(Severity::kDebug, name, message); - } - /** * Writes a log with a severity of debug. * @param attributes The attributes of the log as a key/value object @@ -387,17 +404,6 @@ class Logger */ void Info(nostd::string_view message) noexcept { this->Log(Severity::kInfo, message); } - /** - * Writes a log with a severity of info. - * @param name The name of the log - * @param message The message to log - */ - OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") - void Info(nostd::string_view name, nostd::string_view message) noexcept - { - this->Log(Severity::kInfo, name, message); - } - /** * Writes a log with a severity of info. * @param attributes The attributes of the log as a key/value object @@ -451,17 +457,6 @@ class Logger */ void Warn(nostd::string_view message) noexcept { this->Log(Severity::kWarn, message); } - /** - * Writes a log with a severity of warn. - * @param name The name of the log - * @param message The message to log - */ - OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") - void Warn(nostd::string_view name, nostd::string_view message) noexcept - { - this->Log(Severity::kWarn, name, message); - } - /** * Writes a log with a severity of warn. * @param attributes The attributes of the log as a key/value object @@ -515,17 +510,6 @@ class Logger */ void Error(nostd::string_view message) noexcept { this->Log(Severity::kError, message); } - /** - * Writes a log with a severity of error. - * @param name The name of the log - * @param message The message to log - */ - OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") - void Error(nostd::string_view name, nostd::string_view message) noexcept - { - this->Log(Severity::kError, name, message); - } - /** * Writes a log with a severity of error. * @param attributes The attributes of the log as a key/value object @@ -579,17 +563,6 @@ class Logger */ void Fatal(nostd::string_view message) noexcept { this->Log(Severity::kFatal, message); } - /** - * Writes a log with a severity of fatal. - * @param name The name of the log - * @param message The message to log - */ - OPENTELEMETRY_DEPRECATED_MESSAGE("name will be removed in the future") - void Fatal(nostd::string_view name, nostd::string_view message) noexcept - { - this->Log(Severity::kFatal, name, message); - } - /** * Writes a log with a severity of fatal. * @param attributes The attributes of the log as a key/value object diff --git a/api/include/opentelemetry/logs/noop.h b/api/include/opentelemetry/logs/noop.h index 4663c86c18..d8941510da 100644 --- a/api/include/opentelemetry/logs/noop.h +++ b/api/include/opentelemetry/logs/noop.h @@ -41,24 +41,11 @@ class NoopLogger final : public Logger public: const nostd::string_view GetName() noexcept override { return "noop logger"; } - 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 override - {} + nostd::unique_ptr<LogRecord> CreateLogRecord() noexcept override { return nullptr; } - void Log(Severity /* severity */, - nostd::string_view /* name */, - nostd::string_view /* body */, - const common::KeyValueIterable & /* attributes */, - trace::TraceId /* trace_id */, - trace::SpanId /* span_id */, - trace::TraceFlags /* trace_flags */, - common::SystemTimestamp /* timestamp */) noexcept override - {} + using Logger::EmitLogRecord; + + void EmitLogRecord(nostd::unique_ptr<LogRecord> &&) noexcept override {} }; /** diff --git a/api/include/opentelemetry/nostd/shared_ptr.h b/api/include/opentelemetry/nostd/shared_ptr.h index 7afc30f9be..75b184f61c 100644 --- a/api/include/opentelemetry/nostd/shared_ptr.h +++ b/api/include/opentelemetry/nostd/shared_ptr.h @@ -9,6 +9,7 @@ # include <memory> # include <utility> +# include "opentelemetry/nostd/unique_ptr.h" # include "opentelemetry/version.h" OPENTELEMETRY_BEGIN_NAMESPACE @@ -96,6 +97,20 @@ class shared_ptr shared_ptr(const shared_ptr &other) noexcept { other.wrapper().CopyTo(buffer_); } + shared_ptr(unique_ptr<T> &&other) noexcept + { + std::shared_ptr<T> ptr_(other.release()); + new (buffer_.data) shared_ptr_wrapper{std::move(ptr_)}; + } + +# ifndef HAVE_CPP_STDLIB + shared_ptr(std::unique_ptr<T> &&other) noexcept + { + std::shared_ptr<T> ptr_(other.release()); + new (buffer_.data) shared_ptr_wrapper{std::move(ptr_)}; + } +# endif + ~shared_ptr() { wrapper().~shared_ptr_wrapper(); } shared_ptr &operator=(shared_ptr &&other) noexcept diff --git a/api/test/logs/logger_test.cc b/api/test/logs/logger_test.cc index 0ce3a61037..48e9c375d3 100644 --- a/api/test/logs/logger_test.cc +++ b/api/test/logs/logger_test.cc @@ -66,19 +66,6 @@ TEST(Logger, LogMethodOverloads) logger->Log(Severity::kError, {{"key1", "value 1"}, {"key2", 2}}); logger->Log(Severity::kFatal, "Logging an initializer list", {{"key1", "value 1"}, {"key2", 2}}); - // Deprecated Log overloads - logger->Log(Severity::kTrace, "Log name", "Test log message"); - logger->Log(Severity::kWarn, "Log name", "Logging a map", m, {}, {}, {}, - std::chrono::system_clock::now()); - logger->Log(Severity::kError, "Log name", "Logging a map", {{"key1", "value 1"}, {"key2", 2}}, {}, - {}, {}, std::chrono::system_clock::now()); - logger->Trace("Log name", "Test log message"); - logger->Debug("Log name", "Test log message"); - logger->Info("Log name", "Test log message"); - logger->Warn("Log name", "Test log message"); - logger->Error("Log name", "Test log message"); - logger->Fatal("Log name", "Test log message"); - // Severity methods logger->Trace("Test log message"); logger->Trace("Test log message", m); @@ -117,24 +104,14 @@ class TestLogger : public Logger { const nostd::string_view GetName() noexcept override { return "test logger"; } - void Log(Severity /* severity */, - string_view /* body */, - const common::KeyValueIterable & /* attributes */, - trace::TraceId /* trace_id */, - trace::SpanId /* span_id */, - trace::TraceFlags /* trace_flags */, - common::SystemTimestamp /* timestamp */) noexcept override - {} - - void Log(Severity /* severity */, - nostd::string_view /* name */, - nostd::string_view /* body */, - const common::KeyValueIterable & /* attributes */, - trace::TraceId /* trace_id */, - trace::SpanId /* span_id */, - trace::TraceFlags /* trace_flags */, - common::SystemTimestamp /* timestamp */) noexcept override - {} + nostd::unique_ptr<opentelemetry::logs::LogRecord> CreateLogRecord() noexcept override + { + return nullptr; + } + + using Logger::EmitLogRecord; + + void EmitLogRecord(nostd::unique_ptr<opentelemetry::logs::LogRecord> &&) noexcept override {} }; // Define a basic LoggerProvider class that returns an instance of the logger class defined above diff --git a/exporters/elasticsearch/BUILD b/exporters/elasticsearch/BUILD index a13c881b0b..16fae2edab 100644 --- a/exporters/elasticsearch/BUILD +++ b/exporters/elasticsearch/BUILD @@ -4,6 +4,7 @@ cc_library( name = "es_log_record_exporter", srcs = [ "src/es_log_record_exporter.cc", + "src/es_log_recordable.cc", ], hdrs = [ "include/opentelemetry/exporters/elasticsearch/es_log_record_exporter.h", diff --git a/exporters/elasticsearch/CMakeLists.txt b/exporters/elasticsearch/CMakeLists.txt index ddae27cb71..90064e292d 100644 --- a/exporters/elasticsearch/CMakeLists.txt +++ b/exporters/elasticsearch/CMakeLists.txt @@ -1,5 +1,5 @@ add_library(opentelemetry_exporter_elasticsearch_logs - src/es_log_record_exporter.cc) + src/es_log_record_exporter.cc src/es_log_recordable.cc) set_target_properties(opentelemetry_exporter_elasticsearch_logs PROPERTIES EXPORT_NAME elasticsearch_log_record_exporter) diff --git a/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_record_exporter.h b/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_record_exporter.h index 2659851fd7..7a52810df0 100644 --- a/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_record_exporter.h +++ b/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_record_exporter.h @@ -9,7 +9,7 @@ # include "opentelemetry/ext/http/client/http_client_factory.h" # include "opentelemetry/nostd/type_traits.h" # include "opentelemetry/sdk/logs/exporter.h" -# include "opentelemetry/sdk/logs/log_record.h" +# include "opentelemetry/sdk/logs/recordable.h" # include <time.h> # include <iostream> @@ -77,6 +77,7 @@ class ElasticsearchLogRecordExporter final : public opentelemetry::sdk::logs::Lo /** * Creates a recordable that stores the data in a JSON object + * @return a newly initialized Recordable object. */ std::unique_ptr<opentelemetry::sdk::logs::Recordable> MakeRecordable() noexcept override; diff --git a/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_recordable.h b/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_recordable.h index 3e604ccf17..d6ed78d117 100644 --- a/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_recordable.h +++ b/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_recordable.h @@ -28,208 +28,92 @@ namespace logs class ElasticSearchRecordable final : public sdk::logs::Recordable { private: - // Define a JSON object that will be populated with the log data - nlohmann::json json_; - /** * A helper method that writes a key/value pair under a specified name, the two names used here * being "attributes" and "resources" */ void WriteKeyValue(nostd::string_view key, const opentelemetry::common::AttributeValue &value, - std::string name) - { - switch (value.index()) - { - case common::AttributeType::kTypeBool: - json_[name][key.data()] = opentelemetry::nostd::get<bool>(value) ? true : false; - return; - case common::AttributeType::kTypeInt: - json_[name][key.data()] = opentelemetry::nostd::get<int>(value); - return; - case common::AttributeType::kTypeInt64: - json_[name][key.data()] = opentelemetry::nostd::get<int64_t>(value); - return; - case common::AttributeType::kTypeUInt: - json_[name][key.data()] = opentelemetry::nostd::get<unsigned int>(value); - return; - case common::AttributeType::kTypeUInt64: - json_[name][key.data()] = opentelemetry::nostd::get<uint64_t>(value); - return; - case common::AttributeType::kTypeDouble: - json_[name][key.data()] = opentelemetry::nostd::get<double>(value); - return; - case common::AttributeType::kTypeCString: - json_[name][key.data()] = opentelemetry::nostd::get<const char *>(value); - return; - case common::AttributeType::kTypeString: - json_[name][key.data()] = - opentelemetry::nostd::get<opentelemetry::nostd::string_view>(value).data(); - return; - default: - return; - } - } + std::string name); void WriteKeyValue(nostd::string_view key, const opentelemetry::sdk::common::OwnedAttributeValue &value, - std::string name) - { - namespace common = opentelemetry::sdk::common; - switch (value.index()) - { - case common::kTypeBool: - json_[name][key.data()] = opentelemetry::nostd::get<bool>(value) ? true : false; - return; - case common::kTypeInt: - json_[name][key.data()] = opentelemetry::nostd::get<int>(value); - return; - case common::kTypeInt64: - json_[name][key.data()] = opentelemetry::nostd::get<int64_t>(value); - return; - case common::kTypeUInt: - json_[name][key.data()] = opentelemetry::nostd::get<unsigned int>(value); - return; - case common::kTypeUInt64: - json_[name][key.data()] = opentelemetry::nostd::get<uint64_t>(value); - return; - case common::kTypeDouble: - json_[name][key.data()] = opentelemetry::nostd::get<double>(value); - return; - case common::kTypeString: - json_[name][key.data()] = opentelemetry::nostd::get<std::string>(value).data(); - return; - default: - return; - } - } + std::string name); + + void WriteValue(const opentelemetry::common::AttributeValue &value, std::string name); public: /** - * Set the severity for this log. - * @param severity the severity of the event + * Returns a JSON object contain the log information */ - void SetSeverity(opentelemetry::logs::Severity severity) noexcept override - { - // Convert the severity enum to a string - std::uint32_t severity_index = static_cast<std::uint32_t>(severity); - if (severity_index >= std::extent<decltype(opentelemetry::logs::SeverityNumToText)>::value) - { - std::stringstream sout; - sout << "Invalid severity(" << severity_index << ")"; - json_["severity"] = sout.str(); - } - else - { - json_["severity"] = opentelemetry::logs::SeverityNumToText[severity_index]; - } - } + nlohmann::json GetJSON() noexcept; /** - * Set body field for this log. - * @param message the body to set + * Set the timestamp for this log. + * @param timestamp the timestamp to set */ - void SetBody(nostd::string_view message) noexcept override { json_["body"] = message.data(); } + void SetTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept override; /** - * Set Resource of this log - * @param Resource the resource to set + * Set the observed timestamp for this log. + * @param timestamp the timestamp to set */ - void SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept override - { - for (auto &kv : resource.GetAttributes()) - { - WriteKeyValue(kv.first, kv.second, "resource"); - } - } + void SetObservedTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept override; /** - * Set an attribute of a log. - * @param key the key of the attribute - * @param value the attribute value + * Set the severity for this log. + * @param severity the severity of the event */ - void SetAttribute(nostd::string_view key, - const opentelemetry::common::AttributeValue &value) noexcept override - { - WriteKeyValue(key, value, "attributes"); - } + void SetSeverity(opentelemetry::logs::Severity severity) noexcept override; + + /** + * Set body field for this log. + * @param message the body to set + */ + void SetBody(const opentelemetry::common::AttributeValue &message) noexcept override; /** - * Set trace id for this log. + * Set the trace id for this log. * @param trace_id the trace id to set */ - void SetTraceId(opentelemetry::trace::TraceId trace_id) noexcept override - { - char trace_buf[32]; - trace_id.ToLowerBase16(trace_buf); - json_["traceid"] = std::string(trace_buf, sizeof(trace_buf)); - } + void SetTraceId(const opentelemetry::trace::TraceId &trace_id) noexcept override; /** - * Set span id for this log. + * Set the span id for this log. * @param span_id the span id to set */ - virtual void SetSpanId(opentelemetry::trace::SpanId span_id) noexcept override - { - char span_buf[16]; - span_id.ToLowerBase16(span_buf); - json_["spanid"] = std::string(span_buf, sizeof(span_buf)); - } + void SetSpanId(const opentelemetry::trace::SpanId &span_id) noexcept override; /** - * Inject a trace_flags for this log. - * @param trace_flags the span id to set + * Inject trace_flags for this log. + * @param trace_flags the trace flags to set */ - void SetTraceFlags(opentelemetry::trace::TraceFlags trace_flags) noexcept override - { - char flag_buf[2]; - trace_flags.ToLowerBase16(flag_buf); - json_["traceflags"] = std::string(flag_buf, sizeof(flag_buf)); - } + void SetTraceFlags(const opentelemetry::trace::TraceFlags &trace_flags) noexcept override; /** - * Set the timestamp for this log. - * @param timestamp the timestamp of the event + * Set an attribute of a log. + * @param key the name of the attribute + * @param value the attribute value */ - void SetTimestamp(common::SystemTimestamp timestamp) noexcept override - { - json_["timestamp"] = timestamp.time_since_epoch().count(); - } + void SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept override; /** - * Returns a JSON object contain the log information + * Set Resource of this log + * @param Resource the resource to set */ - nlohmann::json GetJSON() noexcept { return json_; } + void SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept override; /** * Set instrumentation_scope for this log. * @param instrumentation_scope the instrumentation scope to set */ void SetInstrumentationScope(const opentelemetry::sdk::instrumentationscope::InstrumentationScope - &instrumentation_scope) noexcept override - { - json_["name"] = instrumentation_scope.GetName(); - instrumentation_scope_ = &instrumentation_scope; - } - - /** Returns the associated instruementation library */ - OPENTELEMETRY_DEPRECATED_MESSAGE("Please use GetInstrumentationScope instead") - const opentelemetry::sdk::instrumentationscope::InstrumentationScope &GetInstrumentationLibrary() - const noexcept - { - return GetInstrumentationScope(); - } - - /** Returns the associated instruementation library */ - const opentelemetry::sdk::instrumentationscope::InstrumentationScope &GetInstrumentationScope() - const noexcept - { - return *instrumentation_scope_; - } + &instrumentation_scope) noexcept override; private: - const opentelemetry::sdk::instrumentationscope::InstrumentationScope *instrumentation_scope_ = - nullptr; + // Define a JSON object that will be populated with the log data + nlohmann::json json_; }; } // namespace logs } // namespace exporter diff --git a/exporters/elasticsearch/src/es_log_record_exporter.cc b/exporters/elasticsearch/src/es_log_record_exporter.cc index 3bd4fc7b0c..c440be685c 100644 --- a/exporters/elasticsearch/src/es_log_record_exporter.cc +++ b/exporters/elasticsearch/src/es_log_record_exporter.cc @@ -301,7 +301,7 @@ ElasticsearchLogRecordExporter::ElasticsearchLogRecordExporter( std::unique_ptr<sdklogs::Recordable> ElasticsearchLogRecordExporter::MakeRecordable() noexcept { - return std::unique_ptr<sdklogs::Recordable>(new ElasticSearchRecordable); + return std::unique_ptr<sdklogs::Recordable>(new ElasticSearchRecordable()); } sdk::common::ExportResult ElasticsearchLogRecordExporter::Export( diff --git a/exporters/elasticsearch/src/es_log_recordable.cc b/exporters/elasticsearch/src/es_log_recordable.cc new file mode 100644 index 0000000000..03c6c640e5 --- /dev/null +++ b/exporters/elasticsearch/src/es_log_recordable.cc @@ -0,0 +1,296 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifdef ENABLE_LOGS_PREVIEW + +# include "opentelemetry/exporters/elasticsearch/es_log_recordable.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace exporter +{ +namespace logs +{ +void ElasticSearchRecordable::WriteKeyValue(nostd::string_view key, + const opentelemetry::common::AttributeValue &value, + std::string name) +{ + switch (value.index()) + { + case common::AttributeType::kTypeBool: + json_[name][key.data()] = opentelemetry::nostd::get<bool>(value) ? true : false; + return; + case common::AttributeType::kTypeInt: + json_[name][key.data()] = opentelemetry::nostd::get<int>(value); + return; + case common::AttributeType::kTypeInt64: + json_[name][key.data()] = opentelemetry::nostd::get<int64_t>(value); + return; + case common::AttributeType::kTypeUInt: + json_[name][key.data()] = opentelemetry::nostd::get<unsigned int>(value); + return; + case common::AttributeType::kTypeUInt64: + json_[name][key.data()] = opentelemetry::nostd::get<uint64_t>(value); + return; + case common::AttributeType::kTypeDouble: + json_[name][key.data()] = opentelemetry::nostd::get<double>(value); + return; + case common::AttributeType::kTypeCString: + json_[name][key.data()] = opentelemetry::nostd::get<const char *>(value); + return; + case common::AttributeType::kTypeString: + json_[name][key.data()] = + opentelemetry::nostd::get<opentelemetry::nostd::string_view>(value).data(); + return; + default: + return; + } +} + +void ElasticSearchRecordable::WriteKeyValue( + nostd::string_view key, + const opentelemetry::sdk::common::OwnedAttributeValue &value, + std::string name) +{ + namespace common = opentelemetry::sdk::common; + switch (value.index()) + { + case common::kTypeBool: + json_[name][key.data()] = opentelemetry::nostd::get<bool>(value) ? true : false; + return; + case common::kTypeInt: + json_[name][key.data()] = opentelemetry::nostd::get<int>(value); + return; + case common::kTypeInt64: + json_[name][key.data()] = opentelemetry::nostd::get<int64_t>(value); + return; + case common::kTypeUInt: + json_[name][key.data()] = opentelemetry::nostd::get<unsigned int>(value); + return; + case common::kTypeUInt64: + json_[name][key.data()] = opentelemetry::nostd::get<uint64_t>(value); + return; + case common::kTypeDouble: + json_[name][key.data()] = opentelemetry::nostd::get<double>(value); + return; + case common::kTypeString: + json_[name][key.data()] = opentelemetry::nostd::get<std::string>(value).data(); + return; + default: + return; + } +} + +void ElasticSearchRecordable::WriteValue(const opentelemetry::common::AttributeValue &value, + std::string name) +{ + + // Assert size of variant to ensure that this method gets updated if the variant + // definition changes + + if (nostd::holds_alternative<bool>(value)) + { + json_[name] = opentelemetry::nostd::get<bool>(value) ? true : false; + } + else if (nostd::holds_alternative<int>(value)) + { + json_[name] = opentelemetry::nostd::get<int>(value); + } + else if (nostd::holds_alternative<int64_t>(value)) + { + json_[name] = opentelemetry::nostd::get<int64_t>(value); + } + else if (nostd::holds_alternative<unsigned int>(value)) + { + json_[name] = opentelemetry::nostd::get<unsigned int>(value); + } + else if (nostd::holds_alternative<uint64_t>(value)) + { + json_[name] = opentelemetry::nostd::get<uint64_t>(value); + } + else if (nostd::holds_alternative<double>(value)) + { + json_[name] = opentelemetry::nostd::get<double>(value); + } + else if (nostd::holds_alternative<const char *>(value)) + { + json_[name] = std::string(nostd::get<const char *>(value)); + } + else if (nostd::holds_alternative<nostd::string_view>(value)) + { + json_[name] = static_cast<std::string>(opentelemetry::nostd::get<nostd::string_view>(value)); + } + else if (nostd::holds_alternative<nostd::span<const uint8_t>>(value)) + { + nlohmann::json array_value = nlohmann::json::array(); + for (const auto &val : nostd::get<nostd::span<const uint8_t>>(value)) + { + array_value.push_back(val); + } + json_[name] = array_value; + } + else if (nostd::holds_alternative<nostd::span<const bool>>(value)) + { + nlohmann::json array_value = nlohmann::json::array(); + for (const auto &val : nostd::get<nostd::span<const bool>>(value)) + { + array_value.push_back(val); + } + json_[name] = array_value; + } + else if (nostd::holds_alternative<nostd::span<const int>>(value)) + { + nlohmann::json array_value = nlohmann::json::array(); + for (const auto &val : nostd::get<nostd::span<const int>>(value)) + { + array_value.push_back(val); + } + json_[name] = array_value; + } + else if (nostd::holds_alternative<nostd::span<const int64_t>>(value)) + { + nlohmann::json array_value = nlohmann::json::array(); + for (const auto &val : nostd::get<nostd::span<const int64_t>>(value)) + { + array_value.push_back(val); + } + json_[name] = array_value; + } + else if (nostd::holds_alternative<nostd::span<const unsigned int>>(value)) + { + nlohmann::json array_value = nlohmann::json::array(); + for (const auto &val : nostd::get<nostd::span<const unsigned int>>(value)) + { + array_value.push_back(val); + } + json_[name] = array_value; + } + else if (nostd::holds_alternative<nostd::span<const uint64_t>>(value)) + { + nlohmann::json array_value = nlohmann::json::array(); + for (const auto &val : nostd::get<nostd::span<const uint64_t>>(value)) + { + array_value.push_back(val); + } + json_[name] = array_value; + } + else if (nostd::holds_alternative<nostd::span<const double>>(value)) + { + nlohmann::json array_value = nlohmann::json::array(); + for (const auto &val : nostd::get<nostd::span<const double>>(value)) + { + array_value.push_back(val); + } + json_[name] = array_value; + } + else if (nostd::holds_alternative<nostd::span<const nostd::string_view>>(value)) + { + nlohmann::json array_value = nlohmann::json::array(); + for (const auto &val : nostd::get<nostd::span<const nostd::string_view>>(value)) + { + array_value.push_back(static_cast<std::string>(val)); + } + json_[name] = array_value; + } +} + +nlohmann::json ElasticSearchRecordable::GetJSON() noexcept +{ + return json_; +} + +void ElasticSearchRecordable::SetTimestamp( + opentelemetry::common::SystemTimestamp timestamp) noexcept +{ + json_["timestamp"] = timestamp.time_since_epoch().count(); +} + +void ElasticSearchRecordable::SetObservedTimestamp( + opentelemetry::common::SystemTimestamp timestamp) noexcept +{ + json_["observedtimestamp"] = timestamp.time_since_epoch().count(); +} + +void ElasticSearchRecordable::SetSeverity(opentelemetry::logs::Severity severity) noexcept +{ + // Convert the severity enum to a string + std::uint32_t severity_index = static_cast<std::uint32_t>(severity); + if (severity_index >= std::extent<decltype(opentelemetry::logs::SeverityNumToText)>::value) + { + std::stringstream sout; + sout << "Invalid severity(" << severity_index << ")"; + json_["severity"] = sout.str(); + } + else + { + json_["severity"] = opentelemetry::logs::SeverityNumToText[severity_index]; + } +} + +void ElasticSearchRecordable::SetBody(const opentelemetry::common::AttributeValue &message) noexcept +{ + WriteValue(message, "body"); +} + +void ElasticSearchRecordable::SetTraceId(const opentelemetry::trace::TraceId &trace_id) noexcept +{ + if (trace_id.IsValid()) + { + char trace_buf[32]; + trace_id.ToLowerBase16(trace_buf); + json_["traceid"] = std::string(trace_buf, sizeof(trace_buf)); + } + else + { + json_.erase("traceid"); + } +} + +void ElasticSearchRecordable::SetSpanId(const opentelemetry::trace::SpanId &span_id) noexcept +{ + if (span_id.IsValid()) + { + char span_buf[16]; + span_id.ToLowerBase16(span_buf); + json_["spanid"] = std::string(span_buf, sizeof(span_buf)); + } + else + { + json_.erase("spanid"); + } +} + +void ElasticSearchRecordable::SetTraceFlags( + const opentelemetry::trace::TraceFlags &trace_flags) noexcept +{ + char flag_buf[2]; + trace_flags.ToLowerBase16(flag_buf); + json_["traceflags"] = std::string(flag_buf, sizeof(flag_buf)); +} + +void ElasticSearchRecordable::SetAttribute( + nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept +{ + WriteKeyValue(key, value, "attributes"); +} + +void ElasticSearchRecordable::SetResource( + const opentelemetry::sdk::resource::Resource &resource) noexcept +{ + for (auto &attribute : resource.GetAttributes()) + { + WriteKeyValue(attribute.first, attribute.second, "resource"); + } +} + +void ElasticSearchRecordable::SetInstrumentationScope( + const opentelemetry::sdk::instrumentationscope::InstrumentationScope + &instrumentation_scope) noexcept +{ + json_["name"] = instrumentation_scope.GetName(); +} + +} // namespace logs +} // namespace exporter +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/exporters/elasticsearch/test/es_log_record_exporter_test.cc b/exporters/elasticsearch/test/es_log_record_exporter_test.cc index 4cd3b5064f..cc9af2ee2d 100644 --- a/exporters/elasticsearch/test/es_log_record_exporter_test.cc +++ b/exporters/elasticsearch/test/es_log_record_exporter_test.cc @@ -7,7 +7,6 @@ # include "opentelemetry/ext/http/server/http_server.h" # include "opentelemetry/logs/provider.h" # include "opentelemetry/sdk/logs/exporter.h" -# include "opentelemetry/sdk/logs/log_record.h" # include "opentelemetry/sdk/logs/logger_provider.h" # include "opentelemetry/sdk/logs/simple_log_record_processor.h" diff --git a/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h b/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h index 5897d53808..d72fe64edb 100644 --- a/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h +++ b/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h @@ -6,6 +6,7 @@ # include <algorithm> +# include <chrono> # include <cstdint> # include <cstdio> # include <cstdlib> @@ -15,6 +16,7 @@ # include <fstream> # include <map> +# include <unordered_map> # include "opentelemetry/nostd/shared_ptr.h" # include "opentelemetry/nostd/string_view.h" @@ -23,6 +25,7 @@ # include "opentelemetry/common/key_value_iterable_view.h" +# include "opentelemetry/logs/log_record.h" # include "opentelemetry/logs/logger_provider.h" # include "opentelemetry/trace/span_id.h" # include "opentelemetry/trace/trace_id.h" @@ -41,6 +44,88 @@ namespace etw class LoggerProvider; +class LogRecord : public opentelemetry::logs::LogRecord +{ +public: + ~LogRecord() override = default; + + void SetTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept override + { + timestamp_ = timestamp; + } + + opentelemetry::common::SystemTimestamp GetTimestamp() const noexcept { return timestamp_; } + + void SetObservedTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept override + { + observed_timestamp_ = timestamp; + } + + opentelemetry::common::SystemTimestamp GetObservedTimestamp() const noexcept + { + return observed_timestamp_; + } + + void SetSeverity(opentelemetry::logs::Severity severity) noexcept override + { + severity_ = severity; + } + + opentelemetry::logs::Severity GetSeverity() const noexcept { return severity_; } + + void SetBody(const opentelemetry::common::AttributeValue &message) noexcept override + { + body_ = message; + } + + const opentelemetry::common::AttributeValue &GetBody() const noexcept { return body_; } + + void SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept override + { + attributes_map_[static_cast<std::string>(key)] = value; + } + + const std::unordered_map<std::string, opentelemetry::common::AttributeValue> &GetAttributes() + const noexcept + { + return attributes_map_; + } + + void SetTraceId(const opentelemetry::trace::TraceId &trace_id) noexcept override + { + trace_id_ = trace_id; + } + + const opentelemetry::trace::TraceId &GetTraceId() const noexcept { return trace_id_; } + + void SetSpanId(const opentelemetry::trace::SpanId &span_id) noexcept override + { + span_id_ = span_id; + } + + const opentelemetry::trace::SpanId &GetSpanId() const noexcept { return span_id_; } + + void SetTraceFlags(const opentelemetry::trace::TraceFlags &trace_flags) noexcept override + { + trace_flags_ = trace_flags; + } + + const opentelemetry::trace::TraceFlags &GetTraceFlags() const noexcept { return trace_flags_; } + +private: + opentelemetry::logs::Severity severity_ = opentelemetry::logs::Severity::kInvalid; + + std::unordered_map<std::string, opentelemetry::common::AttributeValue> attributes_map_; + opentelemetry::common::AttributeValue body_ = opentelemetry::nostd::string_view(); + opentelemetry::common::SystemTimestamp timestamp_; + opentelemetry::common::SystemTimestamp observed_timestamp_ = std::chrono::system_clock::now(); + + opentelemetry::trace::TraceId trace_id_; + opentelemetry::trace::SpanId span_id_; + opentelemetry::trace::TraceFlags trace_flags_; +}; + /** * @brief Logger class that allows to send logs to ETW Provider. */ @@ -100,53 +185,38 @@ class Logger : public opentelemetry::logs::Logger provHandle(initProvHandle()) {} - void Log(opentelemetry::logs::Severity severity, - nostd::string_view body, - const common::KeyValueIterable &attributes, - opentelemetry::trace::TraceId trace_id, - opentelemetry::trace::SpanId span_id, - opentelemetry::trace::TraceFlags trace_flags, - common::SystemTimestamp timestamp) noexcept override + nostd::unique_ptr<opentelemetry::logs::LogRecord> CreateLogRecord() noexcept { + return nostd::unique_ptr<opentelemetry::logs::LogRecord>(new LogRecord()); + } -# ifdef OPENTELEMETRY_RTTI_ENABLED - common::KeyValueIterable &attribs = const_cast<common::KeyValueIterable &>(attributes); - Properties *evt = dynamic_cast<Properties *>(&attribs); - // Properties *res = dynamic_cast<Properties *>(&resr); + using opentelemetry::logs::Logger::EmitLogRecord; - if (evt != nullptr) + void EmitLogRecord( + nostd::unique_ptr<opentelemetry::logs::LogRecord> &&log_record) noexcept override + { + if (!log_record) { - // Pass as a reference to original modifyable collection without creating a copy - return Log(severity, provId, body, *evt, trace_id, span_id, trace_flags, timestamp); + return; } -# endif - Properties evtCopy = attributes; - return Log(severity, provId, body, evtCopy, trace_id, span_id, trace_flags, timestamp); - } + LogRecord *readable_record = static_cast<LogRecord *>(log_record.get()); - void Log(opentelemetry::logs::Severity severity, - nostd::string_view name, - nostd::string_view body, - const common::KeyValueIterable &attributes, - opentelemetry::trace::TraceId trace_id, - opentelemetry::trace::SpanId span_id, - opentelemetry::trace::TraceFlags trace_flags, - common::SystemTimestamp timestamp) noexcept override - { - -# ifdef OPENTELEMETRY_RTTI_ENABLED - common::KeyValueIterable &attribs = const_cast<common::KeyValueIterable &>(attributes); - Properties *evt = dynamic_cast<Properties *>(&attribs); - // Properties *res = dynamic_cast<Properties *>(&resr); - - if (evt != nullptr) + nostd::string_view body; + if (nostd::holds_alternative<const char *>(readable_record->GetBody())) { - // Pass as a reference to original modifyable collection without creating a copy - return Log(severity, name, body, *evt, trace_id, span_id, trace_flags, timestamp); + body = nostd::get<const char *>(readable_record->GetBody()); } -# endif - Properties evtCopy = attributes; - return Log(severity, name, body, evtCopy, trace_id, span_id, trace_flags, timestamp); + else if (nostd::holds_alternative<nostd::string_view>(readable_record->GetBody())) + { + body = nostd::get<nostd::string_view>(readable_record->GetBody()); + } + // TODO: More body types? + + Properties evtCopy{ + opentelemetry::common::MakeKeyValueIterableView(readable_record->GetAttributes())}; + return Log(readable_record->GetSeverity(), provId, body, evtCopy, readable_record->GetTraceId(), + readable_record->GetSpanId(), readable_record->GetTraceFlags(), + readable_record->GetTimestamp()); } virtual void Log(opentelemetry::logs::Severity severity, diff --git a/exporters/ostream/include/opentelemetry/exporters/ostream/common_utils.h b/exporters/ostream/include/opentelemetry/exporters/ostream/common_utils.h index 1e51815b23..11e098c5c0 100644 --- a/exporters/ostream/include/opentelemetry/exporters/ostream/common_utils.h +++ b/exporters/ostream/include/opentelemetry/exporters/ostream/common_utils.h @@ -41,6 +41,22 @@ void print_value(const std::vector<T> &vec, std::ostream &sout) sout << ']'; } +template <typename T> +void print_value(const nostd::span<T> &vec, std::ostream &sout) +{ + sout << '['; + size_t i = 1; + size_t sz = vec.size(); + for (auto v : vec) + { + sout << v; + if (i != sz) + sout << ','; + i++; + }; + sout << ']'; +} + // Prior to C++14, generic lambda is not available so fallback to functor. #if __cplusplus < 201402L @@ -59,6 +75,23 @@ class OwnedAttributeValueVisitor std::ostream &sout_; }; +class AttributeValueVisitor +{ +public: + AttributeValueVisitor(std::ostream &sout) : sout_(sout) {} + + template <typename T> + void operator()(T &&arg) + { + print_value(arg, sout_); + } + + void operator()(const nostd::string_view &&arg) { sout_.write(arg.data(), arg.size()); } + +private: + std::ostream &sout_; +}; + #endif inline void print_value(const opentelemetry::sdk::common::OwnedAttributeValue &value, @@ -76,6 +109,20 @@ inline void print_value(const opentelemetry::sdk::common::OwnedAttributeValue &v #endif } +inline void print_value(const opentelemetry::common::AttributeValue &value, std::ostream &sout) +{ +#if __cplusplus < 201402L + opentelemetry::nostd::visit(AttributeValueVisitor(sout), value); +#else + opentelemetry::nostd::visit( + [&sout](auto &&arg) { + /* explicit this is needed by some gcc versions (observed with v5.4.0)*/ + print_value(arg, sout); + }, + value); +#endif +} + } // namespace ostream_common } // namespace exporter OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/ostream/include/opentelemetry/exporters/ostream/log_record_exporter.h b/exporters/ostream/include/opentelemetry/exporters/ostream/log_record_exporter.h index 7aa60a8409..f5e400946f 100644 --- a/exporters/ostream/include/opentelemetry/exporters/ostream/log_record_exporter.h +++ b/exporters/ostream/include/opentelemetry/exporters/ostream/log_record_exporter.h @@ -7,7 +7,7 @@ # include "opentelemetry/common/spin_lock_mutex.h" # include "opentelemetry/nostd/type_traits.h" # include "opentelemetry/sdk/logs/exporter.h" -# include "opentelemetry/sdk/logs/log_record.h" + # include "opentelemetry/version.h" # include <iostream> @@ -55,6 +55,9 @@ class OStreamLogRecordExporter final : public opentelemetry::sdk::logs::LogRecor void printAttributes( const std::unordered_map<std::string, opentelemetry::sdk::common::OwnedAttributeValue> &map, const std::string prefix = "\n\t"); + void printAttributes( + const std::unordered_map<std::string, opentelemetry::common::AttributeValue> &map, + const std::string prefix = "\n\t"); }; } // namespace logs } // namespace exporter diff --git a/exporters/ostream/src/log_record_exporter.cc b/exporters/ostream/src/log_record_exporter.cc index 66cff9c41b..ca751b810e 100644 --- a/exporters/ostream/src/log_record_exporter.cc +++ b/exporters/ostream/src/log_record_exporter.cc @@ -3,11 +3,12 @@ #ifdef ENABLE_LOGS_PREVIEW # include "opentelemetry/exporters/ostream/log_record_exporter.h" -# include <mutex> # include "opentelemetry/exporters/ostream/common_utils.h" +# include "opentelemetry/sdk/logs/read_write_log_record.h" # include "opentelemetry/sdk_config.h" # include <iostream> +# include <mutex> # include <type_traits> namespace nostd = opentelemetry::nostd; @@ -27,7 +28,7 @@ OStreamLogRecordExporter::OStreamLogRecordExporter(std::ostream &sout) noexcept std::unique_ptr<sdklogs::Recordable> OStreamLogRecordExporter::MakeRecordable() noexcept { - return std::unique_ptr<sdklogs::Recordable>(new sdklogs::LogRecord()); + return std::unique_ptr<sdklogs::Recordable>(new sdklogs::ReadWriteLogRecord()); } sdk::common::ExportResult OStreamLogRecordExporter::Export( @@ -42,9 +43,8 @@ sdk::common::ExportResult OStreamLogRecordExporter::Export( for (auto &record : records) { - // Convert recordable to a LogRecord so that the getters of the LogRecord can be used - auto log_record = - std::unique_ptr<sdklogs::LogRecord>(static_cast<sdklogs::LogRecord *>(record.release())); + auto log_record = std::unique_ptr<sdklogs::ReadWriteLogRecord>( + static_cast<sdklogs::ReadWriteLogRecord *>(record.release())); if (log_record == nullptr) { @@ -68,9 +68,13 @@ sdk::common::ExportResult OStreamLogRecordExporter::Export( // Print out each field of the log record, noting that severity is separated // into severity_num and severity_text sout_ << "{\n" - << " timestamp : " << log_record->GetTimestamp().time_since_epoch().count() << "\n" - << " severity_num : " << static_cast<std::uint32_t>(log_record->GetSeverity()) << "\n" - << " severity_text : "; + << " timestamp : " << log_record->GetTimestamp().time_since_epoch().count() + << "\n" + << " observed_timestamp : " + << log_record->GetObservedTimestamp().time_since_epoch().count() << "\n" + << " severity_num : " << static_cast<std::uint32_t>(log_record->GetSeverity()) + << "\n" + << " severity_text : "; std::uint32_t severity_index = static_cast<std::uint32_t>(log_record->GetSeverity()); if (severity_index >= std::extent<decltype(opentelemetry::logs::SeverityNumToText)>::value) @@ -82,20 +86,22 @@ sdk::common::ExportResult OStreamLogRecordExporter::Export( sout_ << opentelemetry::logs::SeverityNumToText[severity_index] << "\n"; } - sout_ << " body : " << log_record->GetBody() << "\n" - << " resource : "; + sout_ << " body : "; + opentelemetry::exporter::ostream_common::print_value(log_record->GetBody(), sout_); + sout_ << "\n"; + sout_ << " resource : "; printAttributes(log_record->GetResource().GetAttributes()); sout_ << "\n" - << " attributes : "; + << " attributes : "; printAttributes(log_record->GetAttributes()); sout_ << "\n" - << " trace_id : " << std::string(trace_id, trace_id_len) << "\n" - << " span_id : " << std::string(span_id, span_id__len) << "\n" - << " trace_flags : " << std::string(trace_flags, trace_flags_len) << "\n" + << " trace_id : " << std::string(trace_id, trace_id_len) << "\n" + << " span_id : " << std::string(span_id, span_id__len) << "\n" + << " trace_flags : " << std::string(trace_flags, trace_flags_len) << "\n" << "}\n"; } @@ -126,6 +132,17 @@ void OStreamLogRecordExporter::printAttributes( } } +void OStreamLogRecordExporter::printAttributes( + const std::unordered_map<std::string, opentelemetry::common::AttributeValue> &map, + const std::string prefix) +{ + for (const auto &kv : map) + { + sout_ << prefix << kv.first << ": "; + opentelemetry::exporter::ostream_common::print_value(kv.second, sout_); + } +} + } // namespace logs } // namespace exporter OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/ostream/test/ostream_log_test.cc b/exporters/ostream/test/ostream_log_test.cc index 12551caf83..e247f06038 100644 --- a/exporters/ostream/test/ostream_log_test.cc +++ b/exporters/ostream/test/ostream_log_test.cc @@ -8,6 +8,7 @@ # include "opentelemetry/logs/provider.h" # include "opentelemetry/nostd/span.h" # include "opentelemetry/sdk/logs/logger_provider.h" +# include "opentelemetry/sdk/logs/read_write_log_record.h" # include "opentelemetry/sdk/logs/simple_log_record_processor.h" # include <gtest/gtest.h> @@ -42,7 +43,7 @@ TEST(OStreamLogRecordExporter, Shutdown) // After processor/exporter is shutdown, no logs should be sent to stream auto record = exporter->MakeRecordable(); - record->SetBody("Log record not empty"); + static_cast<sdklogs::ReadWriteLogRecord *>(record.get())->SetBody("Log record not empty"); exporter->Export(nostd::span<std::unique_ptr<sdklogs::Recordable>>(&record, 1)); // Restore original stringstream buffer @@ -77,18 +78,18 @@ TEST(OstreamLogExporter, DefaultLogRecordToCout) std::vector<std::string> expected_output{ "{\n" - " timestamp : 0\n" - " severity_num : 0\n" - " severity_text : INVALID\n" - " body : \n", - " resource : \n", + " timestamp : 0\n", + " severity_num : 0\n" + " severity_text : INVALID\n" + " body : \n", + " resource : \n", "telemetry.sdk.version: " OPENTELEMETRY_VERSION "\n", "telemetry.sdk.name: opentelemetry\n", "telemetry.sdk.language: cpp\n", - " attributes : \n" - " trace_id : 00000000000000000000000000000000\n" - " span_id : 0000000000000000\n" - " trace_flags : 00\n" + " attributes : \n" + " trace_id : 00000000000000000000000000000000\n" + " span_id : 0000000000000000\n" + " trace_flags : 00\n" "}\n"}; for (auto &expected : expected_output) @@ -114,10 +115,12 @@ TEST(OStreamLogRecordExporter, SimpleLogToCout) // Create a log record and manually timestamp, severity, name, message common::SystemTimestamp now(std::chrono::system_clock::now()); - auto record = std::unique_ptr<sdklogs::Recordable>(new sdklogs::LogRecord()); - record->SetTimestamp(now); - record->SetSeverity(logs_api::Severity::kTrace); // kTrace has enum value of 1 - record->SetBody("Message"); + auto record = std::unique_ptr<sdklogs::Recordable>(new sdklogs::ReadWriteLogRecord()); + static_cast<sdklogs::ReadWriteLogRecord *>(record.get())->SetTimestamp(now); + static_cast<sdklogs::ReadWriteLogRecord *>(record.get())->SetObservedTimestamp(now); + static_cast<sdklogs::ReadWriteLogRecord *>(record.get()) + ->SetSeverity(logs_api::Severity::kTrace); // kTrace has enum value of 1 + static_cast<sdklogs::ReadWriteLogRecord *>(record.get())->SetBody("Message"); // Log a record to cout exporter->Export(nostd::span<std::unique_ptr<sdklogs::Recordable>>(&record, 1)); @@ -127,20 +130,23 @@ TEST(OStreamLogRecordExporter, SimpleLogToCout) std::vector<std::string> expected_output{ "{\n" - " timestamp : " + + " timestamp : " + std::to_string(now.time_since_epoch().count()) + "\n" - " severity_num : 1\n" - " severity_text : TRACE\n" - " body : Message\n", - " resource : \n", + " observed_timestamp : " + + std::to_string(now.time_since_epoch().count()) + + "\n" + " severity_num : 1\n" + " severity_text : TRACE\n" + " body : Message\n", + " resource : \n", "telemetry.sdk.version: " OPENTELEMETRY_VERSION "\n", "telemetry.sdk.name: opentelemetry\n", "telemetry.sdk.language: cpp\n", - " attributes : \n" - " trace_id : 00000000000000000000000000000000\n" - " span_id : 0000000000000000\n" - " trace_flags : 00\n" + " attributes : \n" + " trace_id : 00000000000000000000000000000000\n" + " span_id : 0000000000000000\n" + " trace_flags : 00\n" "}\n"}; for (auto &expected : expected_output) @@ -169,10 +175,10 @@ TEST(OStreamLogRecordExporter, LogWithStringAttributesToCerr) // Set resources for this log record only of type <string, string> auto resource = opentelemetry::sdk::resource::Resource::Create({{"key1", "val1"}}); - record->SetResource(resource); + static_cast<sdklogs::ReadWriteLogRecord *>(record.get())->SetResource(resource); // Set attributes to this log record of type <string, AttributeValue> - record->SetAttribute("a", true); + static_cast<sdklogs::ReadWriteLogRecord *>(record.get())->SetAttribute("a", true); // Log record to cerr exporter->Export(nostd::span<std::unique_ptr<sdklogs::Recordable>>(&record, 1)); @@ -182,21 +188,21 @@ TEST(OStreamLogRecordExporter, LogWithStringAttributesToCerr) std::vector<std::string> expected_output{ "{\n" - " timestamp : 0\n" - " severity_num : 0\n" - " severity_text : INVALID\n" - " body : \n", - " resource : \n", + " timestamp : 0\n", + " severity_num : 0\n" + " severity_text : INVALID\n" + " body : \n", + " resource : \n", "telemetry.sdk.version: " OPENTELEMETRY_VERSION "\n", "telemetry.sdk.name: opentelemetry\n", "telemetry.sdk.language: cpp\n", "service.name: unknown_service\n", "key1: val1\n", - " attributes : \n", + " attributes : \n", "\ta: 1\n", - " trace_id : 00000000000000000000000000000000\n" - " span_id : 0000000000000000\n" - " trace_flags : 00\n" + " trace_id : 00000000000000000000000000000000\n" + " span_id : 0000000000000000\n" + " trace_flags : 00\n" "}\n"}; for (auto &expected : expected_output) @@ -229,12 +235,13 @@ TEST(OStreamLogRecordExporter, LogWithVariantTypesToClog) nostd::span<int> data1{array1.data(), array1.size()}; auto resource = opentelemetry::sdk::resource::Resource::Create({{"res1", data1}}); - record->SetResource(resource); + static_cast<sdklogs::ReadWriteLogRecord *>(record.get())->SetResource(resource); // Set resources for this log record of bool types as the value // e.g. key/value is a par of type <string, array of bools> std::array<bool, 3> array = {false, true, false}; - record->SetAttribute("attr1", nostd::span<bool>{array.data(), array.size()}); + static_cast<sdklogs::ReadWriteLogRecord *>(record.get()) + ->SetAttribute("attr1", nostd::span<bool>{array.data(), array.size()}); // Log a record to clog exporter->Export(nostd::span<std::unique_ptr<sdklogs::Recordable>>(&record, 1)); @@ -244,21 +251,21 @@ TEST(OStreamLogRecordExporter, LogWithVariantTypesToClog) std::vector<std::string> expected_output{ "{\n" - " timestamp : 0\n" - " severity_num : 0\n" - " severity_text : INVALID\n" - " body : \n", - " resource : \n", + " timestamp : 0\n", + " severity_num : 0\n" + " severity_text : INVALID\n" + " body : \n", + " resource : \n", "service.name: unknown_service\n", "telemetry.sdk.version: " OPENTELEMETRY_VERSION "\n", "telemetry.sdk.name: opentelemetry\n", "telemetry.sdk.language: cpp\n", "res1: [1,2,3]\n", - "attributes : \n", + "attributes : \n", "\tattr1: [0,1,0]\n" - " trace_id : 00000000000000000000000000000000\n" - " span_id : 0000000000000000\n" - " trace_flags : 00\n" + " trace_id : 00000000000000000000000000000000\n" + " span_id : 0000000000000000\n" + " trace_flags : 00\n" "}\n"}; for (auto &expected : expected_output) @@ -303,21 +310,20 @@ TEST(OStreamLogRecordExporter, IntegrationTest) // Compare actual vs expected outputs std::vector<std::string> expected_output{ "{\n" - " timestamp : " + - std::to_string(now.time_since_epoch().count()) + - "\n" - " severity_num : 5\n" - " severity_text : DEBUG\n" - " body : Hello\n", - " resource : \n", + " timestamp : " + + std::to_string(now.time_since_epoch().count()) + "\n", + " severity_num : 5\n" + " severity_text : DEBUG\n" + " body : Hello\n", + " resource : \n", "telemetry.sdk.version: " OPENTELEMETRY_VERSION "\n", "service.name: unknown_service\n", "telemetry.sdk.name: opentelemetry\n", "telemetry.sdk.language: cpp\n", - " attributes : \n" - " trace_id : 00000000000000000000000000000000\n" - " span_id : 0000000000000000\n" - " trace_flags : 00\n" + " attributes : \n" + " trace_id : 00000000000000000000000000000000\n" + " span_id : 0000000000000000\n" + " trace_flags : 00\n" "}\n"}; for (auto &expected : expected_output) diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_log_recordable.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_log_recordable.h index b10898ac3c..cef1b3ef8f 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_log_recordable.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_log_recordable.h @@ -16,6 +16,7 @@ # include "opentelemetry/common/macros.h" # include "opentelemetry/sdk/common/attribute_utils.h" +# include "opentelemetry/sdk/logs/read_write_log_record.h" # include "opentelemetry/sdk/logs/recordable.h" OPENTELEMETRY_BEGIN_NAMESPACE @@ -32,11 +33,15 @@ class OtlpLogRecordable final : public opentelemetry::sdk::logs::Recordable public: ~OtlpLogRecordable() override = default; - proto::logs::v1::LogRecord &log_record() noexcept { return log_record_; } - const proto::logs::v1::LogRecord &log_record() const noexcept { return log_record_; } + proto::logs::v1::LogRecord &log_record() noexcept { return proto_record_; } + const proto::logs::v1::LogRecord &log_record() const noexcept { return proto_record_; } - /** Dynamically converts the resource of this log into a proto. */ - proto::resource::v1::Resource ProtoResource() const noexcept; + /** Returns the associated resource */ + const opentelemetry::sdk::resource::Resource &GetResource() const noexcept; + + /** Returns the associated instruementation scope */ + const opentelemetry::sdk::instrumentationscope::InstrumentationScope &GetInstrumentationScope() + const noexcept; /** * Set the timestamp for this log. @@ -44,6 +49,12 @@ class OtlpLogRecordable final : public opentelemetry::sdk::logs::Recordable */ void SetTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept override; + /** + * Set the observed timestamp for this log. + * @param timestamp the timestamp to set + */ + void SetObservedTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept override; + /** * Set the severity for this log. * @param severity the severity of the event @@ -54,42 +65,39 @@ class OtlpLogRecordable final : public opentelemetry::sdk::logs::Recordable * Set body field for this log. * @param message the body to set */ - void SetBody(nostd::string_view message) noexcept override; - - /** - * Set Resource of this log - * @param Resource the resource to set - */ - void SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept override; - - /** Returns the associated resource */ - const opentelemetry::sdk::resource::Resource &GetResource() const noexcept; - - /** - * Set an attribute of a log. - * @param key the name of the attribute - * @param value the attribute value - */ - void SetAttribute(nostd::string_view key, - const opentelemetry::common::AttributeValue &value) noexcept override; + void SetBody(const opentelemetry::common::AttributeValue &message) noexcept override; /** * Set the trace id for this log. * @param trace_id the trace id to set */ - void SetTraceId(opentelemetry::trace::TraceId trace_id) noexcept override; + void SetTraceId(const opentelemetry::trace::TraceId &trace_id) noexcept override; /** * Set the span id for this log. * @param span_id the span id to set */ - void SetSpanId(opentelemetry::trace::SpanId span_id) noexcept override; + void SetSpanId(const opentelemetry::trace::SpanId &span_id) noexcept override; /** * Inject trace_flags for this log. * @param trace_flags the trace flags to set */ - void SetTraceFlags(opentelemetry::trace::TraceFlags trace_flags) noexcept override; + void SetTraceFlags(const opentelemetry::trace::TraceFlags &trace_flags) noexcept override; + + /** + * Set an attribute of a log. + * @param key the name of the attribute + * @param value the attribute value + */ + void SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept override; + + /** + * Set Resource of this log + * @param Resource the resource to set + */ + void SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept override; /** * Set instrumentation_scope for this log. @@ -98,22 +106,9 @@ class OtlpLogRecordable final : public opentelemetry::sdk::logs::Recordable void SetInstrumentationScope(const opentelemetry::sdk::instrumentationscope::InstrumentationScope &instrumentation_scope) noexcept override; - OPENTELEMETRY_DEPRECATED_MESSAGE("Please use GetInstrumentationScope instead") - const opentelemetry::sdk::instrumentationscope::InstrumentationScope &GetInstrumentationLibrary() - const noexcept - { - return GetInstrumentationScope(); - } - - /** Returns the associated instruementation scope */ - const opentelemetry::sdk::instrumentationscope::InstrumentationScope &GetInstrumentationScope() - const noexcept; - private: - proto::logs::v1::LogRecord log_record_; + proto::logs::v1::LogRecord proto_record_; const opentelemetry::sdk::resource::Resource *resource_ = nullptr; - // TODO shared resource - // const opentelemetry::sdk::resource::Resource *resource_ = nullptr; const opentelemetry::sdk::instrumentationscope::InstrumentationScope *instrumentation_scope_ = nullptr; }; diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_populate_attribute_utils.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_populate_attribute_utils.h index c64ca90b43..dc43827641 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_populate_attribute_utils.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_populate_attribute_utils.h @@ -3,8 +3,11 @@ #pragma once +// clang-format off #include "opentelemetry/exporters/otlp/protobuf_include_prefix.h" #include "opentelemetry/proto/resource/v1/resource.pb.h" +#include "opentelemetry/exporters/otlp/protobuf_include_suffix.h" +// clang-format on #include "opentelemetry/common/attribute_value.h" #include "opentelemetry/nostd/string_view.h" @@ -27,6 +30,13 @@ class OtlpPopulateAttributeUtils static void PopulateAttribute(opentelemetry::proto::resource::v1::Resource *proto, const opentelemetry::sdk::resource::Resource &resource) noexcept; + static void PopulateAnyValue(opentelemetry::proto::common::v1::AnyValue *proto_value, + const opentelemetry::common::AttributeValue &value) noexcept; + + static void PopulateAnyValue( + opentelemetry::proto::common::v1::AnyValue *proto_value, + const opentelemetry::sdk::common::OwnedAttributeValue &value) noexcept; + static void PopulateAttribute(opentelemetry::proto::common::v1::KeyValue *attribute, nostd::string_view key, const opentelemetry::common::AttributeValue &value) noexcept; diff --git a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable_utils.h b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable_utils.h index 57dbd3b8b0..1ad9514aa9 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable_utils.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_recordable_utils.h @@ -3,6 +3,10 @@ #pragma once +#include <memory> + +#include "opentelemetry/nostd/unique_ptr.h" + #include "opentelemetry/exporters/otlp/protobuf_include_prefix.h" #include "opentelemetry/proto/collector/logs/v1/logs_service.pb.h" @@ -16,8 +20,6 @@ # include "opentelemetry/sdk/logs/recordable.h" #endif -#include <memory> - OPENTELEMETRY_BEGIN_NAMESPACE namespace exporter { diff --git a/exporters/otlp/src/otlp_grpc_log_record_exporter.cc b/exporters/otlp/src/otlp_grpc_log_record_exporter.cc index 75e6b36597..e8a3b8a46a 100644 --- a/exporters/otlp/src/otlp_grpc_log_record_exporter.cc +++ b/exporters/otlp/src/otlp_grpc_log_record_exporter.cc @@ -51,8 +51,7 @@ OtlpGrpcLogRecordExporter::OtlpGrpcLogRecordExporter( std::unique_ptr<opentelemetry::sdk::logs::Recordable> OtlpGrpcLogRecordExporter::MakeRecordable() noexcept { - return std::unique_ptr<opentelemetry::sdk::logs::Recordable>( - new exporter::otlp::OtlpLogRecordable()); + return std::unique_ptr<opentelemetry::sdk::logs::Recordable>(new OtlpLogRecordable()); } opentelemetry::sdk::common::ExportResult OtlpGrpcLogRecordExporter::Export( diff --git a/exporters/otlp/src/otlp_http_log_record_exporter.cc b/exporters/otlp/src/otlp_http_log_record_exporter.cc index 04bd05d063..81bc37a340 100644 --- a/exporters/otlp/src/otlp_http_log_record_exporter.cc +++ b/exporters/otlp/src/otlp_http_log_record_exporter.cc @@ -67,8 +67,7 @@ OtlpHttpLogRecordExporter::OtlpHttpLogRecordExporter(std::unique_ptr<OtlpHttpCli std::unique_ptr<opentelemetry::sdk::logs::Recordable> OtlpHttpLogRecordExporter::MakeRecordable() noexcept { - return std::unique_ptr<opentelemetry::sdk::logs::Recordable>( - new exporter::otlp::OtlpLogRecordable()); + return std::unique_ptr<opentelemetry::sdk::logs::Recordable>(new OtlpLogRecordable()); } opentelemetry::sdk::common::ExportResult OtlpHttpLogRecordExporter::Export( diff --git a/exporters/otlp/src/otlp_log_recordable.cc b/exporters/otlp/src/otlp_log_recordable.cc index 568bfa1a0a..cc4d712795 100644 --- a/exporters/otlp/src/otlp_log_recordable.cc +++ b/exporters/otlp/src/otlp_log_recordable.cc @@ -6,9 +6,9 @@ # include "opentelemetry/common/macros.h" # include "opentelemetry/exporters/otlp/otlp_log_recordable.h" - # include "opentelemetry/exporters/otlp/otlp_populate_attribute_utils.h" # include "opentelemetry/exporters/otlp/otlp_recordable_utils.h" +# include "opentelemetry/sdk/logs/readable_log_record.h" namespace nostd = opentelemetry::nostd; @@ -18,24 +18,30 @@ namespace exporter namespace otlp { -proto::resource::v1::Resource OtlpLogRecordable::ProtoResource() const noexcept +const opentelemetry::sdk::resource::Resource &OtlpLogRecordable::GetResource() const noexcept { - proto::resource::v1::Resource proto; - if (nullptr == resource_) - { - OtlpPopulateAttributeUtils::PopulateAttribute(&proto, sdk::resource::Resource::GetDefault()); - } - else - { - OtlpPopulateAttributeUtils::PopulateAttribute(&proto, *resource_); - } + OPENTELEMETRY_LIKELY_IF(nullptr != resource_) { return *resource_; } + + return opentelemetry::sdk::logs::ReadableLogRecord::GetDefaultResource(); +} + +const opentelemetry::sdk::instrumentationscope::InstrumentationScope & +OtlpLogRecordable::GetInstrumentationScope() const noexcept +{ + OPENTELEMETRY_LIKELY_IF(nullptr != instrumentation_scope_) { return *instrumentation_scope_; } - return proto; + return opentelemetry::sdk::logs::ReadableLogRecord::GetDefaultInstrumentationScope(); } void OtlpLogRecordable::SetTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept { - log_record_.set_time_unix_nano(timestamp.time_since_epoch().count()); + proto_record_.set_time_unix_nano(timestamp.time_since_epoch().count()); +} + +void OtlpLogRecordable::SetObservedTimestamp( + opentelemetry::common::SystemTimestamp timestamp) noexcept +{ + proto_record_.set_observed_time_unix_nano(timestamp.time_since_epoch().count()); } void OtlpLogRecordable::SetSeverity(opentelemetry::logs::Severity severity) noexcept @@ -43,171 +49,178 @@ void OtlpLogRecordable::SetSeverity(opentelemetry::logs::Severity severity) noex switch (severity) { case opentelemetry::logs::Severity::kTrace: { - log_record_.set_severity_text("TRACE"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_TRACE); + proto_record_.set_severity_text("TRACE"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_TRACE); break; } case opentelemetry::logs::Severity::kTrace2: { - log_record_.set_severity_text("TRACE2"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_TRACE2); + proto_record_.set_severity_text("TRACE2"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_TRACE2); break; } case opentelemetry::logs::Severity::kTrace3: { - log_record_.set_severity_text("TRACE3"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_TRACE3); + proto_record_.set_severity_text("TRACE3"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_TRACE3); break; } case opentelemetry::logs::Severity::kTrace4: { - log_record_.set_severity_text("TRACE4"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_TRACE4); + proto_record_.set_severity_text("TRACE4"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_TRACE4); break; } case opentelemetry::logs::Severity::kDebug: { - log_record_.set_severity_text("DEBUG"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_DEBUG); + proto_record_.set_severity_text("DEBUG"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_DEBUG); break; } case opentelemetry::logs::Severity::kDebug2: { - log_record_.set_severity_text("DEBUG2"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_DEBUG2); + proto_record_.set_severity_text("DEBUG2"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_DEBUG2); break; } case opentelemetry::logs::Severity::kDebug3: { - log_record_.set_severity_text("DEBUG3"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_DEBUG3); + proto_record_.set_severity_text("DEBUG3"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_DEBUG3); break; } case opentelemetry::logs::Severity::kDebug4: { - log_record_.set_severity_text("DEBUG4"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_DEBUG4); + proto_record_.set_severity_text("DEBUG4"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_DEBUG4); break; } case opentelemetry::logs::Severity::kInfo: { - log_record_.set_severity_text("INFO"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_INFO); + proto_record_.set_severity_text("INFO"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_INFO); break; } case opentelemetry::logs::Severity::kInfo2: { - log_record_.set_severity_text("INFO2"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_INFO2); + proto_record_.set_severity_text("INFO2"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_INFO2); break; } case opentelemetry::logs::Severity::kInfo3: { - log_record_.set_severity_text("INFO3"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_INFO3); + proto_record_.set_severity_text("INFO3"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_INFO3); break; } case opentelemetry::logs::Severity::kInfo4: { - log_record_.set_severity_text("INFO4"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_INFO4); + proto_record_.set_severity_text("INFO4"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_INFO4); break; } case opentelemetry::logs::Severity::kWarn: { - log_record_.set_severity_text("WARN"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_WARN); + proto_record_.set_severity_text("WARN"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_WARN); break; } case opentelemetry::logs::Severity::kWarn2: { - log_record_.set_severity_text("WARN2"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_WARN2); + proto_record_.set_severity_text("WARN2"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_WARN2); break; } case opentelemetry::logs::Severity::kWarn3: { - log_record_.set_severity_text("WARN3"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_WARN3); + proto_record_.set_severity_text("WARN3"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_WARN3); break; } case opentelemetry::logs::Severity::kWarn4: { - log_record_.set_severity_text("WARN4"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_WARN4); + proto_record_.set_severity_text("WARN4"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_WARN4); break; } case opentelemetry::logs::Severity::kError: { - log_record_.set_severity_text("ERROR"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_ERROR); + proto_record_.set_severity_text("ERROR"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_ERROR); break; } case opentelemetry::logs::Severity::kError2: { - log_record_.set_severity_text("ERROR2"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_ERROR2); + proto_record_.set_severity_text("ERROR2"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_ERROR2); break; } case opentelemetry::logs::Severity::kError3: { - log_record_.set_severity_text("ERROR3"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_ERROR3); + proto_record_.set_severity_text("ERROR3"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_ERROR3); break; } case opentelemetry::logs::Severity::kError4: { - log_record_.set_severity_text("ERROR4"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_ERROR4); + proto_record_.set_severity_text("ERROR4"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_ERROR4); break; } case opentelemetry::logs::Severity::kFatal: { - log_record_.set_severity_text("FATAL"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_FATAL); + proto_record_.set_severity_text("FATAL"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_FATAL); break; } case opentelemetry::logs::Severity::kFatal2: { - log_record_.set_severity_text("FATAL2"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_FATAL2); + proto_record_.set_severity_text("FATAL2"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_FATAL2); break; } case opentelemetry::logs::Severity::kFatal3: { - log_record_.set_severity_text("FATAL3"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_FATAL3); + proto_record_.set_severity_text("FATAL3"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_FATAL3); break; } case opentelemetry::logs::Severity::kFatal4: { - log_record_.set_severity_text("FATAL4"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_FATAL4); + proto_record_.set_severity_text("FATAL4"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_FATAL4); break; } default: { - log_record_.set_severity_text("INVALID"); - log_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_UNSPECIFIED); + proto_record_.set_severity_text("INVALID"); + proto_record_.set_severity_number(proto::logs::v1::SEVERITY_NUMBER_UNSPECIFIED); break; } } } -void OtlpLogRecordable::SetBody(nostd::string_view message) noexcept +void OtlpLogRecordable::SetBody(const opentelemetry::common::AttributeValue &message) noexcept { - log_record_.mutable_body()->set_string_value(message.data(), message.size()); + OtlpPopulateAttributeUtils::PopulateAnyValue(proto_record_.mutable_body(), message); } -void OtlpLogRecordable::SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept -{ - resource_ = &resource; -} - -const opentelemetry::sdk::resource::Resource &OtlpLogRecordable::GetResource() const noexcept +void OtlpLogRecordable::SetTraceId(const opentelemetry::trace::TraceId &trace_id) noexcept { - OPENTELEMETRY_LIKELY_IF(nullptr != resource_) { return *resource_; } - - return opentelemetry::sdk::resource::Resource::GetDefault(); + if (trace_id.IsValid()) + { + proto_record_.set_trace_id(reinterpret_cast<const char *>(trace_id.Id().data()), + trace_id.Id().size()); + } + else + { + proto_record_.clear_trace_id(); + } } -void OtlpLogRecordable::SetAttribute(nostd::string_view key, - const opentelemetry::common::AttributeValue &value) noexcept +void OtlpLogRecordable::SetSpanId(const opentelemetry::trace::SpanId &span_id) noexcept { - OtlpPopulateAttributeUtils::PopulateAttribute(log_record_.add_attributes(), key, value); + if (span_id.IsValid()) + { + proto_record_.set_span_id(reinterpret_cast<const char *>(span_id.Id().data()), + span_id.Id().size()); + } + else + { + proto_record_.clear_span_id(); + } } -void OtlpLogRecordable::SetTraceId(opentelemetry::trace::TraceId trace_id) noexcept +void OtlpLogRecordable::SetTraceFlags(const opentelemetry::trace::TraceFlags &trace_flags) noexcept { - log_record_.set_trace_id(reinterpret_cast<const char *>(trace_id.Id().data()), - trace::TraceId::kSize); + proto_record_.set_flags(trace_flags.flags()); } -void OtlpLogRecordable::SetSpanId(opentelemetry::trace::SpanId span_id) noexcept +void OtlpLogRecordable::SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept { - log_record_.set_span_id(reinterpret_cast<const char *>(span_id.Id().data()), - trace::SpanId::kSize); + OtlpPopulateAttributeUtils::PopulateAttribute(proto_record_.add_attributes(), key, value); } -void OtlpLogRecordable::SetTraceFlags(opentelemetry::trace::TraceFlags trace_flags) noexcept +void OtlpLogRecordable::SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept { - log_record_.set_flags(trace_flags.flags()); + resource_ = &resource; } void OtlpLogRecordable::SetInstrumentationScope( @@ -217,18 +230,6 @@ void OtlpLogRecordable::SetInstrumentationScope( instrumentation_scope_ = &instrumentation_scope; } -const opentelemetry::sdk::instrumentationscope::InstrumentationScope & -OtlpLogRecordable::GetInstrumentationScope() const noexcept -{ - OPENTELEMETRY_LIKELY_IF(nullptr != instrumentation_scope_) { return *instrumentation_scope_; } - - static opentelemetry::nostd::unique_ptr< - opentelemetry::sdk::instrumentationscope::InstrumentationScope> - default_instrumentation = - opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( - "default", "1.0.0", "https://opentelemetry.io/schemas/1.11.0"); - return *default_instrumentation; -} } // namespace otlp } // namespace exporter OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/otlp/src/otlp_populate_attribute_utils.cc b/exporters/otlp/src/otlp_populate_attribute_utils.cc index 6dff7c4d01..d86953506c 100644 --- a/exporters/otlp/src/otlp_populate_attribute_utils.cc +++ b/exporters/otlp/src/otlp_populate_attribute_utils.cc @@ -17,12 +17,11 @@ namespace otlp const int kAttributeValueSize = 16; const int kOwnedAttributeValueSize = 15; -void OtlpPopulateAttributeUtils::PopulateAttribute( - opentelemetry::proto::common::v1::KeyValue *attribute, - nostd::string_view key, +void OtlpPopulateAttributeUtils::PopulateAnyValue( + opentelemetry::proto::common::v1::AnyValue *proto_value, const opentelemetry::common::AttributeValue &value) noexcept { - if (nullptr == attribute) + if (nullptr == proto_value) { return; } @@ -33,107 +32,102 @@ void OtlpPopulateAttributeUtils::PopulateAttribute( nostd::variant_size<opentelemetry::common::AttributeValue>::value == kAttributeValueSize, "AttributeValue contains unknown type"); - attribute->set_key(key.data(), key.size()); - if (nostd::holds_alternative<bool>(value)) { - attribute->mutable_value()->set_bool_value(nostd::get<bool>(value)); + proto_value->set_bool_value(nostd::get<bool>(value)); } else if (nostd::holds_alternative<int>(value)) { - attribute->mutable_value()->set_int_value(nostd::get<int>(value)); + proto_value->set_int_value(nostd::get<int>(value)); } else if (nostd::holds_alternative<int64_t>(value)) { - attribute->mutable_value()->set_int_value(nostd::get<int64_t>(value)); + proto_value->set_int_value(nostd::get<int64_t>(value)); } else if (nostd::holds_alternative<unsigned int>(value)) { - attribute->mutable_value()->set_int_value(nostd::get<unsigned int>(value)); + proto_value->set_int_value(nostd::get<unsigned int>(value)); } else if (nostd::holds_alternative<uint64_t>(value)) { - attribute->mutable_value()->set_int_value(nostd::get<uint64_t>(value)); + proto_value->set_int_value(nostd::get<uint64_t>(value)); } else if (nostd::holds_alternative<double>(value)) { - attribute->mutable_value()->set_double_value(nostd::get<double>(value)); + proto_value->set_double_value(nostd::get<double>(value)); } else if (nostd::holds_alternative<const char *>(value)) { - attribute->mutable_value()->set_string_value(nostd::get<const char *>(value)); + proto_value->set_string_value(nostd::get<const char *>(value)); } else if (nostd::holds_alternative<nostd::string_view>(value)) { - attribute->mutable_value()->set_string_value(nostd::get<nostd::string_view>(value).data(), - nostd::get<nostd::string_view>(value).size()); + proto_value->set_string_value(nostd::get<nostd::string_view>(value).data(), + nostd::get<nostd::string_view>(value).size()); } else if (nostd::holds_alternative<nostd::span<const uint8_t>>(value)) { for (const auto &val : nostd::get<nostd::span<const uint8_t>>(value)) { - attribute->mutable_value()->mutable_array_value()->add_values()->set_int_value(val); + proto_value->mutable_array_value()->add_values()->set_int_value(val); } } else if (nostd::holds_alternative<nostd::span<const bool>>(value)) { for (const auto &val : nostd::get<nostd::span<const bool>>(value)) { - attribute->mutable_value()->mutable_array_value()->add_values()->set_bool_value(val); + proto_value->mutable_array_value()->add_values()->set_bool_value(val); } } else if (nostd::holds_alternative<nostd::span<const int>>(value)) { for (const auto &val : nostd::get<nostd::span<const int>>(value)) { - attribute->mutable_value()->mutable_array_value()->add_values()->set_int_value(val); + proto_value->mutable_array_value()->add_values()->set_int_value(val); } } else if (nostd::holds_alternative<nostd::span<const int64_t>>(value)) { for (const auto &val : nostd::get<nostd::span<const int64_t>>(value)) { - attribute->mutable_value()->mutable_array_value()->add_values()->set_int_value(val); + proto_value->mutable_array_value()->add_values()->set_int_value(val); } } else if (nostd::holds_alternative<nostd::span<const unsigned int>>(value)) { for (const auto &val : nostd::get<nostd::span<const unsigned int>>(value)) { - attribute->mutable_value()->mutable_array_value()->add_values()->set_int_value(val); + proto_value->mutable_array_value()->add_values()->set_int_value(val); } } else if (nostd::holds_alternative<nostd::span<const uint64_t>>(value)) { for (const auto &val : nostd::get<nostd::span<const uint64_t>>(value)) { - attribute->mutable_value()->mutable_array_value()->add_values()->set_int_value(val); + proto_value->mutable_array_value()->add_values()->set_int_value(val); } } else if (nostd::holds_alternative<nostd::span<const double>>(value)) { for (const auto &val : nostd::get<nostd::span<const double>>(value)) { - attribute->mutable_value()->mutable_array_value()->add_values()->set_double_value(val); + proto_value->mutable_array_value()->add_values()->set_double_value(val); } } else if (nostd::holds_alternative<nostd::span<const nostd::string_view>>(value)) { for (const auto &val : nostd::get<nostd::span<const nostd::string_view>>(value)) { - attribute->mutable_value()->mutable_array_value()->add_values()->set_string_value(val.data(), - val.size()); + proto_value->mutable_array_value()->add_values()->set_string_value(val.data(), val.size()); } } } -/** Maps from C++ attribute into OTLP proto attribute. */ -void OtlpPopulateAttributeUtils::PopulateAttribute( - opentelemetry::proto::common::v1::KeyValue *attribute, - nostd::string_view key, +void OtlpPopulateAttributeUtils::PopulateAnyValue( + opentelemetry::proto::common::v1::AnyValue *proto_value, const opentelemetry::sdk::common::OwnedAttributeValue &value) noexcept { - if (nullptr == attribute) + if (nullptr == proto_value) { return; } @@ -144,87 +138,126 @@ void OtlpPopulateAttributeUtils::PopulateAttribute( kOwnedAttributeValueSize, "OwnedAttributeValue contains unknown type"); - attribute->set_key(key.data(), key.size()); - if (nostd::holds_alternative<bool>(value)) { - attribute->mutable_value()->set_bool_value(nostd::get<bool>(value)); + proto_value->set_bool_value(nostd::get<bool>(value)); } else if (nostd::holds_alternative<int32_t>(value)) { - attribute->mutable_value()->set_int_value(nostd::get<int32_t>(value)); + proto_value->set_int_value(nostd::get<int32_t>(value)); } else if (nostd::holds_alternative<int64_t>(value)) { - attribute->mutable_value()->set_int_value(nostd::get<int64_t>(value)); + proto_value->set_int_value(nostd::get<int64_t>(value)); } else if (nostd::holds_alternative<uint32_t>(value)) { - attribute->mutable_value()->set_int_value(nostd::get<uint32_t>(value)); + proto_value->set_int_value(nostd::get<uint32_t>(value)); } else if (nostd::holds_alternative<uint64_t>(value)) { - attribute->mutable_value()->set_int_value(nostd::get<uint64_t>(value)); + proto_value->set_int_value(nostd::get<uint64_t>(value)); } else if (nostd::holds_alternative<double>(value)) { - attribute->mutable_value()->set_double_value(nostd::get<double>(value)); + proto_value->set_double_value(nostd::get<double>(value)); } else if (nostd::holds_alternative<std::string>(value)) { - attribute->mutable_value()->set_string_value(nostd::get<std::string>(value)); + proto_value->set_string_value(nostd::get<std::string>(value)); } else if (nostd::holds_alternative<std::vector<bool>>(value)) { for (const auto val : nostd::get<std::vector<bool>>(value)) { - attribute->mutable_value()->mutable_array_value()->add_values()->set_bool_value(val); + proto_value->mutable_array_value()->add_values()->set_bool_value(val); } } else if (nostd::holds_alternative<std::vector<int32_t>>(value)) { for (const auto &val : nostd::get<std::vector<int32_t>>(value)) { - attribute->mutable_value()->mutable_array_value()->add_values()->set_int_value(val); + proto_value->mutable_array_value()->add_values()->set_int_value(val); } } else if (nostd::holds_alternative<std::vector<uint32_t>>(value)) { for (const auto &val : nostd::get<std::vector<uint32_t>>(value)) { - attribute->mutable_value()->mutable_array_value()->add_values()->set_int_value(val); + proto_value->mutable_array_value()->add_values()->set_int_value(val); } } else if (nostd::holds_alternative<std::vector<int64_t>>(value)) { for (const auto &val : nostd::get<std::vector<int64_t>>(value)) { - attribute->mutable_value()->mutable_array_value()->add_values()->set_int_value(val); + proto_value->mutable_array_value()->add_values()->set_int_value(val); } } else if (nostd::holds_alternative<std::vector<uint64_t>>(value)) { for (const auto &val : nostd::get<std::vector<uint64_t>>(value)) { - attribute->mutable_value()->mutable_array_value()->add_values()->set_int_value(val); + proto_value->mutable_array_value()->add_values()->set_int_value(val); } } else if (nostd::holds_alternative<std::vector<double>>(value)) { for (const auto &val : nostd::get<std::vector<double>>(value)) { - attribute->mutable_value()->mutable_array_value()->add_values()->set_double_value(val); + proto_value->mutable_array_value()->add_values()->set_double_value(val); } } else if (nostd::holds_alternative<std::vector<std::string>>(value)) { for (const auto &val : nostd::get<std::vector<std::string>>(value)) { - attribute->mutable_value()->mutable_array_value()->add_values()->set_string_value(val); + proto_value->mutable_array_value()->add_values()->set_string_value(val); } } } +void OtlpPopulateAttributeUtils::PopulateAttribute( + opentelemetry::proto::common::v1::KeyValue *attribute, + nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept +{ + if (nullptr == attribute) + { + return; + } + + // Assert size of variant to ensure that this method gets updated if the variant + // definition changes + static_assert( + nostd::variant_size<opentelemetry::common::AttributeValue>::value == kAttributeValueSize, + "AttributeValue contains unknown type"); + + attribute->set_key(key.data(), key.size()); + PopulateAnyValue(attribute->mutable_value(), value); +} + +/** Maps from C++ attribute into OTLP proto attribute. */ +void OtlpPopulateAttributeUtils::PopulateAttribute( + opentelemetry::proto::common::v1::KeyValue *attribute, + nostd::string_view key, + const opentelemetry::sdk::common::OwnedAttributeValue &value) noexcept +{ + if (nullptr == attribute) + { + return; + } + + // Assert size of variant to ensure that this method gets updated if the variant + // definition changes + static_assert(nostd::variant_size<opentelemetry::sdk::common::OwnedAttributeValue>::value == + kOwnedAttributeValueSize, + "OwnedAttributeValue contains unknown type"); + + attribute->set_key(key.data(), key.size()); + PopulateAnyValue(attribute->mutable_value(), value); +} + void OtlpPopulateAttributeUtils::PopulateAttribute( opentelemetry::proto::resource::v1::Resource *proto, const opentelemetry::sdk::resource::Resource &resource) noexcept diff --git a/exporters/otlp/src/otlp_recordable_utils.cc b/exporters/otlp/src/otlp_recordable_utils.cc index 3bfe606bab..a7f688d7f3 100644 --- a/exporters/otlp/src/otlp_recordable_utils.cc +++ b/exporters/otlp/src/otlp_recordable_utils.cc @@ -11,6 +11,7 @@ #include "opentelemetry/exporters/otlp/protobuf_include_suffix.h" #include "opentelemetry/exporters/otlp/otlp_log_recordable.h" +#include "opentelemetry/exporters/otlp/otlp_populate_attribute_utils.h" #include "opentelemetry/exporters/otlp/otlp_recordable.h" #include <list> @@ -109,7 +110,8 @@ void OtlpRecordableUtils::PopulateRequest( { if (!output_resource_log->has_resource()) { - *output_resource_log->mutable_resource() = input_log_record->ProtoResource(); + OtlpPopulateAttributeUtils::PopulateAttribute(output_resource_log->mutable_resource(), + *input_resource_log.first); output_resource_log->set_schema_url(input_resource_log.first->GetSchemaURL()); } 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 34aee61a0c..f87b5bf2d7 100644 --- a/exporters/otlp/test/otlp_grpc_log_record_exporter_test.cc +++ b/exporters/otlp/test/otlp_grpc_log_record_exporter_test.cc @@ -16,7 +16,6 @@ # include "opentelemetry/logs/provider.h" # include "opentelemetry/sdk/logs/batch_log_record_processor.h" # include "opentelemetry/sdk/logs/exporter.h" -# include "opentelemetry/sdk/logs/log_record.h" # include "opentelemetry/sdk/logs/logger_provider.h" # include "opentelemetry/sdk/resource/resource.h" 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 6dc8ef8960..08bc4b1fca 100644 --- a/exporters/otlp/test/otlp_http_log_record_exporter_test.cc +++ b/exporters/otlp/test/otlp_http_log_record_exporter_test.cc @@ -21,7 +21,6 @@ # include "opentelemetry/logs/provider.h" # include "opentelemetry/sdk/logs/batch_log_record_processor.h" # include "opentelemetry/sdk/logs/exporter.h" -# include "opentelemetry/sdk/logs/log_record.h" # include "opentelemetry/sdk/logs/logger_provider.h" # include "opentelemetry/sdk/resource/resource.h" # include "opentelemetry/test_common/ext/http/client/nosend/http_client_nosend.h" diff --git a/exporters/otlp/test/otlp_log_recordable_test.cc b/exporters/otlp/test/otlp_log_recordable_test.cc index a20d80b36a..96c5c66b09 100644 --- a/exporters/otlp/test/otlp_log_recordable_test.cc +++ b/exporters/otlp/test/otlp_log_recordable_test.cc @@ -5,7 +5,10 @@ # include <gtest/gtest.h> +# include <chrono> + # include "opentelemetry/exporters/otlp/otlp_log_recordable.h" +# include "opentelemetry/sdk/logs/read_write_log_record.h" # include "opentelemetry/sdk/resource/resource.h" # include "opentelemetry/sdk/resource/semantic_conventions.h" @@ -17,7 +20,7 @@ namespace otlp namespace resource = opentelemetry::sdk::resource; namespace proto = opentelemetry::proto; -TEST(OtlpLogRecordable, SetTimestamp) +TEST(OtlpLogRecordable, Basic) { OtlpLogRecordable rec; std::chrono::system_clock::time_point now = std::chrono::system_clock::now(); @@ -27,53 +30,34 @@ TEST(OtlpLogRecordable, SetTimestamp) std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count(); rec.SetTimestamp(start_timestamp); - EXPECT_EQ(rec.log_record().time_unix_nano(), unix_start); -} - -TEST(OtlpLogRecordable, SetSeverity) -{ - OtlpLogRecordable rec; rec.SetSeverity(opentelemetry::logs::Severity::kError); - - EXPECT_EQ(rec.log_record().severity_number(), proto::logs::v1::SEVERITY_NUMBER_ERROR); - EXPECT_EQ(rec.log_record().severity_text(), "ERROR"); -} - -TEST(OtlpLogRecordable, SetBody) -{ - OtlpLogRecordable rec; nostd::string_view name = "Test Log Message"; rec.SetBody(name); - EXPECT_EQ(rec.log_record().body().string_value(), name); -} -TEST(OtlpLogRecordable, SetTraceId) -{ - OtlpLogRecordable rec; uint8_t trace_id_bin[opentelemetry::trace::TraceId::kSize] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; - std::string expected_bytes; - expected_bytes.assign( + std::string expected_trace_id_bytes; + expected_trace_id_bytes.assign( reinterpret_cast<char *>(trace_id_bin), reinterpret_cast<char *>(trace_id_bin) + opentelemetry::trace::TraceId::kSize); rec.SetTraceId(opentelemetry::trace::TraceId{trace_id_bin}); - EXPECT_EQ(rec.log_record().trace_id(), expected_bytes); -} - -TEST(OtlpLogRecordable, SetSpanId) -{ - OtlpLogRecordable rec; uint8_t span_id_bin[opentelemetry::trace::SpanId::kSize] = {'7', '6', '5', '4', '3', '2', '1', '0'}; - std::string expected_bytes; - expected_bytes.assign( + std::string expected_span_id_bytes; + expected_span_id_bytes.assign( reinterpret_cast<char *>(span_id_bin), reinterpret_cast<char *>(span_id_bin) + opentelemetry::trace::SpanId::kSize); rec.SetSpanId(opentelemetry::trace::SpanId{span_id_bin}); - EXPECT_EQ(rec.log_record().span_id(), expected_bytes); + + EXPECT_EQ(rec.log_record().time_unix_nano(), unix_start); + EXPECT_EQ(rec.log_record().severity_number(), proto::logs::v1::SEVERITY_NUMBER_ERROR); + EXPECT_EQ(rec.log_record().severity_text(), "ERROR"); + EXPECT_EQ(rec.log_record().body().string_value(), name); + EXPECT_EQ(rec.log_record().trace_id(), expected_trace_id_bytes); + EXPECT_EQ(rec.log_record().span_id(), expected_span_id_bytes); } -TEST(OtlpLogRecordable, SetResource) +TEST(OtlpLogRecordable, GetResource) { OtlpLogRecordable rec; const std::string service_name_key = "service.name"; @@ -82,51 +66,21 @@ TEST(OtlpLogRecordable, SetResource) opentelemetry::sdk::resource::Resource::Create({{service_name_key, service_name}}); rec.SetResource(resource); - auto proto_resource = rec.ProtoResource(); - bool found_service_name = false; - for (int i = 0; i < proto_resource.attributes_size(); i++) - { - auto attr = proto_resource.attributes(static_cast<int>(i)); - if (attr.key() == service_name_key && attr.value().string_value() == service_name) - { - found_service_name = true; - } - } - EXPECT_TRUE(found_service_name); + EXPECT_EQ(&rec.GetResource(), &resource); } TEST(OtlpLogRecordable, DefaultResource) { OtlpLogRecordable rec; - auto proto_resource = rec.ProtoResource(); - int found_resource_count = 0; - for (int i = 0; i < proto_resource.attributes_size(); i++) - { - auto attr = proto_resource.attributes(static_cast<int>(i)); - if (attr.key() == resource::SemanticConventions::kTelemetrySdkLanguage) - { - EXPECT_EQ(attr.value().string_value(), "cpp"); - ++found_resource_count; - } - else if (attr.key() == resource::SemanticConventions::kTelemetrySdkName) - { - EXPECT_EQ(attr.value().string_value(), "opentelemetry"); - ++found_resource_count; - } - else if (attr.key() == resource::SemanticConventions::kTelemetrySdkVersion) - { - EXPECT_EQ(attr.value().string_value(), OPENTELEMETRY_SDK_VERSION); - ++found_resource_count; - } - } - EXPECT_EQ(3, found_resource_count); + EXPECT_EQ(&rec.GetResource(), &opentelemetry::sdk::logs::ReadableLogRecord::GetDefaultResource()); } // Test non-int single types. Int single types are tested using templates (see IntAttributeTest) TEST(OtlpLogRecordable, SetSingleAttribute) { OtlpLogRecordable rec; + nostd::string_view bool_key = "bool_attr"; common::AttributeValue bool_val(true); rec.SetAttribute(bool_key, bool_val); @@ -139,21 +93,33 @@ TEST(OtlpLogRecordable, SetSingleAttribute) common::AttributeValue str_val(nostd::string_view("Test")); rec.SetAttribute(str_key, str_val); - EXPECT_EQ(rec.log_record().attributes(0).key(), bool_key); - EXPECT_EQ(rec.log_record().attributes(0).value().bool_value(), nostd::get<bool>(bool_val)); - - EXPECT_EQ(rec.log_record().attributes(1).key(), double_key); - EXPECT_EQ(rec.log_record().attributes(1).value().double_value(), nostd::get<double>(double_val)); - - EXPECT_EQ(rec.log_record().attributes(2).key(), str_key); - EXPECT_EQ(rec.log_record().attributes(2).value().string_value(), - nostd::get<nostd::string_view>(str_val).data()); + int checked_attributes = 0; + for (auto &attribute : rec.log_record().attributes()) + { + if (attribute.key() == bool_key) + { + ++checked_attributes; + EXPECT_EQ(attribute.value().bool_value(), nostd::get<bool>(bool_val)); + } + else if (attribute.key() == double_key) + { + ++checked_attributes; + EXPECT_EQ(attribute.value().double_value(), nostd::get<double>(double_val)); + } + else if (attribute.key() == str_key) + { + ++checked_attributes; + EXPECT_EQ(attribute.value().string_value(), nostd::get<nostd::string_view>(str_val).data()); + } + } + EXPECT_EQ(3, checked_attributes); } // Test non-int array types. Int array types are tested using templates (see IntAttributeTest) TEST(OtlpLogRecordable, SetArrayAttribute) { OtlpLogRecordable rec; + const int kArraySize = 3; bool bool_arr[kArraySize] = {true, false, true}; @@ -168,24 +134,42 @@ TEST(OtlpLogRecordable, SetArrayAttribute) nostd::span<const nostd::string_view> str_span(str_arr); rec.SetAttribute("str_arr_attr", str_span); + const opentelemetry::proto::common::v1::ArrayValue *bool_values = nullptr; + const opentelemetry::proto::common::v1::ArrayValue *double_values = nullptr; + const opentelemetry::proto::common::v1::ArrayValue *string_values = nullptr; + for (int i = 0; i < rec.log_record().attributes_size(); i++) + { + if (rec.log_record().attributes(i).value().array_value().values(0).has_bool_value()) + { + bool_values = &rec.log_record().attributes(i).value().array_value(); + } + else if (rec.log_record().attributes(i).value().array_value().values(0).has_double_value()) + { + double_values = &rec.log_record().attributes(i).value().array_value(); + } + else if (rec.log_record().attributes(i).value().array_value().values(0).has_string_value()) + { + string_values = &rec.log_record().attributes(i).value().array_value(); + } + } + for (int i = 0; i < kArraySize; i++) { - EXPECT_EQ(rec.log_record().attributes(0).value().array_value().values(i).bool_value(), - bool_span[i]); - EXPECT_EQ(rec.log_record().attributes(1).value().array_value().values(i).double_value(), - double_span[i]); - EXPECT_EQ(rec.log_record().attributes(2).value().array_value().values(i).string_value(), - str_span[i]); + EXPECT_EQ(bool_values->values(i).bool_value(), bool_span[i]); + EXPECT_EQ(double_values->values(i).double_value(), double_span[i]); + EXPECT_EQ(string_values->values(i).string_value(), str_span[i]); } } TEST(OtlpLogRecordable, SetInstrumentationScope) { OtlpLogRecordable rec; + auto inst_lib = opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create("test", "v1"); rec.SetInstrumentationScope(*inst_lib); - EXPECT_EQ(rec.GetInstrumentationScope(), *inst_lib); + + EXPECT_EQ(&rec.GetInstrumentationScope(), inst_lib.get()); } /** @@ -209,7 +193,9 @@ TYPED_TEST(OtlpLogRecordableIntAttributeTest, SetIntSingleAttribute) common::AttributeValue int_val(i); OtlpLogRecordable rec; + rec.SetAttribute("int_attr", int_val); + EXPECT_EQ(rec.log_record().attributes(0).value().int_value(), nostd::get<IntType>(int_val)); } @@ -222,6 +208,7 @@ TYPED_TEST(OtlpLogRecordableIntAttributeTest, SetIntArrayAttribute) nostd::span<const IntType> int_span(int_arr); OtlpLogRecordable rec; + rec.SetAttribute("int_arr_attr", int_span); for (int i = 0; i < kArraySize; i++) diff --git a/sdk/include/opentelemetry/sdk/common/circular_buffer.h b/sdk/include/opentelemetry/sdk/common/circular_buffer.h index 6af9001833..9f34659352 100644 --- a/sdk/include/opentelemetry/sdk/common/circular_buffer.h +++ b/sdk/include/opentelemetry/sdk/common/circular_buffer.h @@ -115,6 +115,14 @@ class CircularBuffer return true; } + bool Add(std::unique_ptr<T> &&ptr) noexcept + { + // rvalue to lvalue reference + bool result = Add(std::ref(ptr)); + ptr.reset(); + return result; + } + /** * Clear the circular buffer. * diff --git a/sdk/include/opentelemetry/sdk/logs/batch_log_record_processor_factory.h b/sdk/include/opentelemetry/sdk/logs/batch_log_record_processor_factory.h index a3ebb0e877..3177eb31e1 100644 --- a/sdk/include/opentelemetry/sdk/logs/batch_log_record_processor_factory.h +++ b/sdk/include/opentelemetry/sdk/logs/batch_log_record_processor_factory.h @@ -5,6 +5,8 @@ #ifdef ENABLE_LOGS_PREVIEW +# include <memory> + # include "opentelemetry/sdk/logs/batch_log_record_processor_options.h" # include "opentelemetry/sdk/logs/exporter.h" # include "opentelemetry/sdk/logs/processor.h" diff --git a/sdk/include/opentelemetry/sdk/logs/exporter.h b/sdk/include/opentelemetry/sdk/logs/exporter.h index 02865dc204..a531577aef 100644 --- a/sdk/include/opentelemetry/sdk/logs/exporter.h +++ b/sdk/include/opentelemetry/sdk/logs/exporter.h @@ -6,6 +6,7 @@ # include <memory> # include <vector> + # include "opentelemetry/nostd/span.h" # include "opentelemetry/sdk/common/exporter_utils.h" # include "opentelemetry/sdk/logs/processor.h" @@ -27,7 +28,7 @@ class LogRecordExporter /** * Create a log recordable. This object will be used to record log data and * will subsequently be passed to LogRecordExporter::Export. Vendors can implement - * custom recordables or use the default LogRecord recordable provided by the + * custom recordables or use the default ReadWriteLogRecord recordable provided by the * SDK. * @return a newly initialized Recordable object * diff --git a/sdk/include/opentelemetry/sdk/logs/log_record.h b/sdk/include/opentelemetry/sdk/logs/log_record.h deleted file mode 100644 index 8b7ac19570..0000000000 --- a/sdk/include/opentelemetry/sdk/logs/log_record.h +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -#pragma once -#ifdef ENABLE_LOGS_PREVIEW - -# include <map> -# include <unordered_map> -# include "opentelemetry/sdk/common/attribute_utils.h" -# include "opentelemetry/sdk/logs/recordable.h" -# include "opentelemetry/sdk/resource/resource.h" -# include "opentelemetry/version.h" - -OPENTELEMETRY_BEGIN_NAMESPACE -namespace sdk -{ -namespace logs -{ - -/** - * A default Recordable implemenation to be passed in log statements, - * matching the 10 fields of the Log Data Model. - * (https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#log-and-event-record-definition) - * - */ -class LogRecord final : public Recordable -{ -private: - // Default values are set by the respective data structures' constructors for all fields, - // except the severity field, which must be set manually (an enum with no default value). - opentelemetry::logs::Severity severity_ = opentelemetry::logs::Severity::kInvalid; - const opentelemetry::sdk::resource::Resource *resource_ = nullptr; - common::AttributeMap attributes_map_; - std::string body_; // Currently a simple string, but should be changed to "Any" type - opentelemetry::trace::TraceId trace_id_; - opentelemetry::trace::SpanId span_id_; - opentelemetry::trace::TraceFlags trace_flags_; - opentelemetry::common::SystemTimestamp timestamp_; // uint64 nanoseconds since Unix epoch - -public: - /********** Setters for each field (overrides methods from the Recordable interface) ************/ - - /** - * Set the severity for this log. - * @param severity the severity of the event - */ - void SetSeverity(opentelemetry::logs::Severity severity) noexcept override - { - severity_ = severity; - } - - /** - * Set body field for this log. - * @param message the body to set - */ - void SetBody(nostd::string_view message) noexcept override { body_ = std::string(message); } - - /** - * Set Resource of this log - * @param Resource the resource to set - */ - void SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept override - { - resource_ = &resource; - } - - /** - * Set an attribute of a log. - * @param name the name of the attribute - * @param value the attribute value - */ - - void SetAttribute(nostd::string_view key, - const opentelemetry::common::AttributeValue &value) noexcept override - { - attributes_map_.SetAttribute(key, value); - } - - /** - * Set trace id for this log. - * @param trace_id the trace id to set - */ - void SetTraceId(opentelemetry::trace::TraceId trace_id) noexcept override - { - trace_id_ = trace_id; - } - - /** - * Set span id for this log. - * @param span_id the span id to set - */ - virtual void SetSpanId(opentelemetry::trace::SpanId span_id) noexcept override - { - span_id_ = span_id; - } - - /** - * Inject a trace_flags for this log. - * @param trace_flags the span id to set - */ - void SetTraceFlags(opentelemetry::trace::TraceFlags trace_flags) noexcept override - { - trace_flags_ = trace_flags; - } - - /** - * Set the timestamp for this log. - * @param timestamp the timestamp of the event - */ - void SetTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept override - { - timestamp_ = timestamp; - } - - /************************** Getters for each field ****************************/ - - /** - * Get the severity for this log - * @return the severity for this log - */ - opentelemetry::logs::Severity GetSeverity() const noexcept { return severity_; } - - /** - * Get the body of this log - * @return the body of this log - */ - std::string GetBody() const noexcept { return body_; } - - /** - * Get the resource for this log - * @return the resource for this log - */ - const opentelemetry::sdk::resource::Resource &GetResource() const noexcept - { - if (nullptr == resource_) - { - return sdk::resource::Resource::GetDefault(); - } - return *resource_; - } - - /** - * Get the attributes for this log - * @return the attributes for this log - */ - const std::unordered_map<std::string, common::OwnedAttributeValue> &GetAttributes() const noexcept - { - return attributes_map_.GetAttributes(); - } - - /** - * Get the trace id for this log - * @return the trace id for this log - */ - opentelemetry::trace::TraceId GetTraceId() const noexcept { return trace_id_; } - - /** - * Get the span id for this log - * @return the span id for this log - */ - opentelemetry::trace::SpanId GetSpanId() const noexcept { return span_id_; } - - /** - * Get the trace flags for this log - * @return the trace flags for this log - */ - opentelemetry::trace::TraceFlags GetTraceFlags() const noexcept { return trace_flags_; } - - /** - * Get the timestamp for this log - * @return the timestamp for this log - */ - opentelemetry::common::SystemTimestamp GetTimestamp() const noexcept { return timestamp_; } - - /** - * Set instrumentation_scope for this log. - * @param instrumentation_scope the instrumentation scope to set - */ - void SetInstrumentationScope(const opentelemetry::sdk::instrumentationscope::InstrumentationScope - &instrumentation_scope) noexcept override - { - instrumentation_scope_ = &instrumentation_scope; - } - - OPENTELEMETRY_DEPRECATED_MESSAGE("Please use SetInstrumentationScope instead") - void SetInstrumentationLibrary( - const opentelemetry::sdk::instrumentationscope::InstrumentationScope - &instrumentation_scope) noexcept - { - SetInstrumentationScope(instrumentation_scope); - } - -private: - const opentelemetry::sdk::instrumentationscope::InstrumentationScope *instrumentation_scope_ = - nullptr; -}; -} // namespace logs -} // namespace sdk -OPENTELEMETRY_END_NAMESPACE -#endif diff --git a/sdk/include/opentelemetry/sdk/logs/logger.h b/sdk/include/opentelemetry/sdk/logs/logger.h index 7e4429e0cf..d290df98c3 100644 --- a/sdk/include/opentelemetry/sdk/logs/logger.h +++ b/sdk/include/opentelemetry/sdk/logs/logger.h @@ -4,14 +4,16 @@ #pragma once #ifdef ENABLE_LOGS_PREVIEW +# include <memory> +# include <vector> + # include "opentelemetry/common/macros.h" # include "opentelemetry/logs/logger.h" +# include "opentelemetry/nostd/unique_ptr.h" # include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h" # include "opentelemetry/sdk/logs/logger_context.h" # include "opentelemetry/sdk/logs/logger_provider.h" -# include <vector> - OPENTELEMETRY_BEGIN_NAMESPACE namespace sdk { @@ -38,38 +40,12 @@ class Logger final : public opentelemetry::logs::Logger */ const opentelemetry::nostd::string_view GetName() noexcept override; - /** - * Writes a log record into the processor. - * @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). - * with the log event. - * @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. */ - void Log(opentelemetry::logs::Severity severity, - nostd::string_view body, - const opentelemetry::common::KeyValueIterable &attributes, - opentelemetry::trace::TraceId trace_id, - opentelemetry::trace::SpanId span_id, - opentelemetry::trace::TraceFlags trace_flags, - opentelemetry::common::SystemTimestamp timestamp) noexcept override; + nostd::unique_ptr<opentelemetry::logs::LogRecord> CreateLogRecord() noexcept override; - // Deprecated - void Log(opentelemetry::logs::Severity severity, - nostd::string_view /* name */, - nostd::string_view body, - const opentelemetry::common::KeyValueIterable &attributes, - opentelemetry::trace::TraceId trace_id, - opentelemetry::trace::SpanId span_id, - opentelemetry::trace::TraceFlags trace_flags, - opentelemetry::common::SystemTimestamp timestamp) noexcept override - { - Log(severity, body, attributes, trace_id, span_id, trace_flags, timestamp); - } + using opentelemetry::logs::Logger::EmitLogRecord; + + void EmitLogRecord( + nostd::unique_ptr<opentelemetry::logs::LogRecord> &&log_record) noexcept override; /** Returns the associated instrumentation scope */ const opentelemetry::sdk::instrumentationscope::InstrumentationScope &GetInstrumentationScope() diff --git a/sdk/include/opentelemetry/sdk/logs/logger_context.h b/sdk/include/opentelemetry/sdk/logs/logger_context.h index da41c122b7..fe6db6822a 100644 --- a/sdk/include/opentelemetry/sdk/logs/logger_context.h +++ b/sdk/include/opentelemetry/sdk/logs/logger_context.h @@ -5,6 +5,8 @@ #ifdef ENABLE_LOGS_PREVIEW +# include <memory> + # include "opentelemetry/sdk/logs/processor.h" # include "opentelemetry/sdk/resource/resource.h" # include "opentelemetry/version.h" diff --git a/sdk/include/opentelemetry/sdk/logs/logger_context_factory.h b/sdk/include/opentelemetry/sdk/logs/logger_context_factory.h index 28dc24d56c..377094d5db 100644 --- a/sdk/include/opentelemetry/sdk/logs/logger_context_factory.h +++ b/sdk/include/opentelemetry/sdk/logs/logger_context_factory.h @@ -5,6 +5,8 @@ #ifdef ENABLE_LOGS_PREVIEW +# include <memory> + # include "opentelemetry/sdk/logs/logger_context.h" # include "opentelemetry/sdk/logs/processor.h" # include "opentelemetry/sdk/resource/resource.h" diff --git a/sdk/include/opentelemetry/sdk/logs/multi_recordable.h b/sdk/include/opentelemetry/sdk/logs/multi_recordable.h index 9b37806e2a..8bbc2ae200 100644 --- a/sdk/include/opentelemetry/sdk/logs/multi_recordable.h +++ b/sdk/include/opentelemetry/sdk/logs/multi_recordable.h @@ -37,6 +37,12 @@ class MultiRecordable final : public Recordable */ void SetTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept override; + /** + * Set the observed timestamp for this log. + * @param timestamp the timestamp to set + */ + void SetObservedTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept override; + /** * Set the severity for this log. * @param severity the severity of the event @@ -47,39 +53,39 @@ class MultiRecordable final : public Recordable * Set body field for this log. * @param message the body to set */ - void SetBody(nostd::string_view message) noexcept override; - - /** - * Set Resource of this log - * @param Resource the resource to set - */ - void SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept override; - - /** - * Set an attribute of a log. - * @param key the name of the attribute - * @param value the attribute value - */ - void SetAttribute(nostd::string_view key, - const opentelemetry::common::AttributeValue &value) noexcept override; + void SetBody(const opentelemetry::common::AttributeValue &message) noexcept override; /** * Set the trace id for this log. * @param trace_id the trace id to set */ - void SetTraceId(opentelemetry::trace::TraceId trace_id) noexcept override; + void SetTraceId(const opentelemetry::trace::TraceId &trace_id) noexcept override; /** * Set the span id for this log. * @param span_id the span id to set */ - void SetSpanId(opentelemetry::trace::SpanId span_id) noexcept override; + void SetSpanId(const opentelemetry::trace::SpanId &span_id) noexcept override; /** * Inject trace_flags for this log. * @param trace_flags the trace flags to set */ - void SetTraceFlags(opentelemetry::trace::TraceFlags trace_flags) noexcept override; + void SetTraceFlags(const opentelemetry::trace::TraceFlags &trace_flags) noexcept override; + + /** + * Set an attribute of a log. + * @param key the name of the attribute + * @param value the attribute value + */ + void SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept override; + + /** + * Set Resource of this log + * @param Resource the resource to set + */ + void SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept override; /** * Set instrumentation_scope for this log. @@ -88,21 +94,8 @@ class MultiRecordable final : public Recordable void SetInstrumentationScope(const opentelemetry::sdk::instrumentationscope::InstrumentationScope &instrumentation_scope) noexcept override; - /** Returns the associated instrumentation scope */ - const opentelemetry::sdk::instrumentationscope::InstrumentationScope &GetInstrumentationScope() - const noexcept; - - OPENTELEMETRY_DEPRECATED_MESSAGE("Please use GetInstrumentationScope instead") - const opentelemetry::sdk::instrumentationscope::InstrumentationScope &GetInstrumentationLibrary() - const noexcept - { - return GetInstrumentationScope(); - } - private: std::unordered_map<std::size_t, std::unique_ptr<Recordable>> recordables_; - const opentelemetry::sdk::instrumentationscope::InstrumentationScope *instrumentation_scope_ = - nullptr; }; } // namespace logs } // namespace sdk diff --git a/sdk/include/opentelemetry/sdk/logs/processor.h b/sdk/include/opentelemetry/sdk/logs/processor.h index 536140f7db..97f823a25b 100644 --- a/sdk/include/opentelemetry/sdk/logs/processor.h +++ b/sdk/include/opentelemetry/sdk/logs/processor.h @@ -6,6 +6,8 @@ # include <chrono> # include <memory> + +# include "opentelemetry/nostd/unique_ptr.h" # include "opentelemetry/sdk/logs/recordable.h" OPENTELEMETRY_BEGIN_NAMESPACE @@ -25,6 +27,7 @@ class LogRecordProcessor /** * Create a log recordable. This requests a new log recordable from the * associated exporter. + * * @return a newly initialized recordable * * Note: This method must be callable from multiple threads. @@ -33,7 +36,7 @@ class LogRecordProcessor /** * OnEmit is called by the SDK once a log record has been successfully created. - * @param record the log record + * @param record the log recordable object */ virtual void OnEmit(std::unique_ptr<Recordable> &&record) noexcept = 0; diff --git a/sdk/include/opentelemetry/sdk/logs/read_write_log_record.h b/sdk/include/opentelemetry/sdk/logs/read_write_log_record.h new file mode 100644 index 0000000000..c81a2da126 --- /dev/null +++ b/sdk/include/opentelemetry/sdk/logs/read_write_log_record.h @@ -0,0 +1,191 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include <memory> +# include <string> + +# include "opentelemetry/common/attribute_value.h" +# include "opentelemetry/common/key_value_iterable.h" +# include "opentelemetry/common/timestamp.h" +# include "opentelemetry/logs/log_record.h" +# include "opentelemetry/logs/severity.h" +# include "opentelemetry/nostd/unique_ptr.h" +# include "opentelemetry/sdk/common/attribute_utils.h" +# include "opentelemetry/sdk/common/empty_attributes.h" +# include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h" +# include "opentelemetry/sdk/logs/readable_log_record.h" +# include "opentelemetry/sdk/resource/resource.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 sdk +{ +namespace logs +{ +/** + * Maintains a representation of a log in a format that can be processed by a recorder. + * + * This class is thread-compatible. + */ +class ReadWriteLogRecord final : public ReadableLogRecord +{ +public: + ReadWriteLogRecord(); + ~ReadWriteLogRecord() override; + + /** + * Set the timestamp for this log. + * @param timestamp the timestamp to set + */ + void SetTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept override; + + /** + * Get the timestamp of this log. + * @return the timestamp of this log + */ + opentelemetry::common::SystemTimestamp GetTimestamp() const noexcept override; + + /** + * Set the observed timestamp for this log. + * @param timestamp the timestamp to set + */ + void SetObservedTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept override; + + /** + * Get the observed timestamp of this log. + * @return the observed timestamp of this log + */ + opentelemetry::common::SystemTimestamp GetObservedTimestamp() const noexcept override; + + /** + * Set the severity for this log. + * @param severity the severity of the event + */ + void SetSeverity(opentelemetry::logs::Severity severity) noexcept override; + + /** + * Get the severity of this log. + * @return the severity of this log + */ + opentelemetry::logs::Severity GetSeverity() const noexcept override; + + /** + * Set body field for this log. + * @param message the body to set + */ + void SetBody(const opentelemetry::common::AttributeValue &message) noexcept override; + + /** + * Get body field of this log. + * @return the body field for this log. + */ + const opentelemetry::common::AttributeValue &GetBody() const noexcept override; + + /** + * Set the trace id for this log. + * @param trace_id the trace id to set + */ + void SetTraceId(const opentelemetry::trace::TraceId &trace_id) noexcept override; + + /** + * Get the trace id of this log. + * @return the trace id of this log + */ + const opentelemetry::trace::TraceId &GetTraceId() const noexcept override; + + /** + * Set the span id for this log. + * @param span_id the span id to set + */ + void SetSpanId(const opentelemetry::trace::SpanId &span_id) noexcept override; + + /** + * Get the span id of this log. + * @return the span id of this log + */ + const opentelemetry::trace::SpanId &GetSpanId() const noexcept override; + + /** + * Inject trace_flags for this log. + * @param trace_flags the trace flags to set + */ + void SetTraceFlags(const opentelemetry::trace::TraceFlags &trace_flags) noexcept override; + + /** + * Inject trace_flags of this log. + * @return trace_flags of this log + */ + const opentelemetry::trace::TraceFlags &GetTraceFlags() const noexcept override; + + /** + * Set an attribute of a log. + * @param key the name of the attribute + * @param value the attribute value + */ + void SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept override; + + /** + * Get attributes of this log. + * @return the body field of this log + */ + const std::unordered_map<std::string, opentelemetry::common::AttributeValue> &GetAttributes() + const noexcept override; + + /** + * Get resource of this log + * @return the resource of this log + */ + const opentelemetry::sdk::resource::Resource &GetResource() const noexcept override; + + /** + * Set Resource of this log + * @param Resource the resource to set + */ + void SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept override; + + /** + * Get instrumentation_scope of this log. + * @return the instrumentation_scope of this log + */ + const opentelemetry::sdk::instrumentationscope::InstrumentationScope &GetInstrumentationScope() + const noexcept override; + + /** + * Set instrumentation_scope for this log. + * @param instrumentation_scope the instrumentation scope to set + */ + void SetInstrumentationScope(const opentelemetry::sdk::instrumentationscope::InstrumentationScope + &instrumentation_scope) noexcept override; + +private: + // Default values are set by the respective data structures' constructors for all fields, + // except the severity field, which must be set manually (an enum with no default value). + opentelemetry::logs::Severity severity_; + const opentelemetry::sdk::resource::Resource *resource_; + const opentelemetry::sdk::instrumentationscope::InstrumentationScope *instrumentation_scope_; + + std::unordered_map<std::string, opentelemetry::common::AttributeValue> attributes_map_; + opentelemetry::common::AttributeValue body_; + opentelemetry::common::SystemTimestamp timestamp_; + opentelemetry::common::SystemTimestamp observed_timestamp_; + + // We do not pay for trace state when not necessary + struct TraceState + { + opentelemetry::trace::TraceId trace_id; + opentelemetry::trace::SpanId span_id; + opentelemetry::trace::TraceFlags trace_flags; + }; + std::unique_ptr<TraceState> trace_state_; +}; +} // namespace logs +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/sdk/include/opentelemetry/sdk/logs/readable_log_record.h b/sdk/include/opentelemetry/sdk/logs/readable_log_record.h new file mode 100644 index 0000000000..7b3d8ad502 --- /dev/null +++ b/sdk/include/opentelemetry/sdk/logs/readable_log_record.h @@ -0,0 +1,121 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#pragma once +#ifdef ENABLE_LOGS_PREVIEW + +# include <string> +# include <unordered_map> + +# include "opentelemetry/common/attribute_value.h" +# include "opentelemetry/common/key_value_iterable.h" +# include "opentelemetry/common/timestamp.h" +# include "opentelemetry/logs/severity.h" +# include "opentelemetry/sdk/common/attribute_utils.h" +# include "opentelemetry/sdk/common/empty_attributes.h" +# include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h" +# include "opentelemetry/sdk/logs/recordable.h" +# include "opentelemetry/sdk/resource/resource.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 sdk +{ +namespace logs +{ +/** + * Maintains a representation of a log in a format that can be processed by a recorder. + * + * This class is thread-compatible. + */ +class ReadableLogRecord : public Recordable +{ +public: + /** + * Get the timestamp of this log. + * @return the timestamp of this log + */ + virtual opentelemetry::common::SystemTimestamp GetTimestamp() const noexcept = 0; + + /** + * Get the observed timestamp of this log. + * @return the observed timestamp of this log + */ + virtual opentelemetry::common::SystemTimestamp GetObservedTimestamp() const noexcept = 0; + + /** + * Get the severity of this log. + * @return the severity of this log + */ + virtual opentelemetry::logs::Severity GetSeverity() const noexcept = 0; + + /** + * Get the severity text of this log. + * @return the severity text for this log + */ + virtual nostd::string_view GetSeverityText() const noexcept; + + /** + * Get body field of this log. + * @return the body field for this log. + */ + virtual const opentelemetry::common::AttributeValue &GetBody() const noexcept = 0; + + /** + * Get the trace id of this log. + * @return the trace id of this log + */ + virtual const opentelemetry::trace::TraceId &GetTraceId() const noexcept = 0; + + /** + * Get the span id of this log. + * @return the span id of this log + */ + virtual const opentelemetry::trace::SpanId &GetSpanId() const noexcept = 0; + + /** + * Inject trace_flags of this log. + * @return trace_flags of this log + */ + virtual const opentelemetry::trace::TraceFlags &GetTraceFlags() const noexcept = 0; + + /** + * Get attributes of this log. + * @return the body field of this log + */ + virtual const std::unordered_map<std::string, opentelemetry::common::AttributeValue> + &GetAttributes() const noexcept = 0; + + /** + * Get resource of this log + * @return the resource of this log + */ + virtual const opentelemetry::sdk::resource::Resource &GetResource() const noexcept = 0; + + /** + * Get instrumentation scope of this log. + * @return the instrumentation scope of this log + */ + virtual const opentelemetry::sdk::instrumentationscope::InstrumentationScope & + GetInstrumentationScope() const noexcept = 0; + + /** + * Get default instrumentation scope of logs. + * @return the default instrumentation scope of logs + */ + static const opentelemetry::sdk::instrumentationscope::InstrumentationScope & + GetDefaultInstrumentationScope() noexcept; + + /** + * Get default resource of logs. + * @return the default resource of logs + */ + static const opentelemetry::sdk::resource::Resource &GetDefaultResource() noexcept; +}; +} // namespace logs +} // namespace sdk +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/sdk/include/opentelemetry/sdk/logs/recordable.h b/sdk/include/opentelemetry/sdk/logs/recordable.h index 13e834ee49..983a2e6b57 100644 --- a/sdk/include/opentelemetry/sdk/logs/recordable.h +++ b/sdk/include/opentelemetry/sdk/logs/recordable.h @@ -7,12 +7,13 @@ # include "opentelemetry/common/attribute_value.h" # include "opentelemetry/common/key_value_iterable.h" # include "opentelemetry/common/timestamp.h" +# include "opentelemetry/logs/log_record.h" # include "opentelemetry/logs/severity.h" +# include "opentelemetry/sdk/common/attribute_utils.h" # include "opentelemetry/sdk/common/empty_attributes.h" # include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h" +# include "opentelemetry/sdk/logs/recordable.h" # include "opentelemetry/sdk/resource/resource.h" -# include "opentelemetry/trace/span.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" @@ -28,61 +29,16 @@ namespace logs * * This class is thread-compatible. */ -class Recordable + +class Recordable : public opentelemetry::logs::LogRecord { public: - virtual ~Recordable() = default; - - /** - * Set the timestamp for this log. - * @param timestamp the timestamp to set - */ - virtual void SetTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept = 0; - - /** - * Set the severity for this log. - * @param severity the severity of the event - */ - virtual void SetSeverity(opentelemetry::logs::Severity severity) noexcept = 0; - - /** - * Set body field for this log. - * @param message the body to set - */ - virtual void SetBody(nostd::string_view message) noexcept = 0; - /** * Set Resource of this log * @param Resource the resource to set */ virtual void SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept = 0; - /** - * Set an attribute of a log. - * @param key the name of the attribute - * @param value the attribute value - */ - virtual void SetAttribute(nostd::string_view key, - const opentelemetry::common::AttributeValue &value) noexcept = 0; - - /** - * Set the trace id for this log. - * @param trace_id the trace id to set - */ - virtual void SetTraceId(opentelemetry::trace::TraceId trace_id) noexcept = 0; - - /** - * Set the span id for this log. - * @param span_id the span id to set - */ - virtual void SetSpanId(opentelemetry::trace::SpanId span_id) noexcept = 0; - - /** - * Inject trace_flags for this log. - * @param trace_flags the trace flags to set - */ - virtual void SetTraceFlags(opentelemetry::trace::TraceFlags trace_flags) noexcept = 0; - /** * Set instrumentation_scope for this log. * @param instrumentation_scope the instrumentation scope to set @@ -90,15 +46,8 @@ class Recordable virtual void SetInstrumentationScope( const opentelemetry::sdk::instrumentationscope::InstrumentationScope &instrumentation_scope) noexcept = 0; - - OPENTELEMETRY_DEPRECATED_MESSAGE("Please use SetInstrumentationScope instead") - void SetInstrumentationLibrary( - const opentelemetry::sdk::instrumentationscope::InstrumentationScope - &instrumentation_scope) noexcept - { - SetInstrumentationScope(instrumentation_scope); - } }; + } // namespace logs } // namespace sdk OPENTELEMETRY_END_NAMESPACE diff --git a/sdk/include/opentelemetry/sdk/logs/simple_log_record_processor.h b/sdk/include/opentelemetry/sdk/logs/simple_log_record_processor.h index 0e4ce3f2ab..f3d6bc27c3 100644 --- a/sdk/include/opentelemetry/sdk/logs/simple_log_record_processor.h +++ b/sdk/include/opentelemetry/sdk/logs/simple_log_record_processor.h @@ -5,6 +5,7 @@ #ifdef ENABLE_LOGS_PREVIEW # include <atomic> +# include <memory> # include <mutex> # include "opentelemetry/common/spin_lock_mutex.h" diff --git a/sdk/include/opentelemetry/sdk/logs/simple_log_record_processor_factory.h b/sdk/include/opentelemetry/sdk/logs/simple_log_record_processor_factory.h index 7ba2c3ac0f..a71ba05684 100644 --- a/sdk/include/opentelemetry/sdk/logs/simple_log_record_processor_factory.h +++ b/sdk/include/opentelemetry/sdk/logs/simple_log_record_processor_factory.h @@ -5,6 +5,8 @@ #ifdef ENABLE_LOGS_PREVIEW +# include <memory> + # include "opentelemetry/sdk/logs/exporter.h" # include "opentelemetry/sdk/logs/processor.h" diff --git a/sdk/src/logs/CMakeLists.txt b/sdk/src/logs/CMakeLists.txt index 546e66614b..ff43c4d92b 100644 --- a/sdk/src/logs/CMakeLists.txt +++ b/sdk/src/logs/CMakeLists.txt @@ -11,7 +11,9 @@ add_library( logger_context_factory.cc multi_log_record_processor.cc multi_log_record_processor_factory.cc - multi_recordable.cc) + multi_recordable.cc + read_write_log_record.cc + readable_log_record.cc) set_target_properties(opentelemetry_logs PROPERTIES EXPORT_NAME logs) diff --git a/sdk/src/logs/batch_log_record_processor.cc b/sdk/src/logs/batch_log_record_processor.cc index 87992e7822..7903c3b24c 100644 --- a/sdk/src/logs/batch_log_record_processor.cc +++ b/sdk/src/logs/batch_log_record_processor.cc @@ -61,7 +61,7 @@ void BatchLogRecordProcessor::OnEmit(std::unique_ptr<Recordable> &&record) noexc return; } - if (buffer_.Add(record) == false) + if (buffer_.Add(std::unique_ptr<Recordable>(record.release())) == false) { return; } diff --git a/sdk/src/logs/logger.cc b/sdk/src/logs/logger.cc index d7ab485dff..a87e4af8a2 100644 --- a/sdk/src/logs/logger.cc +++ b/sdk/src/logs/logger.cc @@ -3,7 +3,6 @@ #ifdef ENABLE_LOGS_PREVIEW # include "opentelemetry/sdk/logs/logger.h" -# include "opentelemetry/sdk/logs/log_record.h" # include "opentelemetry/sdk_config.h" # include "opentelemetry/trace/provider.h" @@ -30,88 +29,31 @@ const nostd::string_view Logger::GetName() noexcept return logger_name_; } -/** - * Create and populate recordable with the log event's fields passed in. - * The timestamp, severity, traceid, spanid, and traceflags, are injected - * if the user does not specify them. - */ -void Logger::Log(opentelemetry::logs::Severity severity, - nostd::string_view body, - const common::KeyValueIterable &attributes, - trace_api::TraceId trace_id, - trace_api::SpanId span_id, - trace_api::TraceFlags trace_flags, - common::SystemTimestamp timestamp) noexcept +nostd::unique_ptr<opentelemetry::logs::LogRecord> Logger::CreateLogRecord() noexcept { - // If this logger does not have a processor, no need to create a log record + // If this logger does not have a processor, no need to create a log recordable if (!context_) { - return; + return nullptr; } - auto &processor = context_->GetProcessor(); - // TODO: Sampler (should include check for minSeverity) + return nostd::unique_ptr<opentelemetry::logs::LogRecord>( + context_->GetProcessor().MakeRecordable().release()); +} - auto recordable = processor.MakeRecordable(); - if (recordable == nullptr) +void Logger::EmitLogRecord(nostd::unique_ptr<opentelemetry::logs::LogRecord> &&log_record) noexcept +{ + if (!log_record) { - OTEL_INTERNAL_LOG_ERROR("[LOGGER] Recordable creation failed"); return; } - // Populate recordable fields - recordable->SetTimestamp(timestamp); - recordable->SetSeverity(severity); - recordable->SetBody(body); - recordable->SetInstrumentationScope(GetInstrumentationScope()); - - recordable->SetResource(context_->GetResource()); - - attributes.ForEachKeyValue([&](nostd::string_view key, common::AttributeValue value) noexcept { - recordable->SetAttribute(key, value); - return true; - }); - - // Inject trace_id/span_id/trace_flags if none is set by user - auto provider = trace_api::Provider::GetTracerProvider(); - auto tracer = provider->GetTracer(logger_name_); - auto span_context = tracer->GetCurrentSpan()->GetContext(); - - // Leave these fields in the recordable empty if neither the passed in values - // nor the context values are valid (e.g. the application is not using traces) - - // TraceId - if (trace_id.IsValid()) - { - recordable->SetTraceId(trace_id); - } - else if (span_context.trace_id().IsValid()) - { - recordable->SetTraceId(span_context.trace_id()); - } - - // SpanId - if (span_id.IsValid()) - { - recordable->SetSpanId(span_id); - } - else if (span_context.span_id().IsValid()) - { - recordable->SetSpanId(span_context.span_id()); - } + auto &processor = context_->GetProcessor(); - // TraceFlags - if (trace_flags.IsSampled()) - { - recordable->SetTraceFlags(trace_flags); - } - else if (span_context.trace_flags().IsSampled()) - { - recordable->SetTraceFlags(span_context.trace_flags()); - } + // TODO: Sampler (should include check for minSeverity) - // Send the log record to the processor - processor.OnEmit(std::move(recordable)); + // Send the log recordable to the processor + processor.OnEmit(std::unique_ptr<Recordable>(static_cast<Recordable *>(log_record.release()))); } const opentelemetry::sdk::instrumentationscope::InstrumentationScope & diff --git a/sdk/src/logs/logger_provider.cc b/sdk/src/logs/logger_provider.cc index 6f806d5be9..3000aa8230 100644 --- a/sdk/src/logs/logger_provider.cc +++ b/sdk/src/logs/logger_provider.cc @@ -91,7 +91,7 @@ nostd::shared_ptr<opentelemetry::logs::Logger> LoggerProvider::GetLogger( */ // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/logs/data-model.md#field-instrumentationscope - opentelemetry::nostd::unique_ptr<instrumentationscope::InstrumentationScope> lib; + std::unique_ptr<instrumentationscope::InstrumentationScope> lib; if (library_name.empty()) { lib = instrumentationscope::InstrumentationScope::Create(logger_name, library_version, diff --git a/sdk/src/logs/multi_log_record_processor.cc b/sdk/src/logs/multi_log_record_processor.cc index a6f20be7eb..2859126f80 100644 --- a/sdk/src/logs/multi_log_record_processor.cc +++ b/sdk/src/logs/multi_log_record_processor.cc @@ -40,7 +40,7 @@ void MultiLogRecordProcessor::AddProcessor(std::unique_ptr<LogRecordProcessor> & std::unique_ptr<Recordable> MultiLogRecordProcessor::MakeRecordable() noexcept { - auto recordable = std::unique_ptr<Recordable>(new MultiRecordable); + auto recordable = std::unique_ptr<Recordable>(new MultiRecordable()); auto multi_recordable = static_cast<MultiRecordable *>(recordable.get()); for (auto &processor : processors_) { diff --git a/sdk/src/logs/multi_recordable.cc b/sdk/src/logs/multi_recordable.cc index c91ffc6b82..17e2c29777 100644 --- a/sdk/src/logs/multi_recordable.cc +++ b/sdk/src/logs/multi_recordable.cc @@ -60,7 +60,22 @@ void MultiRecordable::SetTimestamp(opentelemetry::common::SystemTimestamp timest { for (auto &recordable : recordables_) { - recordable.second->SetTimestamp(timestamp); + if (recordable.second) + { + recordable.second->SetTimestamp(timestamp); + } + } +} + +void MultiRecordable::SetObservedTimestamp( + opentelemetry::common::SystemTimestamp timestamp) noexcept +{ + for (auto &recordable : recordables_) + { + if (recordable.second) + { + recordable.second->SetObservedTimestamp(timestamp); + } } } @@ -68,56 +83,77 @@ void MultiRecordable::SetSeverity(opentelemetry::logs::Severity severity) noexce { for (auto &recordable : recordables_) { - recordable.second->SetSeverity(severity); + if (recordable.second) + { + recordable.second->SetSeverity(severity); + } } } -void MultiRecordable::SetBody(nostd::string_view message) noexcept +void MultiRecordable::SetBody(const opentelemetry::common::AttributeValue &message) noexcept { for (auto &recordable : recordables_) { - recordable.second->SetBody(message); + if (recordable.second) + { + recordable.second->SetBody(message); + } } } -void MultiRecordable::SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept +void MultiRecordable::SetTraceId(const opentelemetry::trace::TraceId &trace_id) noexcept { for (auto &recordable : recordables_) { - recordable.second->SetResource(resource); + if (recordable.second) + { + recordable.second->SetTraceId(trace_id); + } } } -void MultiRecordable::SetAttribute(nostd::string_view key, - const opentelemetry::common::AttributeValue &value) noexcept +void MultiRecordable::SetSpanId(const opentelemetry::trace::SpanId &span_id) noexcept { for (auto &recordable : recordables_) { - recordable.second->SetAttribute(key, value); + if (recordable.second) + { + recordable.second->SetSpanId(span_id); + } } } -void MultiRecordable::SetTraceId(opentelemetry::trace::TraceId trace_id) noexcept +void MultiRecordable::SetTraceFlags(const opentelemetry::trace::TraceFlags &trace_flags) noexcept { for (auto &recordable : recordables_) { - recordable.second->SetTraceId(trace_id); + if (recordable.second) + { + recordable.second->SetTraceFlags(trace_flags); + } } } -void MultiRecordable::SetSpanId(opentelemetry::trace::SpanId span_id) noexcept +void MultiRecordable::SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept { for (auto &recordable : recordables_) { - recordable.second->SetSpanId(span_id); + if (recordable.second) + { + recordable.second->SetAttribute(key, value); + } } } -void MultiRecordable::SetTraceFlags(opentelemetry::trace::TraceFlags trace_flags) noexcept +void MultiRecordable::SetResource(const opentelemetry::sdk::resource::Resource &resource) noexcept { for (auto &recordable : recordables_) { - recordable.second->SetTraceFlags(trace_flags); + if (recordable.second) + { + recordable.second->SetResource(resource); + } } } @@ -125,14 +161,15 @@ void MultiRecordable::SetInstrumentationScope( const opentelemetry::sdk::instrumentationscope::InstrumentationScope &instrumentation_scope) noexcept { - instrumentation_scope_ = &instrumentation_scope; + for (auto &recordable : recordables_) + { + if (recordable.second) + { + recordable.second->SetInstrumentationScope(instrumentation_scope); + } + } } -const opentelemetry::sdk::instrumentationscope::InstrumentationScope & -MultiRecordable::GetInstrumentationScope() const noexcept -{ - return *instrumentation_scope_; -} } // namespace logs } // namespace sdk diff --git a/sdk/src/logs/read_write_log_record.cc b/sdk/src/logs/read_write_log_record.cc new file mode 100644 index 0000000000..e452fa20e9 --- /dev/null +++ b/sdk/src/logs/read_write_log_record.cc @@ -0,0 +1,174 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifdef ENABLE_LOGS_PREVIEW + +# include <cstddef> +# include <type_traits> + +# include "opentelemetry/sdk/logs/read_write_log_record.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace logs +{ + +ReadWriteLogRecord::ReadWriteLogRecord() + : severity_(opentelemetry::logs::Severity::kInvalid), + resource_(nullptr), + instrumentation_scope_(nullptr), + body_(nostd::string_view()), + observed_timestamp_(std::chrono::system_clock::now()) +{} + +ReadWriteLogRecord::~ReadWriteLogRecord() {} + +void ReadWriteLogRecord::SetTimestamp(opentelemetry::common::SystemTimestamp timestamp) noexcept +{ + timestamp_ = timestamp; +} + +opentelemetry::common::SystemTimestamp ReadWriteLogRecord::GetTimestamp() const noexcept +{ + return timestamp_; +} + +void ReadWriteLogRecord::SetObservedTimestamp( + opentelemetry::common::SystemTimestamp timestamp) noexcept +{ + observed_timestamp_ = timestamp; +} + +opentelemetry::common::SystemTimestamp ReadWriteLogRecord::GetObservedTimestamp() const noexcept +{ + return observed_timestamp_; +} + +void ReadWriteLogRecord::SetSeverity(opentelemetry::logs::Severity severity) noexcept +{ + severity_ = severity; +} + +opentelemetry::logs::Severity ReadWriteLogRecord::GetSeverity() const noexcept +{ + return severity_; +} + +void ReadWriteLogRecord::SetBody(const opentelemetry::common::AttributeValue &message) noexcept +{ + body_ = message; +} + +const opentelemetry::common::AttributeValue &ReadWriteLogRecord::GetBody() const noexcept +{ + return body_; +} + +void ReadWriteLogRecord::SetTraceId(const opentelemetry::trace::TraceId &trace_id) noexcept +{ + if (!trace_state_) + { + trace_state_ = std::unique_ptr<TraceState>(new TraceState()); + } + + trace_state_->trace_id = trace_id; +} + +const opentelemetry::trace::TraceId &ReadWriteLogRecord::GetTraceId() const noexcept +{ + if (trace_state_) + { + return trace_state_->trace_id; + } + + static opentelemetry::trace::TraceId empty; + return empty; +} + +void ReadWriteLogRecord::SetSpanId(const opentelemetry::trace::SpanId &span_id) noexcept +{ + if (!trace_state_) + { + trace_state_ = std::unique_ptr<TraceState>(new TraceState()); + } + + trace_state_->span_id = span_id; +} + +const opentelemetry::trace::SpanId &ReadWriteLogRecord::GetSpanId() const noexcept +{ + if (trace_state_) + { + return trace_state_->span_id; + } + + static opentelemetry::trace::SpanId empty; + return empty; +} + +void ReadWriteLogRecord::SetTraceFlags(const opentelemetry::trace::TraceFlags &trace_flags) noexcept +{ + if (!trace_state_) + { + trace_state_ = std::unique_ptr<TraceState>(new TraceState()); + } + + trace_state_->trace_flags = trace_flags; +} + +const opentelemetry::trace::TraceFlags &ReadWriteLogRecord::GetTraceFlags() const noexcept +{ + if (trace_state_) + { + return trace_state_->trace_flags; + } + + static opentelemetry::trace::TraceFlags empty; + return empty; +} + +void ReadWriteLogRecord::SetAttribute(nostd::string_view key, + const opentelemetry::common::AttributeValue &value) noexcept +{ + attributes_map_[static_cast<std::string>(key)] = value; +} + +const std::unordered_map<std::string, opentelemetry::common::AttributeValue> + &ReadWriteLogRecord::GetAttributes() const noexcept +{ + return attributes_map_; +} + +const opentelemetry::sdk::resource::Resource &ReadWriteLogRecord::GetResource() const noexcept +{ + OPENTELEMETRY_LIKELY_IF(nullptr != resource_) { return *resource_; } + + return GetDefaultResource(); +} + +void ReadWriteLogRecord::SetResource( + const opentelemetry::sdk::resource::Resource &resource) noexcept +{ + resource_ = &resource; +} + +const opentelemetry::sdk::instrumentationscope::InstrumentationScope & +ReadWriteLogRecord::GetInstrumentationScope() const noexcept +{ + OPENTELEMETRY_LIKELY_IF(nullptr != instrumentation_scope_) { return *instrumentation_scope_; } + + return GetDefaultInstrumentationScope(); +} + +void ReadWriteLogRecord::SetInstrumentationScope( + const opentelemetry::sdk::instrumentationscope::InstrumentationScope + &instrumentation_scope) noexcept +{ + instrumentation_scope_ = &instrumentation_scope; +} +} // namespace logs +} // namespace sdk + +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/sdk/src/logs/readable_log_record.cc b/sdk/src/logs/readable_log_record.cc new file mode 100644 index 0000000000..9ed5ca7ae7 --- /dev/null +++ b/sdk/src/logs/readable_log_record.cc @@ -0,0 +1,51 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +#ifdef ENABLE_LOGS_PREVIEW + +# include <cstddef> +# include <type_traits> + +# include "opentelemetry/sdk/logs/readable_log_record.h" + +OPENTELEMETRY_BEGIN_NAMESPACE +namespace sdk +{ +namespace logs +{ + +nostd::string_view ReadableLogRecord::GetSeverityText() const noexcept +{ + std::size_t severity_index = static_cast<std::size_t>(GetSeverity()); + if (severity_index >= std::extent<decltype(opentelemetry::logs::SeverityNumToText)>::value) + { + return opentelemetry::logs::SeverityNumToText[0]; + } + + return opentelemetry::logs::SeverityNumToText[severity_index]; +} + +const opentelemetry::sdk::instrumentationscope::InstrumentationScope & +ReadableLogRecord::GetDefaultInstrumentationScope() noexcept +{ + // FIXME: Use shared default instrumentation scope? + static std::unique_ptr<opentelemetry::sdk::instrumentationscope::InstrumentationScope> + default_scope = opentelemetry::sdk::instrumentationscope::InstrumentationScope::Create( + "otel-cpp", OPENTELEMETRY_SDK_VERSION, "https://opentelemetry.io/schemas/1.15.0"); + return *default_scope; +} + +const opentelemetry::sdk::resource::Resource &ReadableLogRecord::GetDefaultResource() noexcept +{ + static opentelemetry::sdk::resource::Resource default_resource = + opentelemetry::sdk::resource::Resource::Create( + {}, GetDefaultInstrumentationScope().GetSchemaURL()); + + return default_resource; +} + +} // namespace logs +} // namespace sdk + +OPENTELEMETRY_END_NAMESPACE +#endif diff --git a/sdk/test/logs/batch_log_record_processor_test.cc b/sdk/test/logs/batch_log_record_processor_test.cc index bbf1fc3016..de3beb66fe 100644 --- a/sdk/test/logs/batch_log_record_processor_test.cc +++ b/sdk/test/logs/batch_log_record_processor_test.cc @@ -5,7 +5,7 @@ # include "opentelemetry/sdk/logs/batch_log_record_processor.h" # include "opentelemetry/sdk/logs/exporter.h" -# include "opentelemetry/sdk/logs/log_record.h" +# include "opentelemetry/sdk/logs/recordable.h" # include <gtest/gtest.h> # include <chrono> @@ -15,6 +15,53 @@ using namespace opentelemetry::sdk::logs; using namespace opentelemetry::sdk::common; +namespace nostd = opentelemetry::nostd; + +class MockLogRecordable final : public opentelemetry::sdk::logs::Recordable +{ +public: + void SetTimestamp(opentelemetry::common::SystemTimestamp) noexcept override {} + + void SetObservedTimestamp(opentelemetry::common::SystemTimestamp) noexcept override {} + + void SetSeverity(opentelemetry::logs::Severity) noexcept override {} + + nostd::string_view GetBody() const noexcept { return body_; } + + void SetBody(const opentelemetry::common::AttributeValue &message) noexcept override + { + if (nostd::holds_alternative<const char *>(message)) + { + body_ = nostd::get<const char *>(message); + } + else if (nostd::holds_alternative<nostd::string_view>(message)) + { + body_ = static_cast<std::string>(nostd::get<nostd::string_view>(message)); + } + } + + void SetBody(const std::string &message) noexcept { body_ = message; } + + void SetTraceId(const opentelemetry::trace::TraceId &) noexcept override {} + + void SetSpanId(const opentelemetry::trace::SpanId &) noexcept override {} + + void SetTraceFlags(const opentelemetry::trace::TraceFlags &) noexcept override {} + + void SetAttribute(nostd::string_view, + const opentelemetry::common::AttributeValue &) noexcept override + {} + + void SetResource(const opentelemetry::sdk::resource::Resource &) noexcept override {} + + void SetInstrumentationScope( + const opentelemetry::sdk::instrumentationscope::InstrumentationScope &) noexcept override + {} + +private: + std::string body_; +}; + /** * A sample log exporter * for testing the batch log processor @@ -22,7 +69,7 @@ using namespace opentelemetry::sdk::common; class MockLogExporter final : public LogRecordExporter { public: - MockLogExporter(std::shared_ptr<std::vector<std::unique_ptr<LogRecord>>> logs_received, + MockLogExporter(std::shared_ptr<std::vector<std::unique_ptr<MockLogRecordable>>> logs_received, std::shared_ptr<std::atomic<bool>> is_shutdown, std::shared_ptr<std::atomic<bool>> is_export_completed, const std::chrono::milliseconds export_delay = std::chrono::milliseconds(0)) @@ -34,7 +81,7 @@ class MockLogExporter final : public LogRecordExporter std::unique_ptr<Recordable> MakeRecordable() noexcept override { - return std::unique_ptr<Recordable>(new LogRecord()); + return std::unique_ptr<Recordable>(new MockLogRecordable()); } // Export method stores the logs received into a shared list of record names @@ -45,13 +92,19 @@ class MockLogExporter final : public LogRecordExporter for (auto &record : records) { - auto log = std::unique_ptr<LogRecord>(static_cast<LogRecord *>(record.release())); + auto log = + std::unique_ptr<MockLogRecordable>(static_cast<MockLogRecordable *>(record.release())); if (log != nullptr) { logs_received_->push_back(std::move(log)); } } + if (export_delay_ > std::chrono::milliseconds::zero()) + { + std::this_thread::sleep_for(export_delay_); + } + *is_export_completed_ = true; return ExportResult::kSuccess; } @@ -64,7 +117,7 @@ class MockLogExporter final : public LogRecordExporter } private: - std::shared_ptr<std::vector<std::unique_ptr<LogRecord>>> logs_received_; + std::shared_ptr<std::vector<std::unique_ptr<MockLogRecordable>>> logs_received_; std::shared_ptr<std::atomic<bool>> is_shutdown_; std::shared_ptr<std::atomic<bool>> is_export_completed_; const std::chrono::milliseconds export_delay_; @@ -80,7 +133,7 @@ class BatchLogRecordProcessorTest : public testing::Test // ::testing::Test // returns a batch log processor that received a batch of log records, a shared pointer to a // is_shutdown flag, and the processor configuration options (default if unspecified) std::shared_ptr<LogRecordProcessor> GetMockProcessor( - std::shared_ptr<std::vector<std::unique_ptr<LogRecord>>> logs_received, + std::shared_ptr<std::vector<std::unique_ptr<MockLogRecordable>>> logs_received, std::shared_ptr<std::atomic<bool>> is_shutdown, std::shared_ptr<std::atomic<bool>> is_export_completed = std::shared_ptr<std::atomic<bool>>(new std::atomic<bool>(false)), @@ -99,8 +152,8 @@ class BatchLogRecordProcessorTest : public testing::Test // ::testing::Test TEST_F(BatchLogRecordProcessorTest, TestShutdown) { // initialize a batch log processor with the test exporter - std::shared_ptr<std::vector<std::unique_ptr<LogRecord>>> logs_received( - new std::vector<std::unique_ptr<LogRecord>>); + std::shared_ptr<std::vector<std::unique_ptr<MockLogRecordable>>> logs_received( + new std::vector<std::unique_ptr<MockLogRecordable>>); std::shared_ptr<std::atomic<bool>> is_shutdown(new std::atomic<bool>(false)); auto batch_processor = GetMockProcessor(logs_received, is_shutdown); @@ -111,7 +164,7 @@ TEST_F(BatchLogRecordProcessorTest, TestShutdown) for (int i = 0; i < num_logs; ++i) { auto log = batch_processor->MakeRecordable(); - log->SetBody("Log" + std::to_string(i)); + static_cast<MockLogRecordable *>(log.get())->SetBody("Log" + std::to_string(i)); batch_processor->OnEmit(std::move(log)); } @@ -137,8 +190,8 @@ TEST_F(BatchLogRecordProcessorTest, TestShutdown) TEST_F(BatchLogRecordProcessorTest, TestForceFlush) { std::shared_ptr<std::atomic<bool>> is_shutdown(new std::atomic<bool>(false)); - std::shared_ptr<std::vector<std::unique_ptr<LogRecord>>> logs_received( - new std::vector<std::unique_ptr<LogRecord>>); + std::shared_ptr<std::vector<std::unique_ptr<MockLogRecordable>>> logs_received( + new std::vector<std::unique_ptr<MockLogRecordable>>); auto batch_processor = GetMockProcessor(logs_received, is_shutdown); const int num_logs = 2048; @@ -146,7 +199,7 @@ TEST_F(BatchLogRecordProcessorTest, TestForceFlush) for (int i = 0; i < num_logs; ++i) { auto log = batch_processor->MakeRecordable(); - log->SetBody("Log" + std::to_string(i)); + static_cast<MockLogRecordable *>(log.get())->SetBody("Log" + std::to_string(i)); batch_processor->OnEmit(std::move(log)); } @@ -162,7 +215,7 @@ TEST_F(BatchLogRecordProcessorTest, TestForceFlush) for (int i = 0; i < num_logs; ++i) { auto log = batch_processor->MakeRecordable(); - log->SetBody("Log" + std::to_string(i)); + static_cast<MockLogRecordable *>(log.get())->SetBody("Log" + std::to_string(i)); batch_processor->OnEmit(std::move(log)); } @@ -180,8 +233,8 @@ TEST_F(BatchLogRecordProcessorTest, TestManyLogsLoss) /* Test that when exporting more than max_queue_size logs, some are most likely lost*/ std::shared_ptr<std::atomic<bool>> is_shutdown(new std::atomic<bool>(false)); - std::shared_ptr<std::vector<std::unique_ptr<LogRecord>>> logs_received( - new std::vector<std::unique_ptr<LogRecord>>); + std::shared_ptr<std::vector<std::unique_ptr<MockLogRecordable>>> logs_received( + new std::vector<std::unique_ptr<MockLogRecordable>>); const int max_queue_size = 4096; @@ -191,7 +244,7 @@ TEST_F(BatchLogRecordProcessorTest, TestManyLogsLoss) for (int i = 0; i < max_queue_size; ++i) { auto log = batch_processor->MakeRecordable(); - log->SetBody("Log" + std::to_string(i)); + static_cast<MockLogRecordable *>(log.get())->SetBody("Log" + std::to_string(i)); batch_processor->OnEmit(std::move(log)); } @@ -206,8 +259,8 @@ TEST_F(BatchLogRecordProcessorTest, TestManyLogsLossLess) /* Test that no logs are lost when sending max_queue_size logs */ std::shared_ptr<std::atomic<bool>> is_shutdown(new std::atomic<bool>(false)); - std::shared_ptr<std::vector<std::unique_ptr<LogRecord>>> logs_received( - new std::vector<std::unique_ptr<LogRecord>>); + std::shared_ptr<std::vector<std::unique_ptr<MockLogRecordable>>> logs_received( + new std::vector<std::unique_ptr<MockLogRecordable>>); auto batch_processor = GetMockProcessor(logs_received, is_shutdown); const int num_logs = 2048; @@ -215,7 +268,7 @@ TEST_F(BatchLogRecordProcessorTest, TestManyLogsLossLess) for (int i = 0; i < num_logs; ++i) { auto log = batch_processor->MakeRecordable(); - log->SetBody("Log" + std::to_string(i)); + static_cast<MockLogRecordable *>(log.get())->SetBody("Log" + std::to_string(i)); batch_processor->OnEmit(std::move(log)); } @@ -235,8 +288,8 @@ TEST_F(BatchLogRecordProcessorTest, TestScheduledDelayMillis) std::shared_ptr<std::atomic<bool>> is_shutdown(new std::atomic<bool>(false)); std::shared_ptr<std::atomic<bool>> is_export_completed(new std::atomic<bool>(false)); - std::shared_ptr<std::vector<std::unique_ptr<LogRecord>>> logs_received( - new std::vector<std::unique_ptr<LogRecord>>); + std::shared_ptr<std::vector<std::unique_ptr<MockLogRecordable>>> logs_received( + new std::vector<std::unique_ptr<MockLogRecordable>>); const std::chrono::milliseconds export_delay(0); const std::chrono::milliseconds scheduled_delay_millis(2000); @@ -248,7 +301,7 @@ TEST_F(BatchLogRecordProcessorTest, TestScheduledDelayMillis) for (std::size_t i = 0; i < max_export_batch_size; ++i) { auto log = batch_processor->MakeRecordable(); - log->SetBody("Log" + std::to_string(i)); + static_cast<MockLogRecordable *>(log.get())->SetBody("Log" + std::to_string(i)); batch_processor->OnEmit(std::move(log)); } // Sleep for scheduled_delay_millis milliseconds @@ -257,7 +310,7 @@ TEST_F(BatchLogRecordProcessorTest, TestScheduledDelayMillis) // small delay to give time to export, which is being performed // asynchronously by the worker thread (this thread will not // forcibly join() the main thread unless processor's shutdown() is called). - std::this_thread::sleep_for(std::chrono::milliseconds(50)); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); // Logs should be exported by now EXPECT_TRUE(is_export_completed->load()); diff --git a/sdk/test/logs/log_record_test.cc b/sdk/test/logs/log_record_test.cc index 89b07473a3..3ad3acaca5 100644 --- a/sdk/test/logs/log_record_test.cc +++ b/sdk/test/logs/log_record_test.cc @@ -3,28 +3,27 @@ #ifdef ENABLE_LOGS_PREVIEW -# include "opentelemetry/sdk/logs/log_record.h" # include "opentelemetry/nostd/variant.h" +# include "opentelemetry/sdk/logs/read_write_log_record.h" # include "opentelemetry/trace/span_id.h" # include "opentelemetry/trace/trace_id.h" # include <gtest/gtest.h> -using opentelemetry::sdk::logs::LogRecord; +using opentelemetry::sdk::logs::ReadWriteLogRecord; namespace trace_api = opentelemetry::trace; namespace logs_api = opentelemetry::logs; namespace nostd = opentelemetry::nostd; -// Test what a default LogRecord with no fields set holds -TEST(LogRecord, GetDefaultValues) +// Test what a default ReadWriteLogRecord with no fields set holds +TEST(ReadWriteLogRecord, GetDefaultValues) { trace_api::TraceId zero_trace_id; trace_api::SpanId zero_span_id; trace_api::TraceFlags zero_trace_flags; - LogRecord record; + ReadWriteLogRecord record; ASSERT_EQ(record.GetSeverity(), logs_api::Severity::kInvalid); - ASSERT_EQ(record.GetBody(), ""); ASSERT_NE(record.GetResource().GetAttributes().size(), 0); ASSERT_EQ(record.GetAttributes().size(), 0); ASSERT_EQ(record.GetTraceId(), zero_trace_id); @@ -33,16 +32,16 @@ TEST(LogRecord, GetDefaultValues) ASSERT_EQ(record.GetTimestamp().time_since_epoch(), std::chrono::nanoseconds(0)); } -// Test LogRecord fields are properly set and get -TEST(LogRecord, SetAndGet) +// Test ReadWriteLogRecord fields are properly set and get +TEST(ReadWriteLogRecord, SetAndGet) { trace_api::TraceId trace_id; trace_api::SpanId span_id; trace_api::TraceFlags trace_flags; opentelemetry::common::SystemTimestamp now(std::chrono::system_clock::now()); - // Set all fields of the LogRecord - LogRecord record; + // Set most fields of the ReadWriteLogRecord + ReadWriteLogRecord record; auto resource = opentelemetry::sdk::resource::Resource::Create({{"res1", true}}); record.SetSeverity(logs_api::Severity::kInvalid); record.SetBody("Message"); @@ -55,7 +54,14 @@ TEST(LogRecord, SetAndGet) // Test that all fields match what was set ASSERT_EQ(record.GetSeverity(), logs_api::Severity::kInvalid); - ASSERT_EQ(record.GetBody(), "Message"); + if (nostd::holds_alternative<const char *>(record.GetBody())) + { + ASSERT_EQ(std::string(nostd::get<const char *>(record.GetBody())), "Message"); + } + else if (nostd::holds_alternative<nostd::string_view>(record.GetBody())) + { + ASSERT_TRUE(nostd::get<nostd::string_view>(record.GetBody()) == "Message"); + } ASSERT_TRUE(nostd::get<bool>(record.GetResource().GetAttributes().at("res1"))); ASSERT_EQ(nostd::get<int64_t>(record.GetAttributes().at("attr1")), 314159); ASSERT_EQ(record.GetTraceId(), trace_id); diff --git a/sdk/test/logs/logger_provider_sdk_test.cc b/sdk/test/logs/logger_provider_sdk_test.cc index 4f517f8fd4..9339560377 100644 --- a/sdk/test/logs/logger_provider_sdk_test.cc +++ b/sdk/test/logs/logger_provider_sdk_test.cc @@ -7,9 +7,9 @@ # include "opentelemetry/logs/provider.h" # include "opentelemetry/nostd/shared_ptr.h" # include "opentelemetry/nostd/string_view.h" -# include "opentelemetry/sdk/logs/log_record.h" # include "opentelemetry/sdk/logs/logger.h" # include "opentelemetry/sdk/logs/logger_provider.h" +# include "opentelemetry/sdk/logs/recordable.h" # include "opentelemetry/sdk/logs/simple_log_record_processor.h" # include <gtest/gtest.h> @@ -79,11 +79,39 @@ TEST(LoggerProviderSDK, LoggerProviderLoggerArguments) ASSERT_EQ(sdk_logger2->GetInstrumentationScope(), sdk_logger1->GetInstrumentationScope()); } +class DummyLogRecordable final : public opentelemetry::sdk::logs::Recordable +{ +public: + void SetTimestamp(opentelemetry::common::SystemTimestamp) noexcept override {} + + void SetObservedTimestamp(opentelemetry::common::SystemTimestamp) noexcept override {} + + void SetSeverity(opentelemetry::logs::Severity) noexcept override {} + + void SetBody(const opentelemetry::common::AttributeValue &) noexcept override {} + + void SetTraceId(const opentelemetry::trace::TraceId &) noexcept override {} + + void SetSpanId(const opentelemetry::trace::SpanId &) noexcept override {} + + void SetTraceFlags(const opentelemetry::trace::TraceFlags &) noexcept override {} + + void SetAttribute(nostd::string_view, + const opentelemetry::common::AttributeValue &) noexcept override + {} + + void SetResource(const opentelemetry::sdk::resource::Resource &) noexcept override {} + + void SetInstrumentationScope( + const opentelemetry::sdk::instrumentationscope::InstrumentationScope &) noexcept override + {} +}; + class DummyProcessor : public LogRecordProcessor { std::unique_ptr<Recordable> MakeRecordable() noexcept override { - return std::unique_ptr<Recordable>(new LogRecord); + return std::unique_ptr<Recordable>(new DummyLogRecordable()); } void OnEmit(std::unique_ptr<Recordable> && /* record */) noexcept override {} diff --git a/sdk/test/logs/logger_sdk_test.cc b/sdk/test/logs/logger_sdk_test.cc index 478d874b8e..b6b597a887 100644 --- a/sdk/test/logs/logger_sdk_test.cc +++ b/sdk/test/logs/logger_sdk_test.cc @@ -3,13 +3,18 @@ #ifdef ENABLE_LOGS_PREVIEW -# include "opentelemetry/sdk/logs/log_record.h" +# include <string> + +# include "opentelemetry/nostd/string_view.h" +# include "opentelemetry/nostd/variant.h" # include "opentelemetry/sdk/logs/logger.h" +# include "opentelemetry/sdk/logs/recordable.h" # include <gtest/gtest.h> using namespace opentelemetry::sdk::logs; namespace logs_api = opentelemetry::logs; +namespace nostd = opentelemetry::nostd; TEST(LoggerSDK, LogToNullProcessor) { @@ -29,34 +34,87 @@ TEST(LoggerSDK, LogToNullProcessor) logger->Debug("Test log"); } +class MockLogRecordable final : public opentelemetry::sdk::logs::Recordable +{ +public: + void SetTimestamp(opentelemetry::common::SystemTimestamp) noexcept override {} + + void SetObservedTimestamp(opentelemetry::common::SystemTimestamp) noexcept override {} + + opentelemetry::logs::Severity GetSeverity() const noexcept { return severity_; } + + void SetSeverity(opentelemetry::logs::Severity severity) noexcept override + { + severity_ = severity; + } + + nostd::string_view GetBody() const noexcept { return body_; } + + void SetBody(const opentelemetry::common::AttributeValue &message) noexcept override + { + if (nostd::holds_alternative<const char *>(message)) + { + body_ = nostd::get<const char *>(message); + } + else if (nostd::holds_alternative<nostd::string_view>(message)) + { + body_ = static_cast<std::string>(nostd::get<nostd::string_view>(message)); + } + } + + void SetBody(const std::string &message) noexcept { body_ = message; } + + void SetTraceId(const opentelemetry::trace::TraceId &) noexcept override {} + + void SetSpanId(const opentelemetry::trace::SpanId &) noexcept override {} + + void SetTraceFlags(const opentelemetry::trace::TraceFlags &) noexcept override {} + + void SetAttribute(nostd::string_view, + const opentelemetry::common::AttributeValue &) noexcept override + {} + + void SetResource(const opentelemetry::sdk::resource::Resource &) noexcept override {} + + void SetInstrumentationScope( + const opentelemetry::sdk::instrumentationscope::InstrumentationScope &) noexcept override + {} + +private: + opentelemetry::logs::Severity severity_ = opentelemetry::logs::Severity::kInvalid; + std::string body_; +}; + class MockProcessor final : public LogRecordProcessor { private: - std::shared_ptr<LogRecord> record_received_; + std::shared_ptr<MockLogRecordable> record_received_; public: // A processor used for testing that keeps a track of the recordable it received - explicit MockProcessor(std::shared_ptr<LogRecord> record_received) noexcept + explicit MockProcessor(std::shared_ptr<MockLogRecordable> record_received) noexcept : record_received_(record_received) {} - std::unique_ptr<Recordable> MakeRecordable() noexcept override + std::unique_ptr<opentelemetry::sdk::logs::Recordable> MakeRecordable() noexcept override { - return std::unique_ptr<Recordable>(new LogRecord); + return std::unique_ptr<opentelemetry::sdk::logs::Recordable>(new MockLogRecordable()); } // OnEmit stores the record it receives into the shared_ptr recordable passed into its // constructor - void OnEmit(std::unique_ptr<Recordable> &&record) noexcept override + void OnEmit(std::unique_ptr<opentelemetry::sdk::logs::Recordable> &&record) noexcept override { - // Cast the recordable received into a concrete LogRecord type - auto copy = std::shared_ptr<LogRecord>(static_cast<LogRecord *>(record.release())); + // Cast the recordable received into a concrete MockLogRecordable type + auto copy = + std::shared_ptr<MockLogRecordable>(static_cast<MockLogRecordable *>(record.release())); // 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()); } + bool ForceFlush(std::chrono::microseconds /* timeout */) noexcept override { return true; } bool Shutdown(std::chrono::microseconds /* timeout */) noexcept override { return true; } }; @@ -80,8 +138,9 @@ TEST(LoggerSDK, LogToAProcessor) 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<LogRecord>(new LogRecord()); - lp->AddProcessor(std::unique_ptr<LogRecordProcessor>(new MockProcessor(shared_recordable))); + auto shared_recordable = std::shared_ptr<MockLogRecordable>(new MockLogRecordable()); + lp->AddProcessor(std::unique_ptr<opentelemetry::sdk::logs::LogRecordProcessor>( + new MockProcessor(shared_recordable))); // Check that the recordable created by the Log() statement is set properly logger->Log(logs_api::Severity::kWarn, "Log Message"); diff --git a/sdk/test/logs/simple_log_record_processor_test.cc b/sdk/test/logs/simple_log_record_processor_test.cc index 47b16eab7e..275991dc10 100644 --- a/sdk/test/logs/simple_log_record_processor_test.cc +++ b/sdk/test/logs/simple_log_record_processor_test.cc @@ -6,7 +6,7 @@ # include "opentelemetry/sdk/logs/simple_log_record_processor.h" # include "opentelemetry/nostd/span.h" # include "opentelemetry/sdk/logs/exporter.h" -# include "opentelemetry/sdk/logs/log_record.h" +# include "opentelemetry/sdk/logs/recordable.h" # include <gtest/gtest.h> @@ -17,6 +17,51 @@ using namespace opentelemetry::sdk::logs; using namespace opentelemetry::sdk::common; namespace nostd = opentelemetry::nostd; +class TestLogRecordable final : public opentelemetry::sdk::logs::Recordable +{ +public: + void SetTimestamp(opentelemetry::common::SystemTimestamp) noexcept override {} + + void SetObservedTimestamp(opentelemetry::common::SystemTimestamp) noexcept override {} + + void SetSeverity(opentelemetry::logs::Severity) noexcept override {} + + nostd::string_view GetBody() const noexcept { return body_; } + + void SetBody(const opentelemetry::common::AttributeValue &message) noexcept override + { + if (nostd::holds_alternative<const char *>(message)) + { + body_ = nostd::get<const char *>(message); + } + else if (nostd::holds_alternative<nostd::string_view>(message)) + { + body_ = static_cast<std::string>(nostd::get<nostd::string_view>(message)); + } + } + + void SetBody(const char *message) noexcept { body_ = message; } + + void SetTraceId(const opentelemetry::trace::TraceId &) noexcept override {} + + void SetSpanId(const opentelemetry::trace::SpanId &) noexcept override {} + + void SetTraceFlags(const opentelemetry::trace::TraceFlags &) noexcept override {} + + void SetAttribute(nostd::string_view, + const opentelemetry::common::AttributeValue &) noexcept override + {} + + void SetResource(const opentelemetry::sdk::resource::Resource &) noexcept override {} + + void SetInstrumentationScope( + const opentelemetry::sdk::instrumentationscope::InstrumentationScope &) noexcept override + {} + +private: + std::string body_; +}; + /* * A test exporter that can return a vector of all the records it has received, * and keep track of the number of times its Shutdown() function was called. @@ -25,7 +70,7 @@ class TestExporter final : public LogRecordExporter { public: TestExporter(int *shutdown_counter, - std::shared_ptr<std::vector<std::unique_ptr<LogRecord>>> logs_received, + std::shared_ptr<std::vector<std::unique_ptr<TestLogRecordable>>> logs_received, size_t *batch_size_received) : shutdown_counter_(shutdown_counter), logs_received_(logs_received), @@ -34,7 +79,7 @@ class TestExporter final : public LogRecordExporter std::unique_ptr<Recordable> MakeRecordable() noexcept override { - return std::unique_ptr<Recordable>(new LogRecord()); + return std::unique_ptr<Recordable>(new TestLogRecordable()); } // Stores the names of the log records this exporter receives to an internal list @@ -43,7 +88,8 @@ class TestExporter final : public LogRecordExporter *batch_size_received = records.size(); for (auto &record : records) { - auto log_record = std::unique_ptr<LogRecord>(static_cast<LogRecord *>(record.release())); + auto log_record = + std::unique_ptr<TestLogRecordable>(static_cast<TestLogRecordable *>(record.release())); if (log_record != nullptr) { @@ -62,7 +108,7 @@ class TestExporter final : public LogRecordExporter private: int *shutdown_counter_; - std::shared_ptr<std::vector<std::unique_ptr<LogRecord>>> logs_received_; + std::shared_ptr<std::vector<std::unique_ptr<TestLogRecordable>>> logs_received_; size_t *batch_size_received; }; @@ -71,8 +117,8 @@ class TestExporter final : public LogRecordExporter TEST(SimpleLogRecordProcessorTest, SendReceivedLogsToExporter) { // Create a simple processor with a TestExporter attached - std::shared_ptr<std::vector<std::unique_ptr<LogRecord>>> logs_received( - new std::vector<std::unique_ptr<LogRecord>>); + std::shared_ptr<std::vector<std::unique_ptr<TestLogRecordable>>> logs_received( + new std::vector<std::unique_ptr<TestLogRecordable>>); size_t batch_size_received = 0; std::unique_ptr<TestExporter> exporter( @@ -85,7 +131,7 @@ TEST(SimpleLogRecordProcessorTest, SendReceivedLogsToExporter) for (int i = 0; i < num_logs; i++) { auto recordable = processor.MakeRecordable(); - recordable->SetBody("Log Body"); + static_cast<TestLogRecordable *>(recordable.get())->SetBody("Log Body"); processor.OnEmit(std::move(recordable)); // Verify that the batch of 1 log record sent by processor matches what exporter received @@ -129,7 +175,7 @@ class FailShutDownExporter final : public LogRecordExporter std::unique_ptr<Recordable> MakeRecordable() noexcept override { - return std::unique_ptr<Recordable>(new LogRecord()); + return std::unique_ptr<Recordable>(new TestLogRecordable()); } ExportResult Export(