Packages
ash
3.27.2
3.29.3
3.29.2
3.29.1
3.29.0
3.28.0
3.27.8
3.27.7
3.27.6
3.27.5
3.27.4
3.27.3
3.27.2
3.27.1
3.27.0
3.26.0
3.25.2
3.25.1
3.25.0
retired
3.24.7
3.24.6
3.24.5
3.24.4
3.24.3
3.24.2
3.24.1
3.24.0
3.23.1
3.23.0
3.22.2
3.22.1
3.22.0
3.21.3
3.21.2
3.21.1
3.21.0
3.20.0
3.19.3
3.19.2
3.19.1
3.19.0
3.18.0
3.17.1
3.17.0
3.16.0
3.15.0
3.14.1
3.14.0
retired
3.13.2
3.13.1
3.13.0
3.12.0
3.11.3
3.11.2
3.11.1
3.11.0
3.10.1
3.10.0
3.9.0
3.8.0
3.7.6
3.7.5
3.7.4
3.7.3
3.7.2
3.7.1
3.7.0
retired
3.6.3
retired
3.6.2
3.6.1
3.6.0
3.5.43
3.5.42
3.5.41
3.5.40
3.5.39
3.5.38
3.5.37
3.5.36
3.5.35
3.5.34
3.5.33
3.5.32
3.5.31
3.5.30
3.5.29
3.5.28
3.5.27
3.5.26
3.5.25
3.5.24
3.5.23
3.5.22
3.5.21
3.5.20
3.5.19
3.5.18
3.5.17
3.5.16
3.5.15
3.5.14
3.5.13
3.5.12
3.5.11
3.5.10
3.5.9
3.5.8
3.5.7
3.5.6
3.5.5
3.5.4
3.5.3
3.5.2
3.5.1
3.5.0
3.4.74
retired
3.4.73
3.4.72
3.4.71
3.4.70
3.4.69
3.4.68
3.4.67
3.4.66
3.4.65
3.4.64
3.4.63
3.4.62
3.4.61
3.4.60
3.4.59
3.4.58
3.4.57
3.4.56
3.4.55
3.4.54
3.4.53
3.4.52
3.4.51
3.4.50
3.4.49
3.4.48
3.4.47
3.4.46
3.4.45
3.4.44
3.4.43
3.4.42
3.4.41
3.4.40
3.4.39
3.4.38
3.4.37
3.4.36
3.4.35
3.4.34
3.4.33
3.4.32
3.4.31
3.4.30
3.4.29
3.4.28
3.4.27
3.4.26
3.4.25
3.4.24
3.4.23
3.4.22
3.4.21
3.4.20
3.4.19
3.4.18
3.4.17
3.4.16
3.4.15
3.4.14
3.4.13
3.4.12
3.4.11
3.4.10
3.4.9
3.4.8
3.4.7
3.4.6
3.4.5
3.4.4
3.4.3
3.4.2
3.4.1
3.4.0
3.3.3
3.3.2
3.3.1
3.3.0
3.2.6
3.2.5
3.2.4
3.2.3
3.2.2
3.2.1
3.2.0
3.1.8
3.1.7
3.1.6
3.1.5
3.1.4
3.1.3
3.1.2
3.1.1
3.1.0
3.0.16
3.0.15
3.0.14
3.0.13
3.0.12
3.0.11
3.0.10
3.0.9
3.0.8
3.0.7
3.0.6
3.0.5
3.0.4
3.0.3
3.0.2
3.0.1
3.0.0
3.0.0-rc.46
3.0.0-rc.45
3.0.0-rc.44
3.0.0-rc.43
3.0.0-rc.42
3.0.0-rc.41
3.0.0-rc.40
3.0.0-rc.39
3.0.0-rc.38
3.0.0-rc.37
3.0.0-rc.36
3.0.0-rc.35
3.0.0-rc.34
3.0.0-rc.33
3.0.0-rc.32
3.0.0-rc.31
3.0.0-rc.29
3.0.0-rc.28
3.0.0-rc.27
3.0.0-rc.26
3.0.0-rc.25
3.0.0-rc.24
3.0.0-rc.23
3.0.0-rc.22
3.0.0-rc.21
3.0.0-rc.20
3.0.0-rc.19
3.0.0-rc.18
3.0.0-rc.17
3.0.0-rc.16
3.0.0-rc.15
3.0.0-rc.14
3.0.0-rc.13
3.0.0-rc.12
3.0.0-rc.11
3.0.0-rc.10
3.0.0-rc.9
3.0.0-rc.8
3.0.0-rc.7
3.0.0-rc.6
3.0.0-rc.5
3.0.0-rc.4
3.0.0-rc.3
3.0.0-rc.1
3.0.0-rc.0
2.21.15
2.21.14
2.21.13
2.21.12
2.21.11
2.21.10
2.21.9
2.21.8
2.21.7
2.21.6
2.21.5
2.21.4
2.21.3
2.21.2
2.21.1
2.21.0
2.20.3
2.20.2
2.20.1
2.20.0
2.19.14
2.19.13
2.19.12
2.19.11
2.19.10
2.19.9
2.19.8
2.19.7
2.19.6
2.19.5
2.19.4
2.19.3
retired
2.19.2
retired
2.19.1
retired
2.19.0
retired
2.18.2
2.18.1
2.18.0
2.17.24
2.17.23
2.17.22
2.17.21
2.17.20
2.17.19
2.17.18
2.17.17
2.17.16
2.17.15
2.17.14
2.17.13
2.17.12
2.17.11
2.17.10
2.17.9
2.17.8
2.17.7
2.17.6
2.17.5
2.17.4
2.17.3
2.17.2
2.17.1
2.17.0
2.16.1
2.16.0
2.15.20
2.15.19
2.15.18
2.15.17
2.15.16
2.15.15
2.15.14
2.15.13
2.15.12
2.15.11
2.15.10
2.15.9
2.15.8
2.15.7
2.15.6
2.15.5
2.15.4
2.15.2
2.15.1
2.15.0
2.14.21
2.14.20
2.14.19
2.14.18
2.14.17
2.14.16
2.14.15
2.14.14
2.14.13
2.14.12
2.14.11
2.14.10
2.14.9
2.14.8
2.14.7
2.14.6
2.14.5
2.14.4
2.14.3
2.14.2
2.14.1
2.14.0
2.13.4
retired
2.13.3
2.13.2
2.13.1
2.13.0
2.12.1
2.12.0
2.11.11
2.11.10
2.11.9
2.11.8
2.11.7
2.11.6
2.11.5
2.11.4
2.11.3
2.11.2
2.11.1
2.11.0
2.11.0-rc.3
2.11.0-rc.2
2.11.0-rc.1
2.11.0-rc.0
2.10.2
2.10.1
2.10.0
2.9.29
2.9.28
2.9.27
2.9.26
2.9.25
2.9.24
2.9.23
2.9.22
2.9.21
2.9.20
2.9.19
2.9.18
2.9.17
2.9.16
2.9.15
2.9.14
2.9.13
2.9.12
2.9.11
2.9.10
2.9.9
2.9.8
2.9.7
2.9.6
2.9.5
2.9.4
2.9.3
2.9.2
2.9.1
2.9.0
2.8.1
2.8.0
2.7.1
2.7.0
2.6.31
2.6.30
2.6.29
2.6.28
2.6.27
2.6.26
2.6.25
2.6.24
2.6.23
2.6.22
2.6.21
2.6.20
2.6.19
2.6.18
2.6.17
2.6.16
2.6.15
2.6.14
2.6.13
2.6.11
2.6.10
2.6.9
2.6.8
2.6.7
2.6.6
2.6.5
2.6.4
2.6.3
2.6.2
2.6.1
2.6.0
2.5.16
2.5.15
2.5.14
2.5.13
2.5.12
2.5.11
2.5.10
2.5.9
2.5.8
2.5.7
2.5.6
2.5.5
2.5.4
2.5.3
2.5.2
2.5.1
2.5.0
2.5.0-rc.6
2.5.0-rc.5
2.5.0-rc.4
2.5.0-rc.3
2.5.0-rc.2
2.5.0-rc.1
2.5.0-rc.0
2.4.30
2.4.29
2.4.28
2.4.27
2.4.26
2.4.25
2.4.24
2.4.23
2.4.22
2.4.21
2.4.20
2.4.19
2.4.18
2.4.17
2.4.16
2.4.15
2.4.14
2.4.13
2.4.12
2.4.11
2.4.10
2.4.9
2.4.8
2.4.7
2.4.6
2.4.5
2.4.4
2.4.3
2.4.2
2.4.1
2.4.0
2.3.0
2.2.0
2.1.0
2.0.0
2.0.0-rc.15
2.0.0-rc.14
2.0.0-rc.13
2.0.0-rc.12
2.0.0-rc.11
2.0.0-rc.10
2.0.0-rc.9
2.0.0-rc.8
2.0.0-rc.7
2.0.0-rc.6
2.0.0-rc.5
2.0.0-rc.4
2.0.0-rc.3
2.0.0-rc.2
2.0.0-rc.1
2.0.0-rc.0
2.0.0-pre.8
2.0.0-pre.7
2.0.0-pre.6
2.0.0-pre.5
2.0.0-pre.4
2.0.0-pre.3
2.0.0-pre.2
2.0.0-pre.1
2.0.0-pre.0
1.53.3
1.53.2
1.53.0
1.52.0-rc.22
1.52.0-rc.21
1.52.0-rc.20
1.52.0-rc.19
1.52.0-rc.18
1.52.0-rc.17
1.52.0-rc.16
1.52.0-rc.15
1.52.0-rc.14
1.52.0-rc.13
1.52.0-rc.12
1.52.0-rc.11
1.52.0-rc.10
1.52.0-rc.9
1.52.0-rc.8
1.52.0-rc.7
1.52.0-rc.6
1.52.0-rc.5
1.52.0-rc.4
1.52.0-rc.3
1.52.0-rc.2
1.52.0-rc.1
1.52.0-rc.0
1.51.2
1.51.1
retired
1.51.0
1.50.21
1.50.20
1.50.19
1.50.18
1.50.17
1.50.16
1.50.15
1.50.14
1.50.13
1.50.12
1.50.11
1.50.10
1.50.9
1.50.8
1.50.7
1.50.6
1.50.5
1.50.4
1.50.3
1.50.2
1.50.1
1.50.0
1.49.0
1.48.0-rc.30
1.48.0-rc.29
1.48.0-rc.28
1.48.0-rc.27
1.48.0-rc.26
1.48.0-rc.25
1.48.0-rc.24
1.48.0-rc.23
1.48.0-rc.22
1.48.0-rc.21
1.48.0-rc.20
1.48.0-rc.19
1.48.0-rc.18
1.48.0-rc.17
1.48.0-rc.16
1.48.0-rc.15
1.48.0-rc.14
1.48.0-rc.13
1.48.0-rc.12
1.48.0-rc.11
1.48.0-rc.10
1.48.0-rc.9
1.48.0-rc.8
1.48.0-rc.7
1.48.0-rc.6
1.48.0-rc.5
1.48.0-rc.4
1.48.0-rc.3
1.48.0-rc.2
1.48.0-rc.1
1.48.0-rc.0
1.47.12
1.47.11
1.47.10
1.47.9
1.47.8
1.47.7
1.47.6
1.47.5
1.47.4
1.47.3
1.47.2
1.47.1
1.47.0
1.46.13
1.46.12
1.46.11
1.46.10
1.46.9
1.46.8
1.46.7
1.46.6
1.46.5
1.46.4
1.46.3
1.46.2
1.46.1
1.46.0
1.45.0-rc9
1.45.0-rc8
1.45.0-rc7
1.45.0-rc6
1.45.0-rc5
1.45.0-rc4
1.45.0-rc3
1.45.0-rc20
1.45.0-rc2
1.45.0-rc19
1.45.0-rc18
1.45.0-rc17
1.45.0-rc16
1.45.0-rc15
1.45.0-rc14
1.45.0-rc13
1.45.0-rc12
1.45.0-rc11
1.45.0-rc10
1.45.0-rc1
1.45.0-rc0
1.44.13
1.44.12
1.44.11
1.44.10
1.44.9
1.44.8
1.44.7
1.44.6
1.44.5
1.44.4
1.44.3
1.44.2
1.44.1
1.44.0
1.43.12
1.43.11
1.43.10
1.43.9
1.43.8
1.43.7
1.43.6
1.43.5
1.43.4
1.43.3
1.43.2
1.43.1
1.43.0
1.42.0
1.41.12
1.41.11
1.41.10
1.41.9
1.41.8
1.41.7
1.41.6
1.41.5
1.41.4
1.41.3
1.41.2
1.41.1
1.41.0
1.40.0
1.39.7
1.39.6
1.39.5
1.39.4
1.39.3
1.39.2
1.39.1
1.39.0
1.38.0
1.37.2
1.37.1
1.37.0
1.36.22
1.36.21
1.36.19
1.36.18
1.36.17
1.36.16
1.36.15
1.36.14
1.36.13
1.36.12
1.36.11
1.36.10
1.36.9
1.36.8
1.36.7
1.36.6
1.36.5
1.36.4
1.36.3
1.36.2
1.36.0
1.35.1
1.35.0
1.34.9
1.34.8
1.34.7
1.34.6
1.34.5
1.34.4
1.34.3
1.34.2
1.34.1
1.34.0
1.33.0
1.32.2
1.32.1
1.32.0
1.31.1
1.31.0
1.30.2
1.30.1
1.29.0-rc1
1.29.0-rc0
1.28.1
1.28.0
1.27.1
1.27.0
1.26.13
1.26.12
1.26.11
1.26.10
1.26.9
1.26.8
1.26.7
1.26.6
1.26.5
1.26.4
1.26.2
1.26.1
1.26.0
1.25.8
1.25.7
1.25.6
1.25.5
1.25.4
1.25.3
1.25.2
1.25.1
1.25.0
1.24.2
1.24.1
1.24.0
1.23.3
1.23.2
1.23.1
1.23.0
1.22.1
1.22.0
1.20.1
1.20.0
1.19.1
1.19.0
1.18.1
1.18.0
1.17.1
1.17.0
1.16.2
1.15.1
1.15.0
1.14.0
1.13.4
1.13.3
1.13.2
1.13.1
1.13.0
1.12.0
1.11.1
1.11.0
1.10.0
1.9.0
1.8.0
1.7.0
1.6.8
1.6.7
1.6.6
1.6.5
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.1
1.5.0
1.4.1
1.4.0
1.3.1
1.3.0
1.2.1
1.2.0
1.1.3
1.1.2
1.1.0
1.0.3
1.0.2
1.0.1
1.0.0
0.13.1
0.13.0
0.12.0
0.10.0
0.9.1
0.9.0
0.8.0
0.7.0
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.2
0.5.1
0.5.0
0.4.0
0.3.0
0.2.0
0.1.9
0.1.8
0.1.3
0.1.1
0.1.0
A declarative, extensible framework for building Elixir applications.
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
lib/ash/tracer/tracer.ex
# SPDX-FileCopyrightText: 2019 ash contributors <https://github.com/ash-project/ash/graphs/contributors>
#
# SPDX-License-Identifier: MIT
defmodule Ash.Tracer do
@moduledoc """
A behaviour for implementing tracing for an Ash application.
"""
@type span_type() ::
:action
| :bulk_create
| :bulk_update
| :bulk_destroy
| :bulk_batch
| :changeset
| :query
| :calculate
| :request_step
| :change
| :validation
| :preparation
| :custom
| :notifier
| :before_transaction
| :before_action
| :after_transaction
| :after_action
| {:custom, atom()}
| term()
@type metadata() ::
%{
domain: nil | module(),
resource: nil | module(),
actor: term(),
tenant: term(),
action: atom(),
authorize?: boolean()
}
| map()
@type t :: module
@callback start_span(span_type(), name :: String.t()) :: :ok
@callback stop_span() :: :ok
@callback get_span_context() :: term()
@callback set_span_context(term()) :: :ok
@callback set_error(Exception.t(), Keyword.t()) :: :ok
@callback trace_type?(atom) :: boolean()
@callback set_handled_error(Exception.t(), Keyword.t()) :: :ok
@doc """
Set metadata for the current span.
This may be called multiple times per span, and should ideally merge with previous metadata.
"""
@callback set_metadata(span_type(), metadata()) :: :ok
@callback set_error(Exception.t()) :: :ok
@optional_callbacks set_error: 2, set_error: 1, trace_type?: 1, set_handled_error: 2
defmacro span(type, name, tracer, block_opts \\ []) do
quote generated: true do
type = unquote(type)
name = unquote(name)
tracer = List.wrap(unquote(tracer))
tracer = Enum.filter(tracer, &Ash.Tracer.trace_type?(&1, type))
# no need to use try/rescue/after if no tracers
if Enum.empty?(tracer) do
unquote(block_opts[:do])
else
Ash.Tracer.start_span(tracer, type, name)
try do
unquote(block_opts[:do])
rescue
e ->
Ash.Tracer.set_error(tracer, e, stacktrace: __STACKTRACE__)
reraise e, __STACKTRACE__
after
Ash.Tracer.stop_span(tracer)
end
end
end
end
defmacro telemetry_span(name, metadata, opts \\ [], block_opts) do
quote generated: true do
if unquote(opts[:skip?]) do
unquote(block_opts[:do])
else
telemetry_name = unquote(name)
metadata = unquote(metadata)
compiling? = Code.can_await_module_compilation?()
metadata =
if !compiling? do
case :telemetry.list_handlers(telemetry_name) do
[] -> %{}
_ when is_function(metadata) -> apply(metadata, [])
_ -> metadata
end
end
start = System.monotonic_time()
if !compiling? do
:telemetry.execute(
telemetry_name ++ [:start],
%{system_time: System.system_time()},
metadata
)
end
try do
unquote(block_opts[:do])
after
duration = System.monotonic_time() - start
if !compiling? do
:telemetry.execute(
telemetry_name ++ [:stop],
%{system_time: System.system_time(), duration: duration},
metadata
)
end
end
end
end
end
@spec stop_span(nil | module() | [module()]) :: :ok
def stop_span(nil), do: :ok
def stop_span(tracers) when is_list(tracers) do
Enum.each(tracers, &stop_span/1)
end
def stop_span(tracer) do
result = apply(tracer, :stop_span, [])
if result == :ok do
:ok
else
raise Ash.Error.Framework.InvalidReturnType,
message: """
Invalid value returned from #{inspect(tracer)}.stop_span/0.
The callback #{inspect(__MODULE__)}.stop_span/0 expects :ok.
"""
end
end
@spec trace_type?(module(), atom()) :: boolean()
def trace_type?(tracer, type) do
if function_exported?(tracer, :trace_type?, 1) do
result = apply(tracer, :trace_type?, [type])
if is_boolean(result) do
result
else
raise Ash.Error.Framework.InvalidReturnType,
message: """
Invalid value returned from #{inspect(tracer)}.trace_type?/1.
The callback #{inspect(__MODULE__)}.trace_type?/1 expects a boolean.
"""
end
else
true
end
end
@spec start_span(nil | module() | [module()], span_type(), String.t() | (-> String.t())) :: :ok
def start_span(nil, _type, _name), do: :ok
def start_span(tracers, type, name) when is_list(tracers) do
name = resolve_lazy(name)
Enum.each(tracers, &start_span(&1, type, name))
end
def start_span(tracer, type, name) do
name = resolve_lazy(name)
result = apply(tracer, :start_span, [type, name])
if result == :ok do
:ok
else
raise Ash.Error.Framework.InvalidReturnType,
message: """
Invalid value returned from #{inspect(tracer)}.start_span/2.
The callback #{inspect(__MODULE__)}.start_span/2 expects :ok.
"""
end
end
@spec set_handled_error(nil | module() | [module()], Exception.t(), Keyword.t()) :: :ok
def set_handled_error(nil, _, _), do: :ok
def set_handled_error(tracers, error, opts) when is_list(tracers) do
Enum.each(tracers, &set_handled_error(&1, error, opts))
end
def set_handled_error(tracer, error, opts) do
if function_exported?(tracer, :set_handled_error, 2) do
result = apply(tracer, :set_handled_error, [error, opts])
if result == :ok do
:ok
else
raise Ash.Error.Framework.InvalidReturnType,
message: """
Invalid value returned from #{inspect(tracer)}.set_handled_error/2.
The callback #{inspect(__MODULE__)}.set_handled_error/2 expects :ok.
"""
end
else
:ok
end
end
@spec set_error(nil | module() | [module()], Exception.t(), Keyword.t()) :: :ok
def set_error(nil, _, _), do: :ok
def set_error(tracers, error, opts) when is_list(tracers) do
Enum.each(tracers, &set_error(&1, error, opts))
end
def set_error(tracer, error, opts) do
result =
if function_exported?(tracer, :set_error, 2) do
apply(tracer, :set_error, [error, opts])
else
apply(tracer, :set_error, [error])
end
if result == :ok do
:ok
else
raise Ash.Error.Framework.InvalidReturnType,
message: """
Invalid value returned from #{inspect(tracer)}.set_error/1 or set_error/2.
The callback #{inspect(__MODULE__)}.set_error expects :ok.
"""
end
end
@spec set_error(nil | module() | [module()], Exception.t()) :: :ok
def set_error(nil, _), do: :ok
def set_error(tracers, error) when is_list(tracers) do
Enum.each(tracers, &set_error(&1, error))
end
def set_error(tracer, error) do
result =
if function_exported?(tracer, :set_error, 2) do
apply(tracer, :set_error, [error, []])
else
apply(tracer, :set_error, [error])
end
if result == :ok do
:ok
else
raise Ash.Error.Framework.InvalidReturnType,
message: """
Invalid value returned from #{inspect(tracer)}.set_error/1 or set_error/2.
The callback #{inspect(__MODULE__)}.set_error expects :ok.
"""
end
end
@spec get_span_context(nil | module()) :: term()
def get_span_context(nil), do: :ok
def get_span_context(tracer) when is_list(tracer) do
raise ArgumentError, "Cannot get span context from multiple tracers"
end
def get_span_context(tracer) do
apply(tracer, :get_span_context, [])
end
@spec set_span_context(nil | module(), term()) :: :ok
def set_span_context(nil, _), do: :ok
def set_span_context(tracer, _context) when is_list(tracer) do
raise ArgumentError, "Cannot set span context from multiple tracers"
end
def set_span_context(tracer, context) do
result = apply(tracer, :set_span_context, [context])
if result == :ok do
:ok
else
raise Ash.Error.Framework.InvalidReturnType,
message: """
Invalid value returned from #{inspect(tracer)}.set_span_context/1.
The callback #{inspect(__MODULE__)}.set_span_context/1 expects :ok.
"""
end
end
@spec set_metadata(nil | module() | [module()], span_type(), metadata() | (-> metadata())) ::
:ok
def set_metadata(nil, _type, _metadata), do: :ok
def set_metadata(tracers, type, metadata) when is_list(tracers) do
tracers = Enum.filter(tracers, &Ash.Tracer.trace_type?(&1, type))
if !Enum.empty?(tracers) do
metadata = resolve_lazy(metadata)
Enum.each(tracers, &set_metadata(&1, type, metadata))
end
end
def set_metadata(tracer, type, metadata) do
if Ash.Tracer.trace_type?(tracer, type) do
metadata = resolve_lazy(metadata)
result = apply(tracer, :set_metadata, [type, metadata])
if result == :ok do
:ok
else
raise Ash.Error.Framework.InvalidReturnType,
message: """
Invalid value returned from #{inspect(tracer)}.set_metadata/2.
The callback #{inspect(__MODULE__)}.set_metadata/2 expects :ok.
"""
end
end
end
defmacro __using__(_) do
quote do
@behaviour Ash.Tracer
end
end
defp resolve_lazy(value) do
if is_function(value), do: apply(value, []), else: value
end
end