diff --git a/config/test.exs b/config/test.exs index 785d1c1..0df168b 100644 --- a/config/test.exs +++ b/config/test.exs @@ -1,8 +1,5 @@ import Config config :opentelemetry, - sampler: {:always_on, %{}}, - tracer: :otel_tracer_default, - processors: [ - otel_batch_processor: %{scheduled_delay_ms: 1, exporter: :undefined} - ] + span_processor: :batch, + traces_exporter: {:otel_exporter_stdout, []} diff --git a/lib/opentelemetry_plug.ex b/lib/opentelemetry_plug.ex index dd85cde..6bc1188 100644 --- a/lib/opentelemetry_plug.ex +++ b/lib/opentelemetry_plug.ex @@ -29,7 +29,7 @@ defmodule OpentelemetryPlug do @impl true def call(conn, _opts) do - register_before_send(conn, &merge_resp_headers(&1, :otel_propagator.text_map_inject([]))) + register_before_send(conn, &merge_resp_headers(&1, :otel_propagator_text_map.inject([]))) end end @@ -43,9 +43,6 @@ defmodule OpentelemetryPlug do """ def setup() do - # register the tracer. just re-registers if called for multiple repos - _ = OpenTelemetry.register_application_tracer(:opentelemetry_plug) - :telemetry.attach( {__MODULE__, :plug_router_start}, [:plug, :router_dispatch, :start], @@ -68,11 +65,24 @@ defmodule OpentelemetryPlug do ) end + @spec handle_start( + any, + any, + %{:conn => Plug.Conn.t(), :route => any, optional(any) => any}, + any + ) :: + :undefined + | {:span_ctx, non_neg_integer, non_neg_integer, integer, + [ + {binary | maybe_improper_list(any, binary | []), + binary | maybe_improper_list(any, binary | [])} + ], false | true | :undefined, boolean, false | true | :undefined, + :undefined | {atom, any}} @doc false def handle_start(_, _measurements, %{conn: conn, route: route}, _config) do save_parent_ctx() # setup OpenTelemetry context based on request headers - :otel_propagator.text_map_extract(conn.req_headers) + :otel_propagator_text_map.extract(conn.req_headers) span_name = "#{route}" diff --git a/mix.exs b/mix.exs index 36f7034..2b093c0 100644 --- a/mix.exs +++ b/mix.exs @@ -22,11 +22,11 @@ defmodule OpentelemetryPlug.MixProject do defp deps do [ {:hackney, "~> 1.0", only: :test, runtime: false}, - {:opentelemetry_api, "~> 1.0.0-rc"}, - {:opentelemetry, "~> 1.0.0-rc", only: :test}, - {:plug, ">= 1.10.1"}, - {:plug_cowboy, "~> 2.2", only: :test, runtime: false}, - {:telemetry, "~> 0.4"} + {:opentelemetry_api, "~> 1.0"}, + {:opentelemetry, "~> 1.0", only: :test}, + {:plug, "~> 1.14"}, + {:plug_cowboy, "~> 2.6", only: :test, runtime: false}, + {:telemetry, "~> 1.0"} ] end end diff --git a/mix.lock b/mix.lock index b4769c7..56cc74a 100644 --- a/mix.lock +++ b/mix.lock @@ -1,21 +1,22 @@ %{ - "certifi": {:hex, :certifi, "2.6.1", "dbab8e5e155a0763eea978c913ca280a6b544bfa115633fa20249c3d396d9493", [:rebar3], [], "hexpm", "524c97b4991b3849dd5c17a631223896272c6b0af446778ba4675a1dff53bb7e"}, + "certifi": {:hex, :certifi, "2.9.0", "6f2a475689dd47f19fb74334859d460a2dc4e3252a3324bd2111b8f0429e7e21", [:rebar3], [], "hexpm", "266da46bdb06d6c6d35fde799bcb28d36d985d424ad7c08b5bb48f5b5cdd4641"}, "cowboy": {:hex, :cowboy, "2.9.0", "865dd8b6607e14cf03282e10e934023a1bd8be6f6bacf921a7e2a96d800cd452", [:make, :rebar3], [{:cowlib, "2.11.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "2c729f934b4e1aa149aff882f57c6372c15399a20d54f65c8d67bef583021bde"}, - "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.3.1", "ebd1a1d7aff97f27c66654e78ece187abdc646992714164380d8a041eda16754", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a6efd3366130eab84ca372cbd4a7d3c3a97bdfcfb4911233b035d117063f0af"}, + "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, "cowlib": {:hex, :cowlib, "2.11.0", "0b9ff9c346629256c42ebe1eeb769a83c6cb771a6ee5960bd110ab0b9b872063", [:make, :rebar3], [], "hexpm", "2b3e9da0b21c4565751a6d4901c20d1b4cc25cbb7fd50d91d2ab6dd287bc86a9"}, - "hackney": {:hex, :hackney, "1.17.4", "99da4674592504d3fb0cfef0db84c3ba02b4508bae2dff8c0108baa0d6e0977c", [:rebar3], [{:certifi, "~>2.6.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "de16ff4996556c8548d512f4dbe22dd58a587bf3332e7fd362430a7ef3986b16"}, + "hackney": {:hex, :hackney, "1.18.1", "f48bf88f521f2a229fc7bae88cf4f85adc9cd9bcf23b5dc8eb6a1788c662c4f6", [:rebar3], [{:certifi, "~>2.9.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "a4ecdaff44297e9b5894ae499e9a070ea1888c84afdd1fd9b7b2bc384950128e"}, "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"}, - "mime": {:hex, :mime, "1.6.0", "dabde576a497cef4bbdd60aceee8160e02a6c89250d6c0b29e56c0dfb00db3d2", [:mix], [], "hexpm", "31a1a8613f8321143dde1dafc36006a17d28d02bdfecb9e95a880fa7aabd19a7"}, + "mime": {:hex, :mime, "2.0.3", "3676436d3d1f7b81b5a2d2bd8405f412c677558c81b1c92be58c00562bb59095", [:mix], [], "hexpm", "27a30bf0db44d25eecba73755acf4068cbfe26a4372f9eb3e4ea3a45956bff6b"}, "mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"}, - "opentelemetry": {:hex, :opentelemetry, "1.0.0-rc.2", "d3e1fd9debfd73e00b0241cac464be7cd6ca6ac2bd38ab2ebe0c92401c76a342", [:rebar3], [{:opentelemetry_api, "~> 1.0.0-rc.2", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}], "hexpm", "2f810e2eed70a9ea0c9b6943969b59e37f96a2f9e10920045a6c7676c2ab8181"}, - "opentelemetry_api": {:hex, :opentelemetry_api, "1.0.0-rc.2", "a0ec5b242bb7ce7563b4891e77dcfa529defc9e42c19a5a702574c5ac3d0c6e7", [:mix, :rebar3], [], "hexpm", "426a969c8ee2afa8ab55b58e6e40e81c1f934c064459a1acb530f54042f9a9a3"}, + "opentelemetry": {:hex, :opentelemetry, "1.2.1", "6b374a0b4ebbd206d0c7c13ea34a8b46c63bfefa86d813ed07613876f1811575", [: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", "9a627f3bffcb972d404590ef686309863d0fe09ddf1a4612430b99d781ecf940"}, + "opentelemetry_api": {:hex, :opentelemetry_api, "1.2.0", "454a35655b4c1924405ef1f3587f2c6f141bf73366b2c5e8a38dcc619b53eaa0", [:mix, :rebar3], [], "hexpm", "9e677c68243de0f70538798072e66e1fb1d4a2ca8888a6eb493c0a41e5480c35"}, + "opentelemetry_semantic_conventions": {:hex, :opentelemetry_semantic_conventions, "0.2.0", "b67fe459c2938fcab341cb0951c44860c62347c005ace1b50f8402576f241435", [:mix, :rebar3], [], "hexpm", "d61fa1f5639ee8668d74b527e6806e0503efc55a42db7b5f39939d84c07d6895"}, "parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"}, - "plug": {:hex, :plug, "1.10.1", "c56a6d9da7042d581159bcbaef873ba9d87f15dce85420b0d287bca19f40f9bd", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "b5cd52259817eb8a31f2454912ba1cff4990bca7811918878091cb2ab9e52cb8"}, - "plug_cowboy": {:hex, :plug_cowboy, "2.5.0", "51c998f788c4e68fc9f947a5eba8c215fbb1d63a520f7604134cab0270ea6513", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5b2c8925a5e2587446f33810a58c01e66b3c345652eeec809b76ba007acde71a"}, - "plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"}, + "plug": {:hex, :plug, "1.14.0", "ba4f558468f69cbd9f6b356d25443d0b796fbdc887e03fa89001384a9cac638f", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "bf020432c7d4feb7b3af16a0c2701455cbbbb95e5b6866132cb09eb0c29adc14"}, + "plug_cowboy": {:hex, :plug_cowboy, "2.6.0", "d1cf12ff96a1ca4f52207c5271a6c351a4733f413803488d75b70ccf44aebec2", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "073cf20b753ce6682ed72905cd62a2d4bd9bad1bf9f7feb02a1b8e525bd94fa6"}, + "plug_crypto": {:hex, :plug_crypto, "1.2.3", "8f77d13aeb32bfd9e654cb68f0af517b371fb34c56c9f2b58fe3df1235c1251a", [:mix], [], "hexpm", "b5672099c6ad5c202c45f5a403f21a3411247f164e4a8fab056e5cd8a290f4a2"}, "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"}, - "telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"}, + "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, } diff --git a/test/opentelemetry_plug_test.exs b/test/opentelemetry_plug_test.exs index af21579..8055895 100644 --- a/test/opentelemetry_plug_test.exs +++ b/test/opentelemetry_plug_test.exs @@ -2,15 +2,15 @@ defmodule OpentelemetryPlugTest do use ExUnit.Case, async: false require Record - Record.defrecord(:span, Record.extract(:span, from_lib: "opentelemetry/include/otel_span.hrl")) - - for r <- [:event, :status] do + for r <- [:span, :event] do Record.defrecord( r, - Record.extract(r, from_lib: "opentelemetry_api/include/opentelemetry.hrl") + Record.extract(r, from_lib: "opentelemetry/include/otel_span.hrl") ) end + Record.defrecord(:status, Record.extract(:status, from_lib: "opentelemetry_api/include/opentelemetry.hrl")) + setup_all do OpentelemetryPlug.setup() @@ -46,9 +46,10 @@ defmodule OpentelemetryPlugTest do assert List.keymember?(headers, "traceparent", 0) assert_receive {:span, span(name: "/hello/:foo", attributes: attrs)}, 5000 + attrs_map = elem(attrs, 4) for attr <- @default_attrs do - assert List.keymember?(attrs, attr, 0) + assert Map.has_key?(attrs_map, attr) end end @@ -59,28 +60,32 @@ defmodule OpentelemetryPlugTest do request(:get, "/hello/world", [{"x-forwarded-for", "1.1.1.1"}]) assert_receive {:span, span(attributes: attrs)}, 5000 + attrs_map = elem(attrs, 4) - assert List.keymember?(attrs, :"http.client_ip", 0) - assert List.keymember?(attrs, :"http.server_name", 0) + assert Map.has_key?(attrs_map, :"http.client_ip") + assert Map.has_key?(attrs_map, :"http.server_name") end test "records exceptions" do assert {500, _, _} = request(:get, "/hello/crash") assert_receive {:span, span(attributes: attrs, status: span_status, events: events)}, 5000 - assert {:"http.status_code", 500} = List.keyfind(attrs, :"http.status_code", 0) + assert 500 = Map.get(elem(attrs, 4), :"http.status_code") assert status(code: :error, message: _) = span_status - assert [event(name: "exception", attributes: evt_attrs)] = events + event_extracted = List.first(elem(events, 5)) + assert event(name: "exception", attributes: evt_attrs) = event_extracted + + evt_attrs_map = elem(evt_attrs, 4) for key <- ~w(exception.type exception.message exception.stacktrace) do - assert List.keymember?(evt_attrs, key, 0) + assert Map.has_key?(evt_attrs_map, key) end end test "sets span status on non-successful status codes" do assert {400, _, _} = request(:get, "/hello/bad-request") assert_receive {:span, span(attributes: attrs, status: span_status)}, 5000 - assert {:"http.status_code", 400} = List.keyfind(attrs, :"http.status_code", 0) + assert 400 = Map.get(elem(attrs, 4), :"http.status_code") assert status(code: :error, message: _) = span_status end