Skip to content

Commit 9cd86b8

Browse files
authored
Merge pull request #6 from spandex-project/inject_context
Add inject_context
2 parents 6998f3e + d693774 commit 9cd86b8

File tree

7 files changed

+89
-21
lines changed

7 files changed

+89
-21
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

77
## [Unreleased]
8-
- No unreleased changes currently.
8+
9+
[NEXT]: https://github.com/spandex-project/spandex_datadog/compare/vNEXT...v0.2.0
10+
11+
### Added
12+
- `SpandexDatadog.Adapter.inject_context/3` added to support the new version of
13+
the `Spandex.Adapter` behaviour.
914

1015
## [0.2.0]
1116

lib/spandex_datadog/adapter.ex

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
defmodule SpandexDatadog.Adapter do
22
@moduledoc """
3-
A datadog APM implementation for spandex.
3+
A Datadog APM implementation for Spandex.
44
"""
55

66
@behaviour Spandex.Adapter
77

88
require Logger
9-
alias Spandex.SpanContext
9+
10+
alias Spandex.{
11+
SpanContext,
12+
Tracer
13+
}
1014

1115
@max_id 9_223_372_036_854_775_807
1216

@@ -26,11 +30,10 @@ defmodule SpandexDatadog.Adapter do
2630
end
2731

2832
@doc """
29-
Fetches the datadog trace & parent IDs from the conn request headers
30-
if they are present.
33+
Fetches the Datadog-specific conn request headers if they are present.
3134
"""
3235
@impl Spandex.Adapter
33-
@spec distributed_context(conn :: Plug.Conn.t(), Keyword.t()) ::
36+
@spec distributed_context(conn :: Plug.Conn.t(), Tracer.opts()) ::
3437
{:ok, SpanContext.t()}
3538
| {:error, :no_distributed_trace}
3639
def distributed_context(%Plug.Conn{} = conn, _opts) do
@@ -45,6 +48,26 @@ defmodule SpandexDatadog.Adapter do
4548
end
4649
end
4750

51+
@doc """
52+
Injects Datadog-specific HTTP headers to represent the specified SpanContext
53+
"""
54+
@impl Spandex.Adapter
55+
@spec inject_context([{term(), term()}], SpanContext.t(), Tracer.opts()) :: [{term(), term()}]
56+
def inject_context(headers, %SpanContext{} = span_context, _opts) when is_list(headers) do
57+
span_context
58+
|> tracing_headers()
59+
|> Kernel.++(headers)
60+
end
61+
62+
def inject_context(headers, %SpanContext{} = span_context, _opts) when is_map(headers) do
63+
span_context
64+
|> tracing_headers()
65+
|> Enum.into(%{})
66+
|> Map.merge(headers)
67+
end
68+
69+
# Private Helpers
70+
4871
@spec get_first_header(Plug.Conn.t(), String.t()) :: integer() | nil
4972
defp get_first_header(conn, header_name) do
5073
conn
@@ -61,4 +84,12 @@ defmodule SpandexDatadog.Adapter do
6184
end
6285

6386
defp parse_header(_header), do: nil
87+
88+
defp tracing_headers(%SpanContext{trace_id: trace_id, parent_id: parent_id, priority: priority}) do
89+
[
90+
{"x-datadog-trace-id", to_string(trace_id)},
91+
{"x-datadog-parent-id", to_string(parent_id)},
92+
{"x-datadog-sampling-priority", to_string(priority)}
93+
]
94+
end
6495
end

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ defmodule SpandexDatadog.MixProject do
4141
defp deps do
4242
[
4343
{:ex_doc, ">= 0.0.0", only: :dev},
44-
{:spandex, "~> 2.2"},
44+
{:spandex, "~> 2.3"},
4545
{:httpoison, "~> 0.13", only: :test},
4646
{:msgpax, "~> 1.1"}
4747
]

mix.lock

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
%{
2-
"certifi": {:hex, :certifi, "2.3.1", "d0f424232390bf47d82da8478022301c561cf6445b5b5fb6a84d49a9e76d2639", [:rebar3], [{:parse_trans, "3.2.0", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
2+
"certifi": {:hex, :certifi, "2.4.2", "75424ff0f3baaccfd34b1214184b6ef616d89e420b258bb0a5ea7d7bc628f7f0", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm"},
33
"earmark": {:hex, :earmark, "1.2.6", "b6da42b3831458d3ecc57314dff3051b080b9b2be88c2e5aa41cd642a5b044ed", [:mix], [], "hexpm"},
44
"ex_doc": {:hex, :ex_doc, "0.19.1", "519bb9c19526ca51d326c060cb1778d4a9056b190086a8c6c115828eaccea6cf", [:mix], [{:earmark, "~> 1.1", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.7", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm"},
5-
"hackney": {:hex, :hackney, "1.13.0", "24edc8cd2b28e1c652593833862435c80661834f6c9344e84b6a2255e7aeef03", [:rebar3], [{:certifi, "2.3.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "5.1.2", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
5+
"hackney": {:hex, :hackney, "1.14.0", "66e29e78feba52176c3a4213d42b29bdc4baff93a18cfe480f73b04677139dee", [:rebar3], [{:certifi, "2.4.2", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "6.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.4", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
66
"httpoison": {:hex, :httpoison, "0.13.0", "bfaf44d9f133a6599886720f3937a7699466d23bb0cd7a88b6ba011f53c6f562", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
7-
"idna": {:hex, :idna, "5.1.2", "e21cb58a09f0228a9e0b95eaa1217f1bcfc31a1aaa6e1fdf2f53a33f7dbd9494", [:rebar3], [{:unicode_util_compat, "0.3.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
8-
"makeup": {:hex, :makeup, "0.5.1", "966c5c2296da272d42f1de178c1d135e432662eca795d6dc12e5e8787514edf7", [:mix], [{:nimble_parsec, "~> 0.2.2", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
9-
"makeup_elixir": {:hex, :makeup_elixir, "0.8.0", "1204a2f5b4f181775a0e456154830524cf2207cf4f9112215c05e0b76e4eca8b", [:mix], [{:makeup, "~> 0.5.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 0.2.2", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
7+
"idna": {:hex, :idna, "6.0.0", "689c46cbcdf3524c44d5f3dde8001f364cd7608a99556d8fbd8239a5798d4c10", [:rebar3], [{:unicode_util_compat, "0.4.1", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm"},
8+
"makeup": {:hex, :makeup, "0.5.5", "9e08dfc45280c5684d771ad58159f718a7b5788596099bdfb0284597d368a882", [:mix], [{:nimble_parsec, "~> 0.4", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"},
9+
"makeup_elixir": {:hex, :makeup_elixir, "0.8.2", "ecc130aaf3645d142f50ccd4c727f714afdb490062dcaf009f4c2d86332d1beb", [:mix], [{:makeup, "~> 0.5.5", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"},
1010
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm"},
1111
"mime": {:hex, :mime, "1.3.0", "5e8d45a39e95c650900d03f897fbf99ae04f60ab1daa4a34c7a20a5151b7a5fe", [:mix], [], "hexpm"},
1212
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], [], "hexpm"},
1313
"msgpax": {:hex, :msgpax, "1.1.0", "e31625e256db2decca1ae2b841f21b4d2483b1332649ce3ebc96c7ff7a4986e3", [:mix], [{:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm"},
14-
"nimble_parsec": {:hex, :nimble_parsec, "0.2.2", "d526b23bdceb04c7ad15b33c57c4526bf5f50aaa70c7c141b4b4624555c68259", [:mix], [], "hexpm"},
14+
"nimble_parsec": {:hex, :nimble_parsec, "0.4.0", "ee261bb53214943679422be70f1658fff573c5d0b0a1ecd0f18738944f818efe", [:mix], [], "hexpm"},
1515
"optimal": {:hex, :optimal, "0.3.6", "46bbf52fbbbd238cda81e02560caa84f93a53c75620f1fe19e81e4ae7b07d1dd", [:mix], [], "hexpm"},
16-
"parse_trans": {:hex, :parse_trans, "3.2.0", "2adfa4daf80c14dc36f522cf190eb5c4ee3e28008fc6394397c16f62a26258c2", [:rebar3], [], "hexpm"},
17-
"plug": {:hex, :plug, "1.6.2", "e06a7bd2bb6de5145da0dd950070110dce88045351224bd98e84edfdaaf5ffee", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm"},
18-
"spandex": {:hex, :spandex, "2.2.0", "0d60e2a232074ebf6e299edcd3ee540df87541246ba5f5bd84c68a9bb00171bc", [:mix], [{:optimal, "~> 0.3.3", [hex: :optimal, repo: "hexpm", optional: false]}, {:plug, ">= 1.0.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
19-
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], [], "hexpm"},
20-
"unicode_util_compat": {:hex, :unicode_util_compat, "0.3.1", "a1f612a7b512638634a603c8f401892afbf99b8ce93a45041f8aaca99cadb85e", [:rebar3], [], "hexpm"},
16+
"parse_trans": {:hex, :parse_trans, "3.3.0", "09765507a3c7590a784615cfd421d101aec25098d50b89d7aa1d66646bc571c1", [:rebar3], [], "hexpm"},
17+
"plug": {:hex, :plug, "1.6.3", "43088304337b9e8b8bd22a0383ca2f633519697e4c11889285538148f42cbc5e", [:mix], [{:cowboy, "~> 1.0.1 or ~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}], "hexpm"},
18+
"spandex": {:hex, :spandex, "2.3.0", "fcf214e57b601456369e9028482ccdb7c64ee1ed84cf89d5cc63fd83d46f2dec", [:mix], [{:optimal, "~> 0.3.3", [hex: :optimal, repo: "hexpm", optional: false]}, {:plug, ">= 1.0.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm"},
19+
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.4", "f0eafff810d2041e93f915ef59899c923f4568f4585904d010387ed74988e77b", [:make, :mix, :rebar3], [], "hexpm"},
20+
"unicode_util_compat": {:hex, :unicode_util_compat, "0.4.1", "d869e4c68901dd9531385bb0c8c40444ebf624e60b6962d95952775cac5e90cd", [:rebar3], [], "hexpm"},
2121
}

test/support/adapter_test.exs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,36 @@ defmodule Spandex.Test.Datadog.AdapterTest do
105105
assert {:error, :no_distributed_trace} = Adapter.distributed_context(conn, [])
106106
end
107107
end
108+
109+
describe "inject_context/3" do
110+
test "Prepends distributed tracing headers to an existing list of headers" do
111+
span_context = %SpanContext{trace_id: 123, parent_id: 456, priority: 10}
112+
headers = [{"header1", "value1"}, {"header2", "value2"}]
113+
114+
result = Adapter.inject_context(headers, span_context, [])
115+
116+
assert result == [
117+
{"x-datadog-trace-id", "123"},
118+
{"x-datadog-parent-id", "456"},
119+
{"x-datadog-sampling-priority", "10"},
120+
{"header1", "value1"},
121+
{"header2", "value2"}
122+
]
123+
end
124+
125+
test "Merges distributed tracing headers with an existing map of headers" do
126+
span_context = %SpanContext{trace_id: 123, parent_id: 456, priority: 10}
127+
headers = %{"header1" => "value1", "header2" => "value2"}
128+
129+
result = Adapter.inject_context(headers, span_context, [])
130+
131+
assert result == %{
132+
"x-datadog-trace-id" => "123",
133+
"x-datadog-parent-id" => "456",
134+
"x-datadog-sampling-priority" => "10",
135+
"header1" => "value1",
136+
"header2" => "value2"
137+
}
138+
end
139+
end
108140
end

test/support/api_server_test.exs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ defmodule SpandexDatadog.ApiServerTest do
2929
trace_id = 4_743_028_846_331_200_905
3030

3131
{:ok, span_1} =
32-
Spandex.Span.new(
32+
Span.new(
3333
id: 4_743_028_846_331_200_906,
3434
start: 1_527_752_052_216_478_000,
3535
service: :foo,
@@ -40,7 +40,7 @@ defmodule SpandexDatadog.ApiServerTest do
4040
)
4141

4242
{:ok, span_2} =
43-
Spandex.Span.new(
43+
Span.new(
4444
id: 4_743_029_846_331_200_906,
4545
start: 1_527_752_052_216_578_001,
4646
completion_time: 1_527_752_052_316_578_001,

test/support/datadog_test_api_server.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ defmodule Spandex.Test.DatadogTestApiServer do
33
Simply sends the data that would have been sent to datadog to self() as a message
44
so that the test can assert on payloads that would have been sent to datadog
55
"""
6-
def send_trace(trace, opts \\ []) do
6+
def send_trace(trace, _opts \\ []) do
77
formatted = SpandexDatadog.ApiServer.format(trace)
88
send(self(), {:sent_datadog_spans, formatted})
99
end

0 commit comments

Comments
 (0)