Packages
timber
1.0.5
3.1.2
3.1.1
3.1.0
3.0.0
3.0.0-alpha.3
3.0.0-alpha.2
3.0.0-alpha.1
2.8.4
2.8.3
2.8.2
2.8.1
2.8.0
2.7.0
2.6.1
2.6.0
2.5.6
2.5.5
2.5.4
2.5.3
2.5.2
2.5.1
2.5.0
2.4.5
2.4.4
2.4.3
2.4.2
2.4.1
2.4.0
2.3.4
2.3.3
2.3.1
2.3.0
2.2.1
2.2.0
2.1.8
2.1.7
2.1.6
2.1.5
2.1.4
2.1.3
2.1.2
2.1.1
2.1.0
2.0.2
2.0.1
2.0.0
2.0.0-rc7
2.0.0-rc6
2.0.0-rc5
2.0.0-rc4
2.0.0-rc3
2.0.0-rc2
2.0.0-rc1
1.1.18
1.1.17
1.1.16
1.1.15
1.1.14
1.1.13
1.1.12
1.1.11
1.1.10
1.1.9
1.1.8
1.1.7
1.1.6
1.1.5
1.1.4
1.1.3
1.1.2
1.1.1
1.1.0
1.0.16
1.0.15
1.0.14
1.0.13
1.0.12
1.0.11
1.0.10
1.0.9
1.0.8
1.0.7
1.0.6
1.0.5
1.0.4
1.0.3
1.0.2
1.0.1
1.0.0
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.2
0.3.1
0.3.0
0.2.3
0.2.2
0.2.1
0.2.0
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0
🌲 Great Elixir Logging Made Easy. Official Timber.io Integration.
Current section
Files
Jump to
Current section
Files
lib/timber/events/exception_event.ex
defmodule Timber.Events.ExceptionEvent do
@moduledoc """
The `ExceptionEvent` is used to track exceptions.
Timber can automatically keep track of errors reported by the VM by hooking
into the SASL reporting system to collect exception information, so it should
be unnecessary to track exceptions manually. See `Timber.Integrations.ErrorLogger` for
more details.
"""
alias Timber.Utils.Module, as: UtilsModule
@type stacktrace_entry :: {
module,
atom,
arity,
[file: IO.chardata, line: non_neg_integer] | []
}
@type backtrace_entry :: %{
function: String.t,
file: String.t | nil,
line: non_neg_integer | nil
}
@type t :: %__MODULE__{
backtrace: [backtrace_entry] | [],
name: String.t,
message: String.t,
}
@enforce_keys [:backtrace, :name, :message]
defstruct [:backtrace, :name, :message]
@doc """
Builds a new struct taking care to normalize data into a valid state. This should
be used, where possible, instead of creating the struct directly.
"""
@spec new(atom | Exception.t, [stacktrace_entry] | []) :: t
def new(error, stacktrace \\ []) do
{name, message} = transform_error(error)
backtrace = Enum.map(stacktrace, &transform_stacktrace/1)
%__MODULE__{
name: name,
message: message,
backtrace: backtrace
}
end
@doc """
Message to be used when logging.
"""
@spec message(t) :: IO.chardata
def message(%__MODULE__{name: name, message: message}),
do: [name, ?:, ?\s, message]
defp transform_error(error) when is_atom(error) do
name = inspect(error)
{name, name}
end
defp transform_error(%{__exception__: true, __struct__: module} = error) do
name = UtilsModule.name(module)
msg = Exception.message(error)
{name, msg}
end
defp transform_stacktrace({module, function_name, arity, fileinfo}) do
module_name = UtilsModule.name(module)
function_name = Atom.to_string(function_name)
function = to_string([module_name, ?., function_name, ?/, to_string(arity)])
backtrace_entry = %{
function: function
}
case file_information(fileinfo) do
{filename, lineno} ->
backtrace_entry
|> Map.put(:file, filename)
|> Map.put(:line, lineno)
_ ->
backtrace_entry
end
end
defp file_information([]) do
:no_file
end
defp file_information(fileinfo) do
filename = Keyword.get(fileinfo, :file)
lineno = Keyword.get(fileinfo, :line)
if filename && lineno do
{to_string(filename), to_string(lineno)}
else
:bad_descriptor
end
end
end