diff --git a/instrumentation/otel-webserver-module/README.md b/instrumentation/otel-webserver-module/README.md index a4bbedf2..651ece90 100644 --- a/instrumentation/otel-webserver-module/README.md +++ b/instrumentation/otel-webserver-module/README.md @@ -182,8 +182,9 @@ Currently, Nginx Webserver module monitores some fixed set of modules, which get |*NginxModulePropagatorType* | w3c | OPTIONAL: Specify the Propagator used by the instrumentation (W3C and B3 propagators available). e.g.```NginxModulePropagatorType b3;```| |*NginxModuleOperationName* | | OPTIONAL: Specify the operation name (span name) for any specific endpoint. e.g.```NginxModuleOperationName My_Backend;```| +#### Other Configurations - +- Nginx variables related to traceing info - $opentelemetry_trace_id , $opentelemetry_span_id $opentelemetry_context_traceparent , $opentelemetry_context_b3 ### Build and Installation #### Prerequisites diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkWrapper.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkWrapper.h index c1e53c75..f920f45c 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkWrapper.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/ISdkWrapper.h @@ -38,6 +38,8 @@ class ISdkWrapper { const SpanKind& kind, const OtelKeyValueMap& attributes, const std::unordered_map& carrier = {}) = 0; + + virtual std::string ReturnCurrentSpanId() = 0; virtual void PopulatePropagationHeaders( std::unordered_map& carrier) = 0; diff --git a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkWrapper.h b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkWrapper.h index a8f5d5dc..9a90b56f 100644 --- a/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkWrapper.h +++ b/instrumentation/otel-webserver-module/include/core/sdkwrapper/SdkWrapper.h @@ -41,6 +41,8 @@ class SdkWrapper : public ISdkWrapper{ void PopulatePropagationHeaders( std::unordered_map& carrier) override; + std::string ReturnCurrentSpanId() override; + private: trace::SpanKind GetTraceSpanKind(const SpanKind& kind); diff --git a/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp b/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp index 27986574..8603a550 100644 --- a/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/RequestProcessingEngine.cpp @@ -86,7 +86,7 @@ OTEL_SDK_STATUS_CODE RequestProcessingEngine::startRequest( } auto span = m_sdkWrapper->CreateSpan(spanName, sdkwrapper::SpanKind::SERVER, keyValueMap, payload->get_http_headers()); - + LOG4CXX_TRACE(mLogger, "Span started for context: [" << wscontext <<"] SpanName: " << spanName << ", RequestProtocol: " << payload->get_request_protocol() <<" SpanId: " << span.get()); @@ -200,10 +200,12 @@ OTEL_SDK_STATUS_CODE RequestProcessingEngine::startInteraction( // TODO : confirm and update name later std::string spanName = payload->moduleName + "_" + payload->phaseName; keyValueMap["interactionType"] = "EXIT_CALL"; + std::string parentSpanId = m_sdkWrapper->ReturnCurrentSpanId(); auto interactionSpan = m_sdkWrapper->CreateSpan(spanName, SpanKind::CLIENT, keyValueMap); LOG4CXX_TRACE(mLogger, "Client Span started with SpanName: " << spanName << " Span Id: " << interactionSpan.get()); m_sdkWrapper->PopulatePropagationHeaders(propagationHeaders); + propagationHeaders["Parent_Span_Id"] = parentSpanId; // Add the interaction to the request context. requestContext->addInteraction(interactionSpan); diff --git a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp index 9bf99818..1438650a 100644 --- a/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp +++ b/instrumentation/otel-webserver-module/src/core/api/opentelemetry_ngx_api.cpp @@ -179,7 +179,7 @@ OTEL_SDK_STATUS_CODE startModuleInteraction(OTEL_SDK_HANDLE_REQ req_handle_key, propagationHeaders[*ix].name = temp_key; char *temp_value= (char*)malloc(itr->second.size() + 1); std::strcpy(temp_value, itr->second.c_str()); - propagationHeaders[*ix].value = temp_value; + propagationHeaders[*ix].value = temp_value; ++(*ix); } } diff --git a/instrumentation/otel-webserver-module/src/core/sdkwrapper/ScopedSpan.cpp b/instrumentation/otel-webserver-module/src/core/sdkwrapper/ScopedSpan.cpp index 399244d4..4317e1d9 100644 --- a/instrumentation/otel-webserver-module/src/core/sdkwrapper/ScopedSpan.cpp +++ b/instrumentation/otel-webserver-module/src/core/sdkwrapper/ScopedSpan.cpp @@ -30,7 +30,9 @@ ScopedSpan::ScopedSpan( { trace::StartSpanOptions options{}; options.kind = kind; + mSpan = sdkHelperFactory->GetTracer()->StartSpan(name, attributes, options); + mScope.reset(new trace::Scope(mSpan)); mSpanKind = kind; } diff --git a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkWrapper.cpp b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkWrapper.cpp index a7cfd5aa..0cc1d693 100644 --- a/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkWrapper.cpp +++ b/instrumentation/otel-webserver-module/src/core/sdkwrapper/SdkWrapper.cpp @@ -66,26 +66,37 @@ std::shared_ptr SdkWrapper::CreateSpan( mLogger)); } } - +std::string SdkWrapper::ReturnCurrentSpanId(){ + + auto context = context::RuntimeContext::GetCurrent(); + auto currentSpan = trace::GetSpan(context); + trace::SpanContext spanContext = currentSpan->GetContext(); + trace::SpanId spanId = spanContext.span_id(); + constexpr int len = 2 * trace::SpanId::kSize; + char* data = new char[len]; + spanId.ToLowerBase16(nostd::span{data, len}); + std::string currentSpanId(data, len); + delete[] data; + return currentSpanId; +} void SdkWrapper::PopulatePropagationHeaders( std::unordered_map& carrier) { // TODO : This is inefficient change as we are copying otel carrier data // into unordered map and sending it back to agent. // Ideally agent should keep otelCarrier data structure on its side. - auto otelCarrier = OtelCarrier(); + auto otelCarrier = OtelCarrier(); auto context = context::RuntimeContext::GetCurrent(); for (auto &propagators : mSdkHelperFactory->GetPropagators()) { propagators->Inject(otelCarrier, context); } - - // copy all relevant kv pairs into carrier - for (int i = 0; i < CARRIER_HEADER_LEN; i++) { - auto carrier_header = otelCarrier.Get(CARRIER_HEADER_NAME[i]).data(); - if(carrier_header != ""){ - carrier[CARRIER_HEADER_NAME[i]] = otelCarrier.Get(CARRIER_HEADER_NAME[i]).data(); + // copy all relevant kv pairs into carrier + for (int i = 0; i < CARRIER_HEADER_LEN; i++) { + auto carrier_header = otelCarrier.Get(CARRIER_HEADER_NAME[i]).data(); + if(carrier_header != ""){ + carrier[CARRIER_HEADER_NAME[i]] = otelCarrier.Get(CARRIER_HEADER_NAME[i]).data(); + } } - } } trace::SpanKind SdkWrapper::GetTraceSpanKind(const SpanKind& kind) 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 69798724..6a8625c5 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 @@ -161,6 +161,46 @@ otel_ngx_module otel_monitored_modules[] = { } }; +/* + List of nginx variables. +*/ +static ngx_http_variable_t otel_ngx_variables[] = { + { + ngx_string("opentelemetry_trace_id"), + NULL, + ngx_opentelemetry_initialise_trace_id, + 0, + NGX_HTTP_VAR_NOCACHEABLE | NGX_HTTP_VAR_CHANGEABLE, + 0, + }, + { + ngx_string("opentelemetry_span_id"), + NULL, + ngx_opentelemetry_initialise_span_id, + 0, + NGX_HTTP_VAR_NOCACHEABLE | NGX_HTTP_VAR_CHANGEABLE, + 0, + }, + { + ngx_string("opentelemetry_context_traceparent"), + NULL, + ngx_opentelemetry_initialise_context_traceparent, + 0, + NGX_HTTP_VAR_NOCACHEABLE | NGX_HTTP_VAR_CHANGEABLE, + 0, + }, + { + ngx_string("opentelemetry_context_b3"), + NULL, + ngx_opentelemetry_initialise_context_b3, + 0, + NGX_HTTP_VAR_NOCACHEABLE | NGX_HTTP_VAR_CHANGEABLE, + 0, + }, + + ngx_null_command +}; + /* Here's the list of directives specific to our module, and information about where they @@ -420,8 +460,8 @@ static ngx_command_t ngx_http_opentelemetry_commands[] = { /* The module context. */ static ngx_http_module_t ngx_http_opentelemetry_module_ctx = { - NULL, /* preconfiguration */ - ngx_http_opentelemetry_init, /* postconfiguration */ + ngx_http_opentelemetry_create_variables, /* preconfiguration */ + ngx_http_opentelemetry_init, /* postconfiguration */ NULL, /* create main configuration */ NULL, /* init main configuration */ @@ -430,7 +470,7 @@ static ngx_http_module_t ngx_http_opentelemetry_module_ctx = { NULL, /* merge server configuration */ ngx_http_opentelemetry_create_loc_conf, /* create location configuration */ - ngx_http_opentelemetry_merge_loc_conf /* merge location configuration */ + ngx_http_opentelemetry_merge_loc_conf /* merge location configuration */ }; /* Module definition. */ @@ -559,6 +599,95 @@ static char* ngx_http_opentelemetry_merge_loc_conf(ngx_conf_t *cf, void *parent, NGX_HTTP_TRY_FILES_PHASE ------------------------------------------------------------------------------------------------- */ +static ngx_int_t ngx_http_opentelemetry_create_variables(ngx_conf_t *cf){ + for (ngx_http_variable_t* v = otel_ngx_variables; v->name.len; v++) { + ngx_http_variable_t* var = ngx_http_add_variable(cf, &v->name, v->flags); + if (var == NULL) { + return NGX_ERROR; + } + var->get_handler = v->get_handler; + var->set_handler = v->set_handler; + var->data = v->data; + v->index = var->index = ngx_http_get_variable_index(cf, &v->name); + } + + return NGX_OK; +} + +ngx_int_t ngx_opentelemetry_initialise_trace_id(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { + ngx_http_otel_handles_t* ctx; + ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); + + if(ctx->trace_id.len){ + v->len = ctx->trace_id.len; + v->data = ctx->trace_id.data; + }else{ + v->len = 0; + v->data = ""; + } + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; +} + +ngx_int_t ngx_opentelemetry_initialise_span_id(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { + ngx_http_otel_handles_t* ctx; + ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); + + if(ctx->root_span_id.len){ + v->len = ctx->root_span_id.len; + v->data = ctx->root_span_id.data; + }else{ + v->len = 0; + v->data = ""; + } + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; +} + +ngx_int_t ngx_opentelemetry_initialise_context_traceparent(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { + ngx_http_otel_handles_t* ctx; + ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); + ngx_http_opentelemetry_loc_conf_t *conf = ngx_http_get_module_loc_conf(r, ngx_http_opentelemetry_module); + ngx_str_t propagator_type = conf->nginxModulePropagatorType; + if(ctx->tracing_context.len && !strcmp(propagator_type.data, "w3c")){ + v->len = ctx->tracing_context.len; + v->data = ctx->tracing_context.data; + }else{ + v->len = 0; + v->data = ""; + } + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; +} + +ngx_int_t ngx_opentelemetry_initialise_context_b3(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { + ngx_http_otel_handles_t* ctx; + ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); + ngx_http_opentelemetry_loc_conf_t *conf = ngx_http_get_module_loc_conf(r, ngx_http_opentelemetry_module); + ngx_str_t propagator_type = conf->nginxModulePropagatorType; + if(ctx->tracing_context.len && !strcmp(propagator_type.data, "b3")){ + v->len = ctx->tracing_context.len; + v->data = ctx->tracing_context.data; + }else{ + v->len = 0; + v->data = ""; + } + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + return NGX_OK; +} + static ngx_int_t ngx_http_opentelemetry_init(ngx_conf_t *cf) { ngx_http_core_main_conf_t *cmcf; @@ -863,7 +992,7 @@ static OTEL_SDK_STATUS_CODE otel_startInteraction(ngx_http_request_t* r, const c { resolveBackends = conf->nginxModuleResolveBackends; } - OTEL_SDK_ENV_RECORD* propagationHeaders = ngx_pcalloc(r->pool, 5 * sizeof(OTEL_SDK_ENV_RECORD)); + OTEL_SDK_ENV_RECORD* propagationHeaders = ngx_pcalloc(r->pool, ALL_PROPAGATION_HEADERS_COUNT * sizeof(OTEL_SDK_ENV_RECORD)); if (propagationHeaders == NULL) { ngx_writeError(r->connection->log, __func__, "Failed to allocate memory for propagation headers"); @@ -878,6 +1007,7 @@ static OTEL_SDK_STATUS_CODE otel_startInteraction(ngx_http_request_t* r, const c { removeUnwantedHeader(r); otel_payload_decorator(r, propagationHeaders, ix); + otel_variables_decorator(r); ngx_writeTrace(r->connection->log, __func__, "Interaction begin successful"); } else @@ -895,6 +1025,122 @@ static OTEL_SDK_STATUS_CODE otel_startInteraction(ngx_http_request_t* r, const c return res; } +/* +Function otel_variables_decorator is used to fill the values for Nginx tracing info variables like opentelemetry_trace_id, +opentelemetry_span_id, opentelemetry_context_b3, opentelemetry_context_traceparent. It fills the information into +ctx (module context), which is then later used by the getter function of the given nginx variables. +*/ +static void otel_variables_decorator(ngx_http_request_t* r){ + ngx_str_t trace_id, span_id, tracing_context; + ngx_list_part_t *part; + ngx_table_elt_t *header; + ngx_table_elt_t *h; + ngx_uint_t nelts; + + ngx_http_otel_handles_t* ctx; + ctx = ngx_http_get_module_ctx(r, ngx_http_opentelemetry_module); + ngx_http_opentelemetry_loc_conf_t *conf = ngx_http_get_module_loc_conf(r, ngx_http_opentelemetry_module); + ngx_str_t propagator_type = conf->nginxModulePropagatorType; + part = &r->headers_in.headers.part; + header = (ngx_table_elt_t*)part->elts; + nelts = part->nelts; + if(ctx->trace_id.len == 0){ + // Getting value of trace_id from the request headers. + if(!strcmp(propagator_type.data, "b3")){ + for(ngx_uint_t j = 0; jkey.data)==0){ + trace_id.data = h->value.data; + trace_id.len = h->value.len; + + ctx->trace_id.data = trace_id.data; + ctx->trace_id.len = trace_id.len; + } + } + }else{ + for(ngx_uint_t j = 0; jkey.data)==0){ + u_char *temp_trace_id = ngx_pnalloc(r->pool, TRACE_ID_LEN + 1); + ngx_memcpy(temp_trace_id, h->value.data + 3, TRACE_ID_LEN); + temp_trace_id[TRACE_ID_LEN] = '\0'; + trace_id.data = temp_trace_id; + trace_id.len = TRACE_ID_LEN; + + ctx->trace_id.data = trace_id.data; + ctx->trace_id.len = trace_id.len; + } + } + } + } + + if(ctx->root_span_id.len == 0){ + // Getting root span id fromm ctx->propagationHeaders which is filled during otel_payload_decorator() call. + for(int i = 0 ; i < ctx->pheaderCount ; i++ ){ + if(strcasecmp(ctx->propagationHeaders[i].name , "Parent_Span_Id") == 0){ + ctx->root_span_id.data = ngx_pcalloc(r->pool, strlen(ctx->propagationHeaders[i].value)); + ngx_memcpy(ctx->root_span_id.data, ctx->propagationHeaders[i].value, strlen(ctx->propagationHeaders[i].value)); + ctx->root_span_id.len = strlen(ctx->propagationHeaders[i].value); + } + } + } + + if(ctx->tracing_context.len == 0){ + // Constructing the complete trace context for w3c or b3 headers. + if(!strcmp(propagator_type.data, "w3c")){ + for(ngx_uint_t j = 0; jkey.data)==0){ + ctx->tracing_context.data = ngx_pcalloc(r->pool, h->value.len + 1); + ngx_memcpy(ctx->tracing_context.data, h->value.data, h->value.len + 1); + ngx_memcpy(ctx->tracing_context.data + TRACE_ID_LEN + 4, ctx->root_span_id.data , SPAN_ID_LEN); + // We are trying to replace span_id in the traceparent context, so we need to start after version + // and trace_id in the traceparent context + ctx->tracing_context.len = h->value.len; + } + } + } + else if(!strcmp(propagator_type.data, "b3")){ + ngx_str_t sampled; + ngx_uint_t has_trace_id = 0, has_span_id = 0 , has_sampled = 0; + + for(ngx_uint_t j = 0; jkey.data)==0){ + has_sampled = 1; + sampled.data = h->value.data; + sampled.len = h->value.len; + } + } + if(ctx->root_span_id.len != 0){ + has_span_id = 1; + } + if(ctx->trace_id.len != 0){ + has_trace_id = 1; + } + if(has_trace_id && has_span_id){ + size_t total_length = TRACE_ID_LEN + SPAN_ID_LEN + 1; + ngx_str_t result; + if(has_sampled){ + total_length+=2; + // length of "sampled" field and a '-' + } + ctx->tracing_context.data = ngx_pcalloc(r->pool, total_length+1); + u_char *p = ctx->tracing_context.data; + p = ngx_copy(p, ctx->trace_id.data, ctx->trace_id.len); + p = ngx_copy(p, "-", 1); + p = ngx_copy(p, ctx->root_span_id.data, ctx->root_span_id.len); + if(has_sampled){ + p = ngx_copy(p, "-", 1); + p = ngx_copy(p, sampled.data, sampled.len); + } + p[total_length] = '\0'; + ctx->tracing_context.len = total_length; + } + } + } +} + static void otel_payload_decorator(ngx_http_request_t* r, OTEL_SDK_ENV_RECORD* propagationHeaders, int count) { ngx_list_part_t *part; @@ -1041,7 +1287,7 @@ static void resolve_attributes_variables(ngx_http_request_t* r) ngx_uint_t key; // The variable's hashed key. ngx_http_variable_value_t *value; // Pointer to the value object. - if(var_name.data[0] == '$'){ + if(var_name.data[0] == NGINX_VARIABLE_IDENTIFIER){ // Get the hashed key. ngx_str_t new_var_name = var_name; new_var_name.data++; @@ -1305,10 +1551,6 @@ static void stopMonitoringRequest(ngx_http_request_t* r, return; } - if (r->pool) { - ngx_pfree(r->pool, ctx); - } - ngx_writeTrace(r->connection->log, __func__, "Stopping the Request Monitoring"); response_payload* res_payload = NULL; @@ -1318,6 +1560,10 @@ static void stopMonitoringRequest(ngx_http_request_t* r, res_payload->otel_attributes_count = 0; fillResponsePayload(res_payload, r); } + + if (r->pool) { + ngx_pfree(r->pool, ctx); + } OTEL_SDK_STATUS_CODE res; char* msg = NULL; @@ -1921,13 +2167,30 @@ static void fillResponsePayload(response_payload* res_payload, ngx_http_request_ res_payload->otel_attributes = ngx_pcalloc(r->pool, ((conf->nginxModuleAttributes->nelts + 1)/3) * sizeof(http_headers)); ngx_uint_t otel_attributes_idx=0; - resolve_attributes_variables(r); for (ngx_uint_t j = 0, isKey = 1, isValue = 0; j < conf->nginxModuleAttributes->nelts; j++) { + + ngx_str_t var_name = (((ngx_str_t *)(conf->nginxModuleAttributes->elts))[j]); + ngx_uint_t key; // The variable's hashed key. + ngx_http_variable_value_t *value; // Pointer to the value object. + + if(var_name.data[0] == NGINX_VARIABLE_IDENTIFIER){ + // Get the hashed key. + ngx_str_t new_var_name = var_name; + new_var_name.data++; + new_var_name.len--; + key = ngx_hash_key(new_var_name.data, new_var_name.len); + + // Get the variable. + value = ngx_http_get_variable(r, &new_var_name, key); + if (!(value == NULL || value->not_found)) { + var_name.data = value->data; + var_name.len = value->len; + } + } - ngx_str_t data_obj = ((ngx_str_t *)(conf->nginxModuleAttributes->elts))[j]; - char* data = ngx_pcalloc(r->pool, data_obj.len +1); - ngx_memcpy(data, (const char*)(data_obj.data) , data_obj.len); - data[data_obj.len] = '\0'; + char* data = ngx_pcalloc(r->pool, var_name.len +1); + ngx_memcpy(data, (const char*)(var_name.data) , var_name.len); + data[var_name.len] = '\0'; if(strcmp(data, ",") == 0){ otel_attributes_idx++; 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 097a802a..250ca128 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 @@ -24,6 +24,10 @@ #define LOWEST_HTTP_ERROR_CODE 400 #define STATUS_CODE_BYTE_COUNT 6 static const int CONFIG_COUNT = 18; // Number of key value pairs in config +static const int TRACE_ID_LEN = 32; // Length of trace_id +static const int SPAN_ID_LEN = 16; // Length of span_id +static const char NGINX_VARIABLE_IDENTIFIER = '$'; // Identifier for Nginx variables +static const int ALL_PROPAGATION_HEADERS_COUNT = 16; // Length of span_id /* The following enum has one-to-one mapping with otel_monitored_modules[] defined in .c file. @@ -111,6 +115,7 @@ typedef struct { } ngx_http_opentelemetry_loc_conf_t; + /* Configuration structure for storing information throughout the worker process life-time */ @@ -125,9 +130,12 @@ typedef struct{ }NGX_HTTP_OTEL_RECORDS; typedef struct { - OTEL_SDK_HANDLE_REQ otel_req_handle_key; - OTEL_SDK_ENV_RECORD* propagationHeaders; - int pheaderCount; + OTEL_SDK_HANDLE_REQ otel_req_handle_key; + OTEL_SDK_ENV_RECORD* propagationHeaders; + int pheaderCount; + ngx_str_t trace_id; + ngx_str_t root_span_id; + ngx_str_t tracing_context; }ngx_http_otel_handles_t; typedef struct{ @@ -165,6 +173,7 @@ static void ngx_otel_set_global_context(ngx_http_opentelemetry_loc_conf_t * prev static void ngx_otel_set_attributes(ngx_http_opentelemetry_loc_conf_t * prev, ngx_http_opentelemetry_loc_conf_t * conf); static void ngx_conf_merge_ignore_paths(ngx_http_opentelemetry_loc_conf_t * prev, ngx_http_opentelemetry_loc_conf_t * conf); static void removeUnwantedHeader(ngx_http_request_t* r); +static void otel_variables_decorator(ngx_http_request_t* r); /* Module specific handler */ @@ -198,3 +207,8 @@ static char* computeContextName(ngx_http_request_t *r, ngx_http_opentelemetry_lo // static ngx_int_t ngx_http_opentelemetry_header_filter(ngx_http_request_t *r); // static ngx_int_t ngx_http_opentelemetry_body_filter(ngx_http_request_t *r, ngx_chain_t *in); +static ngx_int_t ngx_http_opentelemetry_create_variables(ngx_conf_t *cf); +ngx_int_t ngx_opentelemetry_initialise_trace_id(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +ngx_int_t ngx_opentelemetry_initialise_span_id(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +ngx_int_t ngx_opentelemetry_initialise_context_traceparent(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +ngx_int_t ngx_opentelemetry_initialise_context_b3(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); \ No newline at end of file diff --git a/instrumentation/otel-webserver-module/test/unit/mocks/mock_sdkwrapper.h b/instrumentation/otel-webserver-module/test/unit/mocks/mock_sdkwrapper.h index f1a664b3..80e8c159 100644 --- a/instrumentation/otel-webserver-module/test/unit/mocks/mock_sdkwrapper.h +++ b/instrumentation/otel-webserver-module/test/unit/mocks/mock_sdkwrapper.h @@ -58,6 +58,9 @@ class MockSdkWrapper : public otel::core::sdkwrapper::ISdkWrapper const otel::core::sdkwrapper::SpanKind& kind, const otel::core::sdkwrapper::OtelKeyValueMap& attributes, const std::unordered_map& carrier)); + MOCK_METHOD(std::string, ReturnCurrentSpanId, + (), + (override)); }; class FakeSdkWrapper : public otel::core::sdkwrapper::SdkWrapper