MEDIUM: otel: added CLI commands for runtime filter management

Added HAProxy CLI commands that allow runtime inspection and modification
of OTel filter settings without requiring a configuration reload.

The new cli.c module registers CLI keywords under the "otel" prefix and
implements the following commands: flt_otel_cli_parse_status() displays a
comprehensive status report of all OTel filter instances including filter
ID, proxy, disabled state, hard-error mode, logging state, rate limit,
analyzer bits, and SDK diagnostic message count;
flt_otel_cli_parse_disabled() enables or disables filtering across all
instances; flt_otel_cli_parse_option() toggles the hard-error mode that
controls whether errors disable the filter for a stream or are silently
ignored; flt_otel_cli_parse_logging() manages the logging state with
support for off, on, and dontlog-normal modes; flt_otel_cli_parse_rate()
adjusts the sampling rate limit as a floating-point percentage; and
flt_otel_cli_parse_debug() sets the debug verbosity level in debug builds.
All modifications are applied atomically across every OTel filter instance
in every proxy.

The CLI initialization is called from flt_otel_ops_init() during filter
startup via flt_otel_cli_init(), which registers the keyword table through
cli_register_kw().

Supporting changes include the FLT_OTEL_U32_FLOAT macro for converting the
internal uint32_t rate representation to a human-readable percentage, the
FLT_OTEL_PROXIES_LIST_START/END iteration macros for traversing all OTel
filter instances across the proxy list, and flt_otel_filters_dump() for
debug logging of filter instances.
This commit is contained in:
Miroslav Zagorac 2026-04-12 11:31:30 +02:00 committed by William Lallemand
parent b1498910ec
commit cb4cb1065c
8 changed files with 553 additions and 1 deletions

View file

@ -52,6 +52,7 @@ $(error OpenTelemetry C wrapper : can't find library)
endif
OPTIONS_OBJS += \
addons/otel/src/cli.o \
addons/otel/src/conf.o \
addons/otel/src/event.o \
addons/otel/src/filter.o \

28
addons/otel/include/cli.h Normal file
View file

@ -0,0 +1,28 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#ifndef _OTEL_CLI_H_
#define _OTEL_CLI_H_
#define FLT_OTEL_CLI_CMD "flt-otel"
#define FLT_OTEL_CLI_LOGGING_OFF "off"
#define FLT_OTEL_CLI_LOGGING_ON "on"
#define FLT_OTEL_CLI_LOGGING_NOLOGNORM "dontlog-normal"
#define FLT_OTEL_CLI_LOGGING_STATE(a) (((a) & FLT_OTEL_LOGGING_ON) ? (((a) & FLT_OTEL_LOGGING_NOLOGNORM) ? "enabled, " FLT_OTEL_CLI_LOGGING_NOLOGNORM : "enabled") : "disabled")
#define FLT_OTEL_CLI_MSG_CAT(a) (((a) == NULL) ? "" : (a)), (((a) == NULL) ? "" : "\n")
/* Register CLI keywords for the OTel filter. */
void flt_otel_cli_init(void);
#endif /* _OTEL_CLI_H_ */
/*
* Local variables:
* c-indent-level: 8
* c-basic-offset: 8
* End:
*
* vi: noexpandtab shiftwidth=8 tabstop=8
*/

View file

@ -9,9 +9,16 @@
/* Check whether argument at index n is in range, non-NULL and non-empty. */
#define FLT_OTEL_ARG_ISVALID(n) ({ typeof(n) _n = (n); OTELC_IN_RANGE(_n, 0, MAX_LINE_ARGS - 1) && (args[_n] != NULL) && (*args[_n] != '\0'); })
/* Convert a uint32_t rate value to a floating-point percentage. */
#define FLT_OTEL_U32_FLOAT(a) ((a) * 100.0 / UINT32_MAX)
/* Convert a floating-point percentage to a uint32_t rate value. */
#define FLT_OTEL_FLOAT_U32(a) ((uint32_t)((a) / 100.0 * UINT32_MAX + 0.5))
#define FLT_OTEL_STR_DASH_72 "------------------------------------------------------------------------"
#define FLT_OTEL_STR_DASH_78 FLT_OTEL_STR_DASH_72 "------"
#define FLT_OTEL_STR_FLAG_YN(a) ((a) ? "yes" : "no")
/* Compile-time string length excluding the null terminator. */
#define FLT_OTEL_STR_SIZE(a) (sizeof(a) - 1)

View file

@ -28,6 +28,7 @@
#include "config.h"
#include "debug.h"
#include "define.h"
#include "cli.h"
#include "event.h"
#include "conf.h"
#include "conf_funcs.h"

View file

@ -13,6 +13,20 @@
FLT_OTEL_HTTP_METH_DEF(TRACE) \
FLT_OTEL_HTTP_METH_DEF(CONNECT)
/* Iterate over all OTel filter configurations across all proxies. */
#define FLT_OTEL_PROXIES_LIST_START() \
do { \
struct flt_conf *fconf; \
struct proxy *px; \
\
for (px = proxies_list; px != NULL; px = px->next) \
list_for_each_entry(fconf, &(px->filter_configs), list) \
if (fconf->id == otel_flt_id) { \
struct flt_otel_conf *conf = fconf->conf;
#define FLT_OTEL_PROXIES_LIST_END() \
} \
} while (0)
#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
@ -20,10 +34,15 @@
#endif
#ifdef DEBUG_OTEL
#ifndef DEBUG_OTEL
# define flt_otel_filters_dump() while (0)
#else
/* Dump configuration arguments for debugging. */
void flt_otel_args_dump(const char **args);
/* Dump all OTel filter configurations across all proxies. */
void flt_otel_filters_dump(void);
/* Return a label string identifying a channel direction. */
const char *flt_otel_chn_label(const struct channel *chn);

455
addons/otel/src/cli.c Normal file
View file

@ -0,0 +1,455 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "../include/include.h"
/***
* NAME
* flt_otel_cli_set_msg - CLI response message setter
*
* SYNOPSIS
* static int flt_otel_cli_set_msg(struct appctx *appctx, char *err, char *msg)
*
* ARGUMENTS
* appctx - CLI application context
* err - error message string (or NULL)
* msg - informational message string (or NULL)
*
* DESCRIPTION
* Sets the CLI response message and state for the given <appctx>. If <err>
* is non-NULL, it is passed to cli_dynerr() and <msg> is freed; otherwise
* <msg> is passed to cli_dynmsg() at LOG_INFO severity. When neither message
* is available, the function returns 0 without changing state.
*
* RETURN VALUE
* Returns 1 when a message was set, or 0 when both pointers were NULL.
*/
static int flt_otel_cli_set_msg(struct appctx *appctx, char *err, char *msg)
{
OTELC_FUNC("%p, %p, %p", appctx, err, msg);
if ((appctx == NULL) || ((err == NULL) && (msg == NULL)))
OTELC_RETURN_INT(0);
if (err != NULL) {
OTELC_DBG(INFO, "err(%d): \"%s\"", appctx->st0, err);
OTELC_SFREE(msg);
OTELC_RETURN_INT(cli_dynerr(appctx, err));
}
OTELC_DBG(INFO, "msg(%d): \"%s\"", appctx->st0, msg);
OTELC_RETURN_INT(cli_dynmsg(appctx, LOG_INFO, msg));
}
#ifdef DEBUG_OTEL
/***
* NAME
* flt_otel_cli_parse_debug - CLI debug level handler
*
* SYNOPSIS
* static int flt_otel_cli_parse_debug(char **args, char *payload, struct appctx *appctx, void *private)
*
* ARGUMENTS
* args - CLI command arguments array
* payload - CLI command payload string
* appctx - CLI application context
* private - unused private data pointer
*
* DESCRIPTION
* Handles the "otel debug [level]" CLI command. When a level argument is
* provided in <args[2]>, parses it as an integer in the range
* [0, OTELC_DBG_LEVEL_MASK] and atomically stores it as the global debug
* level. Setting a level requires admin access level. When no argument is
* given, reports the current debug level. The response message includes the
* debug level in both decimal and hexadecimal format.
*
* RETURN VALUE
* Returns 1, or 0 on memory allocation failure.
*/
static int flt_otel_cli_parse_debug(char **args, char *payload, struct appctx *appctx, void *private)
{
char *err = NULL, *msg = NULL;
OTELC_FUNC("%p, \"%s\", %p, %p", args, OTELC_STR_ARG(payload), appctx, private);
FLT_OTEL_ARGS_DUMP();
if (FLT_OTEL_ARG_ISVALID(2)) {
int64_t value;
if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
OTELC_RETURN_INT(1);
if (flt_otel_strtoll(args[2], &value, 0, OTELC_DBG_LEVEL_MASK, &err)) {
_HA_ATOMIC_STORE(&otelc_dbg_level, (int)value);
(void)memprintf(&msg, FLT_OTEL_CLI_CMD " : debug level set to %d (0x%04x)", (int)value, (int)value);
}
} else {
int value = _HA_ATOMIC_LOAD(&otelc_dbg_level);
(void)memprintf(&msg, FLT_OTEL_CLI_CMD " : current debug level is %d (0x%04x)", value, value);
}
OTELC_RETURN_INT(flt_otel_cli_set_msg(appctx, err, msg));
}
#endif /* DEBUG_OTEL */
/***
* NAME
* flt_otel_cli_parse_disabled - CLI enable/disable handler
*
* SYNOPSIS
* static int flt_otel_cli_parse_disabled(char **args, char *payload, struct appctx *appctx, void *private)
*
* ARGUMENTS
* args - CLI command arguments array
* payload - CLI command payload string
* appctx - CLI application context
* private - boolean flag cast to pointer (1 = disable, 0 = enable)
*
* DESCRIPTION
* Handles the "otel enable" and "otel disable" CLI commands. The <private>
* parameter determines the action: a value of 1 disables the filter, 0
* enables it. Requires admin access level. The flag_disabled field is
* atomically updated for all OTel filter instances across all proxies.
*
* RETURN VALUE
* Returns 1, or 0 if no OTel filter instances are configured or on memory
* allocation failure.
*/
static int flt_otel_cli_parse_disabled(char **args, char *payload, struct appctx *appctx, void *private)
{
char *msg = NULL;
bool value = (uintptr_t)private;
OTELC_FUNC("%p, \"%s\", %p, %p", args, OTELC_STR_ARG(payload), appctx, private);
FLT_OTEL_ARGS_DUMP();
if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
OTELC_RETURN_INT(1);
FLT_OTEL_PROXIES_LIST_START() {
_HA_ATOMIC_STORE(&(conf->instr->flag_disabled), value);
(void)memprintf(&msg, "%s%s" FLT_OTEL_CLI_CMD " : filter %sabled", FLT_OTEL_CLI_MSG_CAT(msg), value ? "dis" : "en");
} FLT_OTEL_PROXIES_LIST_END();
OTELC_RETURN_INT(flt_otel_cli_set_msg(appctx, NULL, msg));
}
/***
* NAME
* flt_otel_cli_parse_option - CLI error mode handler
*
* SYNOPSIS
* static int flt_otel_cli_parse_option(char **args, char *payload, struct appctx *appctx, void *private)
*
* ARGUMENTS
* args - CLI command arguments array
* payload - CLI command payload string
* appctx - CLI application context
* private - boolean flag cast to pointer (1 = hard-errors, 0 = soft-errors)
*
* DESCRIPTION
* Handles the "otel hard-errors" and "otel soft-errors" CLI commands. The
* <private> parameter determines the error mode: a value of 1 enables
* hard-error mode (filter failure aborts the stream), 0 enables soft-error
* mode (failures are silently ignored). Requires admin access level. The
* flag_harderr field is atomically updated for all OTel filter instances
* across all proxies.
*
* RETURN VALUE
* Returns 1, or 0 if no OTel filter instances are configured or on memory
* allocation failure.
*/
static int flt_otel_cli_parse_option(char **args, char *payload, struct appctx *appctx, void *private)
{
char *msg = NULL;
bool value = (uintptr_t)private;
OTELC_FUNC("%p, \"%s\", %p, %p", args, OTELC_STR_ARG(payload), appctx, private);
FLT_OTEL_ARGS_DUMP();
if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
OTELC_RETURN_INT(1);
FLT_OTEL_PROXIES_LIST_START() {
_HA_ATOMIC_STORE(&(conf->instr->flag_harderr), value);
(void)memprintf(&msg, "%s%s" FLT_OTEL_CLI_CMD " : filter set %s-errors", FLT_OTEL_CLI_MSG_CAT(msg), value ? "hard" : "soft");
} FLT_OTEL_PROXIES_LIST_END();
OTELC_RETURN_INT(flt_otel_cli_set_msg(appctx, NULL, msg));
}
/***
* NAME
* flt_otel_cli_parse_logging - CLI logging state handler
*
* SYNOPSIS
* static int flt_otel_cli_parse_logging(char **args, char *payload, struct appctx *appctx, void *private)
*
* ARGUMENTS
* args - CLI command arguments array
* payload - CLI command payload string
* appctx - CLI application context
* private - unused private data pointer
*
* DESCRIPTION
* Handles the "otel logging [state]" CLI command. When a state argument is
* provided in <args[2]>, it is matched against "off", "on", or "nolognorm"
* and the logging field is atomically updated for all OTel filter instances.
* Setting a value requires admin access level. When no argument is given,
* reports the current logging state for all instances. Invalid values
* produce an error with the accepted options listed.
*
* RETURN VALUE
* Returns 1, or 0 if no OTel filter instances are configured (and no error
* occurred) or on memory allocation failure.
*/
static int flt_otel_cli_parse_logging(char **args, char *payload, struct appctx *appctx, void *private)
{
char *err = NULL, *msg = NULL;
bool flag_set = false;
uint8_t value;
OTELC_FUNC("%p, \"%s\", %p, %p", args, OTELC_STR_ARG(payload), appctx, private);
FLT_OTEL_ARGS_DUMP();
if (FLT_OTEL_ARG_ISVALID(2)) {
if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
OTELC_RETURN_INT(1);
if (strcasecmp(args[2], FLT_OTEL_CLI_LOGGING_OFF) == 0) {
flag_set = true;
value = FLT_OTEL_LOGGING_OFF;
}
else if (strcasecmp(args[2], FLT_OTEL_CLI_LOGGING_ON) == 0) {
flag_set = true;
value = FLT_OTEL_LOGGING_ON;
}
else if (strcasecmp(args[2], FLT_OTEL_CLI_LOGGING_NOLOGNORM) == 0) {
flag_set = true;
value = FLT_OTEL_LOGGING_ON | FLT_OTEL_LOGGING_NOLOGNORM;
}
else {
(void)memprintf(&err, "'%s' : invalid value, use <" FLT_OTEL_CLI_LOGGING_OFF " | " FLT_OTEL_CLI_LOGGING_ON " | " FLT_OTEL_CLI_LOGGING_NOLOGNORM ">", args[2]);
}
if (flag_set) {
FLT_OTEL_PROXIES_LIST_START() {
_HA_ATOMIC_STORE(&(conf->instr->logging), value);
(void)memprintf(&msg, "%s%s" FLT_OTEL_CLI_CMD " : logging is %s", FLT_OTEL_CLI_MSG_CAT(msg), FLT_OTEL_CLI_LOGGING_STATE(value));
} FLT_OTEL_PROXIES_LIST_END();
}
} else {
FLT_OTEL_PROXIES_LIST_START() {
value = _HA_ATOMIC_LOAD(&(conf->instr->logging));
(void)memprintf(&msg, "%s%s" FLT_OTEL_CLI_CMD " : logging is currently %s", FLT_OTEL_CLI_MSG_CAT(msg), FLT_OTEL_CLI_LOGGING_STATE(value));
} FLT_OTEL_PROXIES_LIST_END();
}
OTELC_RETURN_INT(flt_otel_cli_set_msg(appctx, err, msg));
}
/***
* NAME
* flt_otel_cli_parse_rate - CLI rate limit handler
*
* SYNOPSIS
* static int flt_otel_cli_parse_rate(char **args, char *payload, struct appctx *appctx, void *private)
*
* ARGUMENTS
* args - CLI command arguments array
* payload - CLI command payload string
* appctx - CLI application context
* private - unused private data pointer
*
* DESCRIPTION
* Handles the "otel rate [value]" CLI command. When a value argument is
* provided in <args[2]>, it is parsed as a floating-point number in the
* range [0.0, 100.0], converted to a fixed-point uint32_t representation,
* and atomically stored as the rate limit for all OTel filter instances.
* Setting a value requires admin access level. When no argument is given,
* reports the current rate limit percentage for all instances.
*
* RETURN VALUE
* Returns 1, or 0 if no OTel filter instances are configured (and no error
* occurred) or on memory allocation failure.
*/
static int flt_otel_cli_parse_rate(char **args, char *payload, struct appctx *appctx, void *private)
{
char *err = NULL, *msg = NULL;
OTELC_FUNC("%p, \"%s\", %p, %p", args, OTELC_STR_ARG(payload), appctx, private);
FLT_OTEL_ARGS_DUMP();
if (FLT_OTEL_ARG_ISVALID(2)) {
double value;
if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
OTELC_RETURN_INT(1);
if (flt_otel_strtod(args[2], &value, 0.0, 100.0, &err)) {
FLT_OTEL_PROXIES_LIST_START() {
_HA_ATOMIC_STORE(&(conf->instr->rate_limit), FLT_OTEL_FLOAT_U32(value));
(void)memprintf(&msg, "%s%s" FLT_OTEL_CLI_CMD " : rate limit set to %.2f", FLT_OTEL_CLI_MSG_CAT(msg), value);
} FLT_OTEL_PROXIES_LIST_END();
}
} else {
FLT_OTEL_PROXIES_LIST_START() {
uint32_t value = _HA_ATOMIC_LOAD(&(conf->instr->rate_limit));
(void)memprintf(&msg, "%s%s" FLT_OTEL_CLI_CMD " : current rate limit is %.2f", FLT_OTEL_CLI_MSG_CAT(msg), FLT_OTEL_U32_FLOAT(value));
} FLT_OTEL_PROXIES_LIST_END();
}
OTELC_RETURN_INT(flt_otel_cli_set_msg(appctx, err, msg));
}
/***
* NAME
* flt_otel_cli_parse_status - CLI status display handler
*
* SYNOPSIS
* static int flt_otel_cli_parse_status(char **args, char *payload, struct appctx *appctx, void *private)
*
* ARGUMENTS
* args - CLI command arguments array
* payload - CLI command payload string
* appctx - CLI application context
* private - unused private data pointer
*
* DESCRIPTION
* Handles the "otel status" CLI command. Builds a formatted status report
* for all OTel filter instances across all proxies. The report includes
* the library version, proxy name, configuration file path, group and scope
* counts, disable counts, instrumentation ID, tracer state, rate limit, error
* mode, disabled state, logging state, and analyzer bits. When DEBUG_OTEL is
* enabled, the current debug level is also included.
*
* RETURN VALUE
* Returns 1, or 0 on memory allocation failure.
*/
static int flt_otel_cli_parse_status(char **args, char *payload, struct appctx *appctx, void *private)
{
const char *nl = "";
char *msg = NULL;
OTELC_FUNC("%p, \"%s\", %p, %p", args, OTELC_STR_ARG(payload), appctx, private);
FLT_OTEL_ARGS_DUMP();
flt_otel_filters_dump();
(void)memprintf(&msg, " " FLT_OTEL_OPT_NAME " filter status\n" FLT_OTEL_STR_DASH_78 "\n");
(void)memprintf(&msg, "%s library: C++ " OTELCPP_VERSION ", C wrapper %s\n", msg, otelc_version());
#ifdef DEBUG_OTEL
(void)memprintf(&msg, "%s debug level: 0x%02hhx\n", msg, otelc_dbg_level);
#endif
(void)memprintf(&msg, "%s dropped count: %" PRId64 "/%" PRId64 " %" PRIu64 "\n", msg, otelc_processor_dropped_count(0), otelc_processor_dropped_count(1), _HA_ATOMIC_LOAD(&flt_otel_drop_cnt));
FLT_OTEL_PROXIES_LIST_START() {
struct flt_otel_conf_group *grp;
struct flt_otel_conf_scope *scp;
int n_groups = 0, n_scopes = 0;
list_for_each_entry(grp, &(conf->groups), list)
n_groups++;
list_for_each_entry(scp, &(conf->scopes), list)
n_scopes++;
(void)memprintf(&msg, "%s\n%s proxy %s, filter %s\n", msg, nl, px->id, conf->id);
(void)memprintf(&msg, "%s configuration: %s\n", msg, conf->cfg_file);
(void)memprintf(&msg, "%s groups/scopes: %d/%d\n\n", msg, n_groups, n_scopes);
(void)memprintf(&msg, "%s instrumentation %s\n", msg, conf->instr->id);
(void)memprintf(&msg, "%s configuration: %s\n", msg, conf->instr->config);
(void)memprintf(&msg, "%s tracer: %s\n", msg, (conf->instr->tracer != NULL) ? "active" : "not initialized");
(void)memprintf(&msg, "%s rate limit: %.2f %%\n", msg, FLT_OTEL_U32_FLOAT(_HA_ATOMIC_LOAD(&(conf->instr->rate_limit))));
(void)memprintf(&msg, "%s hard errors: %s\n", msg, FLT_OTEL_STR_FLAG_YN(_HA_ATOMIC_LOAD(&(conf->instr->flag_harderr))));
(void)memprintf(&msg, "%s disabled: %s\n", msg, FLT_OTEL_STR_FLAG_YN(_HA_ATOMIC_LOAD(&(conf->instr->flag_disabled))));
(void)memprintf(&msg, "%s logging: %s\n", msg, FLT_OTEL_CLI_LOGGING_STATE(_HA_ATOMIC_LOAD(&(conf->instr->logging))));
(void)memprintf(&msg, "%s analyzers: %08x", msg, conf->instr->analyzers);
#ifdef FLT_OTEL_USE_COUNTERS
(void)memprintf(&msg, "%s\n\n counters\n", msg);
(void)memprintf(&msg, "%s attached: %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 "\n", msg, conf->cnt.attached[0], conf->cnt.attached[1], conf->cnt.attached[2], conf->cnt.attached[3]);
(void)memprintf(&msg, "%s disabled: %" PRIu64 " %" PRIu64, msg, conf->cnt.disabled[0], conf->cnt.disabled[1]);
#endif
nl = "\n";
} FLT_OTEL_PROXIES_LIST_END();
OTELC_RETURN_INT(flt_otel_cli_set_msg(appctx, NULL, msg));
}
/* CLI command table for the OTel filter. */
static struct cli_kw_list cli_kws = { { }, {
#ifdef DEBUG_OTEL
{ { FLT_OTEL_CLI_CMD, "debug", NULL }, FLT_OTEL_CLI_CMD " debug [level] : set the OTEL filter debug level (default: get current debug level)", flt_otel_cli_parse_debug, NULL, NULL, NULL, ACCESS_LVL_ADMIN },
#endif
{ { FLT_OTEL_CLI_CMD, "disable", NULL }, FLT_OTEL_CLI_CMD " disable : disable the OTEL filter", flt_otel_cli_parse_disabled, NULL, NULL, (void *)1, ACCESS_LVL_ADMIN },
{ { FLT_OTEL_CLI_CMD, "enable", NULL }, FLT_OTEL_CLI_CMD " enable : enable the OTEL filter", flt_otel_cli_parse_disabled, NULL, NULL, (void *)0, ACCESS_LVL_ADMIN },
{ { FLT_OTEL_CLI_CMD, "soft-errors", NULL }, FLT_OTEL_CLI_CMD " soft-errors : disable hard-errors mode", flt_otel_cli_parse_option, NULL, NULL, (void *)0, ACCESS_LVL_ADMIN },
{ { FLT_OTEL_CLI_CMD, "hard-errors", NULL }, FLT_OTEL_CLI_CMD " hard-errors : enable hard-errors mode", flt_otel_cli_parse_option, NULL, NULL, (void *)1, ACCESS_LVL_ADMIN },
{ { FLT_OTEL_CLI_CMD, "logging", NULL }, FLT_OTEL_CLI_CMD " logging [state] : set logging state (default: get current logging state)", flt_otel_cli_parse_logging, NULL, NULL, NULL, ACCESS_LVL_ADMIN },
{ { FLT_OTEL_CLI_CMD, "rate", NULL }, FLT_OTEL_CLI_CMD " rate [value] : set the rate limit (default: get current rate value)", flt_otel_cli_parse_rate, NULL, NULL, NULL, ACCESS_LVL_ADMIN },
{ { FLT_OTEL_CLI_CMD, "status", NULL }, FLT_OTEL_CLI_CMD " status : show the OTEL filter status", flt_otel_cli_parse_status, NULL, NULL, NULL, 0 },
{ /* END */ }
}};
/***
* NAME
* flt_otel_cli_init - CLI keyword registration
*
* SYNOPSIS
* void flt_otel_cli_init(void)
*
* ARGUMENTS
* This function takes no arguments.
*
* DESCRIPTION
* Registers the OTel filter CLI keywords with the HAProxy CLI subsystem.
* The keywords include commands for enable/disable, error mode, logging,
* rate limit, status display, and (when DEBUG_OTEL is defined) debug level
* management.
*
* RETURN VALUE
* This function does not return a value.
*/
void flt_otel_cli_init(void)
{
OTELC_FUNC("");
/* Register CLI keywords. */
cli_register_kw(&cli_kws);
OTELC_RETURN();
}
/*
* Local variables:
* c-indent-level: 8
* c-basic-offset: 8
* End:
*
* vi: noexpandtab shiftwidth=8 tabstop=8
*/

View file

@ -367,6 +367,8 @@ static int flt_otel_ops_init(struct proxy *p, struct flt_conf *fconf)
if (conf == NULL)
OTELC_RETURN_INT(retval);
flt_otel_cli_init();
/*
* Initialize the OpenTelemetry library.
*/

View file

@ -38,6 +38,45 @@ void flt_otel_args_dump(const char **args)
}
/***
* NAME
* flt_otel_filters_dump - debug OTel filter instances dump
*
* SYNOPSIS
* void flt_otel_filters_dump(void)
*
* ARGUMENTS
* This function takes no arguments.
*
* DESCRIPTION
* Dumps all OTel filter instances across all proxies. Iterates the global
* proxy list, logging each proxy name and its associated OTel filter IDs.
*
* RETURN VALUE
* This function does not return a value.
*/
void flt_otel_filters_dump(void)
{
struct flt_conf *fconf;
struct proxy *px;
OTELC_FUNC("");
for (px = proxies_list; px != NULL; px = px->next) {
OTELC_DBG(NOTICE, "proxy '%s'", px->id);
list_for_each_entry(fconf, &(px->filter_configs), list)
if (fconf->id == otel_flt_id) {
struct flt_otel_conf *conf = fconf->conf;
OTELC_DBG(NOTICE, " OTEL filter '%s'", conf->id);
}
}
OTELC_RETURN();
}
/***
* NAME
* flt_otel_chn_label - channel direction label