Skip to content
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
24 changes: 24 additions & 0 deletions exporters/etw/include/opentelemetry/exporters/etw/etw_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
#pragma once
#include <map>

#if defined(OPENTELEMETRY_ATTRIBUTE_TIMESTAMP_PREVIEW)
# include <set>
#endif // defined(OPENTELEMETRY_ATTRIBUTE_TIMESTAMP_PREVIEW)

#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/unique_ptr.h"
Expand All @@ -23,10 +27,23 @@ namespace etw
/**
* @brief TelemetryProvider Options passed via SDK API.
*/

#if defined(OPENTELEMETRY_ATTRIBUTE_TIMESTAMP_PREVIEW)
using TelemetryProviderOptions = std::map<std::string,
nostd::variant<std::string,
uint64_t,
float,
bool,
std::map<std::string, std::string>,
std::set<std::string>>>;

#else
using TelemetryProviderOptions = std::map<
std::string,
nostd::variant<std::string, uint64_t, float, bool, std::map<std::string, std::string>>>;

#endif // defined(OPENTELEMETRY_ATTRIBUTE_TIMESTAMP_PREVIEW)

/**
* @brief TelemetryProvider runtime configuration class. Internal representation
* of TelemetryProviderOptions used by various components of SDK.
Expand All @@ -45,6 +62,13 @@ typedef struct
bool enableTableNameMappings; // Map instrumentation scope name to table name with
// `tableNameMappings`
std::map<std::string, std::string> tableNameMappings;

#if defined(OPENTELEMETRY_ATTRIBUTE_TIMESTAMP_PREVIEW)

std::set<std::string> timestampAttributes; // Attributes to use as timestamp

#endif // defined(OPENTELEMETRY_ATTRIBUTE_TIMESTAMP_PREVIEW)

} TelemetryProviderConfiguration;

/**
Expand Down
35 changes: 35 additions & 0 deletions exporters/etw/include/opentelemetry/exporters/etw/etw_logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,35 @@ class Logger : public opentelemetry::logs::Logger
}
evt[ETW_FIELD_LOG_SEVERITY_NUM] = static_cast<uint32_t>(severity);
evt[ETW_FIELD_LOG_BODY] = std::string(body.data(), body.length());

#if defined(OPENTELEMETRY_ATTRIBUTE_TIMESTAMP_PREVIEW)

for (const auto &attr : cfg.timestampAttributes)
{
auto it = evt.find(attr);
if (it != evt.end())
{
auto value_index = it->second.index();
if (value_index != exporter_etw::PropertyType::kTypeInt64 &&
value_index != exporter_etw::PropertyType::kTypeUInt64)
{
continue;
}
int64_t filetime = value_index == exporter_etw::PropertyType::kTypeUInt64
? nostd::get<uint64_t>(it->second)
: nostd::get<int64_t>(it->second);
constexpr int64_t FILETIME_EPOCH_DIFF = 11644473600LL; // Seconds from 1601 to 1970
constexpr int64_t HUNDRED_NANOSECONDS_PER_SECOND = 10000000LL;
int64_t unix_time_seconds =
(filetime / HUNDRED_NANOSECONDS_PER_SECOND) - FILETIME_EPOCH_DIFF;
int64_t unix_time_nanos =
unix_time_seconds * 1'000'000'000 + (filetime % HUNDRED_NANOSECONDS_PER_SECOND) * 100;
it->second = utils::formatUtcTimestampNsAsISO8601(unix_time_nanos);
}
}

#endif // defined(OPENTELEMETRY_ATTRIBUTE_TIMESTAMP_PREVIEW)

etwProvider().write(provHandle, evt, nullptr, nullptr, 0, encoding);
}

Expand Down Expand Up @@ -354,6 +383,12 @@ class LoggerProvider : public opentelemetry::logs::LoggerProvider
GetOption(options, "enableTableNameMappings", config_.enableTableNameMappings, false);
GetOption(options, "tableNameMappings", config_.tableNameMappings, {});

#if defined(OPENTELEMETRY_ATTRIBUTE_TIMESTAMP_PREVIEW)

GetOption(options, "timestampAttributes", config_.timestampAttributes, {});

#endif // defined(OPENTELEMETRY_ATTRIBUTE_TIMESTAMP_PREVIEW)

// Determines what encoding to use for ETW events: TraceLogging Dynamic, MsgPack, XML, etc.
config_.encoding = GetEncoding(options);
}
Expand Down
49 changes: 49 additions & 0 deletions exporters/etw/test/etw_logger_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@

# include <gtest/gtest.h>
# include <map>
# include <set>
# include <string>

# define OPENTELEMETRY_ATTRIBUTE_TIMESTAMP_PREVIEW

# include "opentelemetry/exporters/etw/etw_logger_exporter.h"
# include "opentelemetry/sdk/trace/simple_processor.h"

Expand Down Expand Up @@ -146,4 +149,50 @@ TEST(ETWLogger, LoggerCheckWithTableNameMappings)
logger->Debug("This is a debug log body", 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",
* "tiemstamp1": "2025-02-20T19:18:11.048166700Z",
* "attrib2": "value2",
* "body": "This is a debug log body",
* "severityNumber": 5,
* "severityText": "DEBUG"
* }
* }
*
*/

TEST(ETWLogger, LoggerCheckWithTimestampAttributes)
{
std::string providerName = kGlobalProviderName; // supply unique instrumentation name here
std::set<std::string> timestampAttributes = {{"timestamp1"}};
exporter::etw::TelemetryProviderOptions options = {{"timestampAttributes", timestampAttributes}};
exporter::etw::LoggerProvider lp{options};

auto logger = lp.GetLogger(providerName, "name1");

// Log attributes
Properties attribs = {{"timestamp1", 133845526910481667ULL}, {"attrib2", "value2"}};

EXPECT_NO_THROW(
logger->Debug("This is a debug log body", opentelemetry::common::MakeAttributes(attribs)));
}

#endif // _WIN32
Loading