diff --git a/CHANGELOG.md b/CHANGELOG.md index e9d33a21fe..aaef8a94f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Increment the: ## [Unreleased] +* [API/SDK] Logger: Support for Instrumentation library ([#1128](https://github.com/open-telemetry/opentelemetry-cpp/pull/1128)) * [SDK] Add LogLevel to internal_log ([#1147](https://github.com/open-telemetry/opentelemetry-cpp/pull/1147)) * [API/SDK] Logger: Propagating resources through LoggerProvider ([#1154](https://github.com/open-telemetry/opentelemetry-cpp/pull/1154)) * [API]: Allow to use external abseil for bazel targets ([#1172](https://github.com/open-telemetry/opentelemetry-cpp/pull/1172)) diff --git a/api/include/opentelemetry/logs/logger_provider.h b/api/include/opentelemetry/logs/logger_provider.h index 93ba683f94..5f1795c8ea 100644 --- a/api/include/opentelemetry/logs/logger_provider.h +++ b/api/include/opentelemetry/logs/logger_provider.h @@ -31,10 +31,16 @@ class LoggerProvider */ virtual nostd::shared_ptr GetLogger(nostd::string_view logger_name, - nostd::string_view options = "") = 0; + nostd::string_view options, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") = 0; virtual nostd::shared_ptr GetLogger(nostd::string_view logger_name, - nostd::span args) = 0; + nostd::span args, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") = 0; }; } // namespace logs OPENTELEMETRY_END_NAMESPACE diff --git a/api/include/opentelemetry/logs/noop.h b/api/include/opentelemetry/logs/noop.h index 571c5cdbf8..8186fb8c76 100644 --- a/api/include/opentelemetry/logs/noop.h +++ b/api/include/opentelemetry/logs/noop.h @@ -64,13 +64,19 @@ class NoopLoggerProvider final : public opentelemetry::logs::LoggerProvider {} nostd::shared_ptr GetLogger(nostd::string_view logger_name, - nostd::string_view options) override + nostd::string_view options, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") override { return logger_; } nostd::shared_ptr GetLogger(nostd::string_view logger_name, - nostd::span args) override + nostd::span args, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") override { return logger_; } diff --git a/api/test/logs/logger_test.cc b/api/test/logs/logger_test.cc index dad5cac7f6..b2d2d1d60a 100644 --- a/api/test/logs/logger_test.cc +++ b/api/test/logs/logger_test.cc @@ -25,8 +25,9 @@ namespace trace = opentelemetry::trace; // Check that the default logger is a noop logger instance TEST(Logger, GetLoggerDefault) { - auto lp = Provider::GetLoggerProvider(); - auto logger = lp->GetLogger("TestLogger"); + auto lp = Provider::GetLoggerProvider(); + const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; + auto logger = lp->GetLogger("TestLogger", "", "opentelelemtry_library", "", schema_url); auto name = logger->GetName(); EXPECT_NE(nullptr, logger); EXPECT_EQ(name, "noop logger"); @@ -40,17 +41,19 @@ TEST(Logger, GetNoopLoggerNameWithArgs) // GetLogger(name, list(args)) std::array sv{"string"}; span args{sv}; - lp->GetLogger("NoopLoggerWithArgs", args); + const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; + lp->GetLogger("NoopLoggerWithArgs", args, "opentelelemtry_library", "", schema_url); // GetLogger(name, string options) - lp->GetLogger("NoopLoggerWithOptions", "options"); + lp->GetLogger("NoopLoggerWithOptions", "options", "opentelelemtry_library", "", schema_url); } // Test the Log() overloads TEST(Logger, LogMethodOverloads) { - auto lp = Provider::GetLoggerProvider(); - auto logger = lp->GetLogger("TestLogger"); + auto lp = Provider::GetLoggerProvider(); + const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; + auto logger = lp->GetLogger("TestLogger", "", "opentelelemtry_library", "", schema_url); // Create a map to test the logs with std::map m = {{"key1", "value1"}}; @@ -91,12 +94,20 @@ class TestLogger : public Logger // Define a basic LoggerProvider class that returns an instance of the logger class defined above class TestProvider : public LoggerProvider { - shared_ptr GetLogger(string_view library_name, string_view options = "") override + nostd::shared_ptr GetLogger(nostd::string_view logger_name, + nostd::string_view options, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") override { return shared_ptr(new TestLogger()); } - shared_ptr GetLogger(string_view library_name, span args) override + nostd::shared_ptr GetLogger(nostd::string_view logger_name, + nostd::span args, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") override { return shared_ptr(new TestLogger()); } @@ -111,7 +122,8 @@ TEST(Logger, PushLoggerImplementation) auto lp = Provider::GetLoggerProvider(); // Check that the implementation was pushed by calling TestLogger's GetName() - auto logger = lp->GetLogger("TestLogger"); + nostd::string_view schema_url{"https://opentelemetry.io/schemas/1.2.0"}; + auto logger = lp->GetLogger("TestLogger", "", "opentelelemtry_library", "", schema_url); ASSERT_EQ("test logger", logger->GetName()); } #endif diff --git a/api/test/logs/provider_test.cc b/api/test/logs/provider_test.cc index c9eb7bddc7..64a6b0a86a 100644 --- a/api/test/logs/provider_test.cc +++ b/api/test/logs/provider_test.cc @@ -8,24 +8,29 @@ # include "opentelemetry/logs/provider.h" # include "opentelemetry/nostd/shared_ptr.h" -# include "opentelemetry/nostd/span.h" -# include "opentelemetry/nostd/string_view.h" using opentelemetry::logs::Logger; using opentelemetry::logs::LoggerProvider; using opentelemetry::logs::Provider; using opentelemetry::nostd::shared_ptr; -using opentelemetry::nostd::span; -using opentelemetry::nostd::string_view; +namespace nostd = opentelemetry::nostd; class TestProvider : public LoggerProvider { - shared_ptr GetLogger(string_view library_name, string_view options) override + nostd::shared_ptr GetLogger(nostd::string_view logger_name, + nostd::string_view options, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") override { return shared_ptr(nullptr); } - shared_ptr GetLogger(string_view library_name, span args) override + nostd::shared_ptr GetLogger(nostd::string_view logger_name, + nostd::span args, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") override { return shared_ptr(nullptr); } @@ -57,15 +62,16 @@ TEST(Provider, MultipleLoggerProviders) TEST(Provider, GetLogger) { auto tf = shared_ptr(new TestProvider()); - // tests GetLogger(name, options) - auto logger = tf->GetLogger("logger1"); + // tests GetLogger(name, version, schema) + const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; + auto logger = tf->GetLogger("logger1", "", "opentelelemtry_library", "", schema_url); EXPECT_EQ(nullptr, logger); // tests GetLogger(name, arguments) - std::array sv{"string"}; - span args{sv}; - auto logger2 = tf->GetLogger("logger2", args); + std::array sv{"string"}; + nostd::span args{sv}; + auto logger2 = tf->GetLogger("logger2", args, "opentelelemtry_library", "", schema_url); EXPECT_EQ(nullptr, logger2); } #endif diff --git a/examples/common/logs_foo_library/foo_library.cc b/examples/common/logs_foo_library/foo_library.cc index 7c545f2d1a..2ae5ccfaf6 100644 --- a/examples/common/logs_foo_library/foo_library.cc +++ b/examples/common/logs_foo_library/foo_library.cc @@ -22,7 +22,7 @@ nostd::shared_ptr get_tracer() nostd::shared_ptr get_logger() { auto provider = logs::Provider::GetLoggerProvider(); - return provider->GetLogger("foo_library_logger"); + return provider->GetLogger("foo_library_logger", "", "foo_library"); } } // namespace diff --git a/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_recordable.h b/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_recordable.h old mode 100644 new mode 100755 index 45dbb63ae8..7cc552d2d4 --- a/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_recordable.h +++ b/exporters/elasticsearch/include/opentelemetry/exporters/elasticsearch/es_log_recordable.h @@ -205,7 +205,29 @@ class ElasticSearchRecordable final : public sdk::logs::Recordable /** * Returns a JSON object contain the log information */ - nlohmann::json GetJSON() noexcept { return json_; }; + nlohmann::json GetJSON() noexcept { return json_; } + + /** + * Set instrumentation_library for this log. + * @param instrumentation_library the instrumentation library to set + */ + void SetInstrumentationLibrary( + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + &instrumentation_library) noexcept + { + instrumentation_library_ = &instrumentation_library; + } + + /** Returns the associated instruementation library */ + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary & + GetInstrumentationLibrary() const noexcept + { + return *instrumentation_library_; + } + +private: + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + *instrumentation_library_ = nullptr; }; } // namespace logs } // namespace exporter diff --git a/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h b/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h index 5acd92f3f0..6f3a394b0d 100644 --- a/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h +++ b/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h @@ -221,31 +221,49 @@ class LoggerProvider : public opentelemetry::logs::LoggerProvider config_.encoding = ETWProvider::EventFormat::ETW_MANIFEST; } + nostd::shared_ptr GetLogger( + nostd::string_view logger_name, + nostd::string_view options, + nostd::string_view library_name, + nostd::string_view version = "", + nostd::string_view schema_url = "") override + { + UNREFERENCED_PARAMETER(options); + UNREFERENCED_PARAMETER(library_name); + UNREFERENCED_PARAMETER(version); + UNREFERENCED_PARAMETER(schema_url); + ETWProvider::EventFormat evtFmt = config_.encoding; + return nostd::shared_ptr{ + new (std::nothrow) etw::Logger(*this, logger_name, evtFmt)}; + } + /** * @brief Obtain ETW Tracer. * @param name ProviderId (instrumentation name) - Name or GUID - * * @param args Additional arguments that controls `codec` of the provider. * Possible values are: * - "ETW" - 'classic' Trace Logging Dynamic manifest ETW events. * - "MSGPACK" - MessagePack-encoded binary payload ETW events. * - "XML" - XML events (reserved for future use) + * @param library_name Library name + * @param version Library version + * @param schema_url schema URL * @return */ - nostd::shared_ptr GetLogger(nostd::string_view name, - nostd::string_view args = "") override + nostd::shared_ptr GetLogger( + nostd::string_view logger_name, + nostd::span args, + nostd::string_view library_name, + nostd::string_view version = "", + nostd::string_view schema_url = "") override { UNREFERENCED_PARAMETER(args); + UNREFERENCED_PARAMETER(library_name); + UNREFERENCED_PARAMETER(version); + UNREFERENCED_PARAMETER(schema_url); ETWProvider::EventFormat evtFmt = config_.encoding; - return nostd::shared_ptr{new (std::nothrow) - etw::Logger(*this, name, evtFmt)}; - } - - nostd::shared_ptr GetLogger( - nostd::string_view name, - nostd::span args) override - { - return GetLogger(name, args[0]); + return nostd::shared_ptr{ + new (std::nothrow) etw::Logger(*this, logger_name, evtFmt)}; } }; diff --git a/exporters/etw/test/etw_logger_test.cc b/exporters/etw/test/etw_logger_test.cc index 419e4ad0da..e4cf53ee34 100644 --- a/exporters/etw/test/etw_logger_test.cc +++ b/exporters/etw/test/etw_logger_test.cc @@ -48,7 +48,8 @@ TEST(ETWLogger, LoggerCheckWithBody) std::string providerName = kGlobalProviderName; // supply unique instrumentation name here exporter::etw::LoggerProvider lp; - auto logger = lp.GetLogger(providerName); + const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; + auto logger = lp.GetLogger(providerName, "", schema_url); Properties attribs = {{"attrib1", 1}, {"attrib2", 2}}; EXPECT_NO_THROW( logger->Log(opentelemetry::logs::Severity::kDebug, "My Log", "This is test log body")); @@ -90,7 +91,8 @@ TEST(ETWLogger, LoggerCheckWithAttributes) std::string providerName = kGlobalProviderName; // supply unique instrumentation name here exporter::etw::LoggerProvider lp; - auto logger = lp.GetLogger(providerName); + const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; + auto logger = lp.GetLogger(providerName, "", schema_url); // Log attributes Properties attribs = {{"attrib1", 1}, {"attrib2", 2}}; EXPECT_NO_THROW(logger->Log(opentelemetry::logs::Severity::kDebug, "My Log", attribs)); diff --git a/exporters/ostream/test/ostream_log_test.cc b/exporters/ostream/test/ostream_log_test.cc index 839c323129..8878e9d037 100644 --- a/exporters/ostream/test/ostream_log_test.cc +++ b/exporters/ostream/test/ostream_log_test.cc @@ -259,7 +259,9 @@ TEST(OStreamLogExporter, IntegrationTest) auto apiProvider = nostd::shared_ptr(sdkProvider); auto provider = nostd::shared_ptr(apiProvider); logs_api::Provider::SetLoggerProvider(provider); - auto logger = logs_api::Provider::GetLoggerProvider()->GetLogger("Logger"); + const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; + auto logger = logs_api::Provider::GetLoggerProvider()->GetLogger( + "Logger", "", "opentelelemtry_library", "", schema_url); // Back up cout's streambuf std::streambuf *original = std::cout.rdbuf(); 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 06d0ba7160..b6d02bddcd 100644 --- a/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_log_recordable.h +++ b/exporters/otlp/include/opentelemetry/exporters/otlp/otlp_log_recordable.h @@ -9,6 +9,7 @@ # include "opentelemetry/proto/logs/v1/logs.pb.h" # include "opentelemetry/proto/resource/v1/resource.pb.h" +# include "opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h" # include "opentelemetry/exporters/otlp/protobuf_include_suffix.h" // clang-format on @@ -92,14 +93,25 @@ class OtlpLogRecordable final : public opentelemetry::sdk::logs::Recordable */ void SetTraceFlags(opentelemetry::trace::TraceFlags trace_flags) noexcept override; + /** + * Set instrumentation_library for this log. + * @param instrumentation_library the instrumentation library to set + */ + void SetInstrumentationLibrary( + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + &instrumentation_library) noexcept override; + + /** Returns the associated instruementation library */ + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary & + GetInstrumentationLibrary() const noexcept; + private: proto::logs::v1::LogRecord log_record_; const opentelemetry::sdk::resource::Resource *resource_ = nullptr; // TODO shared resource // const opentelemetry::sdk::resource::Resource *resource_ = nullptr; - // TODO InstrumentationLibrary - // const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary - // *instrumentation_library_ = nullptr; + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + *instrumentation_library_ = nullptr; }; } // namespace otlp diff --git a/exporters/otlp/src/otlp_log_recordable.cc b/exporters/otlp/src/otlp_log_recordable.cc index 9df2b42d07..e859981e9f 100644 --- a/exporters/otlp/src/otlp_log_recordable.cc +++ b/exporters/otlp/src/otlp_log_recordable.cc @@ -205,6 +205,18 @@ void OtlpLogRecordable::SetTraceFlags(opentelemetry::trace::TraceFlags trace_fla log_record_.set_flags(trace_flags.flags()); } +void OtlpLogRecordable::SetInstrumentationLibrary( + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + &instrumentation_library) noexcept +{ + instrumentation_library_ = &instrumentation_library; +} + +const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary & +OtlpLogRecordable::GetInstrumentationLibrary() const noexcept +{ + return *instrumentation_library_; +} } // namespace otlp } // namespace exporter OPENTELEMETRY_END_NAMESPACE diff --git a/exporters/otlp/test/otlp_grpc_log_exporter_test.cc b/exporters/otlp/test/otlp_grpc_log_exporter_test.cc index 81d46ea3e3..f5f621bf9f 100644 --- a/exporters/otlp/test/otlp_grpc_log_exporter_test.cc +++ b/exporters/otlp/test/otlp_grpc_log_exporter_test.cc @@ -137,7 +137,8 @@ TEST_F(OtlpGrpcLogExporterTestPeer, ExportIntegrationTest) '3', '2', '1', '0'}; opentelemetry::trace::SpanId span_id{span_id_bin}; - auto logger = provider->GetLogger("test"); + const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; + auto logger = provider->GetLogger("test", "", "opentelelemtry_library", "", schema_url); logger->Log(opentelemetry::logs::Severity::kInfo, "Log name", "Log message", {{"service.name", "unit_test_service"}, {"tenant.id", "test_user"}, diff --git a/exporters/otlp/test/otlp_http_log_exporter_test.cc b/exporters/otlp/test/otlp_http_log_exporter_test.cc index 35dda11a2e..d79763b031 100755 --- a/exporters/otlp/test/otlp_http_log_exporter_test.cc +++ b/exporters/otlp/test/otlp_http_log_exporter_test.cc @@ -223,7 +223,8 @@ TEST_F(OtlpHttpLogExporterTestPeer, ExportJsonIntegrationTest) char span_id_hex[2 * opentelemetry::trace::SpanId::kSize] = {0}; opentelemetry::trace::SpanId span_id{span_id_bin}; - auto logger = provider->GetLogger("test"); + const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; + auto logger = provider->GetLogger("test", "", "opentelelemtry_library", "", schema_url); logger->Log(opentelemetry::logs::Severity::kInfo, "Log name", "Log message", {{"service.name", "unit_test_service"}, {"tenant.id", "test_user"}, @@ -313,7 +314,8 @@ TEST_F(OtlpHttpLogExporterTestPeer, ExportBinaryIntegrationTest) '3', '2', '1', '0'}; opentelemetry::trace::SpanId span_id{span_id_bin}; - auto logger = provider->GetLogger("test"); + const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; + auto logger = provider->GetLogger("test", "", "opentelelemtry_library", "", schema_url); logger->Log(opentelemetry::logs::Severity::kInfo, "Log name", "Log message", {{"service.name", "unit_test_service"}, {"tenant.id", "test_user"}, diff --git a/exporters/otlp/test/otlp_log_recordable_test.cc b/exporters/otlp/test/otlp_log_recordable_test.cc index b2e2f7bed0..a4945d394b 100644 --- a/exporters/otlp/test/otlp_log_recordable_test.cc +++ b/exporters/otlp/test/otlp_log_recordable_test.cc @@ -190,6 +190,15 @@ TEST(OtlpLogRecordable, SetArrayAttribute) } } +TEST(OtlpLogRecordable, SetInstrumentationLibrary) +{ + OtlpLogRecordable rec; + auto inst_lib = + opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary::Create("test", "v1"); + rec.SetInstrumentationLibrary(*inst_lib); + EXPECT_EQ(rec.GetInstrumentationLibrary(), *inst_lib); +} + /** * AttributeValue can contain different int types, such as int, int64_t, * unsigned int, and uint64_t. To avoid writing test cases for each, we can diff --git a/sdk/include/opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h b/sdk/include/opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h index eeea6cd7aa..48f13b78db 100644 --- a/sdk/include/opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h +++ b/sdk/include/opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h @@ -30,8 +30,8 @@ class InstrumentationLibrary nostd::string_view version = "", nostd::string_view schema_url = "") { - return nostd::unique_ptr(new InstrumentationLibrary{ - std::string{name}, std::string{version}, std::string{schema_url}}); + return nostd::unique_ptr( + new InstrumentationLibrary{name, version, schema_url}); } /** diff --git a/sdk/include/opentelemetry/sdk/logs/log_record.h b/sdk/include/opentelemetry/sdk/logs/log_record.h index 7abe9aca82..502a87a6f0 100644 --- a/sdk/include/opentelemetry/sdk/logs/log_record.h +++ b/sdk/include/opentelemetry/sdk/logs/log_record.h @@ -184,6 +184,21 @@ class LogRecord final : public Recordable * @return the timestamp for this log */ opentelemetry::common::SystemTimestamp GetTimestamp() const noexcept { return timestamp_; } + + /** + * Set instrumentation_library for this log. + * @param instrumentation_library the instrumentation library to set + */ + void SetInstrumentationLibrary( + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + &instrumentation_library) noexcept + { + instrumentation_library_ = &instrumentation_library; + } + +private: + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + *instrumentation_library_ = nullptr; }; } // namespace logs } // namespace sdk diff --git a/sdk/include/opentelemetry/sdk/logs/logger.h b/sdk/include/opentelemetry/sdk/logs/logger.h index fcf9d18abd..f6c9e0a226 100644 --- a/sdk/include/opentelemetry/sdk/logs/logger.h +++ b/sdk/include/opentelemetry/sdk/logs/logger.h @@ -5,6 +5,7 @@ #ifdef ENABLE_LOGS_PREVIEW # include "opentelemetry/logs/logger.h" +# include "opentelemetry/sdk/instrumentationlibrary/instrumentation_library.h" # include "opentelemetry/sdk/logs/logger_context.h" # include "opentelemetry/sdk/logs/logger_provider.h" @@ -25,8 +26,11 @@ class Logger final : public opentelemetry::logs::Logger * @param name The name of this logger instance * @param context The logger provider that owns this logger. */ - explicit Logger(opentelemetry::nostd::string_view name, - std::shared_ptr context) noexcept; + explicit Logger( + opentelemetry::nostd::string_view name, + std::shared_ptr context, + std::unique_ptr instrumentation_library = + instrumentationlibrary::InstrumentationLibrary::Create("")) noexcept; /** * Returns the name of this logger. @@ -55,13 +59,17 @@ class Logger final : public opentelemetry::logs::Logger opentelemetry::trace::TraceFlags trace_flags, opentelemetry::common::SystemTimestamp timestamp) noexcept override; + /** Returns the associated instruementation library */ + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary & + GetInstrumentationLibrary() const noexcept; + private: // The name of this logger std::string logger_name_; - // The logger provider of this Logger. Uses a weak_ptr to avoid cyclic dependency issues the with - // logger provider + // The logger context of this Logger. Uses a weak_ptr to avoid cyclic dependency issues the with std::weak_ptr context_; + std::unique_ptr instrumentation_library_; }; } // namespace logs diff --git a/sdk/include/opentelemetry/sdk/logs/logger_provider.h b/sdk/include/opentelemetry/sdk/logs/logger_provider.h old mode 100644 new mode 100755 index d29b18bc3d..fd0c163b8b --- a/sdk/include/opentelemetry/sdk/logs/logger_provider.h +++ b/sdk/include/opentelemetry/sdk/logs/logger_provider.h @@ -7,7 +7,6 @@ # include # include # include -# include # include # include "opentelemetry/logs/logger_provider.h" @@ -65,24 +64,35 @@ class LoggerProvider final : public opentelemetry::logs::LoggerProvider /** * Creates a logger with the given name, and returns a shared pointer to it. * If a logger with that name already exists, return a shared pointer to it - * @param name The name of the logger to be created. - * @param options (OPTIONAL) The options for the logger. TODO: Once the logging spec defines it, + * @param logger_name The name of the logger to be created. + * @param options The options for the logger. TODO: Once the logging spec defines it, * give a list of options that the logger supports. + * @param library_name The version of the library. + * @param library_version The version of the library. + * @param schema_url The schema URL. */ - opentelemetry::nostd::shared_ptr GetLogger( - opentelemetry::nostd::string_view name, - opentelemetry::nostd::string_view options = "") noexcept override; - + nostd::shared_ptr GetLogger( + nostd::string_view logger_name, + nostd::string_view options, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") noexcept override; /** * Creates a logger with the given name, and returns a shared pointer to it. * If a logger with that name already exists, return a shared pointer to it * @param name The name of the logger to be created. - * @param args (OPTIONAL) The arguments for the logger. TODO: Once the logging spec defines it, + * @param args The arguments for the logger. TODO: Once the logging spec defines it, * give a list of arguments that the logger supports. + * @param library_name The version of the library. + * @param library_version The version of the library. + * @param schema_url The schema URL. */ - opentelemetry::nostd::shared_ptr GetLogger( - opentelemetry::nostd::string_view name, - nostd::span args) noexcept override; + nostd::shared_ptr GetLogger( + nostd::string_view logger_name, + nostd::span args, + nostd::string_view library_name, + nostd::string_view library_version = "", + nostd::string_view schema_url = "") noexcept override; /** * Add the processor that is stored internally in the logger provider. @@ -102,8 +112,7 @@ class LoggerProvider final : public opentelemetry::logs::LoggerProvider std::shared_ptr context_; // A vector of pointers to all the loggers that have been created - std::unordered_map> - loggers_; + std::vector> loggers_; // A mutex that ensures only one thread is using the map of loggers std::mutex lock_; diff --git a/sdk/include/opentelemetry/sdk/logs/multi_recordable.h b/sdk/include/opentelemetry/sdk/logs/multi_recordable.h index fe766b0f6a..59c018d2d6 100644 --- a/sdk/include/opentelemetry/sdk/logs/multi_recordable.h +++ b/sdk/include/opentelemetry/sdk/logs/multi_recordable.h @@ -85,8 +85,22 @@ class MultiRecordable final : public Recordable */ void SetTraceFlags(opentelemetry::trace::TraceFlags trace_flags) noexcept override; + /** + * Set instrumentation_library for this log. + * @param instrumentation_library the instrumentation library to set + */ + void SetInstrumentationLibrary( + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + &instrumentation_library) noexcept override; + + /** Returns the associated instruementation library */ + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary & + GetInstrumentationLibrary() const noexcept; + private: std::unordered_map> recordables_; + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + *instrumentation_library_ = nullptr; }; } // namespace logs } // namespace sdk diff --git a/sdk/include/opentelemetry/sdk/logs/recordable.h b/sdk/include/opentelemetry/sdk/logs/recordable.h index a5d1beb5e1..a858e67d62 100644 --- a/sdk/include/opentelemetry/sdk/logs/recordable.h +++ b/sdk/include/opentelemetry/sdk/logs/recordable.h @@ -88,6 +88,14 @@ class Recordable * @param trace_flags the trace flags to set */ virtual void SetTraceFlags(opentelemetry::trace::TraceFlags trace_flags) noexcept = 0; + + /** + * Set instrumentation_library for this log. + * @param instrumentation_library the instrumentation library to set + */ + virtual void SetInstrumentationLibrary( + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + &instrumentation_library) noexcept = 0; }; } // namespace logs } // namespace sdk diff --git a/sdk/src/logs/logger.cc b/sdk/src/logs/logger.cc index aa1e7180db..3c1d38d03e 100644 --- a/sdk/src/logs/logger.cc +++ b/sdk/src/logs/logger.cc @@ -16,8 +16,13 @@ namespace trace_api = opentelemetry::trace; namespace nostd = opentelemetry::nostd; namespace common = opentelemetry::common; -Logger::Logger(nostd::string_view name, std::shared_ptr context) noexcept - : logger_name_(std::string(name)), context_(context) +Logger::Logger(nostd::string_view name, + std::shared_ptr context, + std::unique_ptr + instrumentation_library) noexcept + : logger_name_(std::string(name)), + context_(context), + instrumentation_library_{std::move(instrumentation_library)} {} const nostd::string_view Logger::GetName() noexcept @@ -61,6 +66,7 @@ void Logger::Log(opentelemetry::logs::Severity severity, recordable->SetSeverity(severity); recordable->SetName(name); recordable->SetBody(body); + recordable->SetInstrumentationLibrary(GetInstrumentationLibrary()); recordable->SetResource(context->GetResource()); @@ -111,6 +117,12 @@ void Logger::Log(opentelemetry::logs::Severity severity, processor.OnReceive(std::move(recordable)); } +const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary & +Logger::GetInstrumentationLibrary() const noexcept +{ + return *instrumentation_library_; +} + } // namespace logs } // namespace sdk OPENTELEMETRY_END_NAMESPACE diff --git a/sdk/src/logs/logger_provider.cc b/sdk/src/logs/logger_provider.cc index 75c02c89ef..08edce783d 100644 --- a/sdk/src/logs/logger_provider.cc +++ b/sdk/src/logs/logger_provider.cc @@ -43,17 +43,25 @@ LoggerProvider::LoggerProvider(std::shared_ptr context : context_{context} {} -nostd::shared_ptr LoggerProvider::GetLogger(nostd::string_view name, - nostd::string_view options) noexcept +nostd::shared_ptr LoggerProvider::GetLogger( + nostd::string_view logger_name, + nostd::string_view options, + nostd::string_view library_name, + nostd::string_view library_version, + nostd::string_view schema_url) noexcept { // Ensure only one thread can read/write from the map of loggers std::lock_guard lock_guard{lock_}; - // If a logger with a name "name" already exists, return it - auto loggerkv = loggers_.find(name.data()); - if (loggerkv != loggers_.end()) + // If a logger with a name "logger_name" already exists, return it + for (auto &logger : loggers_) { - return nostd::shared_ptr(loggerkv->second); + auto &logger_lib = logger->GetInstrumentationLibrary(); + if (logger->GetName() == logger_name && + logger_lib.equal(library_name, library_version, schema_url)) + { + return nostd::shared_ptr{logger}; + } } // Check if creating a new logger would exceed the max number of loggers @@ -70,18 +78,21 @@ nostd::shared_ptr LoggerProvider::GetLogger(nostd::string_view */ // If no logger with that name exists yet, create it and add it to the map of loggers - - nostd::shared_ptr logger(new Logger(name, context_)); - loggers_[name.data()] = logger; - return logger; + auto lib = instrumentationlibrary::InstrumentationLibrary::Create(library_name, library_version, + schema_url); + loggers_.push_back(std::shared_ptr( + new Logger(logger_name, context_, std::move(lib)))); + return nostd::shared_ptr{loggers_.back()}; } -nostd::shared_ptr LoggerProvider::GetLogger( - nostd::string_view name, - nostd::span args) noexcept +nostd::shared_ptr LoggerProvider::GetLogger( + nostd::string_view logger_name, + nostd::span args, + nostd::string_view library_name, + nostd::string_view library_version, + nostd::string_view schema_url) noexcept { - // Currently, no args support - return GetLogger(name); + return GetLogger(logger_name, "", library_name, library_version, schema_url); } void LoggerProvider::AddProcessor(std::unique_ptr processor) noexcept diff --git a/sdk/src/logs/multi_recordable.cc b/sdk/src/logs/multi_recordable.cc index 4db79af48c..b7bb92c627 100644 --- a/sdk/src/logs/multi_recordable.cc +++ b/sdk/src/logs/multi_recordable.cc @@ -129,6 +129,18 @@ void MultiRecordable::SetTraceFlags(opentelemetry::trace::TraceFlags trace_flags } } +void MultiRecordable::SetInstrumentationLibrary( + const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary + &instrumentation_library) noexcept +{ + instrumentation_library_ = &instrumentation_library; +} + +const opentelemetry::sdk::instrumentationlibrary::InstrumentationLibrary & +MultiRecordable::GetInstrumentationLibrary() const noexcept +{ + return *instrumentation_library_; +} } // namespace logs } // namespace sdk diff --git a/sdk/test/instrumentationlibrary/instrumentationlibrary_test.cc b/sdk/test/instrumentationlibrary/instrumentationlibrary_test.cc index b6ac69df1f..a410ca99f2 100644 --- a/sdk/test/instrumentationlibrary/instrumentationlibrary_test.cc +++ b/sdk/test/instrumentationlibrary/instrumentationlibrary_test.cc @@ -14,10 +14,13 @@ using namespace opentelemetry::sdk::instrumentationlibrary; TEST(InstrumentationLibrary, CreateInstrumentationLibrary) { - std::string library_name = "opentelemetry-cpp"; - std::string library_version = "0.1.0"; - auto instrumentation_library = InstrumentationLibrary::Create(library_name, library_version); + std::string library_name = "opentelemetry-cpp"; + std::string library_version = "0.1.0"; + std::string schema_url = "https://opentelemetry.io/schemas/1.2.0"; + auto instrumentation_library = + InstrumentationLibrary::Create(library_name, library_version, schema_url); EXPECT_EQ(instrumentation_library->GetName(), library_name); EXPECT_EQ(instrumentation_library->GetVersion(), library_version); + EXPECT_EQ(instrumentation_library->GetSchemaURL(), schema_url); } diff --git a/sdk/test/logs/logger_provider_sdk_test.cc b/sdk/test/logs/logger_provider_sdk_test.cc index 517c05dc94..e31c1b6825 100644 --- a/sdk/test/logs/logger_provider_sdk_test.cc +++ b/sdk/test/logs/logger_provider_sdk_test.cc @@ -31,19 +31,32 @@ TEST(LoggerProviderSDK, LoggerProviderGetLoggerSimple) { auto lp = std::shared_ptr(new LoggerProvider()); - auto logger1 = lp->GetLogger("logger1"); - auto logger2 = lp->GetLogger("logger2"); + nostd::string_view schema_url{"https://opentelemetry.io/schemas/1.2.0"}; + auto logger1 = lp->GetLogger("logger1", "", "opentelelemtry_library", "", schema_url); + auto logger2 = lp->GetLogger("logger2", "", "opentelelemtry_library", "", schema_url); // Check that the logger is not nullptr ASSERT_NE(logger1, nullptr); ASSERT_NE(logger2, nullptr); + auto sdk_logger1 = static_cast(logger1.get()); + auto sdk_logger2 = static_cast(logger2.get()); + ASSERT_EQ(sdk_logger1->GetInstrumentationLibrary().GetName(), "opentelelemtry_library"); + ASSERT_EQ(sdk_logger1->GetInstrumentationLibrary().GetVersion(), ""); + ASSERT_EQ(sdk_logger1->GetInstrumentationLibrary().GetSchemaURL(), schema_url); + + ASSERT_EQ(sdk_logger2->GetInstrumentationLibrary().GetName(), "opentelelemtry_library"); + ASSERT_EQ(sdk_logger2->GetInstrumentationLibrary().GetVersion(), ""); + ASSERT_EQ(sdk_logger2->GetInstrumentationLibrary().GetSchemaURL(), schema_url); + // Check that two loggers with different names aren't the same instance ASSERT_NE(logger1, logger2); // Check that two loggers with the same name are the same instance - auto logger3 = lp->GetLogger("logger1"); + auto logger3 = lp->GetLogger("logger1", "", "opentelelemtry_library", "", schema_url); ASSERT_EQ(logger1, logger3); + auto sdk_logger3 = static_cast(logger3.get()); + ASSERT_EQ(sdk_logger3->GetInstrumentationLibrary(), sdk_logger1->GetInstrumentationLibrary()); } TEST(LoggerProviderSDK, LoggerProviderLoggerArguments) @@ -53,12 +66,16 @@ TEST(LoggerProviderSDK, LoggerProviderLoggerArguments) // detail to this test auto lp = std::shared_ptr(new LoggerProvider()); - auto logger1 = lp->GetLogger("logger1", ""); + nostd::string_view schema_url{"https://opentelemetry.io/schemas/1.2.0"}; + auto logger1 = lp->GetLogger("logger1", "", "opentelelemtry_library", "", schema_url); // Check GetLogger(logger_name, args) std::array sv{"string"}; nostd::span args{sv}; - auto logger2 = lp->GetLogger("logger2", args); + auto logger2 = lp->GetLogger("logger2", args, "opentelelemtry_library", "", schema_url); + auto sdk_logger1 = static_cast(logger1.get()); + auto sdk_logger2 = static_cast(logger2.get()); + ASSERT_EQ(sdk_logger2->GetInstrumentationLibrary(), sdk_logger1->GetInstrumentationLibrary()); } class DummyProcessor : public LogProcessor diff --git a/sdk/test/logs/logger_sdk_test.cc b/sdk/test/logs/logger_sdk_test.cc index cd2f291a80..aad13f41e2 100644 --- a/sdk/test/logs/logger_sdk_test.cc +++ b/sdk/test/logs/logger_sdk_test.cc @@ -17,9 +17,14 @@ TEST(LoggerSDK, LogToNullProcessor) // even when there is no processor set // since it calls Processor::OnReceive() - auto lp = std::shared_ptr(new LoggerProvider()); - auto logger = lp->GetLogger("logger"); - + auto lp = std::shared_ptr(new LoggerProvider()); + const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; + auto logger = lp->GetLogger("logger", "", "opentelelemtry_library", "", schema_url); + + auto sdk_logger = static_cast(logger.get()); + ASSERT_EQ(sdk_logger->GetInstrumentationLibrary().GetName(), "opentelelemtry_library"); + ASSERT_EQ(sdk_logger->GetInstrumentationLibrary().GetVersion(), ""); + ASSERT_EQ(sdk_logger->GetInstrumentationLibrary().GetSchemaURL(), schema_url); // Log a sample log record to a nullptr processor logger->Debug("Test log"); } @@ -66,15 +71,20 @@ TEST(LoggerSDK, LogToAProcessor) { // Create an API LoggerProvider and logger auto api_lp = std::shared_ptr(new LoggerProvider()); - auto logger = api_lp->GetLogger("logger"); + const std::string schema_url{"https://opentelemetry.io/schemas/1.2.0"}; + auto logger = api_lp->GetLogger("logger", "", "opentelelemtry_library", "", schema_url); // Cast the API LoggerProvider to an SDK Logger Provider and assert that it is still the same // LoggerProvider by checking that getting a logger with the same name as the previously defined // logger is the same instance auto lp = static_cast(api_lp.get()); - auto logger2 = lp->GetLogger("logger"); + auto logger2 = lp->GetLogger("logger", "", "opentelelemtry_library", "", schema_url); ASSERT_EQ(logger, logger2); + auto sdk_logger = static_cast(logger.get()); + ASSERT_EQ(sdk_logger->GetInstrumentationLibrary().GetName(), "opentelelemtry_library"); + ASSERT_EQ(sdk_logger->GetInstrumentationLibrary().GetVersion(), ""); + ASSERT_EQ(sdk_logger->GetInstrumentationLibrary().GetSchemaURL(), schema_url); // Set a processor for the LoggerProvider auto shared_recordable = std::shared_ptr(new LogRecord()); lp->AddProcessor(std::unique_ptr(new MockProcessor(shared_recordable)));