-
Notifications
You must be signed in to change notification settings - Fork 55
/
notice.ex
108 lines (87 loc) · 3.18 KB
/
notice.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
defmodule Honeybadger.Notice do
@doc false
alias Honeybadger.{Backtrace, Utils}
alias Honeybadger.Breadcrumbs.{Collector}
@type error :: %{
backtrace: list,
class: atom | iodata,
fingerprint: String.t(),
message: iodata,
tags: list
}
@type notifier :: %{name: String.t(), url: String.t(), version: String.t()}
@type server :: %{
environment_name: atom,
hostname: String.t(),
project_root: Path.t(),
revision: String.t()
}
@type noticeable :: Exception.t() | String.t() | map() | atom()
@type t :: %__MODULE__{
notifier: notifier(),
server: server(),
error: error(),
breadcrumbs: Collector.t(),
request: map()
}
@url get_in(Honeybadger.Mixfile.project(), [:package, :links, "GitHub"])
@version Honeybadger.Mixfile.project()[:version]
@notifier %{name: "honeybadger-elixir", language: "elixir", url: @url, version: @version}
@derive Jason.Encoder
@enforce_keys [:breadcrumbs, :notifier, :server, :error, :request]
defstruct [:breadcrumbs, :notifier, :server, :error, :request]
@spec new(noticeable(), map(), list(), String.t()) :: t()
def new(error, metadata, stacktrace, fingerprint \\ "")
def new(message, metadata, stacktrace, fingerprint)
when is_binary(message) and is_map(metadata) and is_list(stacktrace) do
new(%RuntimeError{message: message}, metadata, stacktrace, fingerprint)
end
def new(%{class: exception_name, message: message}, metadata, stacktrace, fingerprint)
when is_map(metadata) and is_list(stacktrace) do
new(exception_name, message, metadata, stacktrace, fingerprint)
end
def new(exception, metadata, stacktrace, fingerprint)
when is_map(metadata) and is_list(stacktrace) do
{exception, _stacktrace} = Exception.blame(:error, exception, stacktrace)
%{__struct__: exception_mod} = exception
class = Utils.module_to_string(exception_mod)
message = exception_mod.message(exception)
new(class, message, metadata, stacktrace, fingerprint)
end
# bundles exception (or pseudo exception) information in to notice
defp new(class, message, metadata, stacktrace, fingerprint) do
message = if message, do: IO.iodata_to_binary(message), else: nil
error = %{
class: class,
message: message,
backtrace: Backtrace.from_stacktrace(stacktrace),
tags: Map.get(metadata, :tags, []),
fingerprint: fingerprint
}
request =
metadata
|> Map.get(:plug_env, %{})
|> Map.put(:context, Map.get(metadata, :context, %{}))
filter(%__MODULE__{
breadcrumbs: Map.get(metadata, :breadcrumbs, %{}),
error: error,
request: request,
notifier: @notifier,
server: server()
})
end
defp filter(notice) do
case Honeybadger.get_env(:notice_filter) do
nil -> notice
notice_filter -> notice_filter.filter(notice)
end
end
defp server do
%{
environment_name: Honeybadger.get_env(:environment_name),
hostname: Honeybadger.get_env(:hostname),
project_root: Honeybadger.get_env(:project_root),
revision: Honeybadger.get_env(:revision)
}
end
end