OpenTelemetry Filter Configuration Structures ============================================================================== 1 Overview ------------------------------------------------------------------------------ The OpenTelemetry filter configuration is a tree of C structures that mirrors the hierarchical layout of the filter's configuration file. Each structure type carries a common header macro, and its allocation and deallocation are performed by macro-generated init/free function pairs defined in conf_funcs.h. The root of the tree is flt_otel_conf, which owns the instrumentation settings, groups, and scopes. Scopes contain the actual tracing and metrics definitions: contexts, spans, instruments, and their sample expressions. Source files: include/conf.h Structure definitions and debug macros. include/conf_funcs.h Init/free macro templates and declarations. src/conf.c Init/free implementations for all types. 2 Common Macros ------------------------------------------------------------------------------ Two macros provide the building blocks embedded in every configuration structure. 2.1 FLT_OTEL_CONF_STR(p) Expands to an anonymous struct containing a string pointer and its cached length: struct { char *p; size_t p_len; }; Used for auxiliary string fields that do not need list linkage (e.g. ref_id and ctx_id in flt_otel_conf_span). 2.2 FLT_OTEL_CONF_HDR(p) Expands to an anonymous struct that extends FLT_OTEL_CONF_STR with a configuration file line number and an intrusive list node: struct { char *p; size_t p_len; int cfg_line; struct list list; }; Every configuration structure embeds FLT_OTEL_CONF_HDR as its first member. The

parameter names the identifier field (e.g. "id", "key", "str", "span", "fmt_expr"). The list node chains the structure into its parent's list. The cfg_line records the source line for error reporting. 3 Structure Hierarchy ------------------------------------------------------------------------------ The complete ownership tree, from root to leaves: flt_otel_conf +-- flt_otel_conf_instr (one, via pointer) | +-- flt_otel_conf_ph (ph_groups list) | +-- flt_otel_conf_ph (ph_scopes list) | +-- struct acl (acls list, HAProxy-owned type) | +-- struct logger (proxy_log.loggers, HAProxy type) +-- flt_otel_conf_group (groups list) | +-- flt_otel_conf_ph (ph_scopes list) +-- flt_otel_conf_scope (scopes list) +-- flt_otel_conf_context (contexts list) +-- flt_otel_conf_span (spans list) | +-- flt_otel_conf_link (links list) | +-- flt_otel_conf_sample (attributes list) | | +-- flt_otel_conf_sample_expr (exprs list) | +-- flt_otel_conf_sample (events list) | | +-- flt_otel_conf_sample_expr (exprs list) | +-- flt_otel_conf_sample (baggages list) | | +-- flt_otel_conf_sample_expr (exprs list) | +-- flt_otel_conf_sample (statuses list) | +-- flt_otel_conf_sample_expr (exprs list) +-- flt_otel_conf_str (spans_to_finish list) +-- flt_otel_conf_instrument (instruments list) | +-- flt_otel_conf_sample (samples list) | +-- flt_otel_conf_sample_expr (exprs list) +-- flt_otel_conf_log_record (log_records list) +-- flt_otel_conf_sample (attributes list) | +-- flt_otel_conf_sample_expr (exprs list) +-- flt_otel_conf_sample (samples list) +-- flt_otel_conf_sample_expr (exprs list) All child lists use HAProxy's intrusive doubly-linked list (struct list) threaded through the FLT_OTEL_CONF_HDR embedded in each child structure. 3.1 Placeholder Structures The flt_otel_conf_ph structure serves as an indirection node. During parsing, placeholder entries record names of groups and scopes. At check time (flt_otel_check), these names are resolved to pointers to the actual flt_otel_conf_group or flt_otel_conf_scope structures via the ptr field. Two type aliases exist for clarity: #define flt_otel_conf_ph_group flt_otel_conf_ph #define flt_otel_conf_ph_scope flt_otel_conf_ph Corresponding free aliases ensure the FLT_OTEL_LIST_DESTROY macro can locate the correct free function: #define flt_otel_conf_ph_group_free flt_otel_conf_ph_free #define flt_otel_conf_ph_scope_free flt_otel_conf_ph_free 4 Structure Definitions ------------------------------------------------------------------------------ 4.1 flt_otel_conf (root) proxy Proxy owning the filter. id The OpenTelemetry filter id. cfg_file The OpenTelemetry filter configuration file name. instr The OpenTelemetry instrumentation settings (pointer). groups List of all available groups. scopes List of all available scopes. cnt Various counters related to filter operation. smp_args Deferred sample fetch arguments to resolve at check time. This structure does not use FLT_OTEL_CONF_HDR because it is not part of any list -- it is the unique root, owned by the filter instance. 4.2 flt_otel_conf_instr (instrumentation) FLT_OTEL_CONF_HDR(id) The OpenTelemetry instrumentation name. config The OpenTelemetry configuration file name. tracer The OpenTelemetry tracer handle. meter The OpenTelemetry meter handle. logger The OpenTelemetry logger handle. rate_limit Rate limit as uint32 ([0..2^32-1] maps [0..100]%). flag_harderr Hard-error mode flag. flag_disabled Disabled flag. logging Logging mode (0, 1, or 3). proxy_log The log server list (HAProxy proxy structure). analyzers Defined channel analyzers bitmask. idle_timeout Minimum idle timeout across scopes (ms, 0 = off). acls ACLs declared on this tracer. ph_groups List of all used groups (placeholders). ph_scopes List of all used scopes (placeholders). Exactly one instrumentation block is allowed per filter instance. The parser stores a pointer to it in flt_otel_conf.instr. 4.3 flt_otel_conf_group FLT_OTEL_CONF_HDR(id) The group name. flag_used The indication that the group is being used. ph_scopes List of all used scopes (placeholders). Groups bundle scopes for use with the "otel-group" HAProxy action. 4.4 flt_otel_conf_scope FLT_OTEL_CONF_HDR(id) The scope name. flag_used The indication that the scope is being used. event FLT_OTEL_EVENT_* identifier. idle_timeout Idle timeout interval in milliseconds (0 = off). acls ACLs declared on this scope. cond ACL condition to meet. contexts Declared contexts. spans Declared spans. spans_to_finish The list of spans scheduled for finishing. instruments The list of metric instruments. log_records The list of log records. Each scope binds to a single HAProxy analyzer event (or none, if used only through groups). 4.5 flt_otel_conf_span FLT_OTEL_CONF_HDR(id) The name of the span. FLT_OTEL_CONF_STR(ref_id) The reference name, if used. FLT_OTEL_CONF_STR(ctx_id) The span context name, if used. ctx_flags The type of storage used for the span context. flag_root Whether this is a root span. links The set of linked span names. attributes The set of key:value attributes. events The set of events with key-value attributes. baggages The set of key:value baggage items. statuses Span status code and description. The ref_id and ctx_id fields use FLT_OTEL_CONF_STR because they are simple name strings without list linkage. 4.6 flt_otel_conf_instrument FLT_OTEL_CONF_HDR(id) The name of the instrument. idx Meter instrument index: UNSET (-1) before creation, PENDING (-2) while another thread is creating, or >= 0 for the actual meter index. type Instrument type (or UPDATE). aggr_type Aggregation type for the view (create only). description Instrument description (create only). unit Instrument unit (create only). samples Sample expressions for the value. bounds Histogram bucket boundaries (create only). bounds_num Number of histogram bucket boundaries. attributes Instrument attributes (update only, flt_otel_conf_sample). ref Resolved create-form instrument (update only). Instruments come in two forms: create-form (defines a new metric with type, description, unit, and optional histogram bounds) and update-form (references an existing instrument via the ref pointer). Update-form attributes are stored as flt_otel_conf_sample entries and evaluated at runtime. 4.7 flt_otel_conf_log_record FLT_OTEL_CONF_HDR(id) Required by macro; member is not used directly. severity The severity level. event_id Optional event identifier. event_name Optional event name. span Optional span reference. attributes Log record attributes (flt_otel_conf_sample list). samples Sample expressions for the body. Log records are emitted via the OTel logger at the configured severity. The optional span reference associates the log record with an open span at runtime. Attributes are stored as flt_otel_conf_sample entries added via the 'attr' keyword, which can be repeated. Attribute values are HAProxy sample expressions evaluated at runtime. 4.8 flt_otel_conf_context FLT_OTEL_CONF_HDR(id) The name of the context. flags Storage type from which the span context is extracted. 4.9 flt_otel_conf_sample FLT_OTEL_CONF_HDR(key) The list containing sample names. fmt_string Combined sample-expression arguments string. extra Optional supplementary data. exprs Used to chain sample expressions. num_exprs Number of defined expressions. lf_expr The log-format expression. lf_used Whether lf_expr is used instead of exprs. The extra field carries type-specific data: event name strings (OTELC_VALUE_DATA) for span events, status code integers (OTELC_VALUE_INT32) for span statuses. When the sample value argument contains the "%[" sequence, the parser treats it as a log-format string: the lf_used flag is set and the compiled result is stored in lf_expr, while the exprs list remains empty. At runtime, if lf_used is true, the log-format expression is evaluated via build_logline() instead of the sample expression list. 4.10 flt_otel_conf_sample_expr FLT_OTEL_CONF_HDR(fmt_expr) The original expression format string. expr The sample expression (struct sample_expr). 4.11 Simple Types flt_otel_conf_hdr Generic header; used for simple named entries. flt_otel_conf_str String holder (identical to conf_hdr in layout, but the HDR field is named "str" instead of "id"); used for spans_to_finish. flt_otel_conf_link Span link reference; HDR field named "span". flt_otel_conf_ph Placeholder; carries a ptr field resolved at check time. 5 Initialization ------------------------------------------------------------------------------ 5.1 Macro-Generated Init Functions The FLT_OTEL_CONF_FUNC_INIT macro (conf_funcs.h) generates a function with the following signature for each configuration type: struct flt_otel_conf_ *flt_otel_conf__init(const char *id, int line, struct list *head, char **err); The generated function performs these steps: 1. Validates that is non-NULL and non-empty. 2. Checks the identifier length against FLT_OTEL_ID_MAXLEN (64). 3. If is non-NULL, iterates the list to reject duplicate identifiers (strcmp match). 4. Allocates the structure with OTELC_CALLOC (zeroed memory). 5. Records the configuration line number in cfg_line. 6. Duplicates the identifier string with OTELC_STRDUP. 7. If is non-NULL, appends the structure to the list via LIST_APPEND. 8. Executes any custom initialization body provided as the third macro argument. If any step fails, the function sets an error message via FLT_OTEL_ERR and returns NULL. 5.2 Custom Initialization Bodies Several structure types require additional setup beyond what the macro template provides. The custom init body runs after the base allocation and list insertion succeed: conf_sample: LIST_INIT for exprs. Calls lf_expr_init for lf_expr. conf_span: LIST_INIT for links, attributes, events, baggages, statuses. conf_scope: LIST_INIT for acls, contexts, spans, spans_to_finish, instruments, log_records. conf_group: LIST_INIT for ph_scopes. conf_instrument: Sets idx and type to OTELC_METRIC_INSTRUMENT_UNSET, aggr_type to OTELC_METRIC_AGGREGATION_UNSET. LIST_INIT for samples. conf_log_record: LIST_INIT for samples. conf_instr: Sets rate_limit to FLT_OTEL_FLOAT_U32(100.0) (100%). Calls init_new_proxy for proxy_log. LIST_INIT for acls, ph_groups, ph_scopes. Types with no custom body (hdr, str, link, ph, sample_expr, context) rely entirely on the zeroed OTELC_CALLOC allocation. 5.3 Extended Sample Initialization The flt_otel_conf_sample_init_ex function (conf.c) provides a higher-level initialization for sample structures: 1. Verifies sufficient arguments in the args[] array. 2. Calls flt_otel_conf_sample_init with the sample key. 3. Copies extra data (event name string or status code integer). 4. Concatenates remaining arguments into the fmt_string via flt_otel_args_concat. 5. Counts the number of sample expressions. This function is used by the parser for span attributes, events, baggages, statuses, and instrument samples. 5.4 Top-Level Initialization The flt_otel_conf_init function (conf.c) is hand-written rather than macro-generated because the root structure does not follow the standard header pattern: 1. Allocates flt_otel_conf with OTELC_CALLOC. 2. Stores the proxy reference. 3. Initializes the groups and scopes lists. 6 Deallocation ------------------------------------------------------------------------------ 6.1 Macro-Generated Free Functions The FLT_OTEL_CONF_FUNC_FREE macro (conf_funcs.h) generates a function with the following signature: void flt_otel_conf__free(struct flt_otel_conf_ **ptr); The generated function performs these steps: 1. Checks that both and <*ptr> are non-NULL. 2. Executes any custom cleanup body provided as the third macro argument. 3. Frees the identifier string with OTELC_SFREE. 4. Removes the structure from its list with FLT_OTEL_LIST_DEL. 5. Frees the structure with OTELC_SFREE_CLEAR and sets <*ptr> to NULL. 6.2 Custom Cleanup Bodies Custom cleanup runs before the base teardown, allowing child structures to be freed while the parent is still valid: conf_sample: Frees fmt_string. If extra is OTELC_VALUE_DATA, frees the data pointer. Destroys the exprs list (sample_expr entries). Deinitializes lf_expr via lf_expr_deinit. conf_sample_expr: Releases the HAProxy sample expression via release_sample_expr. conf_span: Frees ref_id and ctx_id strings. Destroys links, attributes, events, baggages, and statuses lists. conf_instrument: Frees description, unit, and bounds. Destroys the samples list. Destroys the attr key-value array via otelc_kv_destroy. conf_log_record: Frees event_name and span strings. Destroys the attr key-value array via otelc_kv_destroy. Destroys the samples list. conf_scope: Prunes and frees each ACL entry. Frees the ACL condition via free_acl_cond. Destroys contexts, spans, spans_to_finish, instruments, and log_records lists. conf_group: Destroys the ph_scopes list. conf_instr: Frees the config string. Prunes and frees each ACL entry. Frees each logger entry from proxy_log.loggers. Destroys the ph_groups and ph_scopes lists. Types with no custom cleanup (hdr, str, link, ph, context) only run the base teardown: free the identifier, unlink, free the structure. 6.3 List Destruction The FLT_OTEL_LIST_DESTROY(type, head) macro (defined in define.h) iterates a list and calls flt_otel_conf__free for each entry. This macro drives the recursive teardown from parent to leaf. 6.4 Top-Level Deallocation The flt_otel_conf_free function (conf.c) is hand-written: 1. Frees the id and cfg_file strings. 2. Calls flt_otel_conf_instr_free for the instrumentation. 3. Destroys the groups list (which recursively frees placeholders). 4. Destroys the scopes list (which recursively frees contexts, spans, instruments, log records, and all their children). 5. Frees the root structure and sets the pointer to NULL. 7 Summary of Init/Free Pairs ------------------------------------------------------------------------------ The following table lists all configuration types and their init/free function pairs. Types marked "macro" are generated by the FLT_OTEL_CONF_FUNC_(INIT|FREE) macros. The HDR field column shows which member name is used for the common header. Type HDR field Source Custom init body --------------- --------- ------ ------------------------- conf (none) manual groups, scopes conf_hdr id macro (none) conf_str str macro (none) conf_link span macro (none) conf_ph id macro (none) conf_sample_expr fmt_expr macro (none) conf_sample key macro exprs, lf_expr conf_sample (ex) key manual extra, fmt_string, exprs conf_context id macro (none) conf_span id macro 5 sub-lists conf_instrument id macro idx, type, samples conf_log_record id macro samples conf_scope id macro 6 sub-lists conf_group id macro ph_scopes conf_instr id macro rate_limit, proxy_log, acls, ph_groups, ph_scopes