@@ -383,10 +383,19 @@ static ngx_command_t ngx_http_opentelemetry_commands[] = {
383
383
NGX_HTTP_LOC_CONF_OFFSET ,
384
384
offsetof(ngx_http_opentelemetry_loc_conf_t , nginxTrustIncomingSpans ),
385
385
NULL },
386
-
387
- ngx_null_command /* command termination */
386
+
387
+ { ngx_string ("NginxAttributes" ),
388
+ NGX_HTTP_MAIN_CONF |NGX_HTTP_SRV_CONF |NGX_HTTP_LOC_CONF |NGX_CONF_1MORE ,
389
+ ngx_otel_attributes_set ,
390
+ NGX_HTTP_LOC_CONF_OFFSET ,
391
+ 0 ,
392
+ NULL },
393
+
394
+ /* command termination */
395
+ ngx_null_command
388
396
};
389
397
398
+
390
399
/* The module context. */
391
400
static ngx_http_module_t ngx_http_opentelemetry_module_ctx = {
392
401
NULL , /* preconfiguration */
@@ -454,6 +463,7 @@ static char* ngx_http_opentelemetry_merge_loc_conf(ngx_conf_t *cf, void *parent,
454
463
ngx_http_opentelemetry_loc_conf_t * prev = parent ;
455
464
ngx_http_opentelemetry_loc_conf_t * conf = child ;
456
465
ngx_otel_set_global_context (prev );
466
+ ngx_otel_set_attributes (prev , conf );
457
467
458
468
ngx_conf_merge_value (conf -> nginxModuleEnabled , prev -> nginxModuleEnabled , 1 );
459
469
ngx_conf_merge_value (conf -> nginxModuleReportAllInstrumentedModules , prev -> nginxModuleReportAllInstrumentedModules , 0 );
@@ -673,6 +683,34 @@ static void ngx_http_opentelemetry_exit_worker(ngx_cycle_t *cycle)
673
683
ngx_log_error (NGX_LOG_ERR , cycle -> log , 0 , "mod_opentelemetry: ngx_http_opentelemetry_exit_worker: Exiting Nginx Worker for process with PID: %s**********" , worker_conf -> pid );
674
684
}
675
685
}
686
+ static char * ngx_otel_attributes_set (ngx_conf_t * cf , ngx_command_t * cmd , void * conf ) {
687
+ ngx_http_opentelemetry_loc_conf_t * my_conf = (ngx_http_opentelemetry_loc_conf_t * )conf ;
688
+
689
+ ngx_str_t * value = cf -> args -> elts ;
690
+
691
+ ngx_array_t * arr ;
692
+ ngx_str_t * elt ;
693
+ ngx_int_t arg_count = cf -> args -> nelts ;
694
+
695
+ arr = ngx_array_create (cf -> pool , arg_count , sizeof (ngx_str_t ));
696
+
697
+ if (arr == NULL ) {
698
+ return NGX_CONF_ERROR ;
699
+ }
700
+
701
+ // Add elements to the array
702
+ for (ngx_int_t i = 1 ; i < arg_count ; i ++ ) {
703
+ elt = ngx_array_push (arr );
704
+ if (elt == NULL ) {
705
+ return NGX_CONF_ERROR ;
706
+ }
707
+ ngx_str_set (elt , value [i ].data );
708
+ elt -> len = ngx_strlen (value [i ].data );
709
+ }
710
+ my_conf -> nginxAttributes = arr ;
711
+ return NGX_CONF_OK ;
712
+
713
+ }
676
714
677
715
static char * ngx_otel_context_set (ngx_conf_t * cf , ngx_command_t * cmd , void * conf ){
678
716
ngx_str_t * value ;
@@ -704,6 +742,20 @@ static void ngx_otel_set_global_context(ngx_http_opentelemetry_loc_conf_t * prev
704
742
}
705
743
}
706
744
745
+ static void ngx_otel_set_attributes (ngx_http_opentelemetry_loc_conf_t * prev , ngx_http_opentelemetry_loc_conf_t * conf )
746
+ {
747
+ if (conf -> nginxAttributes && (conf -> nginxAttributes -> nelts ) > 0 ) {
748
+ return ;
749
+ }
750
+ if (prev -> nginxAttributes && (prev -> nginxAttributes -> nelts ) > 0 ) {
751
+ if ((conf -> nginxAttributes ) == NULL )
752
+ {
753
+ conf -> nginxAttributes = prev -> nginxAttributes ;
754
+ }
755
+ }
756
+ return ;
757
+ }
758
+
707
759
/*
708
760
Begin a new interaction
709
761
*/
@@ -737,6 +789,7 @@ static OTEL_SDK_STATUS_CODE otel_startInteraction(ngx_http_request_t* r, const c
737
789
int ix = 0 ;
738
790
res = startModuleInteraction ((void * )ctx -> otel_req_handle_key , module_name , "" , resolveBackends , propagationHeaders , & ix );
739
791
792
+
740
793
if (OTEL_ISSUCCESS (res ))
741
794
{
742
795
removeUnwantedHeader (r );
@@ -892,6 +945,39 @@ static ngx_uint_t otel_getErrorCode(ngx_http_request_t* r)
892
945
else return 0 ;
893
946
}
894
947
948
+ static void resolve_attributes_variables (ngx_http_request_t * r )
949
+ {
950
+ ngx_http_opentelemetry_loc_conf_t * conf = ngx_http_get_module_loc_conf (r , ngx_http_opentelemetry_module );
951
+
952
+ for (ngx_uint_t j = 0 ; j < conf -> nginxAttributes -> nelts ; j ++ ) {
953
+
954
+ void * element = conf -> nginxAttributes -> elts + (j * conf -> nginxAttributes -> size );
955
+ ngx_str_t var_name = (((ngx_str_t * )(conf -> nginxAttributes -> elts ))[j ]);
956
+ ngx_uint_t key ; // The variable's hashed key.
957
+ ngx_http_variable_value_t * value ; // Pointer to the value object.
958
+
959
+ if (var_name .data [0 ] == '$' ){
960
+ // Get the hashed key.
961
+ ngx_str_t new_var_name = var_name ;
962
+ new_var_name .data ++ ;
963
+ new_var_name .len -- ;
964
+ key = ngx_hash_key (new_var_name .data , new_var_name .len );
965
+
966
+ // Get the variable.
967
+ value = ngx_http_get_variable (r , & new_var_name , key );
968
+
969
+ if (value == NULL || value -> not_found ) {
970
+ // Variable was not found.
971
+ } else {
972
+ ngx_str_t * ngx_str = (ngx_str_t * )(element );
973
+ ngx_str -> data = value -> data ;
974
+ ngx_str -> len = ngx_strlen (value );
975
+ // Variable was found, `value` now contains the value.
976
+ }
977
+ }
978
+ }
979
+ }
980
+
895
981
static ngx_flag_t ngx_initialize_opentelemetry (ngx_http_request_t * r )
896
982
{
897
983
// check to see if we have already been initialized
@@ -1274,7 +1360,7 @@ static ngx_int_t ngx_http_otel_realip_handler(ngx_http_request_t *r){
1274
1360
1275
1361
otel_startInteraction (r , "ngx_http_realip_module" );
1276
1362
ngx_int_t rvalue = h [NGX_HTTP_REALIP_MODULE_INDEX ](r );
1277
- otel_stopInteraction (r , "ngx_http_realip_module" , OTEL_SDK_NO_HANDLE );
1363
+ otel_stopInteraction (r , "ngx_http_realip_module" , OTEL_SDK_NO_HANDLE );
1278
1364
1279
1365
return rvalue ;
1280
1366
}
@@ -1555,6 +1641,7 @@ static void removeUnwantedHeader(ngx_http_request_t* r)
1555
1641
}
1556
1642
}
1557
1643
1644
+
1558
1645
static void fillRequestPayload (request_payload * req_payload , ngx_http_request_t * r ){
1559
1646
ngx_list_part_t * part ;
1560
1647
ngx_table_elt_t * header ;
@@ -1636,6 +1723,7 @@ static void fillRequestPayload(request_payload* req_payload, ngx_http_request_t*
1636
1723
1637
1724
ngx_http_opentelemetry_loc_conf_t * conf =
1638
1725
ngx_http_get_module_loc_conf (r , ngx_http_opentelemetry_module );
1726
+
1639
1727
part = & r -> headers_in .headers .part ;
1640
1728
header = (ngx_table_elt_t * )part -> elts ;
1641
1729
nelts = part -> nelts ;
@@ -1669,6 +1757,7 @@ static void fillRequestPayload(request_payload* req_payload, ngx_http_request_t*
1669
1757
}
1670
1758
req_payload -> propagation_count = propagation_headers_idx ;
1671
1759
req_payload -> request_headers_count = request_headers_idx ;
1760
+
1672
1761
}
1673
1762
1674
1763
static void fillResponsePayload (response_payload * res_payload , ngx_http_request_t * r )
@@ -1689,6 +1778,36 @@ static void fillResponsePayload(response_payload* res_payload, ngx_http_request_
1689
1778
res_payload -> response_headers = ngx_pcalloc (r -> pool , nelts * sizeof (http_headers ));
1690
1779
ngx_uint_t headers_count = 0 ;
1691
1780
1781
+ ngx_http_opentelemetry_loc_conf_t * conf = ngx_http_get_module_loc_conf (r , ngx_http_opentelemetry_module );
1782
+
1783
+ if (conf -> nginxAttributes && (conf -> nginxAttributes -> nelts ) > 0 ) {
1784
+
1785
+ res_payload -> otel_attributes = ngx_pcalloc (r -> pool , ((nelts + 1 )/3 ) * sizeof (http_headers ));
1786
+ int otel_attributes_idx = 0 ;
1787
+
1788
+ resolve_attributes_variables (r );
1789
+ for (ngx_uint_t j = 0 , isKey = 1 , isValue = 0 ; j < conf -> nginxAttributes -> nelts ; j ++ ) {
1790
+ const char * data = (const char * )(((ngx_str_t * )(conf -> nginxAttributes -> elts ))[j ]).data ;
1791
+ if (strcmp (data , "," ) == 0 ){
1792
+ otel_attributes_idx ++ ;
1793
+ continue ;
1794
+ }
1795
+ else if (isKey ){
1796
+ res_payload -> otel_attributes [otel_attributes_idx ].name = data ;
1797
+ }
1798
+ else {
1799
+ res_payload -> otel_attributes [otel_attributes_idx ].value = data ;
1800
+ }
1801
+ isKey = !isKey ;
1802
+ isValue = !isValue ;
1803
+ }
1804
+ res_payload -> otel_attributes_count = otel_attributes_idx + 1 ;
1805
+ }else {
1806
+ res_payload -> otel_attributes_count = 0 ;
1807
+ }
1808
+
1809
+
1810
+
1692
1811
for (ngx_uint_t j = 0 ; j < nelts ; j ++ ) {
1693
1812
h = & header [j ];
1694
1813
0 commit comments