-
Notifications
You must be signed in to change notification settings - Fork 446
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 Exporter - Add support for Sampler and ID Generator #1547
Changes from 9 commits
1dd5b5f
baa4b06
ddb47c9
9f48332
0dc35b7
cc1035f
5e3a17c
f2f4f10
bd68184
3773f51
9381a99
beee84b
e0ddc94
3f7bb6a
2760e06
ceef1e9
9edcb10
8456710
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// Copyright The OpenTelemetry Authors | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
#pragma once | ||
#include "opentelemetry/sdk/trace/id_generator.h" | ||
#include "opentelemetry/version.h" | ||
|
||
#ifdef _WIN32 | ||
# include "Windows.h" | ||
#endif | ||
|
||
OPENTELEMETRY_BEGIN_NAMESPACE | ||
namespace sdk | ||
{ | ||
namespace trace | ||
{ | ||
|
||
class ETWRandomIdGenerator : public IdGenerator | ||
{ | ||
|
||
opentelemetry::trace::SpanId GenerateSpanId() noexcept override | ||
{ | ||
GUID span_id; | ||
// Generate random GUID | ||
CoCreateGuid(&span_id); | ||
const auto *spanIdPtr = reinterpret_cast<const uint8_t *>(std::addressof(span_id)); | ||
|
||
// Populate SpanId with that GUID | ||
nostd::span<const uint8_t, opentelemetry::trace::SpanId::kSize> spanIdBytes( | ||
spanIdPtr, spanIdPtr + opentelemetry::trace::SpanId::kSize); | ||
return opentelemetry::trace::SpanId(spanIdBytes); | ||
} | ||
|
||
opentelemetry::trace::TraceId GenerateTraceId() noexcept override | ||
{ | ||
GUID trace_id; | ||
CoCreateGuid(&trace_id); | ||
// Populate TraceId of the Tracer with the above GUID | ||
const auto *traceIdPtr = reinterpret_cast<const uint8_t *>(std::addressof(trace_id)); | ||
nostd::span<const uint8_t, opentelemetry::trace::TraceId::kSize> traceIdBytes( | ||
traceIdPtr, traceIdPtr + opentelemetry::trace::TraceId::kSize); | ||
return opentelemetry::trace::TraceId(traceIdBytes); | ||
} | ||
}; | ||
} // namespace trace | ||
} // namespace sdk | ||
OPENTELEMETRY_END_NAMESPACE |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,18 +26,21 @@ | |
|
||
#include "opentelemetry/common/key_value_iterable_view.h" | ||
|
||
#include "opentelemetry/trace/span.h" | ||
#include "opentelemetry/trace/noop.h" | ||
//#include "opentelemetry/trace/span.h" | ||
#include "opentelemetry/trace/span_context_kv_iterable_view.h" | ||
#include "opentelemetry/trace/span_id.h" | ||
#include "opentelemetry/trace/trace_id.h" | ||
#include "opentelemetry/trace/tracer_provider.h" | ||
|
||
#include "opentelemetry/sdk/trace/exporter.h" | ||
#include "opentelemetry/sdk/trace/samplers/always_on.h" | ||
|
||
#include "opentelemetry/exporters/etw/etw_config.h" | ||
#include "opentelemetry/exporters/etw/etw_fields.h" | ||
#include "opentelemetry/exporters/etw/etw_properties.h" | ||
#include "opentelemetry/exporters/etw/etw_provider.h" | ||
#include "opentelemetry/exporters/etw/etw_random_id_generator.h" | ||
#include "opentelemetry/exporters/etw/utils.h" | ||
|
||
OPENTELEMETRY_BEGIN_NAMESPACE | ||
|
@@ -154,7 +157,9 @@ void UpdateStatus(T &t, Properties &props) | |
/** | ||
* @brief Tracer class that allows to send spans to ETW Provider. | ||
*/ | ||
class Tracer : public opentelemetry::trace::Tracer | ||
|
||
class Tracer : public opentelemetry::trace::Tracer, | ||
public std::enable_shared_from_this<trace::Tracer> | ||
{ | ||
|
||
/** | ||
|
@@ -353,14 +358,7 @@ class Tracer : public opentelemetry::trace::Tracer | |
encoding(encoding), | ||
provHandle(initProvHandle()) | ||
{ | ||
// Generate random GUID | ||
GUID trace_id; | ||
CoCreateGuid(&trace_id); | ||
// Populate TraceId of the Tracer with the above GUID | ||
const auto *traceIdPtr = reinterpret_cast<const uint8_t *>(std::addressof(trace_id)); | ||
nostd::span<const uint8_t, opentelemetry::trace::TraceId::kSize> traceIdBytes( | ||
traceIdPtr, traceIdPtr + opentelemetry::trace::TraceId::kSize); | ||
traceId_ = opentelemetry::trace::TraceId(traceIdBytes); | ||
traceId_ = GetIdGenerator(tracerProvider_).GenerateTraceId(); | ||
} | ||
|
||
/** | ||
|
@@ -377,6 +375,30 @@ class Tracer : public opentelemetry::trace::Tracer | |
const opentelemetry::trace::SpanContextKeyValueIterable &links, | ||
const opentelemetry::trace::StartSpanOptions &options = {}) noexcept override | ||
{ | ||
const auto &cfg = GetConfiguration(tracerProvider_); | ||
|
||
// Parent Context: | ||
// - either use current span | ||
// - or attach to parent SpanContext specified in options | ||
opentelemetry::trace::SpanContext parentContext = GetCurrentSpan()->GetContext(); | ||
if (nostd::holds_alternative<opentelemetry::trace::SpanContext>(options.parent)) | ||
{ | ||
auto span_context = nostd::get<opentelemetry::trace::SpanContext>(options.parent); | ||
if (span_context.IsValid()) | ||
{ | ||
parentContext = span_context; | ||
} | ||
} | ||
auto sampling_result = | ||
GetSampler(tracerProvider_) | ||
.ShouldSample(parentContext, traceId_, name, options.kind, attributes, links); | ||
if (sampling_result.decision == sdk::trace::Decision::DROP) | ||
{ | ||
static nostd::shared_ptr<trace::Span> noop_span( | ||
new trace::NoopSpan{this->shared_from_this()}); | ||
return noop_span; | ||
} | ||
|
||
#ifdef OPENTELEMETRY_RTTI_ENABLED | ||
common::KeyValueIterable &attribs = const_cast<common::KeyValueIterable &>(attributes); | ||
Properties *evt = dynamic_cast<Properties *>(&attribs); | ||
|
@@ -686,27 +708,6 @@ class Span : public opentelemetry::trace::Span | |
|
||
opentelemetry::trace::SpanContext context_; | ||
|
||
const opentelemetry::trace::SpanContext CreateContext() | ||
{ | ||
GUID activity_id; | ||
// Generate random GUID | ||
CoCreateGuid(&activity_id); | ||
const auto *activityIdPtr = reinterpret_cast<const uint8_t *>(std::addressof(activity_id)); | ||
|
||
// Populate SpanId with that GUID | ||
nostd::span<const uint8_t, opentelemetry::trace::SpanId::kSize> spanIdBytes( | ||
activityIdPtr, activityIdPtr + opentelemetry::trace::SpanId::kSize); | ||
const opentelemetry::trace::SpanId spanId(spanIdBytes); | ||
|
||
// Inherit trace_id from Tracer | ||
const opentelemetry::trace::TraceId traceId{owner_.trace_id()}; | ||
// TODO: TraceFlags are not supported by ETW exporter. | ||
const opentelemetry::trace::TraceFlags flags{0}; | ||
// TODO: Remote parent is not supported by ETW exporter. | ||
const bool hasRemoteParent = false; | ||
return opentelemetry::trace::SpanContext{traceId, spanId, flags, hasRemoteParent}; | ||
} | ||
|
||
public: | ||
/** | ||
* @brief Update Properties object with current Span status | ||
|
@@ -764,7 +765,8 @@ class Span : public opentelemetry::trace::Span | |
start_time_(std::chrono::system_clock::now()), | ||
owner_(owner), | ||
parent_(parent), | ||
context_(CreateContext()) | ||
context_{owner.traceId_, GetIdGenerator(owner.tracerProvider_).GenerateSpanId(), | ||
opentelemetry::trace::TraceFlags{0}, false} | ||
{ | ||
name_ = name; | ||
UNREFERENCED_PARAMETER(options); | ||
|
@@ -920,11 +922,31 @@ class TracerProvider : public opentelemetry::trace::TracerProvider | |
*/ | ||
TelemetryProviderConfiguration config_; | ||
|
||
/** | ||
* @brief Sampler configured | ||
* | ||
*/ | ||
std::unique_ptr<sdk::trace::Sampler> sampler_; | ||
|
||
/** | ||
* @brief IdGenerator for trace_id and span_id | ||
* | ||
*/ | ||
std::unique_ptr<sdk::trace::IdGenerator> id_generator_; | ||
|
||
/** | ||
* @brief Construct instance of TracerProvider with given options | ||
* @param options Configuration options | ||
*/ | ||
TracerProvider(TelemetryProviderOptions options) : opentelemetry::trace::TracerProvider() | ||
TracerProvider(TelemetryProviderOptions options, | ||
std::unique_ptr<sdk::trace::Sampler> sampler = | ||
std::unique_ptr<sdk::trace::AlwaysOnSampler>(new sdk::trace::AlwaysOnSampler), | ||
std::unique_ptr<sdk::trace::IdGenerator> id_generator = | ||
std::unique_ptr<opentelemetry::sdk::trace::IdGenerator>( | ||
new sdk::trace::ETWRandomIdGenerator())) | ||
: opentelemetry::trace::TracerProvider(), | ||
sampler_{std::move(sampler)}, | ||
id_generator_{std::move(id_generator)} | ||
{ | ||
// By default we ensure that all events carry their with TraceId and SpanId | ||
GetOption(options, "enableTraceId", config_.enableTraceId, true); | ||
|
@@ -955,7 +977,11 @@ class TracerProvider : public opentelemetry::trace::TracerProvider | |
config_.encoding = GetEncoding(options); | ||
} | ||
|
||
TracerProvider() : opentelemetry::trace::TracerProvider() | ||
TracerProvider() | ||
: opentelemetry::trace::TracerProvider(), | ||
sampler_{std::unique_ptr<sdk::trace::AlwaysOnSampler>(new sdk::trace::AlwaysOnSampler)}, | ||
id_generator_{std::unique_ptr<opentelemetry::sdk::trace::IdGenerator>( | ||
new sdk::trace::ETWRandomIdGenerator())} | ||
{ | ||
config_.enableTraceId = true; | ||
config_.enableSpanId = true; | ||
|
@@ -985,8 +1011,9 @@ class TracerProvider : public opentelemetry::trace::TracerProvider | |
UNREFERENCED_PARAMETER(args); | ||
UNREFERENCED_PARAMETER(schema_url); | ||
ETWProvider::EventFormat evtFmt = config_.encoding; | ||
return nostd::shared_ptr<opentelemetry::trace::Tracer>{new (std::nothrow) | ||
std::shared_ptr<opentelemetry::trace::Tracer> tracer{new (std::nothrow) | ||
Tracer(*this, name, evtFmt)}; | ||
return nostd::shared_ptr<opentelemetry::trace::Tracer>{tracer}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ThomsonTan - Can you please review this PR when you have time? The changes were crashing earlier while creating Spans that are not sampled. The fix is to create the |
||
} | ||
}; | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this neede?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not required. Removed now.