Miroslav Zagorac bab0ea7b77 MEDIUM: otel: implemented scope execution and span management
Implemented the scope execution engine that creates OTel spans, evaluates
sample expressions to collect telemetry data, and manages span lifecycle
during request and response processing.

The scope runner flt_otel_scope_run() was expanded from a stub into a
complete implementation that evaluates ACL conditions on the scope,
extracts span contexts from HTTP headers when configured, iterates over
the scope's span definitions calling flt_otel_scope_run_span() for each,
marks and finishes completed spans, and cleans up unused runtime
resources.

The span runner flt_otel_scope_run_span() creates OTel spans via the
tracer with optional parent references (from other spans or extracted
contexts), collects telemetry by calling flt_otel_sample_add() for each
configured attribute, event, baggage and status entry, then applies the
collected data to the span (attributes, events with their own key-value
arrays, baggage items, and status code with description) and injects the
span context into HTTP headers when configured.

The sample evaluation layer converts HAProxy sample expressions into OTel
telemetry data.  flt_otel_sample_add() evaluates each sample expression
against the stream, converts the result via flt_otel_sample_to_value()
which preserves native types (booleans as OTELC_VALUE_BOOL, integers as
OTELC_VALUE_INT64, all others as strings), and routes the key-value pair
to the appropriate collector based on the sample type (attribute, event,
baggage, or status).  The key-value arrays grow dynamically using the
FLT_OTEL_ATTR_INIT_SIZE and FLT_OTEL_ATTR_INC_SIZE constants.

Span finishing is handled in two phases: flt_otel_scope_finish_mark()
marks spans and contexts for completion using exact name matching or
wildcards ("*" for all, "*req*" for request-direction, "*res*" for
response-direction), and flt_otel_scope_finish_marked() ends all marked
spans with a common monotonic timestamp and destroys their contexts.
2026-04-13 09:23:26 +02:00

77 lines
2.7 KiB
C

/* SPDX-License-Identifier: LGPL-2.1-or-later */
#ifndef _OTEL_UTIL_H_
#define _OTEL_UTIL_H_
#define FLT_OTEL_HTTP_METH_DEFINES \
FLT_OTEL_HTTP_METH_DEF(OPTIONS) \
FLT_OTEL_HTTP_METH_DEF(GET) \
FLT_OTEL_HTTP_METH_DEF(HEAD) \
FLT_OTEL_HTTP_METH_DEF(POST) \
FLT_OTEL_HTTP_METH_DEF(PUT) \
FLT_OTEL_HTTP_METH_DEF(DELETE) \
FLT_OTEL_HTTP_METH_DEF(TRACE) \
FLT_OTEL_HTTP_METH_DEF(CONNECT)
#ifdef DEBUG_OTEL
# define FLT_OTEL_ARGS_DUMP() do { if (otelc_dbg_level & (1 << OTELC_DBG_LEVEL_LOG)) flt_otel_args_dump((const char **)args); } while (0)
#else
# define FLT_OTEL_ARGS_DUMP() while (0)
#endif
#ifdef DEBUG_OTEL
/* Dump configuration arguments for debugging. */
void flt_otel_args_dump(const char **args);
/* Return a label string identifying a channel direction. */
const char *flt_otel_chn_label(const struct channel *chn);
/* Return the proxy mode string for a stream. */
const char *flt_otel_pr_mode(const struct stream *s);
/* Return the stream processing position as a string. */
const char *flt_otel_stream_pos(const struct stream *s);
/* Return the filter type string for a filter instance. */
const char *flt_otel_type(const struct filter *f);
/* Return the analyzer name string for an analyzer bit. */
const char *flt_otel_analyzer(uint an_bit);
/* Dump a linked list of configuration items as a string. */
const char *flt_otel_list_dump(const struct list *head);
#endif
/* Count the number of non-NULL arguments in an argument array. */
int flt_otel_args_count(const char **args);
/* Concatenate argument array elements into a single string. */
int flt_otel_args_concat(const char **args, int idx, int n, char **str);
/* Parse a string to double with range validation. */
bool flt_otel_strtod(const char *nptr, double *value, double limit_min, double limit_max, char **err);
/* Parse a string to int64_t with range validation. */
bool flt_otel_strtoll(const char *nptr, int64_t *value, int64_t limit_min, int64_t limit_max, char **err);
/* Convert sample data to a string representation. */
int flt_otel_sample_to_str(const struct sample_data *data, char *value, size_t size, char **err);
/* Convert sample data to an OTel value. */
int flt_otel_sample_to_value(const char *key, const struct sample_data *data, struct otelc_value *value, char **err);
/* Evaluate a sample expression and add the result to scope data. */
int flt_otel_sample_add(struct stream *s, uint dir, struct flt_otel_conf_sample *sample, struct flt_otel_scope_data *data, int type, char **err);
#endif /* _OTEL_UTIL_H_ */
/*
* Local variables:
* c-indent-level: 8
* c-basic-offset: 8
* End:
*
* vi: noexpandtab shiftwidth=8 tabstop=8
*/