Monitoring System 0.1.0
System resource monitoring with pluggable collectors and alerting
Loading...
Searching...
No Matches
trace_exporters.h
Go to the documentation of this file.
1#pragma once
2
3// BSD 3-Clause License
4// Copyright (c) 2025, 🍀☀🌕🌥 🌊
5// See the LICENSE file in the project root for full license information.
6
7
22#include "../core/error_codes.h"
25#include "http_transport.h"
26#include "grpc_transport.h"
27#include <vector>
28#include <string>
29#include <memory>
30#include <chrono>
31#include <optional>
32#include <functional>
33#include <atomic>
34#include <algorithm>
35#include <unordered_map>
36#include <sstream>
37#include <iomanip>
38#include <cmath>
39#include <thread>
40
41namespace kcenon { namespace monitoring {
42
56
62 std::string endpoint;
64 std::chrono::milliseconds timeout{30000};
65 std::chrono::milliseconds batch_timeout{5000};
66 std::size_t max_batch_size = 512;
67 std::size_t max_queue_size = 2048;
68 bool enable_compression = true;
69 std::unordered_map<std::string, std::string> headers;
70 std::optional<std::string> service_name;
71
75 common::VoidResult validate() const {
76 if (endpoint.empty()) {
77 return common::VoidResult::err(error_info(monitoring_error_code::invalid_configuration,
78 "Export endpoint cannot be empty", "monitoring_system").to_common_error());
79 }
80
81 if (timeout.count() <= 0) {
82 return common::VoidResult::err(error_info(monitoring_error_code::invalid_configuration,
83 "Timeout must be positive", "monitoring_system").to_common_error());
84 }
85
86 if (max_batch_size == 0) {
87 return common::VoidResult::err(error_info(monitoring_error_code::invalid_configuration,
88 "Batch size must be greater than 0", "monitoring_system").to_common_error());
89 }
90
92 return common::VoidResult::err(error_info(monitoring_error_code::invalid_configuration,
93 "Queue size must be at least batch size", "monitoring_system").to_common_error());
94 }
95
96 return common::ok();
97 }
98};
99
105 std::string trace_id;
106 std::string span_id;
107 std::string parent_span_id;
108 std::string operation_name;
109 std::string service_name;
110 std::chrono::microseconds start_time;
111 std::chrono::microseconds duration;
112 std::vector<std::pair<std::string, std::string>> tags;
113 std::vector<std::pair<std::string, std::string>> process_tags;
114
118 std::string to_thrift_json() const {
119 std::ostringstream json;
120 json << "{";
121 json << "\"traceIdHigh\":0,";
122 json << "\"traceIdLow\":" << std::hash<std::string>{}(trace_id) << ",";
123 json << "\"spanId\":" << std::hash<std::string>{}(span_id) << ",";
124 json << "\"parentSpanId\":" << (parent_span_id.empty() ? "0" : std::to_string(std::hash<std::string>{}(parent_span_id))) << ",";
125 json << "\"operationName\":\"" << operation_name << "\",";
126 json << "\"startTime\":" << start_time.count() << ",";
127 json << "\"duration\":" << duration.count() << ",";
128
129 // Tags
130 json << "\"tags\":[";
131 bool first = true;
132 for (const auto& [key, value] : tags) {
133 if (!first) json << ",";
134 json << "{\"key\":\"" << key << "\",\"vType\":\"STRING\",\"vStr\":\"" << value << "\"}";
135 first = false;
136 }
137 json << "],";
138
139 // Process
140 json << "\"process\":{\"serviceName\":\"" << service_name << "\",\"tags\":[";
141 first = true;
142 for (const auto& [key, value] : process_tags) {
143 if (!first) json << ",";
144 json << "{\"key\":\"" << key << "\",\"vType\":\"STRING\",\"vStr\":\"" << value << "\"}";
145 first = false;
146 }
147 json << "]}";
148
149 json << "}";
150 return json.str();
151 }
152
156 std::vector<uint8_t> to_protobuf() const {
157 // Protobuf serialization requires generated code
158 // Return empty for now - full implementation would use protobuf library
159 return {};
160 }
161};
162
168 std::string trace_id;
169 std::string span_id;
170 std::string parent_id;
171 std::string name;
172 std::string kind;
173 std::chrono::microseconds timestamp;
174 std::chrono::microseconds duration;
177 std::unordered_map<std::string, std::string> tags;
178 bool shared = false;
179
183 std::string to_json_v2() const {
184 std::ostringstream json;
185 json << "{";
186 json << "\"traceId\":\"" << trace_id << "\",";
187 json << "\"id\":\"" << span_id << "\",";
188 if (!parent_id.empty()) {
189 json << "\"parentId\":\"" << parent_id << "\",";
190 }
191 json << "\"name\":\"" << name << "\",";
192 json << "\"kind\":\"" << kind << "\",";
193 json << "\"timestamp\":" << timestamp.count() << ",";
194 json << "\"duration\":" << duration.count() << ",";
195
196 // Local endpoint
197 json << "\"localEndpoint\":{\"serviceName\":\"" << local_endpoint_service_name << "\"},";
198
199 // Remote endpoint (if set)
200 if (!remote_endpoint_service_name.empty()) {
201 json << "\"remoteEndpoint\":{\"serviceName\":\"" << remote_endpoint_service_name << "\"},";
202 }
203
204 // Tags
205 json << "\"tags\":{";
206 bool first = true;
207 for (const auto& [key, value] : tags) {
208 if (!first) json << ",";
209 json << "\"" << key << "\":\"" << value << "\"";
210 first = false;
211 }
212 json << "}";
213
214 if (shared) {
215 json << ",\"shared\":true";
216 }
217
218 json << "}";
219 return json.str();
220 }
221
225 std::vector<uint8_t> to_protobuf() const {
226 // Protobuf serialization requires generated code
227 // Return empty for now - full implementation would use protobuf library
228 return {};
229 }
230};
231
237public:
238 virtual ~trace_exporter_interface() = default;
239
243 virtual common::VoidResult export_spans(const std::vector<trace_span>& spans) = 0;
244
248 virtual common::VoidResult flush() = 0;
249
253 virtual common::VoidResult shutdown() = 0;
254
258 virtual std::unordered_map<std::string, std::size_t> get_stats() const = 0;
259};
260
269private:
271 std::unique_ptr<http_transport> transport_;
272 std::atomic<std::size_t> exported_spans_{0};
273 std::atomic<std::size_t> failed_exports_{0};
274 std::atomic<std::size_t> dropped_spans_{0};
275 std::size_t max_retries_{3};
276 std::chrono::milliseconds base_retry_delay_{100};
277
278public:
281
282 jaeger_exporter(const trace_export_config& config, std::unique_ptr<http_transport> transport)
283 : config_(config), transport_(std::move(transport)) {}
284
289 jaeger_span_data jaeger_span;
290 jaeger_span.trace_id = span.trace_id;
291 jaeger_span.span_id = span.span_id;
292 jaeger_span.parent_span_id = span.parent_span_id;
293 jaeger_span.operation_name = span.operation_name;
294 jaeger_span.service_name = config_.service_name.value_or(span.service_name);
295
296 // Convert timestamps
297 auto start_epoch = span.start_time.time_since_epoch();
298 jaeger_span.start_time = std::chrono::duration_cast<std::chrono::microseconds>(start_epoch);
299
300 auto end_epoch = span.end_time.time_since_epoch();
301 jaeger_span.duration = std::chrono::duration_cast<std::chrono::microseconds>(end_epoch - start_epoch);
302
303 // Convert tags
304 for (const auto& [key, value] : span.tags) {
305 jaeger_span.tags.emplace_back(key, value);
306 }
307
308 // Add process tags
309 jaeger_span.process_tags.emplace_back("service.name", jaeger_span.service_name);
310
311 return jaeger_span;
312 }
313
314 common::VoidResult export_spans(const std::vector<trace_span>& spans) override {
315 try {
316 std::vector<jaeger_span_data> jaeger_spans;
317 jaeger_spans.reserve(spans.size());
318
319 for (const auto& span : spans) {
320 jaeger_spans.push_back(convert_span(span));
321 }
322
323 // Convert to appropriate format and send
324 common::VoidResult send_result = common::ok();
326 send_result = send_thrift_batch(jaeger_spans);
328 send_result = send_grpc_batch(jaeger_spans);
329 } else {
330 return common::VoidResult::err(error_info(monitoring_error_code::invalid_configuration,
331 "Invalid Jaeger export format", "monitoring_system").to_common_error());
332 }
333
334 if (send_result.is_ok()) {
335 exported_spans_ += spans.size();
336 } else {
338 return send_result;
339 }
340
341 return common::ok();
342
343 } catch (const std::exception& e) {
345 return common::VoidResult::err(error_info(monitoring_error_code::operation_failed,
346 "Jaeger export failed: " + std::string(e.what()), "monitoring_system").to_common_error());
347 }
348 }
349
350 common::VoidResult flush() override {
351 // Jaeger exporter typically sends immediately, so flush is a no-op
352 return common::ok();
353 }
354
355 common::VoidResult shutdown() override {
356 return flush();
357 }
358
359 std::unordered_map<std::string, std::size_t> get_stats() const override {
360 return {
361 {"exported_spans", exported_spans_.load()},
362 {"failed_exports", failed_exports_.load()},
363 {"dropped_spans", dropped_spans_.load()}
364 };
365 }
366
367private:
368 common::VoidResult send_thrift_batch(const std::vector<jaeger_span_data>& spans) {
369 // Build JSON payload for Thrift over HTTP
370 std::ostringstream payload;
371 payload << "{\"data\":[{\"spans\":[";
372 bool first = true;
373 for (const auto& span : spans) {
374 if (!first) payload << ",";
375 payload << span.to_thrift_json();
376 first = false;
377 }
378 payload << "]}]}";
379
380 std::string body = payload.str();
381
382 // Build HTTP request
383 http_request request;
384 request.url = config_.endpoint + "/api/traces";
385 request.method = "POST";
386 request.headers["Content-Type"] = "application/x-thrift";
387 request.headers["Accept"] = "application/json";
388 for (const auto& [key, value] : config_.headers) {
389 request.headers[key] = value;
390 }
391 request.body = std::vector<uint8_t>(body.begin(), body.end());
392 request.timeout = config_.timeout;
393
394 // Send with retry
395 return send_with_retry(request);
396 }
397
398 common::VoidResult send_grpc_batch(const std::vector<jaeger_span_data>& spans) {
399 // gRPC would require a different transport mechanism
400 // For now, fall back to HTTP POST with protobuf
401 std::vector<uint8_t> payload;
402 for (const auto& span : spans) {
403 auto proto = span.to_protobuf();
404 payload.insert(payload.end(), proto.begin(), proto.end());
405 }
406
407 http_request request;
408 request.url = config_.endpoint;
409 request.method = "POST";
410 request.headers["Content-Type"] = "application/grpc+proto";
411 for (const auto& [key, value] : config_.headers) {
412 request.headers[key] = value;
413 }
414 request.body = payload;
415 request.timeout = config_.timeout;
416
417 return send_with_retry(request);
418 }
419
420 common::VoidResult send_with_retry(const http_request& request) {
421 std::size_t attempt = 0;
422 std::chrono::milliseconds delay = base_retry_delay_;
423
424 while (attempt < max_retries_) {
425 auto result = transport_->send(request);
426 if (result.is_ok()) {
427 const auto& response = result.value();
428 if (response.status_code >= 200 && response.status_code < 300) {
429 return common::ok();
430 }
431 // Retry on 5xx errors
432 if (response.status_code >= 500) {
433 attempt++;
434 if (attempt < max_retries_) {
435 std::this_thread::sleep_for(delay);
436 delay *= 2; // Exponential backoff
437 }
438 continue;
439 }
440 // Non-retryable error
441 return common::VoidResult::err(error_info(monitoring_error_code::operation_failed,
442 "Jaeger export failed with status: " + std::to_string(response.status_code),
443 "monitoring_system").to_common_error());
444 }
445 attempt++;
446 if (attempt < max_retries_) {
447 std::this_thread::sleep_for(delay);
448 delay *= 2;
449 }
450 }
451 return common::VoidResult::err(error_info(monitoring_error_code::operation_failed,
452 "Jaeger export failed after " + std::to_string(max_retries_) + " retries",
453 "monitoring_system").to_common_error());
454 }
455};
456
465private:
467 std::unique_ptr<http_transport> transport_;
468 std::atomic<std::size_t> exported_spans_{0};
469 std::atomic<std::size_t> failed_exports_{0};
470 std::atomic<std::size_t> dropped_spans_{0};
471 std::size_t max_retries_{3};
472 std::chrono::milliseconds base_retry_delay_{100};
473
474public:
477
478 zipkin_exporter(const trace_export_config& config, std::unique_ptr<http_transport> transport)
479 : config_(config), transport_(std::move(transport)) {}
480
485 zipkin_span_data zipkin_span;
486 zipkin_span.trace_id = span.trace_id;
487 zipkin_span.span_id = span.span_id;
488 zipkin_span.parent_id = span.parent_span_id;
489 zipkin_span.name = span.operation_name;
491
492 // Convert timestamps (Zipkin uses microseconds since epoch)
493 auto start_epoch = span.start_time.time_since_epoch();
494 zipkin_span.timestamp = std::chrono::duration_cast<std::chrono::microseconds>(start_epoch);
495
496 auto end_epoch = span.end_time.time_since_epoch();
497 zipkin_span.duration = std::chrono::duration_cast<std::chrono::microseconds>(end_epoch - start_epoch);
498
499 // Determine span kind from tags
500 auto kind_it = span.tags.find("span.kind");
501 if (kind_it != span.tags.end()) {
502 zipkin_span.kind = kind_it->second;
503 } else {
504 zipkin_span.kind = "INTERNAL";
505 }
506
507 // Convert tags (exclude special fields)
508 for (const auto& [key, value] : span.tags) {
509 if (key != "span.kind") {
510 zipkin_span.tags[key] = value;
511 }
512 }
513
514 return zipkin_span;
515 }
516
517 common::VoidResult export_spans(const std::vector<trace_span>& spans) override {
518 try {
519 std::vector<zipkin_span_data> zipkin_spans;
520 zipkin_spans.reserve(spans.size());
521
522 for (const auto& span : spans) {
523 zipkin_spans.push_back(convert_span(span));
524 }
525
526 // Convert to appropriate format and send
527 common::VoidResult send_result = common::ok();
529 send_result = send_json_batch(zipkin_spans);
531 send_result = send_protobuf_batch(zipkin_spans);
532 } else {
533 return common::VoidResult::err(error_info(monitoring_error_code::invalid_configuration,
534 "Invalid Zipkin export format", "monitoring_system").to_common_error());
535 }
536
537 if (send_result.is_ok()) {
538 exported_spans_ += spans.size();
539 } else {
541 return send_result;
542 }
543
544 return common::ok();
545
546 } catch (const std::exception& e) {
548 return common::VoidResult::err(error_info(monitoring_error_code::operation_failed,
549 "Zipkin export failed: " + std::string(e.what()), "monitoring_system").to_common_error());
550 }
551 }
552
553 common::VoidResult flush() override {
554 // Zipkin exporter typically sends immediately, so flush is a no-op
555 return common::ok();
556 }
557
558 common::VoidResult shutdown() override {
559 return flush();
560 }
561
562 std::unordered_map<std::string, std::size_t> get_stats() const override {
563 return {
564 {"exported_spans", exported_spans_.load()},
565 {"failed_exports", failed_exports_.load()},
566 {"dropped_spans", dropped_spans_.load()}
567 };
568 }
569
570private:
571 common::VoidResult send_json_batch(const std::vector<zipkin_span_data>& spans) {
572 // Build JSON array payload for Zipkin v2 API
573 std::ostringstream payload;
574 payload << "[";
575 bool first = true;
576 for (const auto& span : spans) {
577 if (!first) payload << ",";
578 payload << span.to_json_v2();
579 first = false;
580 }
581 payload << "]";
582
583 std::string body = payload.str();
584
585 // Build HTTP request
586 http_request request;
587 request.url = config_.endpoint + "/api/v2/spans";
588 request.method = "POST";
589 request.headers["Content-Type"] = "application/json";
590 request.headers["Accept"] = "application/json";
591 for (const auto& [key, value] : config_.headers) {
592 request.headers[key] = value;
593 }
594 request.body = std::vector<uint8_t>(body.begin(), body.end());
595 request.timeout = config_.timeout;
596
597 return send_with_retry(request);
598 }
599
600 common::VoidResult send_protobuf_batch(const std::vector<zipkin_span_data>& spans) {
601 // Build protobuf payload
602 std::vector<uint8_t> payload;
603 for (const auto& span : spans) {
604 auto proto = span.to_protobuf();
605 payload.insert(payload.end(), proto.begin(), proto.end());
606 }
607
608 http_request request;
609 request.url = config_.endpoint + "/api/v2/spans";
610 request.method = "POST";
611 request.headers["Content-Type"] = "application/x-protobuf";
612 for (const auto& [key, value] : config_.headers) {
613 request.headers[key] = value;
614 }
615 request.body = payload;
616 request.timeout = config_.timeout;
617
618 return send_with_retry(request);
619 }
620
621 common::VoidResult send_with_retry(const http_request& request) {
622 std::size_t attempt = 0;
623 std::chrono::milliseconds delay = base_retry_delay_;
624
625 while (attempt < max_retries_) {
626 auto result = transport_->send(request);
627 if (result.is_ok()) {
628 const auto& response = result.value();
629 if (response.status_code >= 200 && response.status_code < 300) {
630 return common::ok();
631 }
632 // Retry on 5xx errors
633 if (response.status_code >= 500) {
634 attempt++;
635 if (attempt < max_retries_) {
636 std::this_thread::sleep_for(delay);
637 delay *= 2; // Exponential backoff
638 }
639 continue;
640 }
641 // Non-retryable error
642 return common::VoidResult::err(error_info(monitoring_error_code::operation_failed,
643 "Zipkin export failed with status: " + std::to_string(response.status_code),
644 "monitoring_system").to_common_error());
645 }
646 attempt++;
647 if (attempt < max_retries_) {
648 std::this_thread::sleep_for(delay);
649 delay *= 2;
650 }
651 }
652 return common::VoidResult::err(error_info(monitoring_error_code::operation_failed,
653 "Zipkin export failed after " + std::to_string(max_retries_) + " retries",
654 "monitoring_system").to_common_error());
655 }
656};
657
663private:
665 std::unique_ptr<opentelemetry_tracer_adapter> otel_adapter_;
666 std::atomic<std::size_t> exported_spans_{0};
667 std::atomic<std::size_t> failed_exports_{0};
668 std::atomic<std::size_t> dropped_spans_{0};
669
670public:
671 explicit otlp_exporter(const trace_export_config& config, const otel_resource& resource)
672 : config_(config), otel_adapter_(std::make_unique<opentelemetry_tracer_adapter>(resource)) {}
673
674 common::VoidResult export_spans(const std::vector<trace_span>& spans) override {
675 try {
676 // Convert to OpenTelemetry format first
677 auto otel_result = otel_adapter_->convert_spans(spans);
678 if (otel_result.is_err()) {
680 return common::VoidResult::err(error_info(monitoring_error_code::processing_failed,
681 "Failed to convert spans to OTEL format: " + otel_result.error().message, "monitoring_system").to_common_error());
682 }
683
684 const auto& otel_spans = otel_result.value();
685
686 // Send via appropriate OTLP protocol
687 common::VoidResult send_result = common::ok();
689 send_result = send_grpc_batch(otel_spans);
691 send_result = send_http_json_batch(otel_spans);
693 send_result = send_http_protobuf_batch(otel_spans);
694 } else {
695 return common::VoidResult::err(error_info(monitoring_error_code::invalid_configuration,
696 "Invalid OTLP export format", "monitoring_system").to_common_error());
697 }
698
699 if (send_result.is_ok()) {
700 exported_spans_ += spans.size();
701 } else {
703 return send_result;
704 }
705
706 return common::ok();
707
708 } catch (const std::exception& e) {
710 return common::VoidResult::err(error_info(monitoring_error_code::operation_failed,
711 "OTLP export failed: " + std::string(e.what()), "monitoring_system").to_common_error());
712 }
713 }
714
715 common::VoidResult flush() override {
716 // OTLP exporter typically sends immediately, so flush is a no-op
717 return common::ok();
718 }
719
720 common::VoidResult shutdown() override {
721 return flush();
722 }
723
724 std::unordered_map<std::string, std::size_t> get_stats() const override {
725 return {
726 {"exported_spans", exported_spans_.load()},
727 {"failed_exports", failed_exports_.load()},
728 {"dropped_spans", dropped_spans_.load()}
729 };
730 }
731
732private:
733 common::VoidResult send_grpc_batch(const std::vector<otel_span_data>& spans) {
734 // Simulate OTLP gRPC sending
735 // In real implementation, this would use OTLP gRPC client
736 (void)spans; // Suppress unused parameter warning
737 return common::ok();
738 }
739
740 common::VoidResult send_http_json_batch(const std::vector<otel_span_data>& spans) {
741 // Simulate OTLP HTTP JSON sending
742 // In real implementation, this would serialize OTEL spans to JSON and POST
743 (void)spans; // Suppress unused parameter warning
744 return common::ok();
745 }
746
747 common::VoidResult send_http_protobuf_batch(const std::vector<otel_span_data>& spans) {
748 // Simulate OTLP HTTP protobuf sending
749 // In real implementation, this would serialize OTEL spans to protobuf and POST
750 (void)spans; // Suppress unused parameter warning
751 return common::ok();
752 }
753};
754
760public:
764 static std::unique_ptr<trace_exporter_interface> create_exporter(
765 const trace_export_config& config,
766 const otel_resource& resource = create_service_resource("monitoring_system", "2.0.0")) {
767
768 switch (config.format) {
771 return std::make_unique<jaeger_exporter>(config);
772
775 return std::make_unique<zipkin_exporter>(config);
776
780 return std::make_unique<otlp_exporter>(config, resource);
781
782 default:
783 return nullptr;
784 }
785 }
786
790 static std::vector<trace_export_format> get_supported_formats(const std::string& backend) {
791 if (backend == "jaeger") {
793 } else if (backend == "zipkin") {
795 } else if (backend == "otlp") {
798 }
799 return {};
800 }
801};
802
806inline std::unique_ptr<jaeger_exporter> create_jaeger_exporter(
807 const std::string& endpoint,
809
810 trace_export_config config;
811 config.endpoint = endpoint;
812 config.format = format;
813 return std::make_unique<jaeger_exporter>(config);
814}
815
819inline std::unique_ptr<zipkin_exporter> create_zipkin_exporter(
820 const std::string& endpoint,
822
823 trace_export_config config;
824 config.endpoint = endpoint;
825 config.format = format;
826 return std::make_unique<zipkin_exporter>(config);
827}
828
832inline std::unique_ptr<otlp_exporter> create_otlp_exporter(
833 const std::string& endpoint,
834 const otel_resource& resource,
836
837 trace_export_config config;
838 config.endpoint = endpoint;
839 config.format = format;
840 return std::make_unique<otlp_exporter>(config, resource);
841}
842
843} } // namespace kcenon::monitoring
Jaeger trace exporter implementation.
std::chrono::milliseconds base_retry_delay_
std::unordered_map< std::string, std::size_t > get_stats() const override
Get exporter statistics.
common::VoidResult flush() override
Flush any pending spans.
std::atomic< std::size_t > exported_spans_
common::VoidResult send_grpc_batch(const std::vector< jaeger_span_data > &spans)
std::unique_ptr< http_transport > transport_
common::VoidResult send_thrift_batch(const std::vector< jaeger_span_data > &spans)
std::atomic< std::size_t > failed_exports_
jaeger_span_data convert_span(const trace_span &span) const
Convert internal span to Jaeger format.
jaeger_exporter(const trace_export_config &config, std::unique_ptr< http_transport > transport)
common::VoidResult send_with_retry(const http_request &request)
jaeger_exporter(const trace_export_config &config)
common::VoidResult shutdown() override
Shutdown the exporter.
std::atomic< std::size_t > dropped_spans_
common::VoidResult export_spans(const std::vector< trace_span > &spans) override
Export a batch of spans.
Adapter for converting monitoring system traces to OpenTelemetry format.
OpenTelemetry Protocol (OTLP) trace exporter implementation.
std::atomic< std::size_t > exported_spans_
common::VoidResult send_http_json_batch(const std::vector< otel_span_data > &spans)
std::atomic< std::size_t > failed_exports_
common::VoidResult shutdown() override
Shutdown the exporter.
common::VoidResult send_http_protobuf_batch(const std::vector< otel_span_data > &spans)
std::unique_ptr< opentelemetry_tracer_adapter > otel_adapter_
common::VoidResult send_grpc_batch(const std::vector< otel_span_data > &spans)
common::VoidResult flush() override
Flush any pending spans.
common::VoidResult export_spans(const std::vector< trace_span > &spans) override
Export a batch of spans.
otlp_exporter(const trace_export_config &config, const otel_resource &resource)
std::atomic< std::size_t > dropped_spans_
std::unordered_map< std::string, std::size_t > get_stats() const override
Get exporter statistics.
Factory for creating trace exporters.
static std::vector< trace_export_format > get_supported_formats(const std::string &backend)
Get supported formats for a specific backend.
static std::unique_ptr< trace_exporter_interface > create_exporter(const trace_export_config &config, const otel_resource &resource=create_service_resource("monitoring_system", "2.0.0"))
Create a trace exporter based on format.
Abstract interface for trace exporters.
virtual common::VoidResult shutdown()=0
Shutdown the exporter.
virtual std::unordered_map< std::string, std::size_t > get_stats() const =0
Get exporter statistics.
virtual common::VoidResult flush()=0
Flush any pending spans.
virtual common::VoidResult export_spans(const std::vector< trace_span > &spans)=0
Export a batch of spans.
Zipkin trace exporter implementation.
common::VoidResult export_spans(const std::vector< trace_span > &spans) override
Export a batch of spans.
std::unique_ptr< http_transport > transport_
std::unordered_map< std::string, std::size_t > get_stats() const override
Get exporter statistics.
common::VoidResult shutdown() override
Shutdown the exporter.
std::atomic< std::size_t > dropped_spans_
common::VoidResult flush() override
Flush any pending spans.
common::VoidResult send_with_retry(const http_request &request)
zipkin_span_data convert_span(const trace_span &span) const
Convert internal span to Zipkin format.
std::chrono::milliseconds base_retry_delay_
std::atomic< std::size_t > failed_exports_
zipkin_exporter(const trace_export_config &config, std::unique_ptr< http_transport > transport)
std::atomic< std::size_t > exported_spans_
common::VoidResult send_json_batch(const std::vector< zipkin_span_data > &spans)
common::VoidResult send_protobuf_batch(const std::vector< zipkin_span_data > &spans)
zipkin_exporter(const trace_export_config &config)
Distributed tracing implementation for monitoring system.
Monitoring system specific error codes.
gRPC transport layer for OTLP exporters
HTTP transport layer for trace exporters.
@ otlp_grpc
OTLP gRPC metrics protocol.
@ otlp_http_json
OTLP HTTP JSON metrics protocol.
@ otlp_http_protobuf
OTLP HTTP Protocol Buffers metrics.
@ delay
Delay requests until resources are available.
std::unique_ptr< http_transport > create_default_transport()
Create default HTTP transport.
std::unique_ptr< zipkin_exporter > create_zipkin_exporter(const std::string &endpoint, trace_export_format format=trace_export_format::zipkin_json)
Helper function to create a Zipkin exporter.
trace_export_format
Supported trace export formats.
@ zipkin_json
Zipkin JSON v2 format.
@ jaeger_thrift
Jaeger Thrift protocol.
@ otlp_http_json
OTLP HTTP JSON protocol.
@ otlp_http_protobuf
OTLP HTTP Protocol Buffers.
@ zipkin_protobuf
Zipkin Protocol Buffers format.
otel_resource create_service_resource(const std::string &service_name, const std::string &service_version="1.0.0", const std::string &service_namespace="")
Create OpenTelemetry resource with service information.
std::unique_ptr< otlp_exporter > create_otlp_exporter(const std::string &endpoint, const otel_resource &resource, trace_export_format format=trace_export_format::otlp_grpc)
Helper function to create an OTLP exporter.
std::unique_ptr< jaeger_exporter > create_jaeger_exporter(const std::string &endpoint, trace_export_format format=trace_export_format::jaeger_grpc)
Helper function to create a Jaeger exporter.
OpenTelemetry compatibility layer for monitoring system integration.
Result pattern type definitions for monitoring system.
Extended error information with context.
common::error_info to_common_error() const
Convert to common_system error_info.
HTTP request configuration.
std::chrono::milliseconds timeout
std::vector< uint8_t > body
std::unordered_map< std::string, std::string > headers
Jaeger-specific span representation.
std::vector< std::pair< std::string, std::string > > process_tags
std::string to_thrift_json() const
Convert to Jaeger Thrift format (JSON representation)
std::vector< std::pair< std::string, std::string > > tags
std::vector< uint8_t > to_protobuf() const
Convert to Jaeger protobuf format (stub)
std::chrono::microseconds duration
std::chrono::microseconds start_time
OpenTelemetry resource representation.
Configuration for trace exporters.
std::chrono::milliseconds timeout
Request timeout.
bool enable_compression
Enable data compression.
std::chrono::milliseconds batch_timeout
Batch export timeout.
std::size_t max_queue_size
Maximum queued spans.
std::optional< std::string > service_name
Override service name.
common::VoidResult validate() const
Validate export configuration.
std::unordered_map< std::string, std::string > headers
Custom HTTP headers.
std::size_t max_batch_size
Maximum spans per batch.
Trace span representing a unit of work in distributed tracing.
std::unordered_map< std::string, std::string > tags
std::chrono::system_clock::time_point end_time
std::chrono::system_clock::time_point start_time
Zipkin-specific span representation.
std::unordered_map< std::string, std::string > tags
std::chrono::microseconds duration
std::string to_json_v2() const
Convert to Zipkin JSON v2 format.
std::vector< uint8_t > to_protobuf() const
Convert to Zipkin protobuf format (stub)
std::chrono::microseconds timestamp