From 40ea296a86396aff87c067359199ef49b1535518 Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Mon, 3 Jun 2024 11:00:17 -0700 Subject: [PATCH 1/2] [ETW] Add table name mapping for Logs other than the default Log table --- .../opentelemetry/exporters/etw/etw_config.h | 8 ++-- .../opentelemetry/exporters/etw/etw_logger.h | 24 ++++++++-- exporters/etw/test/etw_logger_test.cc | 46 +++++++++++++++++++ 3 files changed, 71 insertions(+), 7 deletions(-) diff --git a/exporters/etw/include/opentelemetry/exporters/etw/etw_config.h b/exporters/etw/include/opentelemetry/exporters/etw/etw_config.h index dae8f5b075..38c04187fb 100644 --- a/exporters/etw/include/opentelemetry/exporters/etw/etw_config.h +++ b/exporters/etw/include/opentelemetry/exporters/etw/etw_config.h @@ -24,7 +24,7 @@ namespace etw * @brief TelemetryProvider Options passed via SDK API. */ using TelemetryProviderOptions = - std::map>; + std::map>>; /** * @brief TelemetryProvider runtime configuration class. Internal representation @@ -38,9 +38,11 @@ typedef struct bool enableActivityTracking; // Emit TraceLogging events for Span/Start and Span/Stop Not used // for Logs bool enableRelatedActivityId; // Assign parent `SpanId` to `RelatedActivityId` - bool enableAutoParent; // Start new spans as children of current active span, Not used for Logs + bool enableAutoParent; // Start new spans as children of current active span, Not used for Logs ETWProvider::EventFormat - encoding; // Event encoding to use for this provider (TLD, MsgPack, XML, etc.). + encoding; // Event encoding to use for this provider (TLD, MsgPack, XML, etc.). + bool enableTableNameMappings; // Map instrumentation scope name to table name with `tableNameMappings` + std::map tableNameMappings; } TelemetryProviderConfiguration; /** diff --git a/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h b/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h index 494211ea0b..9b91ee8a52 100644 --- a/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h +++ b/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h @@ -145,6 +145,8 @@ class Logger : public opentelemetry::logs::Logger */ std::string provId; + std::string eventName_; + /** * @brief Encoding (Manifest, MessagePack or XML) */ @@ -179,10 +181,12 @@ class Logger : public opentelemetry::logs::Logger * @param encoding ETW encoding format to use. */ Logger(etw::LoggerProvider &parent, + nostd::string_view eventName, nostd::string_view providerId = "", ETWProvider::EventFormat encoding = ETWProvider::EventFormat::ETW_MANIFEST) : opentelemetry::logs::Logger(), loggerProvider_(parent), + eventName_(eventName), provId(providerId.data(), providerId.size()), encoding(encoding), provHandle(initProvHandle()) @@ -271,7 +275,7 @@ class Logger : public opentelemetry::logs::Logger #endif // defined(ENABLE_ENV_PROPERTIES) // Populate Etw.EventName attribute at envelope level - evt[ETW_FIELD_NAME] = ETW_VALUE_LOG; + evt[ETW_FIELD_NAME] = eventName_.data(); #ifdef HAVE_FIELD_TIME { @@ -347,6 +351,8 @@ class LoggerProvider : public opentelemetry::logs::LoggerProvider GetOption(options, "enableTraceId", config_.enableTraceId, true); GetOption(options, "enableSpanId", config_.enableSpanId, true); GetOption(options, "enableActivityId", config_.enableActivityId, false); + GetOption(options, "enableTableNameMappings", config_.enableTableNameMappings, false); + GetOption(options, "tableNameMappings", config_.tableNameMappings, {}); // Determines what encoding to use for ETW events: TraceLogging Dynamic, MsgPack, XML, etc. config_.encoding = GetEncoding(options); @@ -359,19 +365,29 @@ class LoggerProvider : public opentelemetry::logs::LoggerProvider nostd::shared_ptr GetLogger( opentelemetry::nostd::string_view logger_name, - opentelemetry::nostd::string_view library_name, + opentelemetry::nostd::string_view library_name = "", opentelemetry::nostd::string_view version = "", opentelemetry::nostd::string_view schema_url = "", const opentelemetry::common::KeyValueIterable &attributes = opentelemetry::common::NoopKeyValueIterable()) override { - UNREFERENCED_PARAMETER(library_name); UNREFERENCED_PARAMETER(version); UNREFERENCED_PARAMETER(schema_url); UNREFERENCED_PARAMETER(attributes); + + std::string event_name{ETW_VALUE_LOG}; + if (config_.enableTableNameMappings) + { + auto it = config_.tableNameMappings.find(std::string(library_name.data(), library_name.size())); + if (it != config_.tableNameMappings.end()) + { + event_name = it->second; + } + } + ETWProvider::EventFormat evtFmt = config_.encoding; return nostd::shared_ptr{ - new (std::nothrow) etw::Logger(*this, logger_name, evtFmt)}; + new (std::nothrow) etw::Logger(*this, event_name, logger_name, evtFmt)}; } }; diff --git a/exporters/etw/test/etw_logger_test.cc b/exporters/etw/test/etw_logger_test.cc index f27d47880b..d30588a5d7 100644 --- a/exporters/etw/test/etw_logger_test.cc +++ b/exporters/etw/test/etw_logger_test.cc @@ -14,6 +14,7 @@ using namespace OPENTELEMETRY_NAMESPACE; using namespace opentelemetry::exporter::etw; +// The ETW provider ID is {4533CB59-77E2-54E9-E340-F0F0549058B7} const char *kGlobalProviderName = "OpenTelemetry-ETW-TLD"; /** @@ -98,4 +99,49 @@ TEST(ETWLogger, LoggerCheckWithAttributes) opentelemetry::common::MakeAttributes(attribs))); } +/** + * @brief Logger Test with structured attributes + * + * Example Event for below test: + * { + * "Timestamp": "2024-06-02T15:04:15.4227815-07:00", + * "ProviderName": "OpenTelemetry-ETW-TLD", + * "Id": 1, + * "Message": null, + * "ProcessId": 37696, + * "Level": "Always", + * "Keywords": "0x0000000000000000", + * "EventName": "table1", + * "ActivityID": null, + * "RelatedActivityID": null, + * "Payload": { + * "SpanId": "0000000000000000", + * "Timestamp": "2021-09-30T22:04:15.066411500Z", + * "TraceId": "00000000000000000000000000000000", + * "_name": "table1", + * "attrib1": 1, + * "attrib2": "value2", + * "body": "This is a debug log body", + * "severityNumber": 5, + * "severityText": "DEBUG" + * } + * } + * + */ + +TEST(ETWLogger, LoggerCheckWithTableNameMappings) +{ + std::string providerName = kGlobalProviderName; // supply unique instrumentation name here + std::map tableNameMappings = {{"name1", "table1"}, {"name2", "table2"}}; + exporter::etw::TelemetryProviderOptions options = {{"enableTableNameMappings", true}, {"tableNameMappings", tableNameMappings}}; + exporter::etw::LoggerProvider lp {options}; + + auto logger = lp.GetLogger(providerName, "name1"); + + // Log attributes + Properties attribs = {{"attrib1", 1}, {"attrib2", "value2"}}; + + EXPECT_NO_THROW(logger->Debug("This is a debug log body", opentelemetry::common::MakeAttributes(attribs))); +} + #endif // _WIN32 From fd1db1439eb45d1542111d1668a62c0395edbc76 Mon Sep 17 00:00:00 2001 From: Tom Tan Date: Mon, 3 Jun 2024 11:37:15 -0700 Subject: [PATCH 2/2] Format --- .../include/opentelemetry/exporters/etw/etw_config.h | 12 +++++++----- .../include/opentelemetry/exporters/etw/etw_logger.h | 7 ++++--- exporters/etw/test/etw_logger_test.cc | 8 +++++--- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/exporters/etw/include/opentelemetry/exporters/etw/etw_config.h b/exporters/etw/include/opentelemetry/exporters/etw/etw_config.h index 38c04187fb..d343589699 100644 --- a/exporters/etw/include/opentelemetry/exporters/etw/etw_config.h +++ b/exporters/etw/include/opentelemetry/exporters/etw/etw_config.h @@ -23,8 +23,9 @@ namespace etw /** * @brief TelemetryProvider Options passed via SDK API. */ -using TelemetryProviderOptions = - std::map>>; +using TelemetryProviderOptions = std::map< + std::string, + nostd::variant>>; /** * @brief TelemetryProvider runtime configuration class. Internal representation @@ -38,10 +39,11 @@ typedef struct bool enableActivityTracking; // Emit TraceLogging events for Span/Start and Span/Stop Not used // for Logs bool enableRelatedActivityId; // Assign parent `SpanId` to `RelatedActivityId` - bool enableAutoParent; // Start new spans as children of current active span, Not used for Logs + bool enableAutoParent; // Start new spans as children of current active span, Not used for Logs ETWProvider::EventFormat - encoding; // Event encoding to use for this provider (TLD, MsgPack, XML, etc.). - bool enableTableNameMappings; // Map instrumentation scope name to table name with `tableNameMappings` + encoding; // Event encoding to use for this provider (TLD, MsgPack, XML, etc.). + bool enableTableNameMappings; // Map instrumentation scope name to table name with + // `tableNameMappings` std::map tableNameMappings; } TelemetryProviderConfiguration; diff --git a/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h b/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h index 9b91ee8a52..c464d572d5 100644 --- a/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h +++ b/exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h @@ -366,8 +366,8 @@ class LoggerProvider : public opentelemetry::logs::LoggerProvider nostd::shared_ptr GetLogger( opentelemetry::nostd::string_view logger_name, opentelemetry::nostd::string_view library_name = "", - opentelemetry::nostd::string_view version = "", - opentelemetry::nostd::string_view schema_url = "", + opentelemetry::nostd::string_view version = "", + opentelemetry::nostd::string_view schema_url = "", const opentelemetry::common::KeyValueIterable &attributes = opentelemetry::common::NoopKeyValueIterable()) override { @@ -378,7 +378,8 @@ class LoggerProvider : public opentelemetry::logs::LoggerProvider std::string event_name{ETW_VALUE_LOG}; if (config_.enableTableNameMappings) { - auto it = config_.tableNameMappings.find(std::string(library_name.data(), library_name.size())); + auto it = + config_.tableNameMappings.find(std::string(library_name.data(), library_name.size())); if (it != config_.tableNameMappings.end()) { event_name = it->second; diff --git a/exporters/etw/test/etw_logger_test.cc b/exporters/etw/test/etw_logger_test.cc index d30588a5d7..c64769d6ee 100644 --- a/exporters/etw/test/etw_logger_test.cc +++ b/exporters/etw/test/etw_logger_test.cc @@ -133,15 +133,17 @@ TEST(ETWLogger, LoggerCheckWithTableNameMappings) { std::string providerName = kGlobalProviderName; // supply unique instrumentation name here std::map tableNameMappings = {{"name1", "table1"}, {"name2", "table2"}}; - exporter::etw::TelemetryProviderOptions options = {{"enableTableNameMappings", true}, {"tableNameMappings", tableNameMappings}}; - exporter::etw::LoggerProvider lp {options}; + exporter::etw::TelemetryProviderOptions options = {{"enableTableNameMappings", true}, + {"tableNameMappings", tableNameMappings}}; + exporter::etw::LoggerProvider lp{options}; auto logger = lp.GetLogger(providerName, "name1"); // Log attributes Properties attribs = {{"attrib1", 1}, {"attrib2", "value2"}}; - EXPECT_NO_THROW(logger->Debug("This is a debug log body", opentelemetry::common::MakeAttributes(attribs))); + EXPECT_NO_THROW( + logger->Debug("This is a debug log body", opentelemetry::common::MakeAttributes(attribs))); } #endif // _WIN32