@@ -30,6 +30,7 @@ struct MainConf : MainConfBase {
3030 std::map<StrView, StrView> resourceAttrs;
3131 bool ssl;
3232 std::string trustedCert;
33+ Target::HeaderVec headers;
3334};
3435
3536struct SpanAttr {
@@ -49,6 +50,7 @@ char* setExporter(ngx_conf_t* cf, ngx_command_t* cmd, void* conf);
4950char * addResourceAttr (ngx_conf_t * cf, ngx_command_t * cmd, void * conf);
5051char * addSpanAttr (ngx_conf_t * cf, ngx_command_t * cmd, void * conf);
5152char * setTrustedCertificate (ngx_conf_t * cf, ngx_command_t * cmd, void * conf);
53+ char * addExporterHeader (ngx_conf_t * cf, ngx_command_t * cmd, void * conf);
5254
5355namespace Propagation {
5456
@@ -120,6 +122,10 @@ ngx_command_t gExporterCommands[] = {
120122 NGX_CONF_TAKE1,
121123 setTrustedCertificate },
122124
125+ { ngx_string (" header" ),
126+ NGX_CONF_TAKE2,
127+ addExporterHeader },
128+
123129 { ngx_string (" interval" ),
124130 NGX_CONF_TAKE1,
125131 ngx_conf_set_msec_slot,
@@ -580,6 +586,7 @@ ngx_int_t initWorkerProcess(ngx_cycle_t* cycle)
580586 target.endpoint = std::string (toStrView (mcf->endpoint ));
581587 target.ssl = mcf->ssl ;
582588 target.trustedCert = mcf->trustedCert ;
589+ target.headers = mcf->headers ;
583590
584591 gExporter .reset (new BatchExporter (
585592 target,
@@ -651,7 +658,7 @@ char* setExporter(ngx_conf_t* cf, ngx_command_t* cmd, void* conf)
651658 continue ;
652659 }
653660
654- if (cf->args ->nelts != 2 ) {
661+ if (cf->args ->nelts != static_cast < unsigned >( ffs (cmd-> type )) ) {
655662 ngx_conf_log_error (NGX_LOG_EMERG, cf, 0 ,
656663 " invalid number of arguments in \" %V\" "
657664 " directive of \" otel_exporter\" " , name);
@@ -747,6 +754,33 @@ char* setTrustedCertificate(ngx_conf_t* cf, ngx_command_t* cmd, void* conf)
747754 return NGX_CONF_OK;
748755}
749756
757+ char * addExporterHeader (ngx_conf_t * cf, ngx_command_t * cmd, void * conf)
758+ {
759+ auto args = (ngx_str_t *)cf->args ->elts ;
760+
761+ // don't force on users lower case name requirement of gRPC
762+ ngx_strlow (args[1 ].data , args[1 ].data , args[1 ].len );
763+
764+ try {
765+ // validate header here to avoid runtime assert failure in gRPC
766+ auto name = toStrView (args[1 ]);
767+ if (!Target::validateHeaderName (name)) {
768+ return (char *)" has invalid header name" ;
769+ }
770+ auto value = toStrView (args[2 ]);
771+ if (!Target::validateHeaderValue (value)) {
772+ return (char *)" has invalid header value" ;
773+ }
774+
775+ getMainConf (cf)->headers .emplace_back (name, value);
776+ } catch (const std::exception& e) {
777+ ngx_conf_log_error (NGX_LOG_EMERG, cf, 0 , " OTel: %s" , e.what ());
778+ return (char *)NGX_CONF_ERROR;
779+ }
780+
781+ return NGX_CONF_OK;
782+ }
783+
750784void * createMainConf (ngx_conf_t * cf)
751785{
752786 auto cln = ngx_pool_cleanup_add (cf->pool , sizeof (MainConf));
0 commit comments