From 38717e4e4af4560eaad830f68a7e22330875945d Mon Sep 17 00:00:00 2001 From: Gabor Javorszky Date: Thu, 17 Oct 2024 18:49:06 +0100 Subject: [PATCH] otel: configuration items and their validation Adds code responsible for users to apply the `telemetry` configuration options. Signed-off-by: Gabor Javorszky Signed-off-by: Ava Hahn Co-authored-by: Ava Hahn --- src/nxt_conf_validation.c | 117 ++++++++++++++++++++++++++++++++++++++ src/nxt_router.c | 45 +++++++++++++++ 2 files changed, 162 insertions(+) diff --git a/src/nxt_conf_validation.c b/src/nxt_conf_validation.c index 5d7f7c52b..b597d8654 100644 --- a/src/nxt_conf_validation.c +++ b/src/nxt_conf_validation.c @@ -241,6 +241,21 @@ static nxt_int_t nxt_conf_vldt_js_module_element(nxt_conf_validation_t *vldt, nxt_conf_value_t *value); #endif +#if (NXT_HAVE_OTEL) +nxt_inline nxt_int_t nxt_otel_validate_endpoint(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data); +nxt_int_t nxt_otel_validate_batch_size(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data); +nxt_int_t nxt_otel_validate_sample_ratio(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data); +nxt_int_t nxt_otel_validate_protocol(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data); +#endif + static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[]; static nxt_conf_vldt_object_t nxt_conf_vldt_http_members[]; @@ -307,6 +322,34 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_root_members[] = { }; + +#if (NXT_HAVE_OTEL) +static nxt_conf_vldt_object_t nxt_conf_vldt_otel_members[] = { + { + .name = nxt_string("endpoint"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_otel_validate_endpoint, + .flags = NXT_CONF_VLDT_REQUIRED + }, { + .name = nxt_string("batch_size"), + .type = NXT_CONF_VLDT_INTEGER, + .validator = nxt_otel_validate_batch_size, + }, { + .name = nxt_string("protocol"), + .type = NXT_CONF_VLDT_STRING, + .validator = nxt_otel_validate_protocol, + .flags = NXT_CONF_VLDT_REQUIRED + }, { + .name = nxt_string("sampling_ratio"), + .type = NXT_CONF_VLDT_NUMBER, + .validator = nxt_otel_validate_sample_ratio, + }, + + NXT_CONF_VLDT_END +}; +#endif + + static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[] = { { .name = nxt_string("listen_threads"), @@ -317,6 +360,13 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_setting_members[] = { .type = NXT_CONF_VLDT_OBJECT, .validator = nxt_conf_vldt_object, .u.members = nxt_conf_vldt_http_members, +#if (NXT_HAVE_OTEL) + }, { + .name = nxt_string("telemetry"), + .type = NXT_CONF_VLDT_OBJECT, + .validator = nxt_conf_vldt_object, + .u.members = nxt_conf_vldt_otel_members, +#endif #if (NXT_HAVE_NJS) }, { .name = nxt_string("js_module"), @@ -1465,6 +1515,73 @@ nxt_conf_validate(nxt_conf_validation_t *vldt) "a number, a string, an array, or an object" + +#if (NXT_HAVE_OTEL) +inline nxt_int_t +nxt_otel_validate_endpoint(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) +{ + // This function is a stub for now + return NXT_OK; +} + + +nxt_int_t +nxt_otel_validate_batch_size(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) +{ + double batch_size; + batch_size = nxt_conf_get_number(value); + if (batch_size <= 0) { + return NXT_ERROR; + } + + return NXT_OK; +} + +nxt_int_t +nxt_otel_validate_sample_ratio(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) +{ + double sample_ratio; + + sample_ratio = nxt_conf_get_number(value); + if (sample_ratio < 0 || sample_ratio > 1) { + return NXT_ERROR; + } + + return NXT_OK; +} + +nxt_int_t +nxt_otel_validate_protocol(nxt_conf_validation_t *vldt, + nxt_conf_value_t *value, + void *data) +{ + nxt_str_t proto; + + nxt_conf_get_string(value, &proto); + if (nxt_str_eq(&proto, "HTTP", 4) || + nxt_str_eq(&proto, "http", 4)) { + goto happy; + } + + if (nxt_str_eq(&proto, "GRPC", 4) || + nxt_str_eq(&proto, "grpc", 4)) { + goto happy; + } + + return NXT_ERROR; + + happy: + return NXT_OK; +} +#endif + + static nxt_int_t nxt_conf_vldt_type(nxt_conf_validation_t *vldt, const nxt_str_t *name, nxt_conf_value_t *value, nxt_conf_vldt_type_t type) diff --git a/src/nxt_router.c b/src/nxt_router.c index 076cd134b..4d6c241c9 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -23,6 +23,10 @@ #include #define NXT_SHARED_PORT_ID 0xFFFFu +#if (NXT_HAVE_OTEL) +#define NXT_OTEL_BATCH_DEFAULT 128 +#define NXT_OTEL_SAMPLING_DEFAULT 1 +#endif typedef struct { nxt_str_t type; @@ -1613,6 +1617,12 @@ static nxt_conf_map_t nxt_router_websocket_conf[] = { }; +#if (NXT_HAVE_OTEL) +static void nxt_otel_log_callback(u_char *arg) { + printf("otel: %s", (char *) arg); +} +#endif + static nxt_int_t nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end) @@ -1635,6 +1645,11 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, #endif #if (NXT_HAVE_NJS) nxt_conf_value_t *js_module; +#endif +#if (NXT_HAVE_OTEL) + nxt_conf_value_t *otel, *otel_endpoint, *otel_sampling, *otel_batching, *otel_proto; + nxt_str_t telemetry_endpoint, telemetry_proto; + double telemetry_sample_fraction, telemetry_batching; #endif nxt_conf_value_t *root, *conf, *http, *value, *websocket; nxt_conf_value_t *applications, *application, *settings; @@ -1671,6 +1686,13 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, nxt_string("/settings/http/websocket"); static const nxt_str_t forwarded_path = nxt_string("/forwarded"); static const nxt_str_t client_ip_path = nxt_string("/client_ip"); +#if (NXT_HAVE_OTEL) + static const nxt_str_t telemetry_path = nxt_string("/settings/telemetry"); + static const nxt_str_t telemetry_endpoint_path = nxt_string("/settings/telemetry/endpoint"); + static const nxt_str_t telemetry_batch_path = nxt_string("/settings/telemetry/batch_size"); + static const nxt_str_t telemetry_sample_path = nxt_string("/settings/telemetry/sampling_ratio"); + static const nxt_str_t telemetry_proto_path = nxt_string("/settings/telemetry/protocol"); +#endif root = nxt_conf_json_parse(tmcf->mem_pool, start, end, NULL); if (root == NULL) { @@ -2172,6 +2194,29 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf, #endif +#if (NXT_HAVE_OTEL) + otel = nxt_conf_get_path(root, &telemetry_path); + otel_endpoint = nxt_conf_get_path(root, &telemetry_endpoint_path); + otel_batching = nxt_conf_get_path(root, &telemetry_batch_path); + otel_sampling = nxt_conf_get_path(root, &telemetry_sample_path); + otel_proto = nxt_conf_get_path(root, &telemetry_proto_path); + + if (otel) { + nxt_conf_get_string(otel_endpoint, &telemetry_endpoint); + nxt_conf_get_string(otel_proto, &telemetry_proto); + telemetry_batching = otel_batching ? nxt_conf_get_number(otel_batching) : NXT_OTEL_BATCH_DEFAULT; + telemetry_sample_fraction = otel_sampling ? nxt_conf_get_number(otel_sampling) : NXT_OTEL_SAMPLING_DEFAULT; + + nxt_otel_rs_init(&nxt_otel_log_callback, + &telemetry_endpoint, + &telemetry_proto, + telemetry_sample_fraction, + telemetry_batching); + } else { + nxt_otel_rs_uninit(); + } +#endif + nxt_queue_add(&deleting_sockets, &router->sockets); nxt_queue_init(&router->sockets);