#include <iostream>
#include <memory>
#include <string>
#include <chrono>
#include <thread>
#include <iomanip>
using namespace std::chrono_literals;
const std::string& parent_id,
int depth);
private:
public:
std::cout <<
"\n[" <<
service_name_ <<
"] Processing " << method <<
" " << endpoint << std::endl;
span.
start_time = std::chrono::system_clock::now();
span.
tags[
"http.method"] = method;
span.
tags[
"http.url"] = endpoint;
span.
tags[
"http.target"] = endpoint;
span.
tags[
"component"] =
"http_server";
span.
baggage[
"user.id"] =
"user-12345";
span.
baggage[
"session.id"] =
"sess-67890";
span.
baggage[
"request.priority"] =
"high";
std::cout <<
" โ Created root span: " << span.
span_id << std::endl;
std::cout <<
" Trace ID: " << span.
trace_id << std::endl;
std::cout <<
" Baggage: user.id=" << span.
baggage[
"user.id"] << std::endl;
return span;
}
std::cout << " โ Context for propagation: "
return ctx;
}
private:
std::string id;
for (int i = 0; i < 32; ++i) {
id += "0123456789abcdef"[rand() % 16];
}
return id;
}
std::string id;
for (int i = 0; i < 16; ++i) {
id += "0123456789abcdef"[rand() % 16];
}
return id;
}
};
private:
public:
std::cout <<
"\n[" <<
service_name_ <<
"] Verifying authentication token" << std::endl;
span.
start_time = std::chrono::system_clock::now();
span.
tags[
"auth.token_type"] =
"bearer";
span.
tags[
"auth.method"] =
"jwt";
std::cout <<
" โ Created child span: " << span.
span_id << std::endl;
std::cout <<
" Inherited baggage: user.id=" << span.
baggage[
"user.id"] << std::endl;
std::this_thread::sleep_for(5ms);
span.
end_time = std::chrono::system_clock::now();
span.
status = trace_span::status_code::ok;
span.
tags[
"auth.result"] =
"success";
std::cout << " โ Authentication successful (duration: "
<< span.
duration.count() <<
"ยตs)" << std::endl;
return span;
}
private:
std::string id;
for (int i = 0; i < 16; ++i) {
id += "0123456789abcdef"[rand() % 16];
}
return id;
}
};
private:
public:
std::cout <<
"\n[" <<
service_name_ <<
"] Fetching user profile" << std::endl;
std::cout <<
" User ID from baggage: " << parent_ctx.
baggage.at(
"user.id") << std::endl;
span.
start_time = std::chrono::system_clock::now();
span.
tags[
"db.system"] =
"postgresql";
span.
tags[
"db.name"] =
"users_db";
span.
tags[
"db.statement"] =
"SELECT * FROM users WHERE id = ?";
span.
tags[
"db.user_id"] = user_id;
std::cout <<
" โ Created child span: " << span.
span_id << std::endl;
std::this_thread::sleep_for(15ms);
span.
end_time = std::chrono::system_clock::now();
span.
status = trace_span::status_code::ok;
span.
tags[
"db.rows_returned"] =
"1";
std::cout << " โ User profile fetched (duration: "
<< span.
duration.count() <<
"ยตs)" << std::endl;
return span;
}
private:
std::string id;
for (int i = 0; i < 16; ++i) {
id += "0123456789abcdef"[rand() % 16];
}
return id;
}
};
private:
public:
std::cout <<
"\n[" <<
service_name_ <<
"] Cache lookup" << std::endl;
span.
start_time = std::chrono::system_clock::now();
span.
tags[
"cache.type"] =
"redis";
span.
tags[
"cache.key"] = key;
std::cout <<
" โ Created child span: " << span.
span_id << std::endl;
std::this_thread::sleep_for(2ms);
span.
end_time = std::chrono::system_clock::now();
span.
status = trace_span::status_code::ok;
span.
tags[
"cache.hit"] =
"false";
std::cout << " โ Cache miss (duration: "
<< span.
duration.count() <<
"ยตs)" << std::endl;
return span;
}
private:
std::string id;
for (int i = 0; i < 16; ++i) {
id += "0123456789abcdef"[rand() % 16];
}
return id;
}
};
std::cout << "\n=== Trace Tree Structure ===" << std::endl;
for (const auto& span : spans) {
root = &span;
break;
}
}
if (!root) {
std::cout << "No root span found" << std::endl;
return;
}
std::cout <<
"\nTrace ID: " << root->
trace_id <<
"\n" << std::endl;
std::cout << "\n=== Total Spans: " << spans.size() << " ===" << std::endl;
std::cout <<
"Total trace duration: " << root->
duration.count() <<
"ยตs" << std::endl;
}
std::string indent(depth * 2, ' ');
std::string prefix = depth == 0 ? "โโ" : "โโ";
std::cout << indent << prefix <<
" [" << span.
service_name <<
"] "
std::cout << indent <<
" Span ID: " << span.
span_id << std::endl;
std::cout << indent <<
" Duration: " << span.
duration.count() <<
"ยตs" << std::endl;
if (!span.
tags.empty()) {
std::cout << indent << " Tags:";
int count = 0;
for (
const auto& [key, value] : span.
tags) {
if (count++ < 3) {
std::cout << " " << key << "=" << value;
}
}
if (span.
tags.size() > 3) {
std::cout <<
" +" << (span.
tags.size() - 3) <<
" more";
}
std::cout << std::endl;
}
}
const std::string& parent_id,
int depth) {
for (const auto& span : spans) {
}
}
}
std::cout << "=== Multi-Service Distributed Tracing Example ===" << std::endl;
std::vector<trace_span> collected_spans;
std::cout << "\n--- Step 1: API Gateway ---" << std::endl;
auto gateway_span = gateway.
handle_request(
"/api/user/profile",
"GET");
std::cout << "\n--- Step 2: Cache Lookup ---" << std::endl;
auto cache_span = cache.
cache_lookup(gateway_ctx,
"user:user-12345");
collected_spans.push_back(cache_span);
std::cout << "\n--- Step 3: Authentication ---" << std::endl;
auto auth_span = auth.
verify_token(gateway_ctx,
"eyJhbGc...");
collected_spans.push_back(auth_span);
user_ctx.
trace_id = gateway_ctx.trace_id;
user_ctx.
span_id = gateway_span.span_id;
user_ctx.
baggage = gateway_ctx.baggage;
std::cout << "\n--- Step 4: User Profile Service ---" << std::endl;
collected_spans.push_back(user_span);
std::this_thread::sleep_for(5ms);
gateway_span.end_time = std::chrono::system_clock::now();
gateway_span.calculate_duration();
gateway_span.status = trace_span::status_code::ok;
gateway_span.tags["http.status_code"] = "200";
collected_spans.insert(collected_spans.begin(), gateway_span);
std::cout << "\n=== Baggage Propagation ===" << std::endl;
std::cout << "Baggage items propagated across all services:" << std::endl;
for (const auto& [key, value] : gateway_span.baggage) {
std::cout << " " << key << " = " << value << std::endl;
}
std::cout << "\n=== Example completed successfully ===" << std::endl;
}
std::cout << "Multi-Service Distributed Tracing Example\n" << std::endl;
std::cout << "\n" << std::string(60, '=') << std::endl;
std::cout << "\nKey Concepts Demonstrated:" << std::endl;
std::cout << "1. Trace context propagation across services" << std::endl;
std::cout << "2. Parent-child span relationships" << std::endl;
std::cout << "3. Baggage propagation for cross-cutting data" << std::endl;
std::cout << "4. W3C Trace Context standard" << std::endl;
std::cout << "5. Service-specific span tags and metadata" << std::endl;
return 0;
}
Simulated API Gateway service.
static std::string generate_trace_id()
trace_span handle_request(const std::string &endpoint, const std::string &method)
Handle incoming HTTP request.
std::string service_name_
trace_context create_context(const trace_span &span)
Create trace context for propagation.
static std::string generate_span_id()
Simulated Authentication service.
trace_span verify_token(const trace_context &parent_ctx, const std::string &)
Verify user authentication.
static std::string generate_span_id()
std::string service_name_
std::string service_name_
static std::string generate_span_id()
trace_span cache_lookup(const trace_context &parent_ctx, const std::string &key)
Check cache for user data.
std::string service_name_
trace_span get_user_profile(const trace_context &parent_ctx, const std::string &user_id)
Fetch user profile.
static std::string generate_span_id()
Distributed tracing implementation for monitoring system.
void display_children(const std::vector< trace_span > &spans, const std::string &parent_id, int depth)
Display children recursively.
void simulate_multi_service_request()
Simulate complete multi-service request flow.
void display_trace_tree(const std::vector< trace_span > &spans)
Display trace tree structure.
void display_span(const trace_span &span, int depth)
Display single span.
Trace context for propagation across service boundaries.
std::string to_w3c_traceparent() const
Serialize to W3C Trace Context format.
std::unordered_map< std::string, std::string > baggage
Trace span representing a unit of work in distributed tracing.
std::string parent_span_id
void calculate_duration()
Calculate duration if span is finished.
std::unordered_map< std::string, std::string > tags
std::unordered_map< std::string, std::string > baggage
std::chrono::system_clock::time_point end_time
std::chrono::microseconds duration
std::string operation_name
std::chrono::system_clock::time_point start_time