Skip to content

Commit

Permalink
add tests for b3 multi propagation
Browse files Browse the repository at this point in the history
  • Loading branch information
seemk committed Dec 4, 2024
1 parent ca6ec64 commit 1cfa98b
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 25 deletions.
10 changes: 9 additions & 1 deletion instrumentation/nginx/src/otel_ngx_module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,14 @@ nostd::string_view WithoutOtelVarPrefix(ngx_str_t value) {

static ngx_int_t
OtelGetSampled(ngx_http_request_t* req, ngx_http_variable_value_t* v, uintptr_t data) {
(void)data;

if (!IsOtelEnabled(req)) {
v->valid = 0;
v->not_found = 1;
return NGX_OK;
}

TraceContext* traceContext = GetTraceContext(req);

if (traceContext == nullptr || !traceContext->request_span) {
Expand All @@ -251,7 +259,7 @@ OtelGetSampled(ngx_http_request_t* req, ngx_http_variable_value_t* v, uintptr_t
if (spanContext.IsValid()) {
u_char* isSampled = spanContext.trace_flags().IsSampled() ? (u_char*) "1" : (u_char*) "0";

v->len = strlen((const char*)isSampled);
v->len = 1;
v->valid = 1;
v->no_cacheable = 1;
v->not_found = 0;
Expand Down
15 changes: 2 additions & 13 deletions instrumentation/nginx/src/propagate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,6 @@ static bool FindHeader(ngx_http_request_t* req, nostd::string_view key, nostd::s
}


static bool HasHeader(ngx_http_request_t* req, nostd::string_view header) {
nostd::string_view value;
return FindHeader(req, header, &value);
}

class TextMapCarrierNgx : public opentelemetry::context::propagation::TextMapCarrier
{
public:
Expand Down Expand Up @@ -79,15 +74,9 @@ opentelemetry::context::Context ExtractContext(OtelCarrier* carrier) {
case TracePropagationW3C: {
return OtelW3CPropagator().Extract(textMapCarrier, root);
}
case TracePropagationB3Multi: {
return OtelB3MultiPropagator().Extract(textMapCarrier, root);
}
case TracePropagationB3Multi:
case TracePropagationB3: {
if (HasHeader(carrier->req, "b3")) {
return OtelB3Propagator().Extract(textMapCarrier, root);
}

return OtelB3MultiPropagator().Extract(textMapCarrier, root);
return OtelB3Propagator().Extract(textMapCarrier, root);
}
default:
return root;
Expand Down
24 changes: 24 additions & 0 deletions instrumentation/nginx/test/backend/php/b3multi.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php
$b3_trace_id = $_SERVER["HTTP_B3_TRACEID"];
$b3_span_id = $_SERVER["HTTP_B3_SPANID"];
$b3_sampled = $_SERVER["HTTP_B3_SAMPLED"];

if (!preg_match("/^([0-9a-f]{32}|[0-9a-f]{16})$/", $b3_trace_id)) {
throw new Exception("invalid or missing x-b3-traceid header");
}

if (!preg_match("/^[0-9a-f]{16}$/", $b3_span_id)) {
throw new Exception("invalid or missing x-b3-spanid header");
}

if (!preg_match("/^[0-1]$/", $b3_sampled)) {
throw new Exception("invalid or missing x-b3-sampled header");
}

header("Content-Type: application/json");
echo(json_encode(array(
"x-b3-traceid" => $b3_trace_id,
"x-b3-spanid" => $b3_span_id,
"x-b3-sampled" => $b3_sampled
)));
?>
30 changes: 27 additions & 3 deletions instrumentation/nginx/test/backend/simple_express/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const express = require('express')
const app = express()
const port = 3500
const express = require('express');
const app = express();
const port = 3500;

const traceparentRegex = /00-[0-9a-f]{32}-[0-9a-f]{16}-0[0-1]/;

Expand All @@ -22,6 +22,30 @@ app.get("/b3", (req, res) => {
res.json({"b3": header});
});

app.get("/b3multi", (req, res) => {
let traceId = req.header("x-b3-traceid");
let spanId = req.header("x-b3-spanid");
let sampled = req.header("x-b3-sampled");

if (!/^([0-9a-f]{32}|[0-9a-f]{16})$/.test(traceId)) {
throw "Missing x-b3-traceid header";
}

if (!/^[0-9a-f]{16}$/.test(spanId)) {
throw "Missing x-b3-spanid header";
}

if (!["0", "1"].includes(sampled)) {
throw "Missing x-b3-sampled header";
}

res.json({
"x-b3-traceid": traceId,
"x-b3-spanid": spanId,
"x-b3-sampled": sampled
});
});

app.get("/off", (req, res) => {
if (req.header("traceparent") !== undefined) {
throw "Found traceparent header, but expected none";
Expand Down
22 changes: 22 additions & 0 deletions instrumentation/nginx/test/conf/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ http {
proxy_pass http://node-backend/b3;
}

location = /b3multi {
opentelemetry_operation_name test_b3multi;
opentelemetry_propagate b3multi;
proxy_pass http://node-backend/b3multi;
}

location = /off {
opentelemetry off;
proxy_pass http://node-backend/off;
Expand Down Expand Up @@ -126,6 +132,22 @@ http {
return 200 "";
}

location = /b3multi.php {
include /etc/nginx/fastcgi_params;
root /var/www/html/php;
opentelemetry_operation_name php_fpm_b3multi;
opentelemetry_propagate b3multi;
fastcgi_pass php-backend:9000;
}

location = /b3.php {
include /etc/nginx/fastcgi_params;
root /var/www/html/php;
opentelemetry_operation_name php_fpm_b3;
opentelemetry_propagate b3;
fastcgi_pass php-backend:9000;
}

location ~ \.php$ {
include /etc/nginx/fastcgi_params;
root /var/www/html/php;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,29 +316,79 @@ defmodule InstrumentationTest do
test_parent_span("#{@host}/app.php", ctx)
end

test "HTTP upstream | test b3 injection", %{trace_file: trace_file} do
%HTTPoison.Response{status_code: status} = HTTPoison.get!("#{@host}/b3")
test "HTTP upstream | b3 injection", %{trace_file: trace_file} do
%HTTPoison.Response{status_code: status, body: body} = HTTPoison.get!("#{@host}/b3")

%{"b3" => b3} = Jason.decode!(body)
[trace_id, span_id, _] = String.split(b3, "-")

[trace] = read_traces(trace_file, 1)
[span] = collect_spans(trace)

assert status == 200
assert span["parentSpanId"] == ""
assert span["traceId"] == trace_id
assert span["spanId"] == span_id
assert span["name"] == "test_b3"
end

test "PHP-FPM upstream | test b3 injection", %{trace_file: trace_file} do
%HTTPoison.Response{status_code: status} = HTTPoison.get!("#{@host}/b3")
test "PHP-FPM upstream | b3 propagation", %{trace_file: trace_file} do
input_trace_id = "aad85b4f655feed4d594a01cfa6a1d64"
input_span_id = "2a9d49c3e3b7c461"

%HTTPoison.Response{status_code: status, body: body} =
HTTPoison.get!("#{@host}/b3.php", [
{"b3", "#{input_trace_id}-#{input_span_id}-1"}
])

%{"b3" => b3} = Jason.decode!(body)
[trace_id, span_id, _] = String.split(b3, "-")

assert input_trace_id == trace_id
assert input_span_id != span_id

[trace] = read_traces(trace_file, 1)
[span] = collect_spans(trace)

assert status == 200
assert span["parentSpanId"] == ""
assert span["name"] == "test_b3"
assert span["parentSpanId"] == input_span_id
assert span["traceId"] == input_trace_id
assert span["spanId"] == span_id
assert span["name"] == "php_fpm_b3"
end

test "PHP-FPM upstream | multiheader b3 propagation", %{trace_file: trace_file} do
input_trace_id = "aad85b4f655feed4d594a01cfa6a1d64"
input_span_id = "2a9d49c3e3b7c461"

%HTTPoison.Response{status_code: status, body: body} =
HTTPoison.get!("#{@host}/b3multi.php", [
{"X-B3-TraceId", input_trace_id},
{"X-B3-SpanId", input_span_id},
{"X-B3-Sampled", "1"}
])

%{
"x-b3-traceid" => trace_id,
"x-b3-spanid" => span_id,
"x-b3-sampled" => sampled
} = Jason.decode!(body)

assert sampled == "1"
assert input_trace_id == trace_id
assert input_span_id != span_id

[trace] = read_traces(trace_file, 1)
[span] = collect_spans(trace)

assert status == 200
assert span["parentSpanId"] == input_span_id
assert span["traceId"] == input_trace_id
assert span["spanId"] == span_id
assert span["name"] == "php_fpm_b3multi"
end

test "HTTP upstream | test b3 propagation", %{trace_file: trace_file} do
test "HTTP upstream | b3 propagation", %{trace_file: trace_file} do
parent_span_id = "2a9d49c3e3b7c461"
input_trace_id = "aad85b4f655feed4d594a01cfa6a1d62"

Expand All @@ -361,7 +411,7 @@ defmodule InstrumentationTest do
assert span["name"] == "test_b3"
end

test "HTTP upstream | multiheader b3 propagation", %{trace_file: trace_file} do
test "HTTP upstream | multiheader b3 extraction", %{trace_file: trace_file} do
parent_span_id = "2a9d49c3e3b7c461"
input_trace_id = "aad85b4f655feed4d594a01cfa6a1d62"

Expand All @@ -386,6 +436,34 @@ defmodule InstrumentationTest do
assert span["name"] == "test_b3"
end

test "HTTP upstream | multiheader b3 injection", %{trace_file: trace_file} do
span_id = "2a9d49c3e3b7c462"
trace_id = "aad85b4f655feed4d594a01cfa6a1d63"

%HTTPoison.Response{status_code: status, body: body} =
HTTPoison.get!("#{@host}/b3multi", [
{"b3", "#{trace_id}-#{span_id}-1"}
])

[trace] = read_traces(trace_file, 1)
[span] = collect_spans(trace)

%{
"x-b3-traceid" => header_trace_id,
"x-b3-spanid" => header_span_id,
"x-b3-sampled" => header_sampled
} = Jason.decode!(body)

assert header_trace_id == trace_id
assert header_span_id != span_id
assert header_sampled == "1"

assert status == 200
assert span["parentSpanId"] == span_id
assert span["spanId"] != span_id
assert span["name"] == "test_b3multi"
end

test "Accessing a file produces a span", %{trace_file: trace_file} do
%HTTPoison.Response{status_code: status, body: body} =
HTTPoison.get!("#{@host}/files/content.txt")
Expand Down

0 comments on commit 1cfa98b

Please sign in to comment.