Skip to content

Commit a45a594

Browse files
committed
Support sending custom headers to export endpoint (fix #62).
The headers are configured by "header" directive in "otel_exporter" block, e.g. otel_exporter { endpoint localhost:4317; header X-API-Token "token value"; }
1 parent 88a64bb commit a45a594

File tree

2 files changed

+57
-2
lines changed

2 files changed

+57
-2
lines changed

src/http_module.cpp

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

3536
struct SpanAttr {
@@ -49,6 +50,7 @@ char* setExporter(ngx_conf_t* cf, ngx_command_t* cmd, void* conf);
4950
char* addResourceAttr(ngx_conf_t* cf, ngx_command_t* cmd, void* conf);
5051
char* addSpanAttr(ngx_conf_t* cf, ngx_command_t* cmd, void* conf);
5152
char* 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

5355
namespace 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+
750784
void* createMainConf(ngx_conf_t* cf)
751785
{
752786
auto cln = ngx_pool_cleanup_add(cf->pool, sizeof(MainConf));

src/trace_service_client.hpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,24 @@
99
namespace otel_proto_trace = opentelemetry::proto::collector::trace::v1;
1010

1111
struct Target {
12+
typedef std::vector<std::pair<std::string, std::string>> HeaderVec;
13+
1214
std::string endpoint;
1315
bool ssl;
1416
std::string trustedCert;
17+
HeaderVec headers;
18+
19+
static bool validateHeaderName(StrView name)
20+
{
21+
return grpc_header_key_is_legal(
22+
grpc_slice_from_static_buffer(name.data(), name.size()));
23+
}
24+
25+
static bool validateHeaderValue(StrView value)
26+
{
27+
return grpc_header_nonbin_value_is_legal(
28+
grpc_slice_from_static_buffer(value.data(), value.size()));
29+
}
1530
};
1631

1732
class TraceServiceClient {
@@ -23,7 +38,7 @@ class TraceServiceClient {
2338
typedef std::function<void (Request, Response, grpc::Status)>
2439
ResponseCb;
2540

26-
TraceServiceClient(const Target& target)
41+
TraceServiceClient(const Target& target) : headers(target.headers)
2742
{
2843
std::shared_ptr<grpc::ChannelCredentials> creds;
2944
if (target.ssl) {
@@ -44,6 +59,10 @@ class TraceServiceClient {
4459
{
4560
std::unique_ptr<ActiveCall> call{new ActiveCall{}};
4661

62+
for (auto& header : headers) {
63+
call->context.AddMetadata(header.first, header.second);
64+
}
65+
4766
call->request = std::move(req);
4867
call->cb = std::move(cb);
4968

@@ -113,6 +132,8 @@ class TraceServiceClient {
113132
ResponseCb cb;
114133
};
115134

135+
Target::HeaderVec headers;
136+
116137
std::unique_ptr<TraceService::Stub> stub;
117138
grpc::CompletionQueue queue;
118139

0 commit comments

Comments
 (0)