1+ // Copyright The OpenTelemetry Authors
2+ // SPDX-License-Identifier: Apache-2.0
3+
4+ // Example demonstrating export_unsampled_spans feature
5+ // This example shows how to configure span processors to export unsampled spans
6+
7+ #include < iostream>
8+ #include < memory>
9+
10+ #include " opentelemetry/sdk/trace/batch_span_processor.h"
11+ #include " opentelemetry/sdk/trace/batch_span_processor_options.h"
12+ #include " opentelemetry/sdk/trace/simple_processor.h"
13+ #include " opentelemetry/sdk/trace/simple_processor_options.h"
14+ #include " opentelemetry/sdk/trace/span_data.h"
15+ #include " opentelemetry/trace/span_context.h"
16+ #include " opentelemetry/trace/trace_flags.h"
17+
18+ namespace trace_sdk = opentelemetry::sdk::trace;
19+ namespace trace_api = opentelemetry::trace;
20+
21+ // Simple mock exporter for demonstration
22+ class MockExporter : public trace_sdk ::SpanExporter
23+ {
24+ public:
25+ explicit MockExporter (const std::string &name) : name_(name) {}
26+
27+ std::unique_ptr<trace_sdk::Recordable> MakeRecordable () noexcept override
28+ {
29+ return std::make_unique<trace_sdk::SpanData>();
30+ }
31+
32+ opentelemetry::sdk::common::ExportResult Export (
33+ const opentelemetry::nostd::span<std::unique_ptr<trace_sdk::Recordable>>
34+ &recordables) noexcept override
35+ {
36+ std::cout << name_ << " exported " << recordables.size () << " spans" << std::endl;
37+ return opentelemetry::sdk::common::ExportResult::kSuccess ;
38+ }
39+
40+ bool ForceFlush (std::chrono::microseconds) noexcept override { return true ; }
41+ bool Shutdown (std::chrono::microseconds) noexcept override { return true ; }
42+
43+ private:
44+ std::string name_;
45+ };
46+
47+ // Create a test span with specific sampling status
48+ std::unique_ptr<trace_sdk::SpanData> CreateTestSpan (bool sampled)
49+ {
50+ auto span = std::make_unique<trace_sdk::SpanData>();
51+ span->SetName (" test_span" );
52+
53+ // Set up valid context with proper sampling
54+ trace_api::TraceFlags flags (sampled ? trace_api::TraceFlags::kIsSampled : 0 );
55+ uint8_t trace_id_bytes[16 ] = {1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , 16 };
56+ uint8_t span_id_bytes[8 ] = {1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 };
57+
58+ trace_api::TraceId trace_id{opentelemetry::nostd::span<const uint8_t , 16 >(trace_id_bytes)};
59+ trace_api::SpanId span_id{opentelemetry::nostd::span<const uint8_t , 8 >(span_id_bytes)};
60+
61+ trace_api::SpanContext context (trace_id, span_id, flags, false );
62+ span->SetIdentity (context, trace_api::SpanId ());
63+
64+ return span;
65+ }
66+
67+ int main ()
68+ {
69+ std::cout << " OpenTelemetry C++ Export Unsampled Spans Demo\n " << std::endl;
70+
71+ // Example 1: BatchSpanProcessor without export_unsampled_spans (default behavior)
72+ {
73+ std::cout << " === Example 1: BatchSpanProcessor (default behavior) ===" << std::endl;
74+
75+ trace_sdk::BatchSpanProcessorOptions options;
76+ // export_unsampled_spans is false by default
77+
78+ auto processor = std::make_unique<trace_sdk::BatchSpanProcessor>(
79+ std::make_unique<MockExporter>(" BatchProcessor-Default" ), options);
80+
81+ // Create one sampled and one unsampled span
82+ auto sampled_span = CreateTestSpan (true );
83+ auto unsampled_span = CreateTestSpan (false );
84+
85+ processor->OnEnd (std::unique_ptr<trace_sdk::Recordable>(sampled_span.release ()));
86+ processor->OnEnd (std::unique_ptr<trace_sdk::Recordable>(unsampled_span.release ()));
87+
88+ processor->ForceFlush ();
89+ std::cout << " Expected: Only 1 span exported (sampled span only)\n " << std::endl;
90+ }
91+
92+ // Example 2: BatchSpanProcessor with export_unsampled_spans enabled
93+ {
94+ std::cout << " === Example 2: BatchSpanProcessor (export_unsampled_spans = true) ==="
95+ << std::endl;
96+
97+ trace_sdk::BatchSpanProcessorOptions options;
98+ options.export_unsampled_spans = true ; // Enable exporting unsampled spans
99+
100+ auto processor = std::make_unique<trace_sdk::BatchSpanProcessor>(
101+ std::make_unique<MockExporter>(" BatchProcessor-WithUnsampled" ), options);
102+
103+ // Create one sampled and one unsampled span
104+ auto sampled_span = CreateTestSpan (true );
105+ auto unsampled_span = CreateTestSpan (false );
106+
107+ processor->OnEnd (std::unique_ptr<trace_sdk::Recordable>(sampled_span.release ()));
108+ processor->OnEnd (std::unique_ptr<trace_sdk::Recordable>(unsampled_span.release ()));
109+
110+ processor->ForceFlush ();
111+ std::cout << " Expected: 2 spans exported (both sampled and unsampled)\n " << std::endl;
112+ }
113+
114+ // Example 3: SimpleSpanProcessor with export_unsampled_spans enabled
115+ {
116+ std::cout << " === Example 3: SimpleSpanProcessor (export_unsampled_spans = true) ==="
117+ << std::endl;
118+
119+ trace_sdk::SimpleSpanProcessorOptions options;
120+ options.export_unsampled_spans = true ; // Enable exporting unsampled spans
121+
122+ auto processor = std::make_unique<trace_sdk::SimpleSpanProcessor>(
123+ std::make_unique<MockExporter>(" SimpleProcessor-WithUnsampled" ), options);
124+
125+ // Create one sampled and one unsampled span
126+ auto sampled_span = CreateTestSpan (true );
127+ auto unsampled_span = CreateTestSpan (false );
128+
129+ processor->OnEnd (std::unique_ptr<trace_sdk::Recordable>(sampled_span.release ()));
130+ processor->OnEnd (std::unique_ptr<trace_sdk::Recordable>(unsampled_span.release ()));
131+
132+ std::cout << " Expected: 2 separate exports (one for each span)\n " << std::endl;
133+ }
134+
135+ std::cout << " Demo completed!" << std::endl;
136+ return 0 ;
137+ }
0 commit comments