Packages
timber
0.4.1
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 exception event 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.ErrorLogger` for
more details.
"""
@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] | [],
description: String.t,
name: String.t,
message: String.t
}
defstruct [:backtrace, :description, :name, :message]
@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,
description: message,
message: message,
backtrace: backtrace
}
end
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 = module_name(module)
msg = Exception.message(error)
{name, msg}
end
defp transform_stacktrace({module, function_name, arity, fileinfo}) do
module_name = module_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
defp module_name(module) do
module
|> List.wrap()
|> Module.concat()
|> Atom.to_string()
end
end