opentelemetry-erlang-contrib/instrumentation/opentelemetry_bandit/test/bandit/opentelemetry_bandit_test.exs

246 lines
7.1 KiB
Elixir
Raw Normal View History

defmodule OpentelemetryBanditTest do
use ExUnit.Case, async: true
require OpenTelemetry.Tracer
require OpenTelemetry.Span
require Record
use ServerHelper
for {name, spec} <- Record.extract_all(from_lib: "opentelemetry/include/otel_span.hrl") do
Record.defrecord(name, spec)
end
describe "http integration" do
test "default span generation for 200" do
Req.get("http://localhost:4000/hello")
assert_receive {:span,
span(
name: "HTTP GET /hello",
kind: :server,
status: {:status, :ok, _},
attributes: attributes
)}
assert %{
"net.peer.name": "localhost",
"http.method": "GET",
"http.target": "/hello",
"http.scheme": :http,
"http.status_code": 200
} = :otel_attributes.map(attributes)
end
test "default span generation for 200 without user-agent" do
{:ok, {{_, 200, _}, _, _}} =
:httpc.request(:get, {~c"http://localhost:4000/hello", []}, [], [])
assert_receive {:span,
span(
name: "HTTP GET /hello",
kind: :server,
status: {:status, :ok, _},
attributes: attributes
)}
assert %{
"net.peer.name": "localhost",
"http.method": "GET",
"http.target": "/hello",
"http.scheme": :http,
"http.status_code": 200,
"http.client_ip": "127.0.0.1"
} = :otel_attributes.map(attributes)
end
test "default span generation for 200 with x-forwarded-for" do
Req.get("http://localhost:4000/hello", headers: %{x_forwarded_for: "127.0.0.1"})
assert_receive {:span,
span(
name: "HTTP GET /hello",
kind: :server,
status: {:status, :ok, _},
attributes: attributes
)}
assert %{
"net.peer.name": "localhost",
"http.method": "GET",
"http.target": "/hello",
"http.scheme": :http,
"http.status_code": 200,
"http.client_ip": "127.0.0.1"
} = :otel_attributes.map(attributes)
end
test "default span generation for halted connection" do
Req.get("http://localhost:4000/fail", retry: false)
assert_receive {:span,
span(
name: "HTTP GET /fail",
kind: :server,
status: {:status, :ok, _},
attributes: attributes
)}
assert %{
"net.peer.name": "localhost",
"http.method": "GET",
"http.target": "/fail",
"http.scheme": :http,
"http.status_code": 500
} = :otel_attributes.map(attributes)
end
test "default span generation for 500 response" do
:telemetry.execute(
[:bandit, :request, :stop],
%{duration: 444, resp_body_bytes: 10},
%{
conn: nil,
status: 500,
error: "Internal Server Error",
method: "GET",
request_target: {nil, nil, nil, "/not_existing_route"}
}
)
assert_receive {:span,
span(
name: "HTTP GET /not_existing_route",
kind: :error,
status: {:status, :error, "Internal Server Error"},
attributes: attributes
)}
assert %{
"http.url": _,
"http.method": "GET",
"http.status_code": 500,
"http.response_content_length": 10,
"net.transport": :"IP.TCP"
} = :otel_attributes.map(attributes)
end
test "span when request_target is empty" do
:telemetry.execute(
[:bandit, :request, :stop],
%{duration: 444, resp_body_bytes: 10},
%{
conn: nil,
status: 500,
error: "Internal Server Error",
method: "GET",
request_target: nil
}
)
assert_receive {:span,
span(
name: "HTTP GET",
kind: :error,
status: {:status, :error, "Internal Server Error"},
attributes: attributes
)}
assert %{
"http.url": _,
"http.method": "GET",
"http.status_code": 500,
"http.response_content_length": 10,
"net.transport": :"IP.TCP"
} = :otel_attributes.map(attributes)
end
test "exception catch span" do
Req.get("http://localhost:4000/exception", retry: false)
assert_receive {:span,
span(
name: "HTTP exception RuntimeError",
kind: :error,
status: {:status, :error, _}
)}
end
end
describe "websocket integration" do
test "span when request finished successfully" do
:telemetry.execute(
[:bandit, :websocket, :stop],
%{
duration: 444,
send_binary_frame_bytes: 10,
recv_binary_frame_bytes: 15
},
%{}
)
assert_receive {:span,
span(
name: "Websocket",
kind: :server,
status: {:status, :ok, _},
attributes: attributes
)}
assert %{
"net.transport": :websocket,
"websocket.recv.binary.frame.bytes": 10,
"websocket.send.binary.frame.bytes": 15
} = :otel_attributes.map(attributes)
end
test "span when error is set" do
:telemetry.execute(
[:bandit, :websocket, :stop],
%{
duration: 444,
send_binary_frame_bytes: 10,
recv_binary_frame_bytes: 15
},
%{error: "Internal Server Error"}
)
assert_receive {:span,
span(
name: "Websocket",
kind: :error,
status: {:status, :error, _},
attributes: attributes
)}
assert %{
"net.transport": :websocket,
"websocket.recv.binary.frame.bytes": 10,
"websocket.send.binary.frame.bytes": 15
} = :otel_attributes.map(attributes)
end
end
setup do
:otel_simple_processor.set_exporter(:otel_exporter_pid, self())
{:ok, _} = start_supervised({Bandit, plug: __MODULE__, port: 4000, startup_log: false})
OpentelemetryBandit.setup()
:ok
end
def hello(conn) do
conn |> send_resp(200, "OK")
end
def fail(conn) do
conn |> send_resp(500, "Internal Server Error") |> halt()
end
def exception(_conn) do
raise "boom"
end
end