Page MenuHomePhorge

No OneTemporary

Size
10 KB
Referenced Files
None
Subscribers
None
diff --git a/lib/tesla/middleware/telemetry.ex b/lib/tesla/middleware/telemetry.ex
index e1914fc..cb0ac65 100644
--- a/lib/tesla/middleware/telemetry.ex
+++ b/lib/tesla/middleware/telemetry.ex
@@ -1,116 +1,116 @@
if Code.ensure_loaded?(:telemetry) do
defmodule Tesla.Middleware.Telemetry do
@behaviour Tesla.Middleware
@moduledoc """
Emits events using the `:telemetry` library to expose instrumentation.
- ### Example usage
+ ## Example usage
+
```
defmodule MyClient do
use Tesla
plug Tesla.Middleware.Telemetry
end
:telemetry.attach("my-tesla-telemetry", [:tesla, :request, stop], fn event, measurements, meta, config ->
# Do something with the event
end)
```
- ### Options
+ ## Options
* `:event_prefix` - a list of atoms to prefix to the telemetry event name. This can be set if you need to distinguish events from different clients. Defaults to `[]`
## Telemetry Events
* `[:tesla, :request, :start]` - emitted at the beginning of the request.
* Measurement: `%{time: System.monotonic_time}`
* Metadata: `%{env: Tesla.Env.t}`
* `[:tesla, :request, :stop]` - emitted at the end of the request.
* Measurement: `%{duration: native_time}`
* Metadata: `%{env: Tesla.Env.t}`
- * `[:tesla, :request, :error]` - emitted at the end of the request when there is an error.
- * Measurement: `%{duration: native_time}`
- * Metadata: `%{env: Tesla.Env.t, reason: term}`
-
- * `[:tesla, :request, :exception]` - emitted at the end of the request when an exception is raised.
- * Measurement: `%{duration: native_time}`
- * Metadata: `%{env: Tesla.Env.t, exception: Exception.t, stacktrace: Exception.stacktrace}`
+ * `[:tesla, :request, :error]` - emitted when there is an error.
+ * Measurement: `%{value: 1}`
+ * Metadata: `%{env: Tesla.Env.t, kind: Exception.kind | nil, reason: term, stacktrace: Exception.stacktrace}`
- ### Legacy Telemetry Events
+ ## Legacy Telemetry Events
* `[:tesla, :request]` - This event is emitted for backwards compatibility only and should be considered deprecated.
This event can be disabled by setting `config :tesla, Tesla.Middleware.Telemetry, disable_legacy_event: true` in your config. Be sure to run `mix deps.compile --force tesla` after changing this setting to ensure the change is picked up.
Please check the [telemetry](https://hexdocs.pm/telemetry/) for the further usage.
"""
@disable_legacy_event Application.get_env(:tesla, Tesla.Middleware.Telemetry,
disable_legacy_event: false
)[:disable_legacy_event]
- @doc false
+ @behaviour Tesla.Middleware
+
+ @impl Tesla.Middleware
def call(env, next, opts) do
prefix = Keyword.get(opts, :event_prefix, [])
start_time = System.monotonic_time()
emit_start(env, start_time, prefix)
- result =
- try do
- Tesla.run(env, next)
- rescue
- e ->
- stacktrace = System.stacktrace()
- metadata = %{env: env, exception: e, stacktrace: stacktrace}
+ try do
+ Tesla.run(env, next)
+ catch
+ kind, reason ->
+ stacktrace = System.stacktrace()
+ metadata = %{env: env, kind: kind, reason: reason, stacktrace: stacktrace}
- :telemetry.execute(
- prefix ++ [:tesla, :request, :exception],
- %{duration: System.monotonic_time() - start_time},
- metadata
- )
+ :telemetry.execute(
+ prefix ++ [:tesla, :request, :error],
+ %{value: 1},
+ metadata
+ )
- reraise e, stacktrace
- end
+ emit_stop(env, start_time, prefix, {:error, reason})
- duration = System.monotonic_time() - start_time
+ :erlang.raise(kind, reason, stacktrace)
+ else
+ {:ok, env} = result ->
+ emit_stop(env, start_time, prefix, result)
+ result
- emit_stop(env, duration, prefix, result)
+ {:error, error} = result ->
+ :telemetry.execute(
+ prefix ++ [:tesla, :request, :error],
+ %{value: 1},
+ %{env: env, kind: nil, reason: error, stacktrace: []}
+ )
- result
+ emit_stop(env, start_time, prefix, result)
+ result
+ end
end
defp emit_start(env, start_time, prefix) do
:telemetry.execute(prefix ++ [:tesla, :request, :start], %{time: start_time}, %{
env: env
})
end
- defp emit_stop(req_env, duration, prefix, result) do
- case result do
- {:ok, env} ->
- :telemetry.execute(
- prefix ++ [:tesla, :request, :stop],
- %{duration: duration},
- %{env: env}
- )
+ defp emit_stop(env, start_time, prefix, result) do
+ duration = System.monotonic_time() - start_time
- {:error, error} ->
- :telemetry.execute(
- prefix ++ [:tesla, :request, :error],
- %{duration: duration},
- %{env: req_env, reason: error}
- )
- end
+ :telemetry.execute(
+ prefix ++ [:tesla, :request, :stop],
+ %{duration: duration},
+ %{env: env}
+ )
if !@disable_legacy_event do
# retained for backwards compatibility - remove in 2.0
:telemetry.execute([:tesla, :request], %{request_time: duration}, %{result: result})
end
end
end
end
diff --git a/test/tesla/middleware/telemetry_test.exs b/test/tesla/middleware/telemetry_test.exs
index 6ab2d47..523bb55 100644
--- a/test/tesla/middleware/telemetry_test.exs
+++ b/test/tesla/middleware/telemetry_test.exs
@@ -1,116 +1,137 @@
defmodule Tesla.Middleware.TelemetryTest do
use ExUnit.Case, async: true
defmodule Client do
use Tesla
plug Tesla.Middleware.Telemetry
adapter fn env ->
case env.url do
"/telemetry" -> {:ok, env}
"/telemetry_error" -> {:error, :econnrefused}
"/telemetry_exception" -> raise "some exception"
end
end
end
defmodule ClientWithOptions do
use Tesla
plug Tesla.Middleware.Telemetry, event_prefix: [:my_client]
adapter fn env ->
case env.url do
"/telemetry" -> {:ok, env}
end
end
end
setup do
Application.ensure_all_started(:telemetry)
on_exit(fn ->
:telemetry.list_handlers([])
|> Enum.each(&:telemetry.detach(&1.id))
end)
:ok
end
test "accepts options" do
:telemetry.attach("with_opts", [:my_client, :tesla, :request, :stop], &echo_event/4, %{
caller: self()
})
ClientWithOptions.get("/telemetry")
assert_receive {:event, [:my_client, :tesla, :request, :stop], %{duration: time},
%{env: %Tesla.Env{url: "/telemetry", method: :get}}}
end
test "with default options" do
:telemetry.attach("with_default_opts_start", [:tesla, :request, :start], &echo_event/4, %{
caller: self()
})
:telemetry.attach("with_default_opts_stop", [:tesla, :request, :stop], &echo_event/4, %{
caller: self()
})
:telemetry.attach("with_default_opts_legacy", [:tesla, :request, :stop], &echo_event/4, %{
caller: self()
})
Client.get("/telemetry")
assert_receive {:event, [:tesla, :request, :start], %{time: time},
%{env: %Tesla.Env{url: "/telemetry", method: :get}}}
assert_receive {:event, [:tesla, :request, :stop], %{duration: time},
%{env: %Tesla.Env{url: "/telemetry", method: :get}}}
end
test "legacy_event_emitted_by_default" do
:telemetry.attach("with_default_opts_legacy", [:tesla, :request], &echo_event/4, %{
caller: self()
})
Client.get("/telemetry")
assert_receive {:event, [:tesla, :request], %{request_time: time}, %{result: result}}
end
test "with an error returned" do
:telemetry.attach("with_error", [:tesla, :request, :error], &echo_event/4, %{caller: self()})
+ :telemetry.attach("with_error_gets_stop", [:tesla, :request, :stop], &echo_event/4, %{
+ caller: self()
+ })
+
Client.get("/telemetry_error")
- assert_receive {:event, [:tesla, :request, :error], %{duration: time},
+ assert_receive {:event, [:tesla, :request, :error], %{value: 1},
%{
env: %Tesla.Env{url: "/telemetry_error", method: :get},
- reason: :econnrefused
+ kind: kind,
+ reason: :econnrefused,
+ stacktrace: []
+ }}
+
+ assert_receive {:event, [:tesla, :request, :stop], %{duration: time},
+ %{
+ env: %Tesla.Env{url: "/telemetry_error", method: :get}
}}
end
test "with an exception raised" do
- :telemetry.attach("with_exception", [:tesla, :request, :exception], &echo_event/4, %{
+ :telemetry.attach("with_exception", [:tesla, :request, :error], &echo_event/4, %{
+ caller: self()
+ })
+
+ :telemetry.attach("with_exception_gets_stop", [:tesla, :request, :stop], &echo_event/4, %{
caller: self()
})
assert_raise RuntimeError, fn ->
Client.get("/telemetry_exception")
end
- assert_receive {:event, [:tesla, :request, :exception], %{duration: time},
+ assert_receive {:event, [:tesla, :request, :error], %{value: 1},
%{
env: %Tesla.Env{url: "/telemetry_exception", method: :get},
- exception: kind,
+ kind: kind,
+ reason: reason,
stacktrace: stacktrace
}}
+
+ assert_receive {:event, [:tesla, :request, :stop], %{duration: time},
+ %{
+ env: %Tesla.Env{url: "/telemetry_exception", method: :get}
+ }}
end
def echo_event(event, measurements, metadata, config) do
send(config.caller, {:event, event, measurements, metadata})
end
end

File Metadata

Mime Type
text/x-diff
Expires
Tue, Nov 26, 12:18 AM (1 d, 7 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40102
Default Alt Text
(10 KB)

Event Timeline