// Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 #include #include #include #include #include #include #include "opentelemetry/common/key_value_iterable_view.h" #include "opentelemetry/context/context_value.h" // IWYU pragma: keep #include "opentelemetry/exporters/memory/in_memory_span_exporter.h" #include "opentelemetry/nostd/shared_ptr.h" #include "opentelemetry/sdk/resource/resource.h" #include "opentelemetry/sdk/trace/exporter.h" #include "opentelemetry/sdk/trace/processor.h" #include "opentelemetry/sdk/trace/sampler.h" #include "opentelemetry/sdk/trace/samplers/always_off.h" #include "opentelemetry/sdk/trace/samplers/always_on.h" #include "opentelemetry/sdk/trace/samplers/parent.h" #include "opentelemetry/sdk/trace/samplers/trace_id_ratio.h" #include "opentelemetry/sdk/trace/simple_processor.h" #include "opentelemetry/sdk/trace/tracer.h" #include "opentelemetry/sdk/trace/tracer_context.h" #include "opentelemetry/trace/span.h" #include "opentelemetry/trace/span_context.h" #include "opentelemetry/trace/span_context_kv_iterable_view.h" #include "opentelemetry/trace/span_metadata.h" #include "opentelemetry/trace/trace_id.h" #include "opentelemetry/trace/tracer.h" using namespace opentelemetry::sdk::trace; using opentelemetry::exporter::memory::InMemorySpanExporter; using opentelemetry::trace::SpanContext; namespace { // Sampler constructor used as a baseline to compare with other samplers void BM_AlwaysOffSamplerConstruction(benchmark::State &state) { while (state.KeepRunning()) { benchmark::DoNotOptimize(AlwaysOffSampler()); } } BENCHMARK(BM_AlwaysOffSamplerConstruction); // Sampler constructor used as a baseline to compare with other samplers void BM_AlwaysOnSamplerConstruction(benchmark::State &state) { while (state.KeepRunning()) { benchmark::DoNotOptimize(AlwaysOnSampler()); } } BENCHMARK(BM_AlwaysOnSamplerConstruction); /* Fails to build with GCC. See upstream bug: https://github.com/google/benchmark/issues/1675 */ #if 0 void BM_ParentBasedSamplerConstruction(benchmark::State &state) { while (state.KeepRunning()) { benchmark::DoNotOptimize(ParentBasedSampler(std::make_shared())); } } BENCHMARK(BM_ParentBasedSamplerConstruction); void BM_TraceIdRatioBasedSamplerConstruction(benchmark::State &state) { while (state.KeepRunning()) { benchmark::DoNotOptimize(TraceIdRatioBasedSampler(0.01)); } } BENCHMARK(BM_TraceIdRatioBasedSamplerConstruction); #endif // Sampler Helper Function void BenchmarkShouldSampler(Sampler &sampler, benchmark::State &state) { opentelemetry::trace::TraceId trace_id; opentelemetry::trace::SpanKind span_kind = opentelemetry::trace::SpanKind::kInternal; using M = std::map; M m1 = {{}}; using L = std::vector>>; L l1 = {{opentelemetry::trace::SpanContext(false, false), {}}, {opentelemetry::trace::SpanContext(false, false), {}}}; opentelemetry::common::KeyValueIterableView view{m1}; opentelemetry::trace::SpanContextKeyValueIterableView links{l1}; while (state.KeepRunning()) { auto invalid_ctx = SpanContext::GetInvalid(); benchmark::DoNotOptimize( sampler.ShouldSample(invalid_ctx, trace_id, "", span_kind, view, links)); } } // Sampler used as a baseline to compare with other samplers void BM_AlwaysOffSamplerShouldSample(benchmark::State &state) { AlwaysOffSampler sampler; BenchmarkShouldSampler(sampler, state); } BENCHMARK(BM_AlwaysOffSamplerShouldSample); // Sampler used as a baseline to compare with other samplers void BM_AlwaysOnSamplerShouldSample(benchmark::State &state) { AlwaysOnSampler sampler; BenchmarkShouldSampler(sampler, state); } BENCHMARK(BM_AlwaysOnSamplerShouldSample); void BM_ParentBasedSamplerShouldSample(benchmark::State &state) { ParentBasedSampler sampler(std::make_shared()); BenchmarkShouldSampler(sampler, state); } BENCHMARK(BM_ParentBasedSamplerShouldSample); void BM_TraceIdRatioBasedSamplerShouldSample(benchmark::State &state) { TraceIdRatioBasedSampler sampler(0.01); BenchmarkShouldSampler(sampler, state); } BENCHMARK(BM_TraceIdRatioBasedSamplerShouldSample); // Sampler Helper Function void BenchmarkSpanCreation(std::unique_ptr &&sampler, benchmark::State &state) { std::unique_ptr exporter(new InMemorySpanExporter()); std::unique_ptr processor(new SimpleSpanProcessor(std::move(exporter))); std::vector> processors; processors.push_back(std::move(processor)); auto resource = opentelemetry::sdk::resource::Resource::Create({}); auto context = std::make_shared(std::move(processors), resource, std::move(sampler)); auto tracer = std::shared_ptr(new Tracer(context)); while (state.KeepRunning()) { auto span = tracer->StartSpan("span"); span->SetAttribute("attr1", 3.1); span->End(); } } // Test to measure performance for span creation void BM_SpanCreation(benchmark::State &state) { std::unique_ptr sampler(new AlwaysOnSampler()); BenchmarkSpanCreation(std::move(sampler), state); } BENCHMARK(BM_SpanCreation); // Test to measure performance overhead for no-op span creation void BM_NoopSpanCreation(benchmark::State &state) { std::unique_ptr sampler(new AlwaysOffSampler()); BenchmarkSpanCreation(std::move(sampler), state); } BENCHMARK(BM_NoopSpanCreation); } // namespace BENCHMARK_MAIN();