Skip to content

Commit 04a94e6

Browse files
authored
Merge pull request #568 from carrascoacd/acc/add-context-propagation
OTel - Add context propagation
2 parents 958f856 + 077bfd3 commit 04a94e6

File tree

4 files changed

+72
-13
lines changed

4 files changed

+72
-13
lines changed

lib/tesla/middleware/timeout.ex

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,30 @@ defmodule Tesla.Middleware.Timeout do
44
55
## Examples
66
7-
```
8-
defmodule MyClient do
9-
use Tesla
7+
defmodule MyClient do
8+
use Tesla
109
11-
plug Tesla.Middleware.Timeout, timeout: 2_000
12-
end
13-
```
10+
plug Tesla.Middleware.Timeout, timeout: 2_000
11+
end
12+
13+
If you are using OpenTelemetry in your project, you may be interested in
14+
using `OpentelemetryProcessPropagator.Task` to have a better integration using
15+
the `task_module` option.
16+
17+
defmodule MyClient do
18+
use Tesla
19+
20+
plug Tesla.Middleware.Timeout,
21+
timeout: 2_000,
22+
task_module: OpentelemetryProcessPropagator.Task
23+
end
1424
1525
## Options
1626
1727
- `:timeout` - number of milliseconds a request is allowed to take (defaults to `1000`)
28+
- `:task_module` - the `Task` module used to spawn tasks. Useful when you want
29+
use alternatives such as `OpentelemetryProcessPropagator.Task` from OTEL
30+
project.
1831
"""
1932

2033
@behaviour Tesla.Middleware
@@ -25,22 +38,23 @@ defmodule Tesla.Middleware.Timeout do
2538
def call(env, next, opts) do
2639
opts = opts || []
2740
timeout = Keyword.get(opts, :timeout, @default_timeout)
41+
task_module = Keyword.get(opts, :task_module, Task)
2842

29-
task = safe_async(fn -> Tesla.run(env, next) end)
43+
task = safe_async(task_module, fn -> Tesla.run(env, next) end)
3044

3145
try do
3246
task
33-
|> Task.await(timeout)
47+
|> task_module.await(timeout)
3448
|> repass_error
3549
catch
3650
:exit, {:timeout, _} ->
37-
Task.shutdown(task, 0)
51+
task_module.shutdown(task, 0)
3852
{:error, :timeout}
3953
end
4054
end
4155

42-
defp safe_async(func) do
43-
Task.async(fn ->
56+
defp safe_async(task_module, func) do
57+
task_module.async(fn ->
4458
try do
4559
{:ok, func.()}
4660
rescue

mix.exs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ defmodule Tesla.Mixfile do
22
use Mix.Project
33

44
@source_url "https://github.com/teamon/tesla"
5-
@version "1.5.1"
5+
@version "1.6.0"
66

77
def project do
88
[
@@ -75,6 +75,7 @@ defmodule Tesla.Mixfile do
7575
{:telemetry, "~> 0.4 or ~> 1.0", optional: true},
7676

7777
# testing & docs
78+
{:opentelemetry_process_propagator, "~> 0.1", only: [:test, :dev]},
7879
{:excoveralls, "~> 0.8", only: :test},
7980
{:httparrot, "~> 1.3", only: :test},
8081
{:ex_doc, "~> 0.21", only: :dev, runtime: false},

mix.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
"nimble_options": {:hex, :nimble_options, "0.4.0", "c89babbab52221a24b8d1ff9e7d838be70f0d871be823165c94dd3418eea728f", [:mix], [], "hexpm", "e6701c1af326a11eea9634a3b1c62b475339ace9456c1a23ec3bc9a847bca02d"},
3737
"nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"},
3838
"nimble_pool": {:hex, :nimble_pool, "0.2.6", "91f2f4c357da4c4a0a548286c84a3a28004f68f05609b4534526871a22053cde", [:mix], [], "hexpm", "1c715055095d3f2705c4e236c18b618420a35490da94149ff8b580a2144f653f"},
39+
"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"},
40+
"opentelemetry_process_propagator": {:hex, :opentelemetry_process_propagator, "0.2.2", "85244a49f0c32ae1e2f3d58c477c265bd6125ee3480ade82b0fa9324b85ed3f0", [:mix, :rebar3], [{:opentelemetry_api, "~> 1.0", [hex: :opentelemetry_api, repo: "hexpm", optional: false]}], "hexpm", "04db13302a34bea8350a13ed9d49c22dfd32c4bc590d8aa88b6b4b7e4f346c61"},
41+
"opentelemetry_semantic_conventions": {:hex, :opentelemetry_semantic_conventions, "0.2.0", "b67fe459c2938fcab341cb0951c44860c62347c005ace1b50f8402576f241435", [:mix, :rebar3], [], "hexpm", "d61fa1f5639ee8668d74b527e6806e0503efc55a42db7b5f39939d84c07d6895"},
3942
"parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"},
4043
"poison": {:hex, :poison, "5.0.0", "d2b54589ab4157bbb82ec2050757779bfed724463a544b6e20d79855a9e43b24", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "11dc6117c501b80c62a7594f941d043982a1bd05a1184280c0d9166eb4d8d3fc"},
4144
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},

test/tesla/middleware/timeout_test.exs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,26 @@ defmodule Tesla.Middleware.TimeoutTest do
4949
end
5050
end
5151

52+
defmodule OtelTimeoutClient do
53+
use Tesla
54+
55+
plug Tesla.Middleware.Timeout,
56+
timeout: 100,
57+
task_module: OpentelemetryProcessPropagator.Task
58+
59+
adapter fn env ->
60+
case env.url do
61+
"/sleep_50ms" ->
62+
Process.sleep(50)
63+
{:ok, %{env | status: 200}}
64+
65+
"/sleep_150ms" ->
66+
Process.sleep(150)
67+
{:ok, %{env | status: 200}}
68+
end
69+
end
70+
end
71+
5272
describe "using custom timeout (100ms)" do
5373
test "should return timeout error when the stack timeout" do
5474
assert {:error, :timeout} = Client.get("/sleep_150ms")
@@ -111,7 +131,7 @@ defmodule Tesla.Middleware.TimeoutTest do
111131
[_, {timeout_module, _, _, module_file_info} | _] = __STACKTRACE__
112132

113133
assert Tesla.Middleware.Timeout == timeout_module
114-
assert module_file_info == [file: 'lib/tesla/middleware/timeout.ex', line: 45]
134+
assert module_file_info == [file: 'lib/tesla/middleware/timeout.ex', line: 59]
115135
else
116136
_ ->
117137
flunk("Expected exception to be thrown")
@@ -126,4 +146,25 @@ defmodule Tesla.Middleware.TimeoutTest do
126146
assert catch_exit(Client.get("/exit")) == :exit_value
127147
end
128148
end
149+
150+
describe "swapping task_module for OpentelemetryProcessPropagator.Task" do
151+
test "should return timeout error when the stack timeout" do
152+
assert {:error, :timeout} = OtelTimeoutClient.get("/sleep_150ms")
153+
end
154+
155+
test "should return the response when not timeout" do
156+
assert {:ok, %Tesla.Env{status: 200}} = OtelTimeoutClient.get("/sleep_50ms")
157+
end
158+
159+
test "should not kill calling process" do
160+
Process.flag(:trap_exit, true)
161+
162+
pid =
163+
spawn_link(fn ->
164+
assert {:error, :timeout} = Client.get("/sleep_150ms")
165+
end)
166+
167+
assert_receive {:EXIT, ^pid, :normal}, 200
168+
end
169+
end
129170
end

0 commit comments

Comments
 (0)