From 5d1842c5f26a5b1404787d7728e92b763af54ec1 Mon Sep 17 00:00:00 2001 From: Roy Teeuwen Date: Tue, 23 Jan 2024 22:17:00 +0100 Subject: [PATCH] fixes #364: Add option to set extra resource attributes on the traces in Apache and Nginx --- .../otel-webserver-module/README.md | 84 ++++++++++--------- .../conf/nginx/opentelemetry_module.conf | 1 + .../include/apache/ApacheConfig.h | 7 ++ .../include/core/api/OpentelemetrySdk.h | 1 + .../include/core/api/TenantConfig.h | 4 + .../opentelemetry_module.conf | 1 + .../src/apache/ApacheConfig.cpp | 15 ++++ .../src/apache/ApacheHooks.cpp | 5 ++ .../src/apache/mod_apache_otel.cpp | 6 ++ .../src/core/api/ApiUtils.cpp | 5 ++ .../src/core/sdkwrapper/SdkHelperFactory.cpp | 16 ++++ .../src/nginx/ngx_http_opentelemetry_module.c | 16 ++++ .../src/nginx/ngx_http_opentelemetry_module.h | 1 + 13 files changed, 121 insertions(+), 41 deletions(-) diff --git a/instrumentation/otel-webserver-module/README.md b/instrumentation/otel-webserver-module/README.md index 8e17c46c1..0b0b4c017 100644 --- a/instrumentation/otel-webserver-module/README.md +++ b/instrumentation/otel-webserver-module/README.md @@ -40,25 +40,26 @@ Monitoring individual modules is crucial to the instrumentation of Apache web se | Apr-util | 1.6.1 | ### Configuration -| Configuration Directives | Default Values | Remarks | -| ---------------------------------------------- | --------------- | ------------------------------------------ | -|*ApacheModuleEnabled* | ON | OPTIONAL: Needed for instrumenting Apache Webserver | -|*ApacheModuleOtelSpanExporter* | otlp | OPTIONAL: Specify the span exporter to be used. Supported values are "otlp" and "ostream". All other supported values would be added in future. | -|*ApacheModuleOtelExporterEndpoint:* | | REQUIRED: The endpoint otel exporter exports to. Example "docker.for.mac.localhost:4317" | -|*ApacheModuleOtelSpanProcessor* | batch | OPTIONAL: Specify the processor to select to. Supported values are "simple" and "batch".| -|*ApacheModuleOtelSampler* | AlwaysOn | OPTIONAL: Supported values are "AlwaysOn" and "AlwaysOff" | -|*ApacheModuleOtelMaxQueueSize* | 2048 | OPTIONAL: The maximum queue size. After the size is reached spans are dropped| -|*ApacheModuleOtelScheduledDelayMillis* | 5000 | OPTIONAL: The delay interval in milliseconds between two consecutive exports| -|*ApacheModuleOtelExportTimeoutMillis* | 30000 | OPTIONAL: How long the export can run in milliseconds before it is cancelled| -|*ApacheModuleOtelMaxExportBatchSize* | 512 | OPTIONAL: The maximum batch size of every export. It must be smaller or equal to maxQueueSize | -|*ApacheModuleServiceName* | | REQUIRED: Logical name of the service | -|*ApacheModuleServiceNamespace* | | REQUIRED: A namespace for the ServiceName | -|*ApacheModuleServiceInstanceId* | | REQUIRED: The string ID of the service instance | -|*ApacheModuleTraceAsError* | | OPTIONAL: Trace level for logging to Apache log| -|*ApacheModuleWebserverContext* | | OPTIONAL: Takes 3 values(space-seperated) ServiceName, ServiceNamespace and ServiceInstanceId| -|*ApacheModuleSegmentType* | | OPTIONAL: Specify the string (FIRST/LAST/CUSTOM) to be filtered for Span Name Creation| -|*ApacheModuleSegmentParameter* | | OPTIONAL: Specify the segment count or segment numbers that you want to display for Span Creation| -|*ApacheModuleOtelExporterHeaders* | | OPTIONAL: OTEL Exporter header info or Metadata like API key for OTLP endpoint. a list of key value pairs, and these are expected to be represented in a format matching to the W3C Correlation-Context, except that additional semi-colon delimited metadata is not supported, i.e.: key1=value1,key2=value2. | +| Configuration Directives | Default Values | Remarks | +|----------------------------------------| --------------- |---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| *ApacheModuleEnabled* | ON | OPTIONAL: Needed for instrumenting Apache Webserver | +| *ApacheModuleOtelSpanExporter* | otlp | OPTIONAL: Specify the span exporter to be used. Supported values are "otlp" and "ostream". All other supported values would be added in future. | +| *ApacheModuleOtelExporterEndpoint:* | | REQUIRED: The endpoint otel exporter exports to. Example "docker.for.mac.localhost:4317" | +| *ApacheModuleOtelSpanProcessor* | batch | OPTIONAL: Specify the processor to select to. Supported values are "simple" and "batch". | +| *ApacheModuleOtelSampler* | AlwaysOn | OPTIONAL: Supported values are "AlwaysOn" and "AlwaysOff" | +| *ApacheModuleOtelMaxQueueSize* | 2048 | OPTIONAL: The maximum queue size. After the size is reached spans are dropped | +| *ApacheModuleOtelScheduledDelayMillis* | 5000 | OPTIONAL: The delay interval in milliseconds between two consecutive exports | +| *ApacheModuleOtelExportTimeoutMillis* | 30000 | OPTIONAL: How long the export can run in milliseconds before it is cancelled | +| *ApacheModuleOtelMaxExportBatchSize* | 512 | OPTIONAL: The maximum batch size of every export. It must be smaller or equal to maxQueueSize | +| *ApacheModuleServiceName* | | REQUIRED: Logical name of the service | +| *ApacheModuleServiceNamespace* | | REQUIRED: A namespace for the ServiceName | +| *ApacheModuleServiceInstanceId* | | REQUIRED: The string ID of the service instance | +| *ApacheModuleTraceAsError* | | OPTIONAL: Trace level for logging to Apache log | +| *ApacheModuleWebserverContext* | | OPTIONAL: Takes 3 values(space-seperated) ServiceName, ServiceNamespace and ServiceInstanceId | +| *ApacheModuleSegmentType* | | OPTIONAL: Specify the string (FIRST/LAST/CUSTOM) to be filtered for Span Name Creation | +| *ApacheModuleSegmentParameter* | | OPTIONAL: Specify the segment count or segment numbers that you want to display for Span Creation | +| *ApacheModuleOtelExporterHeaders* | | OPTIONAL: OTEL Exporter header info or Metadata like API key for OTLP endpoint. a list of key value pairs, and these are expected to be represented in a format matching to the W3C Correlation-Context, except that additional semi-colon delimited metadata is not supported, i.e.: key1=value1,key2=value2. | +| *ApacheModuleOtelResourceAttributes* | | OPTIONAL: OTEL resource attributes, a list of key value pairs, i.e.: key1=value1,key2=value2. | A sample configuration is mentioned in [opentelemetry_module.conf](https://github.com/open-telemetry/opentelemetry-cpp-contrib/blob/main/instrumentation/otel-webserver-module/opentelemetry_module.conf) @@ -155,28 +156,29 @@ Currently, Nginx Webserver module monitores some fixed set of modules, which get | Apr-util | 1.6.1 | ### Configuration -| Configuration Directives | Default Values | Remarks | -| ---------------------------------------------- | --------------- | ------------------------------------------ | -|*NginxModuleEnabled* | ON | OPTIONAL: Needed for instrumenting Nginx Webserver | -|*NginxModuleOtelSpanExporter* | otlp | OPTIONAL: Specify the span exporter to be used. Supported values are "otlp" and "ostream". All other supported values would be added in future. | -|*NginxModuleOtelExporterEndpoint:* | | REQUIRED: The endpoint otel exporter exports to. Example "docker.for.mac.localhost:4317" | -|*NginxModuleOtelSpanProcessor* | batch | OPTIONAL: Specify the processor to select to. Supported values are "simple" and "batch".| -|*NginxModuleOtelSampler* | AlwaysOn | OPTIONAL: Supported values are "AlwaysOn" and "AlwaysOff" | -|*NginxModuleOtelMaxQueueSize* | 2048 | OPTIONAL: The maximum queue size. After the size is reached spans are dropped| -|*NginxModuleOtelScheduledDelayMillis* | 5000 | OPTIONAL: The delay interval in milliseconds between two consecutive exports| -|*NginxModuleOtelExportTimeoutMillis* | 30000 | OPTIONAL: How long the export can run in milliseconds before it is cancelled| -|*NginxModuleOtelMaxExportBatchSize* | 512 | OPTIONAL: The maximum batch size of every export. It must be smaller or equal to maxQueueSize | -|*NginxModuleServiceName* | | REQUIRED: Logical name of the service | -|*NginxModuleServiceNamespace* | | REQUIRED: A namespace for the ServiceName | -|*NginxModuleServiceInstanceId* | | REQUIRED: The string ID of the service instance | -|*NginxModuleTraceAsError* | | OPTIONAL: Trace level for logging to Apache log| -|*NginxModuleWebserverContext* | | OPTIONAL: Takes 3 values(space-seperated) ServiceName, ServiceNamespace and ServiceInstanceId| -|*NginxModuleSegmentType* | | OPTIONAL: Specify the string (FIRST/LAST/CUSTOM) to be filtered for Span Name Creation| -|*NginxModuleSegmentParameter* | | OPTIONAL: Specify the segment count or segment numbers that you want to display for Span Creation| -|*NginxModuleRequestHeaders* | | OPTIONAL: Specify the request headers to be captured in the span attributes. The headers are Case-Sensitive and should be comma-separated. e.g.```NginxModuleRequestHeaders Accept-Charset,Accept-Encoding,User-Agent;```| -|*NginxModuleResponseHeaders* | | OPTIONAL: Specify the response headers to be captured in the span attributes. The headers are Case-Sensitive and should be comma-separated. e.g.```NginxModuleResponseHeaders Content-Length,Content-Type;```| -|*NginxModuleOtelExporterOtlpHeaders* | | OPTIONAL: OTEL exporter headers like Meta data related exposrted end point. a list of key value pairs, and these are expected to be represented in a format matching to the W3C Correlation-Context, except that additional semi-colon delimited metadata is not supported, i.e.: key1=value1,key2=value2.| -|*NginxTrustIncomingSpans* | ON | OPTIONAL: Specify if you want to correlate Nginx instrumented traces and spans with incoming requests.| +| Configuration Directives | Default Values | Remarks | +|---------------------------------------| --------------- |------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| *NginxModuleEnabled* | ON | OPTIONAL: Needed for instrumenting Nginx Webserver | +| *NginxModuleOtelSpanExporter* | otlp | OPTIONAL: Specify the span exporter to be used. Supported values are "otlp" and "ostream". All other supported values would be added in future. | +| *NginxModuleOtelExporterEndpoint:* | | REQUIRED: The endpoint otel exporter exports to. Example "docker.for.mac.localhost:4317" | +| *NginxModuleOtelSpanProcessor* | batch | OPTIONAL: Specify the processor to select to. Supported values are "simple" and "batch". | +| *NginxModuleOtelSampler* | AlwaysOn | OPTIONAL: Supported values are "AlwaysOn" and "AlwaysOff" | +| *NginxModuleOtelMaxQueueSize* | 2048 | OPTIONAL: The maximum queue size. After the size is reached spans are dropped | +| *NginxModuleOtelScheduledDelayMillis* | 5000 | OPTIONAL: The delay interval in milliseconds between two consecutive exports | +| *NginxModuleOtelExportTimeoutMillis* | 30000 | OPTIONAL: How long the export can run in milliseconds before it is cancelled | +| *NginxModuleOtelMaxExportBatchSize* | 512 | OPTIONAL: The maximum batch size of every export. It must be smaller or equal to maxQueueSize | +| *NginxModuleServiceName* | | REQUIRED: Logical name of the service | +| *NginxModuleServiceNamespace* | | REQUIRED: A namespace for the ServiceName | +| *NginxModuleServiceInstanceId* | | REQUIRED: The string ID of the service instance | +| *NginxModuleTraceAsError* | | OPTIONAL: Trace level for logging to Apache log | +| *NginxModuleWebserverContext* | | OPTIONAL: Takes 3 values(space-seperated) ServiceName, ServiceNamespace and ServiceInstanceId | +| *NginxModuleSegmentType* | | OPTIONAL: Specify the string (FIRST/LAST/CUSTOM) to be filtered for Span Name Creation | +| *NginxModuleSegmentParameter* | | OPTIONAL: Specify the segment count or segment numbers that you want to display for Span Creation | +| *NginxModuleRequestHeaders* | | OPTIONAL: Specify the request headers to be captured in the span attributes. The headers are Case-Sensitive and should be comma-separated. e.g.```NginxModuleRequestHeaders Accept-Charset,Accept-Encoding,User-Agent;``` | +| *NginxModuleResponseHeaders* | | OPTIONAL: Specify the response headers to be captured in the span attributes. The headers are Case-Sensitive and should be comma-separated. e.g.```NginxModuleResponseHeaders Content-Length,Content-Type;``` | +| *NginxModuleOtelExporterOtlpHeaders* | | OPTIONAL: OTEL exporter headers like Meta data related exposrted end point. a list of key value pairs, and these are expected to be represented in a format matching to the W3C Correlation-Context, except that additional semi-colon delimited metadata is not supported, i.e.: key1=value1,key2=value2. | +| *NginxModuleOtelResourceAttributes* | | OPTIONAL: OTEL resource attributes. a list of key value pairs, i.e.: key1=value1,key2=value2. | +| *NginxTrustIncomingSpans* | ON | OPTIONAL: Specify if you want to correlate Nginx instrumented traces and spans with incoming requests. | ### Build and Installation #### Prerequisites diff --git a/instrumentation/otel-webserver-module/conf/nginx/opentelemetry_module.conf b/instrumentation/otel-webserver-module/conf/nginx/opentelemetry_module.conf index e3eb6ed2d..ea735a90f 100644 --- a/instrumentation/otel-webserver-module/conf/nginx/opentelemetry_module.conf +++ b/instrumentation/otel-webserver-module/conf/nginx/opentelemetry_module.conf @@ -3,6 +3,7 @@ NginxModuleEnabled ON; NginxModuleOtelSpanExporter otlp; NginxModuleOtelExporterEndpoint docker.for.mac.localhost:4317; #NginxModuleOtelExporterOtlpHeaders Authorization=AuthorizationToken; +NginxModuleOtelResourceAttributes some.key=value; # SSL Certificates #NginxModuleOtelSslEnabled ON #NginxModuleOtelSslCertificatePath diff --git a/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h b/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h index ebef128e4..505449254 100644 --- a/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h +++ b/instrumentation/otel-webserver-module/include/apache/ApacheConfig.h @@ -42,6 +42,9 @@ class otel_cfg const char* getOtelExporterOtlpHeaders() { return otelExporterOtlpHeaders; } int otelExporterOtlpHeadersInitialized() { return otelExporterOtlpHeaders_initialized; } + const char* getOtelResourceAttributes() { return otelResourceAttributes; } + int otelResourceAttributesInitialized() { return otelResourceAttributes_initialized; } + int getOtelSslEnabled() { return otelSslEnabled; } int getOtelSslEnabledInitialized() { return otelSslEnabled_initialized; } @@ -129,6 +132,9 @@ class otel_cfg const char *otelExporterOtlpHeaders; // OPTIONAL: AppDynamics Custom metadata for OTEL Exporter EX: OTEL_EXPORTER_OTLP_HEADERS="api-key=key,other-config-value=value" int otelExporterOtlpHeaders_initialized; + const char *otelResourceAttributes; // OPTIONAL: Custom resource attributes for OTEL Exporter EX: OTEL_RESOURCE_ATTRIBUTES="subsystem=key,other.value=value" + int otelResourceAttributes_initialized; + int otelSslEnabled; // OPTIONAL: Decision whether connection to the Exporter endpoint is secured int otelSslEnabled_initialized; @@ -231,6 +237,7 @@ class ApacheConfigHandlers static const char* otel_set_otelExporterType(cmd_parms *cmd, void *conf, const char *arg); static const char* otel_set_otelExporterEndpoint(cmd_parms *cmd, void *conf, const char *arg); static const char* otel_set_otelExporterOtlpHeaders(cmd_parms *cmd, void *conf, const char *arg); + static const char* otel_set_otelResourceAttributes(cmd_parms *cmd, void *conf, const char *arg); static const char* otel_set_otelSslEnabled(cmd_parms *cmd, void *conf, const char *arg); static const char* otel_set_otelSslCertificatePath(cmd_parms *cmd, void *conf, const char *arg); static const char* otel_set_otelProcessorType(cmd_parms *cmd, void *conf, const char *arg); diff --git a/instrumentation/otel-webserver-module/include/core/api/OpentelemetrySdk.h b/instrumentation/otel-webserver-module/include/core/api/OpentelemetrySdk.h index b7dfec358..7ab987332 100755 --- a/instrumentation/otel-webserver-module/include/core/api/OpentelemetrySdk.h +++ b/instrumentation/otel-webserver-module/include/core/api/OpentelemetrySdk.h @@ -28,6 +28,7 @@ #define OTEL_SDK_ENV_OTEL_EXPORTER_TYPE "OTEL_SDK_ENV_OTEL_EXPORTER_TYPE" #define OTEL_SDK_ENV_OTEL_EXPORTER_ENDPOINT "OTEL_SDK_ENV_OTEL_EXPORTER_ENDPOINT" /*required*/ #define OTEL_SDK_ENV_OTEL_EXPORTER_OTLPHEADERS "OTEL_SDK_ENV_OTEL_EXPORTER_OTLPHEADERS" /*optional*/ +#define OTEL_SDK_ENV_OTEL_RESOURCE_ATTRIBUTES "OTEL_SDK_ENV_OTEL_RESOURCE_ATTRIBUTES" /*optional*/ #define OTEL_SDK_ENV_OTEL_SSL_ENABLED "OTEL_SDK_ENV_OTEL_SSL_ENABLED" /*optional*/ #define OTEL_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH "OTEL_SDK_ENV_OTEL_SSL_CERTIFICATE_PATH" /*optional*/ #define OTEL_SDK_ENV_OTEL_PROCESSOR_TYPE "OTEL_SDK_ENV_OTEL_PROCESSOR_TYPE" diff --git a/instrumentation/otel-webserver-module/include/core/api/TenantConfig.h b/instrumentation/otel-webserver-module/include/core/api/TenantConfig.h index a32016e5e..cb7f62a79 100644 --- a/instrumentation/otel-webserver-module/include/core/api/TenantConfig.h +++ b/instrumentation/otel-webserver-module/include/core/api/TenantConfig.h @@ -46,6 +46,7 @@ class TenantConfig const std::string& getOtelExporterType() const {return otelExporterType;} const std::string& getOtelExporterEndpoint() const {return otelExporterEndpoint;} const std::string& getOtelExporterOtlpHeaders() const {return otelExporterOtlpHeaders;} + const std::string& getOtelResourceAttributes() const {return otelResourceAttributes;} const std::string& getOtelProcessorType() const {return otelProcessorType;} const unsigned getOtelMaxQueueSize() const {return otelMaxQueueSize;} const unsigned getOtelScheduledDelayMillis() const {return otelScheduledDelayMillis;} @@ -63,6 +64,7 @@ class TenantConfig void setOtelExporterType(const std::string& otelExporterType) { this->otelExporterType = otelExporterType; } void setOtelExporterEndpoint(const std::string& otelExporterEndpoint) { this->otelExporterEndpoint = otelExporterEndpoint; } void setOtelExporterOtlpHeaders(const std::string& otelExporterOtlpHeaders) { this->otelExporterOtlpHeaders = otelExporterOtlpHeaders; } + void setOtelResourceAttributes(const std::string& otelResourceAttributes) { this->otelResourceAttributes = otelResourceAttributes; } void setOtelProcessorType(const std::string& otelProcessorType) { this->otelProcessorType = otelProcessorType; } void setOtelMaxQueueSize(const unsigned int otelMaxQueueSize) { this->otelMaxQueueSize = otelMaxQueueSize; } void setOtelScheduledDelayMillis(const unsigned int otelScheduledDelayMillis) { this->otelScheduledDelayMillis = otelScheduledDelayMillis; } @@ -83,6 +85,7 @@ class TenantConfig std::string otelExporterType; std::string otelExporterEndpoint; std::string otelExporterOtlpHeaders; + std::string otelResourceAttributes; bool otelSslEnabled; std::string otelSslCertPath; @@ -112,6 +115,7 @@ inline std::ostream& operator<< (std::ostream &os, const otel::core::TenantConfi << "\n OtelSslEnabled " << config.getOtelSslEnabled() << "\n OtelSslCertPath " << config.getOtelSslCertPath() << "\n OtelExportOtlpHeaders " << config.getOtelExporterOtlpHeaders() + << "\n OtelResourceAttributes " << config.getOtelResourceAttributes() << ""; return os; } diff --git a/instrumentation/otel-webserver-module/opentelemetry_module.conf b/instrumentation/otel-webserver-module/opentelemetry_module.conf index b5b0a9194..7a39300e2 100755 --- a/instrumentation/otel-webserver-module/opentelemetry_module.conf +++ b/instrumentation/otel-webserver-module/opentelemetry_module.conf @@ -15,6 +15,7 @@ ApacheModuleEnabled ON ApacheModuleOtelSpanExporter otlp ApacheModuleOtelExporterEndpoint collector:4317 #ApacheModuleOtelExporterHeaders api-key=abc123 +#ApacheModuleOtelResourceAttributes some.key=value # SSL Certificates #ApacheModuleOtelSslEnabled ON diff --git a/instrumentation/otel-webserver-module/src/apache/ApacheConfig.cpp b/instrumentation/otel-webserver-module/src/apache/ApacheConfig.cpp index 92c59e875..f4cf33461 100644 --- a/instrumentation/otel-webserver-module/src/apache/ApacheConfig.cpp +++ b/instrumentation/otel-webserver-module/src/apache/ApacheConfig.cpp @@ -129,6 +129,14 @@ const char* ApacheConfigHandlers::otel_set_otelExporterOtlpHeaders(cmd_parms *cm return helperChar(cmd, cfg, arg, cfg->otelExporterOtlpHeaders, cfg->otelExporterOtlpHeaders_initialized, "otel_set_otelExporterOtlpHeaders"); } +// char *otelResourceAttributes; +// int otelResourceAttributes_initialized; +const char* ApacheConfigHandlers::otel_set_otelResourceAttributes(cmd_parms *cmd, void *conf, const char *arg) +{ + otel_cfg* cfg = (otel_cfg*) conf; + return helperChar(cmd, cfg, arg, cfg->otelResourceAttributes, cfg->otelResourceAttributes_initialized, "otel_set_otelResourceAttributes"); +} + // char *otelSslEnabled; // int otelSslEnabled_initialized; const char* ApacheConfigHandlers::otel_set_otelSslEnabled(cmd_parms *cmd, void *conf, const char *arg) @@ -444,6 +452,10 @@ void otel_cfg::init() otelExporterOtlpHeaders = ""; otelExporterOtlpHeaders_initialized = 0; + // otelResourceAttributes Optional: OTLP resource attributes as key value pairs + otelResourceAttributes = ""; + otelResourceAttributes_initialized = 0; + // otelSslEnabled OPTIONAL: Decides whether the connection to the endpoint is secured otelSslEnabled = 0; otelSslEnabled_initialized = 0; @@ -786,6 +798,9 @@ otel_cfg* ApacheConfigHandlers::getProcessConfig(const request_rec* r) process_cfg->otelExporterOtlpHeaders = apr_pstrdup(r->server->process->pool, our_config->otelExporterOtlpHeaders); process_cfg->otelExporterOtlpHeaders_initialized = our_config->otelExporterOtlpHeaders_initialized; + process_cfg->otelResourceAttributes = apr_pstrdup(r->server->process->pool, our_config->otelResourceAttributes); + process_cfg->otelResourceAttributes_initialized = our_config->otelResourceAttributes_initialized; + process_cfg->otelSslEnabled = our_config->otelSslEnabled; process_cfg->otelSslEnabled_initialized = our_config->otelSslEnabled_initialized; diff --git a/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp b/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp index 1bb575575..8257016c7 100644 --- a/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp +++ b/instrumentation/otel-webserver-module/src/apache/ApacheHooks.cpp @@ -431,6 +431,11 @@ bool ApacheHooks::initialize_opentelemetry(const request_rec *r) env_config[ix].value = our_config->getOtelExporterOtlpHeaders(); ++ix; + // Resource attributes + env_config[ix].name = OTEL_SDK_ENV_OTEL_RESOURCE_ATTRIBUTES; + env_config[ix].value = our_config->getOtelResourceAttributes(); + ++ix; + // !!! // Remember to update the apr_pcalloc call size if we add another parameter to the input array! // !!! diff --git a/instrumentation/otel-webserver-module/src/apache/mod_apache_otel.cpp b/instrumentation/otel-webserver-module/src/apache/mod_apache_otel.cpp index f01fdd550..82c0a8aeb 100644 --- a/instrumentation/otel-webserver-module/src/apache/mod_apache_otel.cpp +++ b/instrumentation/otel-webserver-module/src/apache/mod_apache_otel.cpp @@ -70,6 +70,12 @@ static const command_rec otel_cmds[] = NULL, OR_ALL, "AppDynamics Otel export Headers key value pairs"), + AP_INIT_TAKE1( + "apacheModuleOtelResourceAttributes", + (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_otelResourceAttributes, + NULL, + OR_ALL, + "Otel resource attributes key value pairs"), AP_INIT_TAKE1( "apacheModuleOtelSslEnabled", (CMD_HAND_TYPE)ApacheConfigHandlers::otel_set_otelSslEnabled, diff --git a/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp b/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp index 1a2931e06..c22b0bd70 100755 --- a/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/ApiUtils.cpp @@ -168,6 +168,7 @@ OTEL_SDK_STATUS_CODE ApiUtils::ReadSettingsFromReader( std::string otelExporterType; std::string otelExporterEndpoint; std::string otelExporterOtlpHeaders; + std::string otelResourceAttributes; bool otelSslEnabled; std::string otelSslCertPath; std::string otelLibraryName; @@ -259,6 +260,9 @@ OTEL_SDK_STATUS_CODE ApiUtils::ReadSettingsFromReader( reader.ReadOptional( std::string(OTEL_SDK_ENV_OTEL_EXPORTER_OTLPHEADERS), otelExporterOtlpHeaders); + reader.ReadOptional( + std::string(OTEL_SDK_ENV_OTEL_RESOURCE_ATTRIBUTES), otelResourceAttributes); + tenantConfig.setServiceNamespace(serviceNamespace); tenantConfig.setServiceName(serviceName); @@ -266,6 +270,7 @@ OTEL_SDK_STATUS_CODE ApiUtils::ReadSettingsFromReader( tenantConfig.setOtelExporterType(otelExporterType); tenantConfig.setOtelExporterEndpoint(otelExporterEndpoint); tenantConfig.setOtelExporterOtlpHeaders(otelExporterOtlpHeaders); + tenantConfig.setOtelResourceAttributes(otelResourceAttributes); tenantConfig.setOtelLibraryName(otelLibraryName); tenantConfig.setOtelProcessorType(otelProcessorType); tenantConfig.setOtelSamplerType(otelSamplerType); diff --git a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp index 0082276c3..84f8b02eb 100644 --- a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp +++ b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkHelperFactory.cpp @@ -65,6 +65,22 @@ SdkHelperFactory::SdkHelperFactory( attributes[kServiceNamespace] = config->getServiceNamespace(); attributes[kServiceInstanceId] = config->getServiceInstanceId(); + opentelemetry::common::KeyValueStringTokenizer tokenizer{config->getOtelResourceAttributes()}; + opentelemetry::nostd::string_view resource_key; + opentelemetry::nostd::string_view resource_value; + bool resource_valid = true; + + while (tokenizer.next(resource_valid, resource_key, resource_value)) + { + if (resource_valid) + { + std::string key = static_cast(resource_key); + std::string value = static_cast(resource_value); + attributes[key] = value; + } + } + + // NOTE : resource attribute values are nostd::variant and so we need to explicitely set it to std::string std::string libraryVersion = MODULE_VERSION; std::string cppSDKVersion = CPP_SDK_VERSION; diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c index 8e4d5005b..fe209b7b4 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.c @@ -209,6 +209,13 @@ static ngx_command_t ngx_http_opentelemetry_commands[] = { offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleOtelExporterOtlpHeaders), NULL}, + { ngx_string("NginxModuleOtelResourceAttributes"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_opentelemetry_loc_conf_t, nginxModuleOtelResourceAttributes), + NULL}, + { ngx_string("NginxModuleOtelSpanProcessor"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, @@ -467,6 +474,7 @@ static char* ngx_http_opentelemetry_merge_loc_conf(ngx_conf_t *cf, void *parent, ngx_conf_merge_str_value(conf->nginxModuleOtelSpanExporter, prev->nginxModuleOtelSpanExporter, ""); ngx_conf_merge_str_value(conf->nginxModuleOtelExporterEndpoint, prev->nginxModuleOtelExporterEndpoint, ""); ngx_conf_merge_str_value(conf->nginxModuleOtelExporterOtlpHeaders, prev->nginxModuleOtelExporterOtlpHeaders, ""); + ngx_conf_merge_str_value(conf->nginxModuleOtelResourceAttributes, prev->nginxModuleOtelResourceAttributes, ""); ngx_conf_merge_value(conf->nginxModuleOtelSslEnabled, prev->nginxModuleOtelSslEnabled, 0); ngx_conf_merge_str_value(conf->nginxModuleOtelSslCertificatePath, prev->nginxModuleOtelSslCertificatePath, ""); ngx_conf_merge_str_value(conf->nginxModuleOtelSpanProcessor, prev->nginxModuleOtelSpanProcessor, ""); @@ -959,6 +967,13 @@ static ngx_flag_t ngx_initialize_opentelemetry(ngx_http_request_t *r) env_config[ix].value = (const char*)(conf->nginxModuleOtelExporterOtlpHeaders).data; ++ix; + // Otel Exporter Resource Attributes + env_config[ix].name = OTEL_SDK_ENV_OTEL_RESOURCE_ATTRIBUTES; + env_config[ix].value = (const char*)(conf->nginxModuleOtelResourceAttributes).data; + ++ix; + + // TODO should resource attributes be added here? + // Otel SSL Enabled env_config[ix].name = OTEL_SDK_ENV_OTEL_SSL_ENABLED; env_config[ix].value = conf->nginxModuleOtelSslEnabled == 1 ? "1" : "0"; @@ -1493,6 +1508,7 @@ static void traceConfig(ngx_http_request_t *r, ngx_http_opentelemetry_loc_conf_t conf->nginxModuleEnabled, (conf->nginxModuleOtelExporterEndpoint).data, (conf->nginxModuleOtelExporterOtlpHeaders).data, + (conf->nginxModuleOtelResourceAttributes).data, conf->nginxModuleOtelSslEnabled, (conf->nginxModuleOtelSslCertificatePath).data, (conf->nginxModuleOtelSpanExporter).data, diff --git a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h index 6043b5b78..cea022431 100644 --- a/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h +++ b/instrumentation/otel-webserver-module/src/nginx/ngx_http_opentelemetry_module.h @@ -103,6 +103,7 @@ typedef struct { ngx_str_t nginxModuleRequestHeaders; ngx_str_t nginxModuleResponseHeaders; ngx_str_t nginxModuleOtelExporterOtlpHeaders; + ngx_str_t nginxModuleOtelResourceAttributes; ngx_flag_t nginxTrustIncomingSpans; } ngx_http_opentelemetry_loc_conf_t;