Monitoring System 0.1.0
System resource monitoring with pluggable collectors and alerting
Loading...
Searching...
No Matches
kcenon::monitoring::otlp_span_converter Class Reference

Converts internal spans to OTLP wire format. More...

#include <otlp_grpc_exporter.h>

Collaboration diagram for kcenon::monitoring::otlp_span_converter:
Collaboration graph

Static Public Member Functions

static std::vector< uint8_t > convert_to_otlp (const std::vector< trace_span > &spans, const std::string &service_name, const std::string &service_version, const std::unordered_map< std::string, std::string > &resource_attributes)
 Convert spans to OTLP protobuf format.
 

Static Private Member Functions

static std::vector< uint8_t > build_resource_spans (const std::vector< trace_span > &spans, const std::string &service_name, const std::string &service_version, const std::unordered_map< std::string, std::string > &resource_attributes)
 
static std::vector< uint8_t > build_resource (const std::string &service_name, const std::string &service_version, const std::unordered_map< std::string, std::string > &extra_attributes)
 
static std::vector< uint8_t > build_scope_spans (const std::vector< trace_span > &spans)
 
static std::vector< uint8_t > build_scope (const std::string &name, const std::string &version)
 
static std::vector< uint8_t > build_span (const trace_span &span)
 
static std::vector< uint8_t > build_key_value (const std::string &key, const std::string &value)
 
static std::vector< uint8_t > build_any_value_string (const std::string &value)
 
static void write_varint (std::vector< uint8_t > &data, uint64_t value)
 
static void write_fixed64 (std::vector< uint8_t > &data, uint64_t value)
 
static std::vector< uint8_t > hex_to_bytes (const std::string &hex, std::size_t expected_size)
 

Detailed Description

Converts internal spans to OTLP wire format.

This class handles the conversion of internal trace_span objects to the OTLP protocol buffer format.

Definition at line 106 of file otlp_grpc_exporter.h.

Member Function Documentation

◆ build_any_value_string()

static std::vector< uint8_t > kcenon::monitoring::otlp_span_converter::build_any_value_string ( const std::string & value)
inlinestaticprivate

Definition at line 324 of file otlp_grpc_exporter.h.

324 {
325 std::vector<uint8_t> data;
326 // Field 1: string_value
327 data.push_back(0x0A);
328 write_varint(data, value.size());
329 data.insert(data.end(), value.begin(), value.end());
330 return data;
331 }
static void write_varint(std::vector< uint8_t > &data, uint64_t value)

References write_varint().

Referenced by build_key_value().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ build_key_value()

static std::vector< uint8_t > kcenon::monitoring::otlp_span_converter::build_key_value ( const std::string & key,
const std::string & value )
inlinestaticprivate

Definition at line 304 of file otlp_grpc_exporter.h.

306 {
307
308 std::vector<uint8_t> data;
309
310 // Field 1: key
311 data.push_back(0x0A);
312 write_varint(data, key.size());
313 data.insert(data.end(), key.begin(), key.end());
314
315 // Field 2: value (AnyValue)
316 auto any_value = build_any_value_string(value);
317 data.push_back(0x12);
318 write_varint(data, any_value.size());
319 data.insert(data.end(), any_value.begin(), any_value.end());
320
321 return data;
322 }
static std::vector< uint8_t > build_any_value_string(const std::string &value)

References build_any_value_string(), and write_varint().

Referenced by build_resource(), and build_span().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ build_resource()

static std::vector< uint8_t > kcenon::monitoring::otlp_span_converter::build_resource ( const std::string & service_name,
const std::string & service_version,
const std::unordered_map< std::string, std::string > & extra_attributes )
inlinestaticprivate

Definition at line 177 of file otlp_grpc_exporter.h.

180 {
181
182 std::vector<uint8_t> data;
183
184 // Field 1: attributes (repeated)
185 // service.name attribute
186 auto attr1 = build_key_value("service.name", service_name);
187 data.push_back(0x0A);
188 write_varint(data, attr1.size());
189 data.insert(data.end(), attr1.begin(), attr1.end());
190
191 // service.version attribute
192 auto attr2 = build_key_value("service.version", service_version);
193 data.push_back(0x0A);
194 write_varint(data, attr2.size());
195 data.insert(data.end(), attr2.begin(), attr2.end());
196
197 // Extra attributes
198 for (const auto& [key, value] : extra_attributes) {
199 auto attr = build_key_value(key, value);
200 data.push_back(0x0A);
201 write_varint(data, attr.size());
202 data.insert(data.end(), attr.begin(), attr.end());
203 }
204
205 return data;
206 }
static std::vector< uint8_t > build_key_value(const std::string &key, const std::string &value)

References build_key_value(), and write_varint().

Referenced by build_resource_spans().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ build_resource_spans()

static std::vector< uint8_t > kcenon::monitoring::otlp_span_converter::build_resource_spans ( const std::vector< trace_span > & spans,
const std::string & service_name,
const std::string & service_version,
const std::unordered_map< std::string, std::string > & resource_attributes )
inlinestaticprivate

Definition at line 154 of file otlp_grpc_exporter.h.

158 {
159
160 std::vector<uint8_t> data;
161
162 // Field 1: resource
163 auto resource_data = build_resource(service_name, service_version, resource_attributes);
164 data.push_back(0x0A); // Field 1, length-delimited
165 write_varint(data, resource_data.size());
166 data.insert(data.end(), resource_data.begin(), resource_data.end());
167
168 // Field 2: scope_spans
169 auto scope_spans_data = build_scope_spans(spans);
170 data.push_back(0x12); // Field 2, length-delimited
171 write_varint(data, scope_spans_data.size());
172 data.insert(data.end(), scope_spans_data.begin(), scope_spans_data.end());
173
174 return data;
175 }
static std::vector< uint8_t > build_scope_spans(const std::vector< trace_span > &spans)
static std::vector< uint8_t > build_resource(const std::string &service_name, const std::string &service_version, const std::unordered_map< std::string, std::string > &extra_attributes)

References build_resource(), build_scope_spans(), and write_varint().

Referenced by convert_to_otlp().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ build_scope()

static std::vector< uint8_t > kcenon::monitoring::otlp_span_converter::build_scope ( const std::string & name,
const std::string & version )
inlinestaticprivate

Definition at line 230 of file otlp_grpc_exporter.h.

232 {
233
234 std::vector<uint8_t> data;
235
236 // Field 1: name
237 data.push_back(0x0A);
238 write_varint(data, name.size());
239 data.insert(data.end(), name.begin(), name.end());
240
241 // Field 2: version
242 data.push_back(0x12);
243 write_varint(data, version.size());
244 data.insert(data.end(), version.begin(), version.end());
245
246 return data;
247 }

References write_varint().

Referenced by build_scope_spans().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ build_scope_spans()

static std::vector< uint8_t > kcenon::monitoring::otlp_span_converter::build_scope_spans ( const std::vector< trace_span > & spans)
inlinestaticprivate

Definition at line 208 of file otlp_grpc_exporter.h.

209 {
210
211 std::vector<uint8_t> data;
212
213 // Field 1: scope (InstrumentationScope)
214 auto scope_data = build_scope("monitoring_system", "2.0.0");
215 data.push_back(0x0A);
216 write_varint(data, scope_data.size());
217 data.insert(data.end(), scope_data.begin(), scope_data.end());
218
219 // Field 2: spans (repeated)
220 for (const auto& span : spans) {
221 auto span_data = build_span(span);
222 data.push_back(0x12);
223 write_varint(data, span_data.size());
224 data.insert(data.end(), span_data.begin(), span_data.end());
225 }
226
227 return data;
228 }
static std::vector< uint8_t > build_span(const trace_span &span)
static std::vector< uint8_t > build_scope(const std::string &name, const std::string &version)

References build_scope(), build_span(), and write_varint().

Referenced by build_resource_spans().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ build_span()

static std::vector< uint8_t > kcenon::monitoring::otlp_span_converter::build_span ( const trace_span & span)
inlinestaticprivate

Definition at line 249 of file otlp_grpc_exporter.h.

249 {
250 std::vector<uint8_t> data;
251
252 // Field 1: trace_id (16 bytes)
253 auto trace_id_bytes = hex_to_bytes(span.trace_id, 16);
254 data.push_back(0x0A);
255 write_varint(data, trace_id_bytes.size());
256 data.insert(data.end(), trace_id_bytes.begin(), trace_id_bytes.end());
257
258 // Field 2: span_id (8 bytes)
259 auto span_id_bytes = hex_to_bytes(span.span_id, 8);
260 data.push_back(0x12);
261 write_varint(data, span_id_bytes.size());
262 data.insert(data.end(), span_id_bytes.begin(), span_id_bytes.end());
263
264 // Field 4: parent_span_id (8 bytes, optional)
265 if (!span.parent_span_id.empty()) {
266 auto parent_id_bytes = hex_to_bytes(span.parent_span_id, 8);
267 data.push_back(0x22);
268 write_varint(data, parent_id_bytes.size());
269 data.insert(data.end(), parent_id_bytes.begin(), parent_id_bytes.end());
270 }
271
272 // Field 5: name
273 data.push_back(0x2A);
274 write_varint(data, span.operation_name.size());
275 data.insert(data.end(), span.operation_name.begin(), span.operation_name.end());
276
277 // Field 6: kind (SPAN_KIND_INTERNAL = 1)
278 data.push_back(0x30);
279 data.push_back(0x01);
280
281 // Field 7: start_time_unix_nano (fixed64)
282 auto start_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
283 span.start_time.time_since_epoch()).count();
284 data.push_back(0x39); // Field 7, wire type 1 (64-bit)
285 write_fixed64(data, static_cast<uint64_t>(start_ns));
286
287 // Field 8: end_time_unix_nano (fixed64)
288 auto end_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
289 span.end_time.time_since_epoch()).count();
290 data.push_back(0x41); // Field 8, wire type 1 (64-bit)
291 write_fixed64(data, static_cast<uint64_t>(end_ns));
292
293 // Field 9: attributes (repeated)
294 for (const auto& [key, value] : span.tags) {
295 auto attr = build_key_value(key, value);
296 data.push_back(0x4A);
297 write_varint(data, attr.size());
298 data.insert(data.end(), attr.begin(), attr.end());
299 }
300
301 return data;
302 }
static void write_fixed64(std::vector< uint8_t > &data, uint64_t value)
static std::vector< uint8_t > hex_to_bytes(const std::string &hex, std::size_t expected_size)

References build_key_value(), kcenon::monitoring::trace_span::end_time, hex_to_bytes(), kcenon::monitoring::trace_span::operation_name, kcenon::monitoring::trace_span::parent_span_id, kcenon::monitoring::trace_span::span_id, kcenon::monitoring::trace_span::start_time, kcenon::monitoring::trace_span::tags, kcenon::monitoring::trace_span::trace_id, write_fixed64(), and write_varint().

Referenced by build_scope_spans().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ convert_to_otlp()

static std::vector< uint8_t > kcenon::monitoring::otlp_span_converter::convert_to_otlp ( const std::vector< trace_span > & spans,
const std::string & service_name,
const std::string & service_version,
const std::unordered_map< std::string, std::string > & resource_attributes )
inlinestatic

Convert spans to OTLP protobuf format.

Parameters
spansVector of spans to convert
service_nameService name for resource
service_versionService version
resource_attributesAdditional resource attributes
Returns
Serialized OTLP ExportTraceServiceRequest

Definition at line 116 of file otlp_grpc_exporter.h.

120 {
121
122 // OTLP ExportTraceServiceRequest structure:
123 // - resource_spans (repeated)
124 // - resource
125 // - attributes
126 // - scope_spans (repeated)
127 // - scope
128 // - spans (repeated)
129
130 std::vector<uint8_t> payload;
131
132 // Build minimal OTLP-compatible protobuf structure
133 // Note: Full implementation would use generated protobuf code
134
135 // For now, we serialize to a simplified format that OpenTelemetry
136 // Collector can process. Production use should integrate actual
137 // OTLP proto definitions.
138
139 // Write field 1 (resource_spans) - length-delimited
140 auto resource_spans_data = build_resource_spans(
141 spans, service_name, service_version, resource_attributes);
142
143 // Protobuf wire format: (field_number << 3) | wire_type
144 // Field 1, wire type 2 (length-delimited) = 0x0A
145 payload.push_back(0x0A);
146 write_varint(payload, resource_spans_data.size());
147 payload.insert(payload.end(),
148 resource_spans_data.begin(), resource_spans_data.end());
149
150 return payload;
151 }
static std::vector< uint8_t > build_resource_spans(const std::vector< trace_span > &spans, const std::string &service_name, const std::string &service_version, const std::unordered_map< std::string, std::string > &resource_attributes)

References build_resource_spans(), and write_varint().

Referenced by kcenon::monitoring::otlp_grpc_exporter::export_spans(), TEST_F(), and TEST_F().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ hex_to_bytes()

static std::vector< uint8_t > kcenon::monitoring::otlp_span_converter::hex_to_bytes ( const std::string & hex,
std::size_t expected_size )
inlinestaticprivate

Definition at line 348 of file otlp_grpc_exporter.h.

348 {
349 std::vector<uint8_t> bytes;
350 bytes.reserve(expected_size);
351
352 for (std::size_t i = 0; i + 1 < hex.size(); i += 2) {
353 auto byte_str = hex.substr(i, 2);
354 try {
355 bytes.push_back(static_cast<uint8_t>(std::stoul(byte_str, nullptr, 16)));
356 } catch (...) {
357 bytes.push_back(0);
358 }
359 }
360
361 // Pad or truncate to expected size
362 while (bytes.size() < expected_size) {
363 bytes.insert(bytes.begin(), 0);
364 }
365 if (bytes.size() > expected_size) {
366 bytes.resize(expected_size);
367 }
368
369 return bytes;
370 }

Referenced by build_span().

Here is the caller graph for this function:

◆ write_fixed64()

static void kcenon::monitoring::otlp_span_converter::write_fixed64 ( std::vector< uint8_t > & data,
uint64_t value )
inlinestaticprivate

Definition at line 341 of file otlp_grpc_exporter.h.

341 {
342 for (int i = 0; i < 8; ++i) {
343 data.push_back(static_cast<uint8_t>(value & 0xFF));
344 value >>= 8;
345 }
346 }

Referenced by build_span().

Here is the caller graph for this function:

◆ write_varint()

static void kcenon::monitoring::otlp_span_converter::write_varint ( std::vector< uint8_t > & data,
uint64_t value )
inlinestaticprivate

Definition at line 333 of file otlp_grpc_exporter.h.

333 {
334 while (value >= 0x80) {
335 data.push_back(static_cast<uint8_t>(value | 0x80));
336 value >>= 7;
337 }
338 data.push_back(static_cast<uint8_t>(value));
339 }

Referenced by build_any_value_string(), build_key_value(), build_resource(), build_resource_spans(), build_scope(), build_scope_spans(), build_span(), and convert_to_otlp().

Here is the caller graph for this function:

The documentation for this class was generated from the following file: