#include <iostream>
#include <thread>
#include <map>
#include <vector>
using namespace std::chrono_literals;
private:
public:
const std::map<std::string, std::string>& headers) {
std::cout <<
"[" <<
service_name_ <<
"] Processing request: " << request_id << std::endl;
std::shared_ptr<trace_span> span;
if (context_result.is_ok()) {
context_result.value(),
);
if (span_result.is_ok()) {
span = span_result.value();
<< context_result.value().trace_id << std::endl;
}
} else {
);
if (span_result.is_ok()) {
span = span_result.value();
<< span->trace_id << std::endl;
}
}
if (span) {
span->tags["request_id"] = request_id;
span->tags["http.method"] = "GET";
span->tags["http.url"] = "/api/process";
span->tags["user.id"] = "user123";
span->status = trace_span::status_code::ok;
<< span->span_id << std::endl;
}
}
private:
if (!span_result.is_ok()) return;
auto span = span_result.value();
span->tags["operation"] = "data_processing";
std::cout <<
"[" <<
service_name_ <<
"] Processing business logic..." << std::endl;
std::this_thread::sleep_for(50ms);
}
if (!span_result.is_ok()) return;
auto span = span_result.value();
span->tags["db.type"] = "postgresql";
span->tags["db.statement"] = "SELECT * FROM users WHERE id = ?";
std::cout <<
"[" <<
service_name_ <<
"] Querying database..." << std::endl;
std::this_thread::sleep_for(20ms);
}
if (!span_result.is_ok()) return;
auto span = span_result.value();
span->tags["peer.service"] = "downstream_service";
span->tags["span.kind"] = "client";
std::map<std::string, std::string> headers;
std::cout <<
"[" <<
service_name_ <<
"] Calling downstream service..." << std::endl;
std::cout << " Propagating trace: " << context.trace_id << std::endl;
std::this_thread::sleep_for(30ms);
}
};
WebService database_service(tracer,
"database_service");
std::cout << "\n=== Simulating distributed request flow ===" << std::endl;
std::map<std::string, std::string> initial_headers;
initial_headers["user-agent"] = "example-client";
frontend.handle_request("req-001", initial_headers);
std::cout << "\n=== Simulating request with existing trace ===" << std::endl;
std::map<std::string, std::string> traced_headers;
traced_headers["traceparent"] = "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01";
traced_headers["baggage-user-id"] = "user456";
backend.handle_request("req-002", traced_headers);
}
std::cout << "\n=== Analyzing traces ===" << std::endl;
auto root_span_result = tracer.
start_span(
"analyze_operation",
"analyzer");
if (!root_span_result.is_ok()) return;
auto root_span = root_span_result.value();
root_span->tags["analysis.type"] = "performance";
std::vector<std::shared_ptr<trace_span>> child_spans;
for (int i = 0; i < 5; ++i) {
"sub_operation_" + std::to_string(i));
if (child_result.is_ok()) {
auto child = child_result.value();
child->tags["index"] = std::to_string(i);
child->tags["complexity"] = (i % 2 == 0) ? "low" : "high";
std::this_thread::sleep_for(std::chrono::milliseconds(10 * (i + 1)));
child_spans.push_back(child);
}
}
for (auto& child : child_spans) {
}
auto error_span_result = tracer.
start_child_span(*root_span,
"failing_operation");
if (error_span_result.is_ok()) {
auto error_span = error_span_result.value();
error_span->status = trace_span::status_code::error;
error_span->status_message = "Database connection timeout";
error_span->tags["error"] = "true";
error_span->tags["error.type"] = "timeout";
}
auto trace_result = tracer.
get_trace(root_span->trace_id);
if (trace_result.is_ok()) {
auto& spans = trace_result.value();
std::cout << "Trace ID: " << root_span->trace_id << std::endl;
std::cout << "Total spans in trace: " << spans.size() << std::endl;
if (!spans.empty()) {
auto min_time = spans[0].start_time;
auto max_time = spans[0].end_time;
for (const auto& span : spans) {
if (span.start_time < min_time) min_time = span.start_time;
if (span.end_time > max_time) max_time = span.end_time;
}
auto total_duration = std::chrono::duration_cast<std::chrono::milliseconds>(
max_time - min_time
);
std::cout << "Total trace duration: " << total_duration.count() << " ms" << std::endl;
}
int error_count = 0;
for (const auto& span : spans) {
if (span.status == trace_span::status_code::error) {
error_count++;
std::cout << "Error in span: " << span.operation_name
<< " - " << span.status_message << std::endl;
}
}
std::cout << "Spans with errors: " << error_count << std::endl;
}
}
std::cout << "=== Distributed Tracing Example ===" << std::endl;
try {
std::cout << "\n--- Part 1: Basic Span Management ---" << std::endl;
auto root_span_result = tracer.
start_span(
"main_operation",
"example_service");
if (!root_span_result.is_ok()) {
std::cerr << "Failed to create root span" << std::endl;
return 1;
}
auto root_span = root_span_result.value();
std::cout << "Created root span:" << std::endl;
std::cout << " Trace ID: " << root_span->trace_id << std::endl;
std::cout << " Span ID: " << root_span->span_id << std::endl;
std::cout << " Operation: " << root_span->operation_name << std::endl;
root_span->tags["version"] = "1.0.0";
root_span->tags["environment"] = "development";
root_span->baggage["user.id"] = "user789";
root_span->baggage["session.id"] = "sess123";
std::cout << "\nCreating child spans..." << std::endl;
if (child1_result.is_ok() && child2_result.is_ok()) {
auto child1 = child1_result.value();
auto child2 = child2_result.value();
std::cout << " Child 1 span ID: " << child1->span_id << std::endl;
std::cout << " Child 2 span ID: " << child2->span_id << std::endl;
std::this_thread::sleep_for(10ms);
}
std::cout << "All spans finished" << std::endl;
std::cout << "\n--- Part 2: Distributed System Simulation ---" << std::endl;
std::cout << "\n--- Part 3: Trace Analysis ---" << std::endl;
std::cout << "\n--- Part 4: Context Propagation ---" << std::endl;
auto demo_span_result = tracer.
start_span(
"propagation_demo");
if (demo_span_result.is_ok()) {
auto demo_span = demo_span_result.value();
std::map<std::string, std::string> http_headers;
std::cout << "Context injected into headers:" << std::endl;
for (const auto& [key, value] : http_headers) {
std::cout << " " << key << ": " << value << std::endl;
}
if (extracted_context.is_ok()) {
std::cout << "\nContext extracted from headers:" << std::endl;
std::cout << " Trace ID: " << extracted_context.value().trace_id << std::endl;
std::cout << " Span ID: " << extracted_context.value().span_id << std::endl;
extracted_context.value(),
"continued_operation"
);
if (continued_span.is_ok()) {
std::cout << " Continued span ID: "
<< continued_span.value()->span_id << std::endl;
}
}
}
} catch (const std::exception& e) {
std::cerr << "Exception: " << e.what() << std::endl;
return 1;
}
std::cout << "\n=== Example completed successfully ===" << std::endl;
return 0;
}
void handle_request(const std::string &request_id, const std::map< std::string, std::string > &headers)
void process_business_logic(std::shared_ptr< trace_span > parent_span)
std::string service_name_
WebService(distributed_tracer &tracer, const std::string &name)
void call_downstream_service(std::shared_ptr< trace_span > parent_span)
distributed_tracer & tracer_
void query_database(std::shared_ptr< trace_span > parent_span)
Distributed tracer for managing spans and traces.
common::Result< std::shared_ptr< trace_span > > start_span_from_context(const trace_context &context, const std::string &operation_name)
Start a span from trace context (for incoming requests)
common::Result< trace_context > extract_context_from_carrier(const Carrier &carrier)
Extract trace context from carrier.
trace_context extract_context(const trace_span &span) const
Extract trace context for propagation.
void inject_context(const trace_context &context, Carrier &carrier)
Inject trace context into carrier (e.g., HTTP headers)
common::Result< std::vector< trace_span > > get_trace(const std::string &trace_id) const
Get all spans for a trace.
common::Result< std::shared_ptr< trace_span > > start_span(const std::string &operation_name, const std::string &service_name="monitoring_system")
Start a new root span.
common::Result< bool > finish_span(std::shared_ptr< trace_span > span)
Finish a span.
common::Result< std::shared_ptr< trace_span > > start_child_span(const trace_span &parent, const std::string &operation_name)
Start a child span.
Distributed tracing implementation for monitoring system.
void simulate_distributed_system()
void analyze_traces(distributed_tracer &tracer)
Thread-local context management for request tracking and distributed tracing.