From 2174526e2ef1af2fb0349358293a2964d7095fb4 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Fri, 2 Feb 2024 13:51:15 +0100 Subject: [PATCH] open_telemetry plugin: Unify the configuration between exporter and receiver. --- src/collectd.conf.in | 5 +--- src/collectd.conf.pod | 32 ++++++++------------- src/open_telemetry_exporter.cc | 50 +++++++++++++------------------- src/open_telemetry_receiver.cc | 52 ++++++++++++++++++---------------- 4 files changed, 60 insertions(+), 79 deletions(-) diff --git a/src/collectd.conf.in b/src/collectd.conf.in index 89a2212f4..86dcbb5a1 100644 --- a/src/collectd.conf.in +++ b/src/collectd.conf.in @@ -1339,10 +1339,7 @@ # SSLCertificateKeyFile "/path/to/client.key" # VerifyPeer false # -# -# Host "localhost" -# Port "4317" -# +# Exporter "localhost" "4317" # # diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod index 12b39ebd9..285a0ca1e 100644 --- a/src/collectd.conf.pod +++ b/src/collectd.conf.pod @@ -7153,7 +7153,7 @@ can be configured independently from that option. Defaults to B. =back -=head2 Plugin C +=head2 Plugin C The I implements an OpenTelemetry exporter and receiver using OTLP. Specifically, it implements a gRPC C client and @@ -7169,15 +7169,12 @@ B SSLCertificateKeyFile "/path/to/client.key" VerifyPeer false - - Host "localhost" - Port "4317" - + Exporter "localhost" "4317" =over 4 -=item B I I +=item B I [I] The B statement sets the network address and port to which to bind. Multiple B blocks can be specified to listen on multiple @@ -7186,6 +7183,9 @@ receive any metrics. The argument I may be a hostname, an IPv4 address, or an IPv6 address. +The I argument may be omitted. In that case the default C<"4317"> is +used. + Optionally, B blocks support the following options: =over 4 @@ -7212,23 +7212,15 @@ Enabled by default. =back -=item B I - -The plugin can export metrics to multiple collectors by specifying multiple -B blocks. Within the B blocks, the following options are -available: - -=over 4 - -=item B I
- -Hostname or address to connect to. Defaults to C. +=item B I [I] -=item B I +The B option configures an OTLP export to the given collector +address. Multiple collectors can be specified using multiple B lines. -Service name or port number to connect to. Defaults to C<4317>. +The argument I may be a hostname, an IPv4 address, or an IPv6 address. -=back +The I argument may be omitted. In that case the default C<"4317"> is +used. =back diff --git a/src/open_telemetry_exporter.cc b/src/open_telemetry_exporter.cc index 39886b0d6..3b736c3ae 100644 --- a/src/open_telemetry_exporter.cc +++ b/src/open_telemetry_exporter.cc @@ -42,10 +42,6 @@ extern "C" { #include "opentelemetry/proto/collector/metrics/v1/metrics_service.grpc.pb.h" #include "utils/format_open_telemetry/format_open_telemetry.h" -#ifndef OT_DEFAULT_HOST -#define OT_DEFAULT_HOST "localhost" -#endif - #ifndef OT_DEFAULT_PORT #define OT_DEFAULT_PORT "4317" #endif @@ -58,7 +54,6 @@ using opentelemetry::proto::collector::metrics::v1::MetricsService; * Private variables */ typedef struct { - char *name; int reference_count; char *host; @@ -144,7 +139,6 @@ static void ot_callback_decref(void *data) { cb->stub.reset(); - sfree(cb->name); sfree(cb->host); sfree(cb->port); @@ -185,40 +179,34 @@ static int ot_write(metric_family_t const *fam, user_data_t *user_data) { } int exporter_config(oconfig_item_t *ci) { + if (ci->values_num < 1 || ci->values_num > 2 || + ci->values[0].type != OCONFIG_TYPE_STRING || + (ci->values_num > 1 && ci->values[1].type != OCONFIG_TYPE_STRING)) { + ERROR("open_telemetry plugin: The \"%s\" config option needs " + "one or two string arguments (address and port).", + ci->key); + return EINVAL; + } + ot_callback_t *cb = (ot_callback_t *)calloc(1, sizeof(*cb)); if (cb == NULL) { ERROR("open_telemetry plugin: calloc failed."); return -1; } - cb->reference_count = 1; - cf_util_get_string(ci, &cb->name); - cb->host = strdup(OT_DEFAULT_HOST); - cb->port = strdup(OT_DEFAULT_PORT); - - pthread_mutex_init(&cb->mu, /* attr = */ NULL); - - for (int i = 0; i < ci->children_num; i++) { - oconfig_item_t *child = ci->children + i; - - int status = 0; - if (strcasecmp("Host", child->key) == 0) - status = cf_util_get_string(child, &cb->host); - else if (strcasecmp("Port", child->key) == 0) - status = cf_util_get_service(child, &cb->port); - else { - ERROR("open_telemetry plugin: invalid config option: %s.", child->key); - status = -1; - } - - if (status != 0) { - ot_callback_decref(cb); - return status; - } + *cb = (ot_callback_t){ + .reference_count = 1, + .host = strdup(ci->values[0].value.string), + }; + if (ci->values_num >= 2) { + cb->port = strdup(ci->values[1].value.string); + } else { + cb->port = strdup(OT_DEFAULT_PORT); } + pthread_mutex_init(&cb->mu, /* attr = */ NULL); strbuf_t callback_name = STRBUF_CREATE; - strbuf_printf(&callback_name, "open_telemetry/%s", cb->name); + strbuf_printf(&callback_name, "open_telemetry/[%s]:%s", cb->host, cb->port); user_data_t user_data = { .data = cb, diff --git a/src/open_telemetry_receiver.cc b/src/open_telemetry_receiver.cc index 655caa627..6f3aead09 100644 --- a/src/open_telemetry_receiver.cc +++ b/src/open_telemetry_receiver.cc @@ -47,6 +47,10 @@ extern "C" { #include "opentelemetry/proto/metrics/v1/metrics.pb.h" #include "opentelemetry/proto/resource/v1/resource.pb.h" +#ifndef OT_DEFAULT_PORT +#define OT_DEFAULT_PORT "4317" +#endif + using opentelemetry::proto::collector::metrics::v1::ExportMetricsPartialSuccess; using opentelemetry::proto::collector::metrics::v1::ExportMetricsServiceRequest; using opentelemetry::proto::collector::metrics::v1:: @@ -380,24 +384,19 @@ public: grpc::ServerBuilder builder; - if (listeners.empty()) { - builder.AddListeningPort(default_addr, auth); - INFO("open_telemetry plugin: Listening on %s", default_addr.c_str()); - } else { - for (auto l : listeners) { - grpc::string addr = l.addr + ":" + l.port; - - auto use_ssl = grpc::string(""); - auto a = auth; - if (l.ssl != nullptr) { - use_ssl = grpc::string(" (SSL enabled)"); - a = grpc::SslServerCredentials(*l.ssl); - } - - builder.AddListeningPort(addr, a); - INFO("open_telemetry plugin: Listening on %s%s", addr.c_str(), - use_ssl.c_str()); + for (auto l : listeners) { + grpc::string addr = l.addr + ":" + l.port; + + auto use_ssl = grpc::string(""); + auto a = auth; + if (l.ssl != nullptr) { + use_ssl = grpc::string(" (SSL enabled)"); + a = grpc::SslServerCredentials(*l.ssl); } + + builder.AddListeningPort(addr, a); + INFO("open_telemetry plugin: Listening on %s%s", addr.c_str(), + use_ssl.c_str()); } builder.RegisterService(&metrics_service); @@ -457,17 +456,22 @@ static void receiver_install_callbacks(void) { * collectd plugin interface */ int receiver_config(oconfig_item_t *ci) { - if ((ci->values_num != 2) || (ci->values[0].type != OCONFIG_TYPE_STRING) || - (ci->values[1].type != OCONFIG_TYPE_STRING)) { - ERROR("open_telemetry plugin: The `%s` config option needs exactly " - "two string argument (address and port).", + if (ci->values_num < 1 || ci->values_num > 2 || + ci->values[0].type != OCONFIG_TYPE_STRING || + (ci->values_num > 1 && ci->values[1].type != OCONFIG_TYPE_STRING)) { + ERROR("open_telemetry plugin: The \"%s\" config option needs " + "one or two string arguments (address and port).", ci->key); - return -1; + return EINVAL; } auto listener = Listener(); listener.addr = grpc::string(ci->values[0].value.string); - listener.port = grpc::string(ci->values[1].value.string); + if (ci->values_num >= 2) { + listener.port = grpc::string(ci->values[1].value.string); + } else { + listener.port = grpc::string(OT_DEFAULT_PORT); + } listener.ssl = nullptr; auto ssl_opts = new grpc::SslServerCredentialsOptions( @@ -526,7 +530,7 @@ int receiver_config(oconfig_item_t *ci) { ssl_opts->pem_key_cert_pairs.push_back(pkcp); listener.ssl = ssl_opts; } else { - delete (ssl_opts); + delete ssl_opts; } listeners.push_back(listener); -- 2.47.3