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

[SDK] Add tracer scope configurator #3137

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ae5cdf4
Add tracer_config as per spec
psx95 Nov 8, 2024
9117eff
Update formatting
psx95 Nov 11, 2024
127311b
TracerProvider uses TracerConfig as per spec
psx95 Nov 12, 2024
20cb4e9
Fix iwyu warnings generated
psx95 Nov 13, 2024
df36a54
Fix formatting
psx95 Nov 13, 2024
a80800e
Replace scope_configurator class with typedef
psx95 Nov 13, 2024
694f9c0
Update factories to accept TracerConfigurator
psx95 Nov 14, 2024
f815c3e
Fix IWYU warnings
psx95 Nov 14, 2024
9b89786
Add operator overload to check for equality
psx95 Nov 14, 2024
541c0eb
Add tests for TracerConfig
psx95 Nov 14, 2024
a67ea85
Fix formatting
psx95 Nov 14, 2024
bcd6e94
Fix memory leak issue in test
psx95 Nov 14, 2024
2e2afd4
Replace typedef with type alias
psx95 Nov 15, 2024
4de93cb
Infer trace_config from the context
psx95 Nov 15, 2024
cfd9730
Add tests for Tracer
psx95 Nov 15, 2024
47acb3f
Fix iwyu warnings
psx95 Nov 16, 2024
f7dde19
Add unit test for custom configurator
psx95 Nov 18, 2024
d87997d
Add documentation for the tracer_config.h
psx95 Nov 18, 2024
2f1ee38
Update Changelog
psx95 Nov 18, 2024
31c73a3
Address comments in tracer: fix logic
psx95 Dec 4, 2024
5f6a95f
Add scope_configurator_builder for better class structure
psx95 Dec 5, 2024
501fa47
ScopeConfigurator: make builder inner class
psx95 Dec 6, 2024
c2bf6f9
Fix iwyu warnings
psx95 Dec 6, 2024
47dd040
Add unit test for condition ordering
psx95 Dec 6, 2024
98ca2c3
Remove accidental changes from instrumentation_scope.h
psx95 Dec 6, 2024
be16f38
Merge branch 'main' into add-scope-config
psx95 Dec 11, 2024
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,9 @@ Increment the:
* [EXPORTER] Fix scope attributes missing from otlp traces metrics
[#3185](https://github.com/open-telemetry/opentelemetry-cpp/pull/3185)

* [SDK] Add tracer scope configurator
[#3137](https://github.com/open-telemetry/opentelemetry-cpp/pull/3137)

Important changes:

* [API] Jaeger Propagator should not be deprecated
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#pragma once
#include <functional>

#include "opentelemetry/sdk/instrumentationscope/instrumentation_scope.h"
#include "opentelemetry/version.h"

OPENTELEMETRY_BEGIN_NAMESPACE
namespace sdk
{
namespace instrumentationscope
{
/**
* A scope configurator is a function that returns the scope config for a given instrumentation
* scope.
*/
template <typename T>
class ScopeConfigurator
{
public:
/**
* A builder class for the ScopeConfigurator that facilitates the creation of ScopeConfigurators.
*/
class Builder
{
public:
/**
* Constructor for a builder object that cam be used to create a scope configurator. A minimally
* configured builder would build a ScopeConfigurator that applies the default_scope_config to
* every instrumentation scope.
* @param default_scope_config The default scope config that the built configurator should fall
* back on.
*/
explicit Builder(T default_scope_config) noexcept : default_scope_config_(default_scope_config)
{}

/**
* Allows the user to pass a generic function that evaluates an instrumentation scope through a
* boolean check. If the check passes, the provided config is applied. Conditions are evaluated
* in order.
* @param scope_matcher a function that returns true if the scope being evaluated matches the
* criteria defined by the function.
* @param scope_config the scope configuration to return for the matched scope.
* @return this
*/
Builder AddCondition(std::function<bool(const InstrumentationScope &)> scope_matcher,
T scope_config)
{
conditions_.push_back(Condition{scope_matcher, scope_config});
return *this;
}

/**
* A convenience condition that specifically matches the scope name of the scope being
* evaluated. If the scope name matches to the provided string, then the provided scope
* configuration is applied to the scope.
* @param scope_name The scope name to which the config needs to be applied.
* @param scope_config The scope config for the matching scopes.
* @return this
*/
Builder AddConditionNameEquals(nostd::string_view scope_name, T scope_config)
{
std::function<bool(const InstrumentationScope &)> name_equals_matcher =
[scope_name](const InstrumentationScope &scope_info) {
return scope_info.GetName() == scope_name;
};
conditions_.push_back(Condition{name_equals_matcher, scope_config});
return *this;
}

/**
* Constructs the scope configurator object that can be used to retrieve scope config depending
* on the instrumentation scope.
* @return a configured scope configurator.
*/
ScopeConfigurator<T> Build()
{
if (conditions_.size() == 0)
{
return ScopeConfigurator<T>(
[default_scope_config_ = this->default_scope_config_](const InstrumentationScope &) {
return default_scope_config_;
});
}

// Return a configurator that processes all the conditions
return ScopeConfigurator<T>(
[conditions_ = this->conditions_, default_scope_config_ = this->default_scope_config_](
const InstrumentationScope &scope_info) {
for (Condition condition : conditions_)
{
if (condition.scope_matcher(scope_info))
{
return condition.scope_config;
}
}
return default_scope_config_;
});
}

private:
/**
* An internal struct to encapsulate 'conditions' that can be applied to a
* ScopeConfiguratorBuilder. The applied conditions influence the behavior of the generatred
* ScopeConfigurator.
*/
struct Condition
{
std::function<bool(const InstrumentationScope &)> scope_matcher;
T scope_config;
};

T default_scope_config_;
std::vector<Condition> conditions_;
};

// Public methods for ScopeConfigurator

/**
* Invokes the underlying configurator function to get a valid scope configuration.
* @param scope_info The InstrumentationScope containing scope information for which configuration
* needs to be retrieved.
*/
T ComputeConfig(const InstrumentationScope &scope_info) const
{
return this->configurator_(scope_info);
}

private:
// Prevent direct initialization of ScopeConfigurator objects.
explicit ScopeConfigurator(std::function<T(const InstrumentationScope &)> configurator)
: configurator_(configurator)
{}

std::function<T(const InstrumentationScope &)> configurator_;
};
} // namespace instrumentationscope
} // namespace sdk
OPENTELEMETRY_END_NAMESPACE
4 changes: 4 additions & 0 deletions sdk/include/opentelemetry/sdk/trace/tracer.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
#include "opentelemetry/sdk/trace/id_generator.h"
#include "opentelemetry/sdk/trace/processor.h"
#include "opentelemetry/sdk/trace/sampler.h"
#include "opentelemetry/sdk/trace/tracer_config.h"
#include "opentelemetry/sdk/trace/tracer_context.h"
#include "opentelemetry/trace/noop.h"
#include "opentelemetry/trace/span.h"
#include "opentelemetry/trace/span_context_kv_iterable.h"
#include "opentelemetry/trace/span_startoptions.h"
Expand Down Expand Up @@ -105,6 +107,8 @@ class Tracer final : public opentelemetry::trace::Tracer,
// tracer-context.
std::shared_ptr<InstrumentationScope> instrumentation_scope_;
std::shared_ptr<TracerContext> context_;
TracerConfig tracer_config_;
static const std::shared_ptr<opentelemetry::trace::NoopTracer> kNoopTracer;
};
} // namespace trace
} // namespace sdk
Expand Down
59 changes: 59 additions & 0 deletions sdk/include/opentelemetry/sdk/trace/tracer_config.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "opentelemetry/version.h"

OPENTELEMETRY_BEGIN_NAMESPACE
namespace sdk
{
namespace trace
{
/**
* TracerConfig defines various configurable aspects of a Tracer's behavior.
* This class should not be used directly to configure a Tracer's behavior, instead a
* ScopeConfigurator should be used to compute the desired TracerConfig which can then be used to
* configure a Tracer.
*/
class TracerConfig
{
public:
bool operator==(const TracerConfig &other) const noexcept;

/**
* Returns if the Tracer is enabled or disabled. Tracers are enabled by default.
* @return a boolean indicating if the Tracer is enabled. Defaults to true.
*/
bool IsEnabled() const noexcept;

/**
* Returns a TracerConfig that represents a disabled Tracer. A disabled tracer behaves like a
* no-op tracer.
* @return a static constant TracerConfig that represents a disabled tracer.
*/
static TracerConfig Disabled();

/**
* Returns a TracerConfig that represents an enabled Tracer.
* @return a static constant TracerConfig that represents an enabled tracer.
*/
static TracerConfig Enabled();

/**
* Returns a TracerConfig that represents a Tracer configured with the default behavior.
* The default behavior is guided by the OpenTelemetry specification.
* @return a static constant TracerConfig that represents a tracer configured with default
* behavior.
*/
static TracerConfig Default();

private:
explicit TracerConfig(const bool disabled = false) : disabled_(disabled) {}
Copy link
Member

Choose a reason for hiding this comment

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

Do not use default values = false.

The choice of the default value should not be nested deep in the code, but bubble up in the call stack, up to where the decision is made to use a default.

This will be in the tracer provider factory, when no scope configurator is provided.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a private constructor, so it cannot be called externally and the value of the default is dictated by the spec.

bool disabled_;
static const TracerConfig kDefaultConfig;
static const TracerConfig kDisabledConfig;
};
} // namespace trace
} // namespace sdk
OPENTELEMETRY_END_NAMESPACE
17 changes: 16 additions & 1 deletion sdk/include/opentelemetry/sdk/trace/tracer_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
#include <memory>
#include <vector>

#include "opentelemetry/sdk/instrumentationscope/scope_configurator.h"
#include "opentelemetry/sdk/resource/resource.h"
#include "opentelemetry/sdk/trace/id_generator.h"
#include "opentelemetry/sdk/trace/processor.h"
#include "opentelemetry/sdk/trace/random_id_generator.h"
#include "opentelemetry/sdk/trace/sampler.h"
#include "opentelemetry/sdk/trace/samplers/always_on.h"
#include "opentelemetry/sdk/trace/tracer_config.h"
#include "opentelemetry/version.h"

OPENTELEMETRY_BEGIN_NAMESPACE
Expand Down Expand Up @@ -43,7 +45,12 @@ class TracerContext
opentelemetry::sdk::resource::Resource::Create({}),
std::unique_ptr<Sampler> sampler = std::unique_ptr<AlwaysOnSampler>(new AlwaysOnSampler),
std::unique_ptr<IdGenerator> id_generator =
std::unique_ptr<IdGenerator>(new RandomIdGenerator())) noexcept;
std::unique_ptr<IdGenerator>(new RandomIdGenerator()),
std::unique_ptr<instrumentationscope::ScopeConfigurator<TracerConfig>> tracer_configurator =
std::make_unique<instrumentationscope::ScopeConfigurator<TracerConfig>>(
instrumentationscope::ScopeConfigurator<TracerConfig>::Builder(
TracerConfig::Default())
.Build())) noexcept;

virtual ~TracerContext() = default;

Expand Down Expand Up @@ -77,6 +84,13 @@ class TracerContext
*/
const opentelemetry::sdk::resource::Resource &GetResource() const noexcept;

/**
* Obtain the ScopeConfigurator with this tracer context.
* @return The ScopeConfigurator for this tracer context.
*/
const instrumentationscope::ScopeConfigurator<TracerConfig> &GetTracerConfigurator()
const noexcept;

/**
* Obtain the Id Generator associated with this tracer context.
* @return The ID Generator for this tracer context.
Expand All @@ -100,6 +114,7 @@ class TracerContext
std::unique_ptr<Sampler> sampler_;
std::unique_ptr<IdGenerator> id_generator_;
std::unique_ptr<SpanProcessor> processor_;
std::unique_ptr<instrumentationscope::ScopeConfigurator<TracerConfig>> tracer_configurator_;
};

} // namespace trace
Expand Down
10 changes: 10 additions & 0 deletions sdk/include/opentelemetry/sdk/trace/tracer_context_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ class OPENTELEMETRY_EXPORT TracerContextFactory
const opentelemetry::sdk::resource::Resource &resource,
std::unique_ptr<Sampler> sampler,
std::unique_ptr<IdGenerator> id_generator);

/**
* Create a TracerContext.
*/
static std::unique_ptr<TracerContext> Create(
std::vector<std::unique_ptr<SpanProcessor>> &&processors,
const opentelemetry::sdk::resource::Resource &resource,
std::unique_ptr<Sampler> sampler,
std::unique_ptr<IdGenerator> id_generator,
std::unique_ptr<instrumentationscope::ScopeConfigurator<TracerConfig>> tracer_configurator);
};

} // namespace trace
Expand Down
16 changes: 14 additions & 2 deletions sdk/include/opentelemetry/sdk/trace/tracer_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,22 +39,34 @@ class OPENTELEMETRY_EXPORT TracerProvider final : public opentelemetry::trace::T
* not be a nullptr.
* @param id_generator The custom id generator for this tracer provider. This must
* not be a nullptr
* @param tracer_configurator Provides access to a function that computes the TracerConfig for
* Tracers provided by this TracerProvider.
*/
explicit TracerProvider(
std::unique_ptr<SpanProcessor> processor,
const opentelemetry::sdk::resource::Resource &resource =
opentelemetry::sdk::resource::Resource::Create({}),
std::unique_ptr<Sampler> sampler = std::unique_ptr<AlwaysOnSampler>(new AlwaysOnSampler),
std::unique_ptr<IdGenerator> id_generator =
std::unique_ptr<IdGenerator>(new RandomIdGenerator())) noexcept;
std::unique_ptr<IdGenerator>(new RandomIdGenerator()),
std::unique_ptr<instrumentationscope::ScopeConfigurator<TracerConfig>> tracer_configurator =
std::make_unique<instrumentationscope::ScopeConfigurator<TracerConfig>>(
instrumentationscope::ScopeConfigurator<TracerConfig>::Builder(
TracerConfig::Default())
.Build())) noexcept;

explicit TracerProvider(
std::vector<std::unique_ptr<SpanProcessor>> &&processors,
const opentelemetry::sdk::resource::Resource &resource =
opentelemetry::sdk::resource::Resource::Create({}),
std::unique_ptr<Sampler> sampler = std::unique_ptr<AlwaysOnSampler>(new AlwaysOnSampler),
std::unique_ptr<IdGenerator> id_generator =
std::unique_ptr<IdGenerator>(new RandomIdGenerator())) noexcept;
std::unique_ptr<IdGenerator>(new RandomIdGenerator()),
std::unique_ptr<instrumentationscope::ScopeConfigurator<TracerConfig>> tracer_configurator =
std::make_unique<instrumentationscope::ScopeConfigurator<TracerConfig>>(
instrumentationscope::ScopeConfigurator<TracerConfig>::Builder(
TracerConfig::Default())
.Build())) noexcept;

/**
* Initialize a new tracer provider with a specified context
Expand Down
18 changes: 16 additions & 2 deletions sdk/include/opentelemetry/sdk/trace/tracer_provider_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace trace
class OPENTELEMETRY_EXPORT TracerProviderFactory
{
public:
/* Serie of builders with a single processor. */
/* Series of creator methods with a single processor. */

static std::unique_ptr<opentelemetry::sdk::trace::TracerProvider> Create(
std::unique_ptr<SpanProcessor> processor);
Expand All @@ -48,7 +48,14 @@ class OPENTELEMETRY_EXPORT TracerProviderFactory
std::unique_ptr<Sampler> sampler,
std::unique_ptr<IdGenerator> id_generator);

/* Serie of builders with a vector of processor. */
static std::unique_ptr<opentelemetry::sdk::trace::TracerProvider> Create(
std::unique_ptr<SpanProcessor> processor,
const opentelemetry::sdk::resource::Resource &resource,
std::unique_ptr<Sampler> sampler,
std::unique_ptr<IdGenerator> id_generator,
std::unique_ptr<instrumentationscope::ScopeConfigurator<TracerConfig>> tracer_configurator);

/* Series of creator methods with a single processor. */

static std::unique_ptr<opentelemetry::sdk::trace::TracerProvider> Create(
std::vector<std::unique_ptr<SpanProcessor>> &&processors);
Expand All @@ -68,6 +75,13 @@ class OPENTELEMETRY_EXPORT TracerProviderFactory
std::unique_ptr<Sampler> sampler,
std::unique_ptr<IdGenerator> id_generator);

static std::unique_ptr<opentelemetry::sdk::trace::TracerProvider> Create(
std::vector<std::unique_ptr<SpanProcessor>> &&processors,
const opentelemetry::sdk::resource::Resource &resource,
std::unique_ptr<Sampler> sampler,
std::unique_ptr<IdGenerator> id_generator,
std::unique_ptr<instrumentationscope::ScopeConfigurator<TracerConfig>> tracer_configurator);

/* Create with a tracer context. */

static std::unique_ptr<opentelemetry::sdk::trace::TracerProvider> Create(
Expand Down
3 changes: 2 additions & 1 deletion sdk/src/trace/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ add_library(
samplers/trace_id_ratio.cc
samplers/trace_id_ratio_factory.cc
random_id_generator.cc
random_id_generator_factory.cc)
random_id_generator_factory.cc
tracer_config.cc)

set_target_properties(opentelemetry_trace PROPERTIES EXPORT_NAME trace)
set_target_version(opentelemetry_trace)
Expand Down
Loading
Loading