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";
}
This commit is contained in:
parent
a23ffa955c
commit
d0385c8f68
2 changed files with 57 additions and 2 deletions
|
|
@ -30,6 +30,7 @@ struct MainConf : MainConfBase {
|
||||||
std::map<StrView, StrView> resourceAttrs;
|
std::map<StrView, StrView> resourceAttrs;
|
||||||
bool ssl;
|
bool ssl;
|
||||||
std::string trustedCert;
|
std::string trustedCert;
|
||||||
|
Target::HeaderVec headers;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SpanAttr {
|
struct SpanAttr {
|
||||||
|
|
@ -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* addResourceAttr(ngx_conf_t* cf, ngx_command_t* cmd, void* conf);
|
||||||
char* addSpanAttr(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* 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 {
|
namespace Propagation {
|
||||||
|
|
||||||
|
|
@ -120,6 +122,10 @@ ngx_command_t gExporterCommands[] = {
|
||||||
NGX_CONF_TAKE1,
|
NGX_CONF_TAKE1,
|
||||||
setTrustedCertificate },
|
setTrustedCertificate },
|
||||||
|
|
||||||
|
{ ngx_string("header"),
|
||||||
|
NGX_CONF_TAKE2,
|
||||||
|
addExporterHeader },
|
||||||
|
|
||||||
{ ngx_string("interval"),
|
{ ngx_string("interval"),
|
||||||
NGX_CONF_TAKE1,
|
NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_msec_slot,
|
ngx_conf_set_msec_slot,
|
||||||
|
|
@ -580,6 +586,7 @@ ngx_int_t initWorkerProcess(ngx_cycle_t* cycle)
|
||||||
target.endpoint = std::string(toStrView(mcf->endpoint));
|
target.endpoint = std::string(toStrView(mcf->endpoint));
|
||||||
target.ssl = mcf->ssl;
|
target.ssl = mcf->ssl;
|
||||||
target.trustedCert = mcf->trustedCert;
|
target.trustedCert = mcf->trustedCert;
|
||||||
|
target.headers = mcf->headers;
|
||||||
|
|
||||||
gExporter.reset(new BatchExporter(
|
gExporter.reset(new BatchExporter(
|
||||||
target,
|
target,
|
||||||
|
|
@ -651,7 +658,7 @@ char* setExporter(ngx_conf_t* cf, ngx_command_t* cmd, void* conf)
|
||||||
continue;
|
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,
|
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
|
||||||
"invalid number of arguments in \"%V\" "
|
"invalid number of arguments in \"%V\" "
|
||||||
"directive of \"otel_exporter\"", name);
|
"directive of \"otel_exporter\"", name);
|
||||||
|
|
@ -747,6 +754,33 @@ char* setTrustedCertificate(ngx_conf_t* cf, ngx_command_t* cmd, void* conf)
|
||||||
return NGX_CONF_OK;
|
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)
|
void* createMainConf(ngx_conf_t* cf)
|
||||||
{
|
{
|
||||||
auto cln = ngx_pool_cleanup_add(cf->pool, sizeof(MainConf));
|
auto cln = ngx_pool_cleanup_add(cf->pool, sizeof(MainConf));
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,24 @@
|
||||||
namespace otel_proto_trace = opentelemetry::proto::collector::trace::v1;
|
namespace otel_proto_trace = opentelemetry::proto::collector::trace::v1;
|
||||||
|
|
||||||
struct Target {
|
struct Target {
|
||||||
|
typedef std::vector<std::pair<std::string, std::string>> HeaderVec;
|
||||||
|
|
||||||
std::string endpoint;
|
std::string endpoint;
|
||||||
bool ssl;
|
bool ssl;
|
||||||
std::string trustedCert;
|
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 {
|
class TraceServiceClient {
|
||||||
|
|
@ -23,7 +38,7 @@ public:
|
||||||
typedef std::function<void (Request, Response, grpc::Status)>
|
typedef std::function<void (Request, Response, grpc::Status)>
|
||||||
ResponseCb;
|
ResponseCb;
|
||||||
|
|
||||||
TraceServiceClient(const Target& target)
|
TraceServiceClient(const Target& target) : headers(target.headers)
|
||||||
{
|
{
|
||||||
std::shared_ptr<grpc::ChannelCredentials> creds;
|
std::shared_ptr<grpc::ChannelCredentials> creds;
|
||||||
if (target.ssl) {
|
if (target.ssl) {
|
||||||
|
|
@ -44,6 +59,10 @@ public:
|
||||||
{
|
{
|
||||||
std::unique_ptr<ActiveCall> call{new ActiveCall{}};
|
std::unique_ptr<ActiveCall> call{new ActiveCall{}};
|
||||||
|
|
||||||
|
for (auto& header : headers) {
|
||||||
|
call->context.AddMetadata(header.first, header.second);
|
||||||
|
}
|
||||||
|
|
||||||
call->request = std::move(req);
|
call->request = std::move(req);
|
||||||
call->cb = std::move(cb);
|
call->cb = std::move(cb);
|
||||||
|
|
||||||
|
|
@ -113,6 +132,8 @@ private:
|
||||||
ResponseCb cb;
|
ResponseCb cb;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Target::HeaderVec headers;
|
||||||
|
|
||||||
std::unique_ptr<TraceService::Stub> stub;
|
std::unique_ptr<TraceService::Stub> stub;
|
||||||
grpc::CompletionQueue queue;
|
grpc::CompletionQueue queue;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue