From e1f4a02d5eaebfb7c00020398dbebc37618e7aee Mon Sep 17 00:00:00 2001 From: Wojtek Mach Date: Mon, 16 Oct 2023 22:40:01 +0200 Subject: [PATCH] opentelemetry_req: Don't assume `request.headers` shape (#193) * opentelemetry_req: Don't assume `request.headers` shape * Update instrumentation/opentelemetry_req/test/opentelemetry_req_test.exs --------- Co-authored-by: Bryan Naegele --- .../lib/opentelemetry_req.ex | 7 ++- instrumentation/opentelemetry_req/mix.exs | 3 +- instrumentation/opentelemetry_req/mix.lock | 1 + .../test/opentelemetry_req_test.exs | 62 ++++++++++++++++++- 4 files changed, 70 insertions(+), 3 deletions(-) diff --git a/instrumentation/opentelemetry_req/lib/opentelemetry_req.ex b/instrumentation/opentelemetry_req/lib/opentelemetry_req.ex index 69a0d36..c761cff 100644 --- a/instrumentation/opentelemetry_req/lib/opentelemetry_req.ex +++ b/instrumentation/opentelemetry_req/lib/opentelemetry_req.ex @@ -202,7 +202,12 @@ defmodule OpentelemetryReq do defp maybe_put_trace_headers(request) do if request.options[:propagate_trace_ctx] do - Map.put(request, :headers, :otel_propagator_text_map.inject(request.headers)) + propagator = :opentelemetry.get_text_map_injector() + headers_to_inject = :otel_propagator_text_map.inject(propagator, [], &[{&1, &2} | &3]) + + Enum.reduce(headers_to_inject, request, fn {name, value}, acc -> + Req.Request.put_header(acc, name, value) + end) else request end diff --git a/instrumentation/opentelemetry_req/mix.exs b/instrumentation/opentelemetry_req/mix.exs index 06665a4..8a2113b 100644 --- a/instrumentation/opentelemetry_req/mix.exs +++ b/instrumentation/opentelemetry_req/mix.exs @@ -60,7 +60,8 @@ defmodule OpentelemetryReq.MixProject do {:opentelemetry_api, "~> 1.0"}, {:opentelemetry_semantic_conventions, "~> 0.2"}, {:req, ">= 0.3.5"}, - {:ex_doc, "~> 0.29", only: [:dev, :test]} + {:ex_doc, "~> 0.29", only: [:dev, :test]}, + {:opentelemetry, "~> 1.0", only: :test} ] end end diff --git a/instrumentation/opentelemetry_req/mix.lock b/instrumentation/opentelemetry_req/mix.lock index 87c69d2..97d1bf0 100644 --- a/instrumentation/opentelemetry_req/mix.lock +++ b/instrumentation/opentelemetry_req/mix.lock @@ -13,6 +13,7 @@ "nimble_options": {:hex, :nimble_options, "0.5.2", "42703307b924880f8c08d97719da7472673391905f528259915782bb346e0a1b", [:mix], [], "hexpm", "4da7f904b915fd71db549bcdc25f8d56f378ef7ae07dc1d372cbe72ba950dce0"}, "nimble_parsec": {:hex, :nimble_parsec, "1.2.3", "244836e6e3f1200c7f30cb56733fd808744eca61fd182f731eac4af635cc6d0b", [:mix], [], "hexpm", "c8d789e39b9131acf7b99291e93dae60ab48ef14a7ee9d58c6964f59efb570b0"}, "nimble_pool": {:hex, :nimble_pool, "0.2.6", "91f2f4c357da4c4a0a548286c84a3a28004f68f05609b4534526871a22053cde", [:mix], [], "hexpm", "1c715055095d3f2705c4e236c18b618420a35490da94149ff8b580a2144f653f"}, + "opentelemetry": {:hex, :opentelemetry, "1.3.0", "988ac3c26acac9720a1d4fb8d9dc52e95b45ecfec2d5b5583276a09e8936bc5e", [:rebar3], [{:opentelemetry_api, "~> 1.2.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}, {:opentelemetry_semantic_conventions, "~> 0.2", [hex: :opentelemetry_semantic_conventions, repo: "hexpm", optional: false]}], "hexpm", "8e09edc26aad11161509d7ecad854a3285d88580f93b63b0b1cf0bac332bfcc0"}, "opentelemetry_api": {:hex, :opentelemetry_api, "1.2.1", "7b69ed4f40025c005de0b74fce8c0549625d59cb4df12d15c32fe6dc5076ff42", [:mix, :rebar3], [{:opentelemetry_semantic_conventions, "~> 0.2", [hex: :opentelemetry_semantic_conventions, repo: "hexpm", optional: false]}], "hexpm", "6d7a27b7cad2ad69a09cabf6670514cafcec717c8441beb5c96322bac3d05350"}, "opentelemetry_semantic_conventions": {:hex, :opentelemetry_semantic_conventions, "0.2.0", "b67fe459c2938fcab341cb0951c44860c62347c005ace1b50f8402576f241435", [:mix, :rebar3], [], "hexpm", "d61fa1f5639ee8668d74b527e6806e0503efc55a42db7b5f39939d84c07d6895"}, "req": {:hex, :req, "0.3.6", "541350d2cc359a8ad17059f2629c18be56d0c85ce0e4ddb27694b6ba482fe923", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.9", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "9181047f32b05f8737f6b5917af5ee5385219158bbe4e507f4ec57791a0a78c3"}, diff --git a/instrumentation/opentelemetry_req/test/opentelemetry_req_test.exs b/instrumentation/opentelemetry_req/test/opentelemetry_req_test.exs index e44c5a5..0ba8b0e 100644 --- a/instrumentation/opentelemetry_req/test/opentelemetry_req_test.exs +++ b/instrumentation/opentelemetry_req/test/opentelemetry_req_test.exs @@ -1,4 +1,64 @@ defmodule OpentelemetryReqTest do - use ExUnit.Case + use ExUnit.Case, async: true doctest OpentelemetryReq + require Record + + for {name, spec} <- Record.extract_all(from_lib: "opentelemetry/include/otel_span.hrl") do + Record.defrecordp(name, spec) + end + + setup do + :application.stop(:opentelemetry) + :application.set_env(:opentelemetry, :tracer, :otel_tracer_default) + + :application.set_env(:opentelemetry, :processors, [ + {:otel_batch_processor, %{scheduled_delay_ms: 1, exporter: {:otel_exporter_pid, self()}}} + ]) + + :application.start(:opentelemetry) + + req = + Req.new() + |> OpentelemetryReq.attach() + + {:ok, req: req} + end + + test "span", %{req: req} do + adapter = fn request -> + assert URI.to_string(request.url) == "/users/3" + {request, Req.Response.new(status: 204)} + end + + resp = + Req.get!(req, + adapter: adapter, + url: "/users/:id", + path_params: [id: 3] + ) + + assert resp.status == 204 + assert_receive {:span, span(name: "/users/:id")} + refute_receive _ + end + + test "propagate traces", %{req: req} do + adapter = fn request -> + assert [value] = Req.Request.get_header(request, "traceparent") + assert byte_size(value) > 10 + {request, Req.Response.new(status: 204)} + end + + resp = + Req.get!(req, + adapter: adapter, + url: "/", + no_path_params: true, + propagate_trace_ctx: true + ) + + assert resp.status == 204 + assert_receive {:span, span()} + refute_receive _ + end end