Skip to content

Commit

Permalink
Support sending custom headers to export endpoint (fix #62).
Browse files Browse the repository at this point in the history
The headers are configured by "header" directive in "otel_exporter" block, e.g.
    otel_exporter {
        endpoint localhost:4317;
        header X-API-Token "token value";
    }
  • Loading branch information
p-pautov committed Dec 19, 2024
1 parent 026a78e commit ff12746
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 2 deletions.
36 changes: 35 additions & 1 deletion src/http_module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ struct MainConf : MainConfBase {
std::map<StrView, StrView> resourceAttrs;
bool ssl;
std::string trustedCert;
Target::HeaderVec headers;
};

struct SpanAttr {
Expand All @@ -49,6 +50,7 @@ char* setExporter(ngx_conf_t* cf, ngx_command_t* cmd, void* conf);
char* addResourceAttr(ngx_conf_t* cf, ngx_command_t* cmd, void* conf);
char* addSpanAttr(ngx_conf_t* cf, ngx_command_t* cmd, void* conf);
char* setTrustedCertificate(ngx_conf_t* cf, ngx_command_t* cmd, void* conf);
char* addExporterHeader(ngx_conf_t* cf, ngx_command_t* cmd, void* conf);

namespace Propagation {

Expand Down Expand Up @@ -120,6 +122,10 @@ ngx_command_t gExporterCommands[] = {
NGX_CONF_TAKE1,
setTrustedCertificate },

{ ngx_string("header"),
NGX_CONF_TAKE2,
addExporterHeader },

{ ngx_string("interval"),
NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
Expand Down Expand Up @@ -580,6 +586,7 @@ ngx_int_t initWorkerProcess(ngx_cycle_t* cycle)
target.endpoint = std::string(toStrView(mcf->endpoint));
target.ssl = mcf->ssl;
target.trustedCert = mcf->trustedCert;
target.headers = mcf->headers;

gExporter.reset(new BatchExporter(
target,
Expand Down Expand Up @@ -651,7 +658,7 @@ char* setExporter(ngx_conf_t* cf, ngx_command_t* cmd, void* conf)
continue;
}

if (cf->args->nelts != 2) {
if (cf->args->nelts != static_cast<unsigned>(ffs(cmd->type))) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid number of arguments in \"%V\" "
"directive of \"otel_exporter\"", name);
Expand Down Expand Up @@ -747,6 +754,33 @@ char* setTrustedCertificate(ngx_conf_t* cf, ngx_command_t* cmd, void* conf)
return NGX_CONF_OK;
}

char* addExporterHeader(ngx_conf_t* cf, ngx_command_t* cmd, void* conf)
{
auto args = (ngx_str_t*)cf->args->elts;

// don't force on users lower case name requirement of gRPC
ngx_strlow(args[1].data, args[1].data, args[1].len);

try {
// validate header here to avoid runtime assert failure in gRPC
auto name = toStrView(args[1]);
if (!Target::validateHeaderName(name)) {
return (char*)"has invalid header name";
}
auto value = toStrView(args[2]);
if (!Target::validateHeaderValue(value)) {
return (char*)"has invalid header value";
}

getMainConf(cf)->headers.emplace_back(name, value);
} catch (const std::exception& e) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "OTel: %s", e.what());
return (char*)NGX_CONF_ERROR;
}

return NGX_CONF_OK;
}

void* createMainConf(ngx_conf_t* cf)
{
auto cln = ngx_pool_cleanup_add(cf->pool, sizeof(MainConf));
Expand Down
23 changes: 22 additions & 1 deletion src/trace_service_client.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,24 @@
namespace otel_proto_trace = opentelemetry::proto::collector::trace::v1;

struct Target {
typedef std::vector<std::pair<std::string, std::string>> HeaderVec;

std::string endpoint;
bool ssl;
std::string trustedCert;
HeaderVec headers;

static bool validateHeaderName(StrView name)
{
return grpc_header_key_is_legal(
grpc_slice_from_static_buffer(name.data(), name.size()));
}

static bool validateHeaderValue(StrView value)
{
return grpc_header_nonbin_value_is_legal(
grpc_slice_from_static_buffer(value.data(), value.size()));
}
};

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

TraceServiceClient(const Target& target)
TraceServiceClient(const Target& target) : headers(target.headers)
{
std::shared_ptr<grpc::ChannelCredentials> creds;
if (target.ssl) {
Expand All @@ -44,6 +59,10 @@ class TraceServiceClient {
{
std::unique_ptr<ActiveCall> call{new ActiveCall{}};

for (auto& header : headers) {
call->context.AddMetadata(header.first, header.second);
}

call->request = std::move(req);
call->cb = std::move(cb);

Expand Down Expand Up @@ -113,6 +132,8 @@ class TraceServiceClient {
ResponseCb cb;
};

Target::HeaderVec headers;

std::unique_ptr<TraceService::Stub> stub;
grpc::CompletionQueue queue;

Expand Down

0 comments on commit ff12746

Please sign in to comment.