Packages

appsignal

2.1.6
2.17.4 2.17.3 2.17.2 2.17.1 2.17.0 2.16.0 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.3 2.15.2 2.15.1 2.15.0 2.14.1 2.14.0 2.13.4 2.13.3 2.13.2 2.13.1 2.13.0 2.12.3 2.12.2 2.12.1 2.12.0 2.11.0 2.10.2 2.10.1 2.10.0 2.9.2 2.9.1 2.9.0 2.8.3 2.8.2 2.8.1 2.8.0 2.7.13 2.7.12 2.7.11 2.7.10 2.7.9 2.7.8 2.7.7 2.7.6 2.7.5 2.7.4 2.7.3 2.7.2 2.7.1 2.7.0 2.7.0-beta.1 2.6.1 2.6.0 2.5.3 2.5.2 2.5.1 2.5.0 2.4.3 2.4.2 2.4.1 2.4.0 2.3.1 2.3.0 2.2.19 2.2.18 2.2.17 2.2.16 2.2.15 2.2.14 2.2.13 2.2.12 retired 2.2.11 2.2.10 2.2.9 2.2.8 2.2.7 2.2.6 2.2.5 2.2.4 2.2.3 2.2.2 2.2.1 2.2.0 2.1.15 2.1.14 2.1.13 2.1.12 2.1.11 2.1.10 2.1.9 2.1.8 2.1.7 2.1.7-beta.1 2.1.6 2.1.5 2.1.4 2.1.3 2.1.2 2.1.1 2.1.0 2.0.8 2.0.7 2.0.6 2.0.6-beta.1 2.0.5 retired 2.0.4 retired 2.0.3 retired 2.0.2 retired 2.0.1 retired 2.0.0 retired 2.0.0-beta.11 2.0.0-beta.10 2.0.0-beta.9 2.0.0-beta.8 2.0.0-beta.7 2.0.0-beta.6 2.0.0-beta.5 2.0.0-beta.4 2.0.0-beta.3 2.0.0-beta.2 2.0.0-beta.1 2.0.0-alpha.7 2.0.0-alpha.6 2.0.0-alpha.5 2.0.0-alpha.4 2.0.0-alpha.3 2.0.0-alpha.2 2.0.0-alpha.1 1.13.5 1.13.4 1.13.3 1.13.2 1.13.1 1.13.0 1.13.0-beta.2 1.13.0-beta.1 1.12.1 1.12.0 1.12.0-beta.3 1.12.0-beta.2 1.12.0-beta.1 1.11.8 1.11.7 1.11.6 1.11.5 1.11.4 1.11.3 1.11.2 1.11.1 1.11.0 1.11.0-beta.1 1.10.13 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.4 1.9.3 1.9.2 1.9.1 1.9.1-beta.1 1.9.0 1.9.0-beta.1 1.9.0-alpha.1 1.8.2 1.8.1 1.8.1-beta.2 1.8.1-beta.1 1.8.0 1.7.2 1.7.1 1.7.0 1.7.0-beta.2 1.7.0-beta.1 1.7.0-alpha.4 1.7.0-alpha.3 1.7.0-alpha.2 1.7.0-alpha.1 1.6.7 1.6.6 1.6.6-beta.2 1.6.6-beta.1 1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.6.0-beta.1 1.6.0-alpha.1 1.5.1 1.5.0 1.5.0-beta.2 1.5.0-beta.1 1.4.11-beta.1 1.4.10 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.4.0-alpha.1 1.3.6 1.3.6-beta.1 1.3.5 1.3.4 1.3.4-beta.1 1.3.3 1.3.2 1.3.1 1.3.0 1.3.0-beta.3 1.3.0-beta.2 1.3.0-beta.1 1.2.3 1.2.2 1.2.1 1.2.0 1.1.1 1.1.0 1.0.4 1.0.3 1.0.2 1.0.1 1.0.0 1.0.0-rc.1 0.13.0 0.12.3 0.12.2 0.12.1 0.12.0 0.11.6 0.11.5 0.11.4 0.11.3 0.11.2 0.11.1 0.11.0 0.10.0 0.9.2 0.9.1 0.9.0 0.8.0 0.7.1 0.7.0 0.6.2 0.6.1 0.6.0 0.5.0 0.4.0 0.3.0 0.2.0 0.1.0 0.0.9 0.0.8 0.0.7 0.0.6 0.0.5 0.0.4 0.0.3 0.0.2 0.0.1

Collects error and performance data from your Elixir applications and sends it to AppSignal

Current section

Files

Jump to
appsignal lib appsignal span.ex
Raw

lib/appsignal/span.ex

defmodule Appsignal.Span do
alias Appsignal.{Config, Nif, Span}
defstruct [:reference, :pid]
@nif Application.get_env(:appsignal, :appsignal_tracer_nif, Appsignal.Nif)
@type t() :: %__MODULE__{
reference: reference(),
pid: pid()
}
@spec create_root(String.t(), pid()) :: t() | nil
@doc """
Create a root `Appsignal.Span` with a namespace and a pid.
For a description of namespaces, see `set_namespace/2`.
## Example
Appsignal.Span.create_root("http_request", self())
"""
def create_root(namespace, pid) do
if Config.active?() do
{:ok, reference} = @nif.create_root_span(namespace)
%Span{reference: reference, pid: pid}
end
end
@spec create_root(String.t(), pid(), integer()) :: t() | nil
@doc """
Create a root `Appsignal.Span` with a namespace, a pid and an explicit start time.
For a description of namespaces, see `set_namespace/2`.
## Example
Appsignal.Span.create_root("http_request", self(), :os.system_time())
"""
def create_root(namespace, pid, start_time) do
if Config.active?() do
sec = :erlang.convert_time_unit(start_time, :native, :second)
nsec = :erlang.convert_time_unit(start_time, :native, :nanosecond) - sec * 1_000_000_000
{:ok, reference} = @nif.create_root_span_with_timestamp(namespace, sec, nsec)
%Span{reference: reference, pid: pid}
end
end
@spec create_child(t() | nil, pid()) :: t() | nil
@doc """
Create a child `Appsignal.Span`.
## Example
Appsignal.Tracer.root_span()
|> Appsignal.Span.create_child(self())
"""
def create_child(%Span{reference: parent}, pid) do
if Config.active?() do
{:ok, reference} = @nif.create_child_span(parent)
%Span{reference: reference, pid: pid}
end
end
@spec create_child(t() | nil, pid(), integer()) :: t() | nil
@doc """
Create a child `Appsignal.Span` with an explicit start time.
## Example
Appsignal.Tracer.root_span()
|> Appsignal.Span.create_child(self(), :os.system_time())
"""
def create_child(%Span{reference: parent}, pid, start_time) do
if Config.active?() do
sec = :erlang.convert_time_unit(start_time, :native, :second)
nsec = :erlang.convert_time_unit(start_time, :native, :nanosecond) - sec * 1_000_000_000
{:ok, reference} = @nif.create_child_span_with_timestamp(parent, sec, nsec)
%Span{reference: reference, pid: pid}
end
end
@spec set_name(t() | nil, String.t()) :: t() | nil
@doc """
Sets an `Appsignal.Span`'s name.
## Example
Appsignal.Tracer.root_span()
|> Appsignal.Span.set_name("PageController#index")
"""
def set_name(%Span{reference: reference} = span, name)
when is_reference(reference) and is_binary(name) do
if Config.active?() do
:ok = @nif.set_span_name(reference, name)
span
end
end
def set_name(_span, _name), do: nil
@spec set_namespace(t() | nil, String.t()) :: t() | nil
@doc """
Sets an `Appsignal.Span`'s namespace. The namespace is `"http_request"` or
`"background_job'` to add the span to the "web" and "background" namespaces
respectively. Passing another string creates a custom namespace to store the
`Appsignal.Span`'s samples in.
## Example
Appsignal.Tracer.root_span()
|> Appsignal.Span.set_namespace("http_request")
"""
def set_namespace(%Span{reference: reference} = span, namespace) when is_binary(namespace) do
:ok = @nif.set_span_namespace(reference, namespace)
span
end
def set_namespace(_span, _name), do: nil
@spec set_attribute(t() | nil, String.t(), String.t() | integer() | boolean() | float()) ::
t() | nil
@doc """
Sets an `Appsignal.Span` attribute.
## Example
Appsignal.Tracer.root_span()
|> Appsignal.Span.set_attribute("appsignal:category", "query.ecto")
"""
def set_attribute(%Span{reference: reference} = span, key, true) when is_binary(key) do
:ok = Nif.set_span_attribute_bool(reference, key, 1)
span
end
def set_attribute(%Span{reference: reference} = span, key, false) when is_binary(key) do
:ok = Nif.set_span_attribute_bool(reference, key, 0)
span
end
def set_attribute(%Span{reference: reference} = span, key, value)
when is_binary(key) and is_binary(value) do
:ok = Nif.set_span_attribute_string(reference, key, value)
span
end
def set_attribute(%Span{reference: reference} = span, key, value)
when is_binary(key) and is_integer(value) do
:ok = Nif.set_span_attribute_int(reference, key, value)
span
end
def set_attribute(%Span{reference: reference} = span, key, value)
when is_binary(key) and is_float(value) do
:ok = Nif.set_span_attribute_double(reference, key, value)
span
end
def set_attribute(_span, _key, _value), do: nil
@spec set_sql(t() | nil, String.t()) :: t() | nil
@doc """
Sets the `"appsignal:body"` attribute with an SQL query string.
## Example
Appsignal.Tracer.root_span()
|> Appsignal.Span.set_sql("SELECT * FROM users")
"""
def set_sql(%Span{reference: reference} = span, body) when is_binary(body) do
:ok = Nif.set_span_attribute_sql_string(reference, "appsignal:body", body)
span
end
def set_sql(_span, _body), do: nil
@spec set_sample_data(t() | nil, String.t(), map()) :: t() | nil
@doc """
Sets sample data for an `Appsignal.Span`.
## Example
Appsignal.Tracer.root_span()
|> Appsignal.Span.set_sample_data("environment", %{"method" => "GET"})
"""
def set_sample_data(%Span{reference: reference} = span, key, value)
when is_binary(key) and is_map(value) do
data =
value
|> Appsignal.Utils.MapFilter.filter()
|> Appsignal.Utils.DataEncoder.encode()
:ok = Nif.set_span_sample_data(reference, key, data)
span
end
def set_sample_data(_span, _key, _value), do: nil
@spec add_error(t() | nil, Exception.kind(), any(), Exception.stacktrace()) :: t() | nil
@doc """
Add an error to an `Appsignal.Span` by passing a `kind` and `reason` from a
`catch` block, and a stack trace.
## Example
span = Appsignal.Tracer.root_span()
try
raise "Exception!"
catch
kind, reason ->
Appsignal.Span.add_error(span, kind, reason, __STACKTRACE__)
end
"""
def add_error(span, kind, reason, stacktrace) do
{name, message, formatted_stacktrace} = Appsignal.Error.metadata(kind, reason, stacktrace)
do_add_error(span, name, message, formatted_stacktrace)
end
@spec add_error(t() | nil, Exception.t(), Exception.stacktrace()) :: t() | nil
@doc """
Add an error to an `Appsignal.Span` by passing an exception from a `rescue`
block, and a stack trace.
## Example
span = Appsignal.Tracer.root_span()
try
raise "Exception!"
rescue
exception ->
Appsignal.Span.add_error(span, exception, __STACKTRACE__)
end
"""
def add_error(span, %_{__exception__: true} = exception, stacktrace) do
{name, message, formatted_stacktrace} = Appsignal.Error.metadata(exception, stacktrace)
do_add_error(span, name, message, formatted_stacktrace)
end
@doc false
def do_add_error(%Span{reference: reference} = span, name, message, stacktrace) do
if Config.active?() do
:ok =
@nif.add_span_error(
reference,
name,
message,
Appsignal.Utils.DataEncoder.encode(stacktrace)
)
span
end
end
def do_add_error(nil, _name, _message, _stacktrace), do: nil
@spec close(t() | nil) :: t() | nil
@doc """
Close an `Appsignal.Span`.
## Example
Appsignal.Tracer.root_span()
|> Span.close()
"""
def close(%Span{reference: reference} = span) do
:ok = @nif.close_span(reference)
span
end
def close(nil), do: nil
@spec close(t() | nil, integer()) :: t() | nil
@doc """
Close an `Appsignal.Span` with an explicit end time.
## Example
Appsignal.Tracer.root_span()
|> Span.close(span, :os.system_time())
"""
def close(%Span{reference: reference} = span, end_time) do
sec = :erlang.convert_time_unit(end_time, :native, :second)
nsec = :erlang.convert_time_unit(end_time, :native, :nanosecond) - sec * 1_000_000_000
:ok = @nif.close_span_with_timestamp(reference, sec, nsec)
span
end
def close(nil, _end_time), do: nil
@doc false
def to_map(%Span{reference: reference}) do
{:ok, json} = Nif.span_to_json(reference)
Appsignal.Json.decode!(json)
end
end