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 Log Exporter #1006

Merged
merged 11 commits into from
Oct 6, 2021
9 changes: 9 additions & 0 deletions exporters/etw/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ install(
if(BUILD_TESTING)
add_executable(etw_provider_test test/etw_provider_test.cc)
add_executable(etw_tracer_test test/etw_tracer_test.cc)
add_executable(etw_logger_test test/etw_logger_test.cc)

add_executable(etw_perf_test test/etw_perf_test.cc)

target_link_libraries(etw_provider_test ${GTEST_BOTH_LIBRARIES}
Expand All @@ -35,6 +37,9 @@ if(BUILD_TESTING)
target_link_libraries(etw_tracer_test ${GTEST_BOTH_LIBRARIES}
opentelemetry_exporter_etw ${CMAKE_THREAD_LIBS_INIT})

target_link_libraries(etw_logger_test ${GTEST_BOTH_LIBRARIES}
opentelemetry_exporter_etw ${CMAKE_THREAD_LIBS_INIT})

target_link_libraries(
etw_perf_test benchmark::benchmark ${GTEST_BOTH_LIBRARIES}
opentelemetry_exporter_etw ${CMAKE_THREAD_LIBS_INIT})
Expand All @@ -47,5 +52,9 @@ if(BUILD_TESTING)
TARGET etw_tracer_test
TEST_PREFIX exporter.
TEST_LIST etw_tracer_test)
gtest_add_tests(
TARGET etw_logger_test
TEST_PREFIX exporter.
TEST_LIST etw_logger_test)

endif() # BUILD_TESTING
186 changes: 186 additions & 0 deletions exporters/etw/include/opentelemetry/exporters/etw/etw_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#pragma once
#include <map>

#include "opentelemetry/nostd/shared_ptr.h"
#include "opentelemetry/nostd/string_view.h"
#include "opentelemetry/nostd/unique_ptr.h"
#include "opentelemetry/nostd/variant.h"
#include "opentelemetry/trace/span_id.h"

#include "opentelemetry/exporters/etw/etw_provider.h"

OPENTELEMETRY_BEGIN_NAMESPACE
namespace exporter
{
namespace etw
{
/**
* @brief TelemetryProvider Options passed via SDK API.
*/
using TelemetryProviderOptions =
std::map<std::string, nostd::variant<std::string, uint64_t, float, bool>>;

/**
* @brief TelemetryProvider runtime configuration class. Internal representation
* of TelemetryProviderOptions used by various components of SDK.
*/
typedef struct
{
bool enableTraceId; // Set `TraceId` on ETW events
bool enableSpanId; // Set `SpanId` on ETW events
bool enableActivityId; // Assign `SpanId` to `ActivityId`
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: keep alignment of comments?

Copy link
Member Author

@lalitb lalitb Oct 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-format tool format this way to keep under configured line limit :)

ColumnLimit: 100

ETWProvider::EventFormat
encoding; // Event encoding to use for this provider (TLD, MsgPack, XML, etc.).
} TelemetryProviderConfiguration;

/**
* @brief Helper template to convert a variant value from TelemetryProviderOptions to
* LoggerProviderConfiguration
*
* @param options TelemetryProviderOptions passed on API surface
* @param key Option name
* @param value Reference to destination value
* @param defaultValue Default value if option is not supplied
*/
template <typename T>
static inline void GetOption(const TelemetryProviderOptions &options,
const char *key,
T &value,
T defaultValue)
{
auto it = options.find(key);
if (it != options.end())
{
auto val = it->second;
value = nostd::get<T>(val);
}
else
{
value = defaultValue;
}
}

/**
* @brief Helper template to convert encoding config option to EventFormat.
* Configuration option passed as `options["encoding"] = "MsgPack"`.
* Default encoding is TraceLogging Dynamic Manifest (TLD).
*
* Valid encoding names listed below.
*
* For MessagePack encoding:
* - "MSGPACK"
* - "MsgPack"
* - "MessagePack"
*
* For XML encoding:
* - "XML"
* - "xml"
*
* For TraceLogging Dynamic encoding:
* - "TLD"
* - "tld"
*
*/
static inline ETWProvider::EventFormat GetEncoding(const TelemetryProviderOptions &options)
{
ETWProvider::EventFormat evtFmt = ETWProvider::EventFormat::ETW_MANIFEST;

auto it = options.find("encoding");
if (it != options.end())
{
auto varValue = it->second;
std::string val = nostd::get<std::string>(varValue);

#pragma warning(push)
#pragma warning(disable : 4307) /* Integral constant overflow - OK while computing hash */
auto h = utils::hashCode(val.c_str());
switch (h)
{
case CONST_HASHCODE(MSGPACK):
// nobrk
case CONST_HASHCODE(MsgPack):
// nobrk
case CONST_HASHCODE(MessagePack):
evtFmt = ETWProvider::EventFormat::ETW_MSGPACK;
break;

case CONST_HASHCODE(XML):
// nobrk
case CONST_HASHCODE(xml):
evtFmt = ETWProvider::EventFormat::ETW_XML;
break;

case CONST_HASHCODE(TLD):
// nobrk
case CONST_HASHCODE(tld):
// nobrk
evtFmt = ETWProvider::EventFormat::ETW_MANIFEST;
break;

default:
break;
}
#pragma warning(pop)
}

return evtFmt;
}

/**
* @brief Utility template to obtain etw::TracerProvider._config or etw::LoggerProvider._config
*
* @tparam T etw::TracerProvider
* @param t etw::TracerProvider ref
* @return TelemetryProviderConfiguration ref
*/
template <class T>
TelemetryProviderConfiguration &GetConfiguration(T &t)
{
return t.config_;
}

/**
* @brief Utility template to convert SpanId or TraceId to hex.
* @param id - value of SpanId or TraceId
* @return Hexadecimal representation of Id as string.
*/
template <class T>
static inline std::string ToLowerBase16(const T &id)
{
char buf[2 * T::kSize] = {0};
id.ToLowerBase16(buf);
return std::string(buf, sizeof(buf));
}

/**
* @brief Utility method to convert span_id (8 byte) to ActivityId GUID (16 bytes)
* @param span OpenTelemetry Span Id object
* @return GUID struct containing 8-bytes of SpanId + 8 NUL bytes.
*/
static inline bool CopySpanIdToActivityId(const opentelemetry::trace::SpanId &span_id,
GUID &outGuid)
{
memset(&outGuid, 0, sizeof(outGuid));
if (!span_id.IsValid())
{
return false;
}
auto spanId = span_id.Id().data();
uint8_t *guidPtr = reinterpret_cast<uint8_t *>(&outGuid);
for (size_t i = 0; i < 8; i++)
{
guidPtr[i] = spanId[i];
}
return true;
}

} // namespace etw
} // namespace exporter
OPENTELEMETRY_END_NAMESPACE
10 changes: 10 additions & 0 deletions exporters/etw/include/opentelemetry/exporters/etw/etw_fields.h
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,22 @@
# define ETW_FIELD_STATUSCODE "StatusCode" /* Span status code */
# define ETW_FIELD_STATUSMESSAGE "StatusMessage" /* Span status message */
# define ETW_FIELD_SUCCESS "Success" /* Span success */
# define ETW_FIELD_TIMESTAMP "Timestamp" /* Log timestamp */
lalitb marked this conversation as resolved.
Show resolved Hide resolved

/* Value constants */
# define ETW_VALUE_SPAN "Span" /* ETW event name for Span */
# define ETW_VALUE_LOG "Log" /* ETW event name for Log */
lalitb marked this conversation as resolved.
Show resolved Hide resolved

# define ETW_VALUE_SPAN_START "SpanStart" /* ETW for Span Start */
# define ETW_VALUE_SPAN_END "SpanEnd" /* ETW for Span Start */


/* Log specific */
# define ETW_FIELD_LOG_BODY "body" /* Log body */
lalitb marked this conversation as resolved.
Show resolved Hide resolved
# define ETW_FIELD_LOG_SEVERITY_TEXT "severityText" /* Sev text */
# define ETW_FIELD_LOG_SEVERITY_NUM "severityNumber" /* Sev num */
lalitb marked this conversation as resolved.
Show resolved Hide resolved


#endif

/* clang-format on */
Loading