diff --git a/README.turnserver b/README.turnserver index cf5119bc6..ba8e88af0 100644 --- a/README.turnserver +++ b/README.turnserver @@ -293,6 +293,10 @@ Flags: disabled. Would listen on port 9641 unther the path /metrics also the path / on this port can be used as a health check. See also options --prometheus-ip and --prometheus-port. + --prometheus-no-username-labels Disable labeling prometheus traffic + metrics with client usernames. Labeling with client usernames is + enabled by default, however this may cause memory leaks when using + authentication with ephemeral usernames (e.g. TURN REST API). -h Help. diff --git a/man/man1/turnserver.1 b/man/man1/turnserver.1 index faf1e2b1d..4a01d3bcf 100644 --- a/man/man1/turnserver.1 +++ b/man/man1/turnserver.1 @@ -440,6 +440,13 @@ Enable prometheus metrics. By default it is disabled. Would listen on port 9641 unther the path /metrics also the path / on this port can be used as a health check. See also \fIoptions\fP \fB\-\-prometheus\-ip\fP and \fB\-\-prometheus\-port\fP. +.TP +.B +\fB\-\-prometheus\-no\-username\-labels\fP +Disable labeling prometheus traffic +metrics with client usernames. Labeling with client usernames is +enabled by default, however this may cause memory leaks when using +authentication with ephemeral usernames (e.g. TURN REST API). .RE .TP .B diff --git a/src/apps/relay/mainrelay.c b/src/apps/relay/mainrelay.c index 073c0290c..468729928 100644 --- a/src/apps/relay/mainrelay.c +++ b/src/apps/relay/mainrelay.c @@ -174,6 +174,7 @@ TURN_CREDENTIALS_NONE, /* ct */ 0, /* user_quota */ #if !defined(TURN_NO_PROMETHEUS) 0, /* prometheus disabled by default */ +1, /* prometheus username labelling enabled by default when prometheus is enabled */ #endif ///////////// Users DB ////////////// { (TURN_USERDB_TYPE)0, {"\0"}, {0,NULL, {NULL,0}} }, @@ -563,6 +564,7 @@ static char Usage[] = "Usage: turnserver [options]\n" " --prometheus Enable prometheus metrics. It is disabled by default.\n" " When enabled, it will listen on port 9641 on the wildcard address under the path /metrics.\n" " The path / on this port can also be used as a health check.\n" +" --prometheus-no-username-labels When metrics are enabled, do not label metrics with client usernames.\n" " --prometheus-ip= IP address for the Prometheus listener. Default is the wildcard address.\n" " --prometheus-port= Prometheus listener port. Default is 9641.\n" #endif @@ -795,6 +797,7 @@ enum EXTRA_OPTS { CHANNEL_LIFETIME_OPT, PERMISSION_LIFETIME_OPT, PROMETHEUS_OPT, + PROMETHEUS_DISABLE_USERNAMES_OPT, PROMETHEUS_IP_OPT, PROMETHEUS_PORT_OPT, AUTH_SECRET_OPT, @@ -913,6 +916,7 @@ static const struct myoption long_options[] = { #endif #if !defined(TURN_NO_PROMETHEUS) { "prometheus", optional_argument, NULL, PROMETHEUS_OPT }, + { "prometheus-no-username-labels", optional_argument, NULL, PROMETHEUS_DISABLE_USERNAMES_OPT }, { "prometheus-ip", required_argument, NULL, PROMETHEUS_IP_OPT }, { "prometheus-port", required_argument, NULL, PROMETHEUS_PORT_OPT }, #endif @@ -1548,6 +1552,9 @@ static void set_option(int c, char *value) case PROMETHEUS_OPT: turn_params.prometheus = turn_params.prometheus == PROM_DISABLED ? PROM_ENABLED : turn_params.prometheus; break; + case PROMETHEUS_DISABLE_USERNAMES_OPT: + turn_params.prometheus_username_labels = 0; + break; case PROMETHEUS_IP_OPT: if(make_ioa_addr((const uint8_t*)value,0,&prometheus_addr)<0) { TURN_LOG_FUNC(TURN_LOG_LEVEL_ERROR,"Cannot parse Prometheus listener address: %s\n", value); diff --git a/src/apps/relay/mainrelay.h b/src/apps/relay/mainrelay.h index 6f48bcf95..164a0726f 100644 --- a/src/apps/relay/mainrelay.h +++ b/src/apps/relay/mainrelay.h @@ -320,6 +320,7 @@ typedef struct _turn_params_ { vint user_quota; #if !defined(TURN_NO_PROMETHEUS) int prometheus; + int prometheus_username_labels; #endif diff --git a/src/apps/relay/prom_server.c b/src/apps/relay/prom_server.c index d5ae8675f..8745e7904 100644 --- a/src/apps/relay/prom_server.c +++ b/src/apps/relay/prom_server.c @@ -33,20 +33,26 @@ int start_prometheus_server(void){ return 1; } prom_collector_registry_default_init(); - - const char *label[] = {"realm"}; + + const char *label[] = {"realm", NULL}; + size_t nlabels = 1; + + if (turn_params.prometheus_username_labels) { + label[1] = "user"; + nlabels++; + } // Create traffic counter metrics - turn_traffic_rcvp = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_rcvp", "Represents finished sessions received packets", 1, label)); - turn_traffic_rcvb = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_rcvb", "Represents finished sessions received bytes", 1, label)); - turn_traffic_sentp = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_sentp", "Represents finished sessions sent packets", 1, label)); - turn_traffic_sentb = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_sentb", "Represents finished sessions sent bytes", 1, label)); + turn_traffic_rcvp = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_rcvp", "Represents finished sessions received packets", nlabels, label)); + turn_traffic_rcvb = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_rcvb", "Represents finished sessions received bytes", nlabels, label)); + turn_traffic_sentp = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_sentp", "Represents finished sessions sent packets", nlabels, label)); + turn_traffic_sentb = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_sentb", "Represents finished sessions sent bytes", nlabels, label)); // Create finished sessions traffic for peers counter metrics - turn_traffic_peer_rcvp = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_peer_rcvp", "Represents finished sessions peer received packets", 1, label)); - turn_traffic_peer_rcvb = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_peer_rcvb", "Represents finished sessions peer received bytes", 1, label)); - turn_traffic_peer_sentp = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_peer_sentp", "Represents finished sessions peer sent packets", 1, label)); - turn_traffic_peer_sentb = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_peer_sentb", "Represents finished sessions peer sent bytes", 1, label)); + turn_traffic_peer_rcvp = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_peer_rcvp", "Represents finished sessions peer received packets", nlabels, label)); + turn_traffic_peer_rcvb = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_peer_rcvb", "Represents finished sessions peer received bytes", nlabels, label)); + turn_traffic_peer_sentp = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_peer_sentp", "Represents finished sessions peer sent packets", nlabels, label)); + turn_traffic_peer_sentb = prom_collector_registry_must_register_metric(prom_counter_new("turn_traffic_peer_sentb", "Represents finished sessions peer sent bytes", nlabels, label)); // Create total finished traffic counter metrics turn_total_traffic_rcvp = prom_collector_registry_must_register_metric(prom_counter_new("turn_total_traffic_rcvp", "Represents total finished sessions received packets", 0, NULL)); @@ -93,11 +99,12 @@ int start_prometheus_server(void){ } void prom_set_finished_traffic(const char* realm, const char* user, unsigned long rsvp, unsigned long rsvb, unsigned long sentp, unsigned long sentb, bool peer){ - (void) user; if (turn_params.prometheus > PROM_DISABLED){ - - const char *label[] = {realm}; + const char *label[] = {realm, NULL}; + if (turn_params.prometheus_username_labels){ + label[1] = user; + } if (peer){ prom_counter_add(turn_traffic_peer_rcvp, rsvp, label);