Skip to content

Commit cb9cd1d

Browse files
authored
[ETW] Add table name mapping for Logs other than the default Log table (#2691)
1 parent 2535c70 commit cb9cd1d

File tree

3 files changed

+77
-8
lines changed

3 files changed

+77
-8
lines changed

exporters/etw/include/opentelemetry/exporters/etw/etw_config.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ namespace etw
2323
/**
2424
* @brief TelemetryProvider Options passed via SDK API.
2525
*/
26-
using TelemetryProviderOptions =
27-
std::map<std::string, nostd::variant<std::string, uint64_t, float, bool>>;
26+
using TelemetryProviderOptions = std::map<
27+
std::string,
28+
nostd::variant<std::string, uint64_t, float, bool, std::map<std::string, std::string>>>;
2829

2930
/**
3031
* @brief TelemetryProvider runtime configuration class. Internal representation
@@ -41,6 +42,9 @@ typedef struct
4142
bool enableAutoParent; // Start new spans as children of current active span, Not used for Logs
4243
ETWProvider::EventFormat
4344
encoding; // Event encoding to use for this provider (TLD, MsgPack, XML, etc.).
45+
bool enableTableNameMappings; // Map instrumentation scope name to table name with
46+
// `tableNameMappings`
47+
std::map<std::string, std::string> tableNameMappings;
4448
} TelemetryProviderConfiguration;
4549

4650
/**

exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ class Logger : public opentelemetry::logs::Logger
145145
*/
146146
std::string provId;
147147

148+
std::string eventName_;
149+
148150
/**
149151
* @brief Encoding (Manifest, MessagePack or XML)
150152
*/
@@ -179,10 +181,12 @@ class Logger : public opentelemetry::logs::Logger
179181
* @param encoding ETW encoding format to use.
180182
*/
181183
Logger(etw::LoggerProvider &parent,
184+
nostd::string_view eventName,
182185
nostd::string_view providerId = "",
183186
ETWProvider::EventFormat encoding = ETWProvider::EventFormat::ETW_MANIFEST)
184187
: opentelemetry::logs::Logger(),
185188
loggerProvider_(parent),
189+
eventName_(eventName),
186190
provId(providerId.data(), providerId.size()),
187191
encoding(encoding),
188192
provHandle(initProvHandle())
@@ -271,7 +275,7 @@ class Logger : public opentelemetry::logs::Logger
271275
#endif // defined(ENABLE_ENV_PROPERTIES)
272276

273277
// Populate Etw.EventName attribute at envelope level
274-
evt[ETW_FIELD_NAME] = ETW_VALUE_LOG;
278+
evt[ETW_FIELD_NAME] = eventName_.data();
275279

276280
#ifdef HAVE_FIELD_TIME
277281
{
@@ -347,6 +351,8 @@ class LoggerProvider : public opentelemetry::logs::LoggerProvider
347351
GetOption(options, "enableTraceId", config_.enableTraceId, true);
348352
GetOption(options, "enableSpanId", config_.enableSpanId, true);
349353
GetOption(options, "enableActivityId", config_.enableActivityId, false);
354+
GetOption(options, "enableTableNameMappings", config_.enableTableNameMappings, false);
355+
GetOption(options, "tableNameMappings", config_.tableNameMappings, {});
350356

351357
// Determines what encoding to use for ETW events: TraceLogging Dynamic, MsgPack, XML, etc.
352358
config_.encoding = GetEncoding(options);
@@ -359,19 +365,30 @@ class LoggerProvider : public opentelemetry::logs::LoggerProvider
359365

360366
nostd::shared_ptr<opentelemetry::logs::Logger> GetLogger(
361367
opentelemetry::nostd::string_view logger_name,
362-
opentelemetry::nostd::string_view library_name,
363-
opentelemetry::nostd::string_view version = "",
364-
opentelemetry::nostd::string_view schema_url = "",
368+
opentelemetry::nostd::string_view library_name = "",
369+
opentelemetry::nostd::string_view version = "",
370+
opentelemetry::nostd::string_view schema_url = "",
365371
const opentelemetry::common::KeyValueIterable &attributes =
366372
opentelemetry::common::NoopKeyValueIterable()) override
367373
{
368-
UNREFERENCED_PARAMETER(library_name);
369374
UNREFERENCED_PARAMETER(version);
370375
UNREFERENCED_PARAMETER(schema_url);
371376
UNREFERENCED_PARAMETER(attributes);
377+
378+
std::string event_name{ETW_VALUE_LOG};
379+
if (config_.enableTableNameMappings)
380+
{
381+
auto it =
382+
config_.tableNameMappings.find(std::string(library_name.data(), library_name.size()));
383+
if (it != config_.tableNameMappings.end())
384+
{
385+
event_name = it->second;
386+
}
387+
}
388+
372389
ETWProvider::EventFormat evtFmt = config_.encoding;
373390
return nostd::shared_ptr<opentelemetry::logs::Logger>{
374-
new (std::nothrow) etw::Logger(*this, logger_name, evtFmt)};
391+
new (std::nothrow) etw::Logger(*this, event_name, logger_name, evtFmt)};
375392
}
376393
};
377394

exporters/etw/test/etw_logger_test.cc

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ using namespace OPENTELEMETRY_NAMESPACE;
1414

1515
using namespace opentelemetry::exporter::etw;
1616

17+
// The ETW provider ID is {4533CB59-77E2-54E9-E340-F0F0549058B7}
1718
const char *kGlobalProviderName = "OpenTelemetry-ETW-TLD";
1819

1920
/**
@@ -98,4 +99,51 @@ TEST(ETWLogger, LoggerCheckWithAttributes)
9899
opentelemetry::common::MakeAttributes(attribs)));
99100
}
100101

102+
/**
103+
* @brief Logger Test with structured attributes
104+
*
105+
* Example Event for below test:
106+
* {
107+
* "Timestamp": "2024-06-02T15:04:15.4227815-07:00",
108+
* "ProviderName": "OpenTelemetry-ETW-TLD",
109+
* "Id": 1,
110+
* "Message": null,
111+
* "ProcessId": 37696,
112+
* "Level": "Always",
113+
* "Keywords": "0x0000000000000000",
114+
* "EventName": "table1",
115+
* "ActivityID": null,
116+
* "RelatedActivityID": null,
117+
* "Payload": {
118+
* "SpanId": "0000000000000000",
119+
* "Timestamp": "2021-09-30T22:04:15.066411500Z",
120+
* "TraceId": "00000000000000000000000000000000",
121+
* "_name": "table1",
122+
* "attrib1": 1,
123+
* "attrib2": "value2",
124+
* "body": "This is a debug log body",
125+
* "severityNumber": 5,
126+
* "severityText": "DEBUG"
127+
* }
128+
* }
129+
*
130+
*/
131+
132+
TEST(ETWLogger, LoggerCheckWithTableNameMappings)
133+
{
134+
std::string providerName = kGlobalProviderName; // supply unique instrumentation name here
135+
std::map<std::string, std::string> tableNameMappings = {{"name1", "table1"}, {"name2", "table2"}};
136+
exporter::etw::TelemetryProviderOptions options = {{"enableTableNameMappings", true},
137+
{"tableNameMappings", tableNameMappings}};
138+
exporter::etw::LoggerProvider lp{options};
139+
140+
auto logger = lp.GetLogger(providerName, "name1");
141+
142+
// Log attributes
143+
Properties attribs = {{"attrib1", 1}, {"attrib2", "value2"}};
144+
145+
EXPECT_NO_THROW(
146+
logger->Debug("This is a debug log body", opentelemetry::common::MakeAttributes(attribs)));
147+
}
148+
101149
#endif // _WIN32

0 commit comments

Comments
 (0)