Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[ETW] Add table name mapping for Logs other than the default Log table #2691

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ namespace etw
/**
* @brief TelemetryProvider Options passed via SDK API.
*/
using TelemetryProviderOptions =
std::map<std::string, nostd::variant<std::string, uint64_t, float, bool>>;
using TelemetryProviderOptions = std::map<
std::string,
nostd::variant<std::string, uint64_t, float, bool, std::map<std::string, std::string>>>;

/**
* @brief TelemetryProvider runtime configuration class. Internal representation
Expand All @@ -41,6 +42,9 @@ typedef struct
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`
std::map<std::string, std::string> tableNameMappings;
} TelemetryProviderConfiguration;

/**
Expand Down
29 changes: 23 additions & 6 deletions exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ class Logger : public opentelemetry::logs::Logger
*/
std::string provId;

std::string eventName_;

/**
* @brief Encoding (Manifest, MessagePack or XML)
*/
Expand Down Expand Up @@ -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())
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -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);
Expand All @@ -359,19 +365,30 @@ class LoggerProvider : public opentelemetry::logs::LoggerProvider

nostd::shared_ptr<opentelemetry::logs::Logger> 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 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()));
ThomsonTan marked this conversation as resolved.
Show resolved Hide resolved
if (it != config_.tableNameMappings.end())
{
event_name = it->second;
}
}

ETWProvider::EventFormat evtFmt = config_.encoding;
return nostd::shared_ptr<opentelemetry::logs::Logger>{
new (std::nothrow) etw::Logger(*this, logger_name, evtFmt)};
new (std::nothrow) etw::Logger(*this, event_name, logger_name, evtFmt)};
}
};

Expand Down
48 changes: 48 additions & 0 deletions exporters/etw/test/etw_logger_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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";

/**
Expand Down Expand Up @@ -98,4 +99,51 @@ 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<std::string, std::string> 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