Skip to content

Commit 2c158b2

Browse files
authored
Do not store error if context/occurrence is not valid (#66)
This commit fixes an issue when providing invalid content inside the error context. It also updates the documentation to explicitly state that the context data must be JSON-encodeable. Previously when providing incorrect context data the Error would be stored but not the Occurrence. This produced Errors that show up on the dashboard but cannot be opened because they have no Occurrences. This commit updates the process to use a DB transaction so it ensures that both the Error and Occurrence are stored properly, or not at all. Closes #65
1 parent 0731f89 commit 2c158b2

File tree

3 files changed

+39
-10
lines changed

3 files changed

+39
-10
lines changed

guides/Getting Started.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ The `ErrorTracker.set_context/1` function stores the given context in the curren
108108
ErrorTracker.set_context(%{user_id: conn.assigns.current_user.id})
109109
```
110110

111+
There are some requirements on the type of data that can be included in the context, so we recommend taking a look at `set_context/1` documentation
112+
111113
## Manual error tracking
112114

113115
If you want to report custom errors that fall outside the default integration scope, you may use `ErrorTracker.report/2`. This allows you to report an exception yourself:

lib/error_tracker.ex

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ defmodule ErrorTracker do
4141
can gather, but aside from that, you can also add your own information. You can
4242
do this in a per-process basis or in a per-call basis (or both).
4343
44+
There are some requirements on the type of data that can be included in the
45+
context, so we recommend taking a look at `set_context/1` documentation.
46+
4447
**Per process**
4548
4649
This allows you to set a general context for the current process such as a Phoenix
@@ -152,6 +155,17 @@ defmodule ErrorTracker do
152155
153156
That means that any existing data on deep levels for he current context will
154157
be replaced if the first level key is received on the new contents.
158+
159+
## Content serialization
160+
161+
The content stored on the context should be serializable using the JSON library
162+
used by the application (usually `Jason`), so it is rather recommended to use
163+
primitive types (strings, numbers, booleans...).
164+
165+
If you still need to pass more complex data types to your context, please test
166+
that they can be encoded to JSON or storing the errors will fail. In the case
167+
of `Jason` that may require defining an Encoder for that data type if not
168+
included by default.
155169
"""
156170
@spec set_context(context()) :: context()
157171
def set_context(params) when is_map(params) do
@@ -188,16 +202,25 @@ defmodule ErrorTracker do
188202
existing_status =
189203
Repo.one(from e in Error, where: [fingerprint: ^error.fingerprint], select: e.status)
190204

191-
error =
192-
Repo.insert!(error,
193-
on_conflict: [set: [status: :unresolved, last_occurrence_at: DateTime.utc_now()]],
194-
conflict_target: :fingerprint
195-
)
196-
197-
occurrence =
198-
error
199-
|> Ecto.build_assoc(:occurrences, stacktrace: stacktrace, context: context, reason: reason)
200-
|> Repo.insert!()
205+
{:ok, {error, occurrence}} =
206+
Repo.transaction(fn ->
207+
error =
208+
Repo.insert!(error,
209+
on_conflict: [set: [status: :unresolved, last_occurrence_at: DateTime.utc_now()]],
210+
conflict_target: :fingerprint
211+
)
212+
213+
occurrence =
214+
error
215+
|> Ecto.build_assoc(:occurrences,
216+
stacktrace: stacktrace,
217+
context: context,
218+
reason: reason
219+
)
220+
|> Repo.insert!()
221+
222+
{error, occurrence}
223+
end)
201224

202225
# If the error existed and was marked as resolved before this exception,
203226
# sent a Telemetry event

lib/error_tracker/repo.ex

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ defmodule ErrorTracker.Repo do
2929
dispatch(:aggregate, [queryable, aggregate], opts)
3030
end
3131

32+
def transaction(fun_or_multi, opts \\ []) do
33+
dispatch(:transaction, [fun_or_multi], opts)
34+
end
35+
3236
def with_adapter(fun) do
3337
adapter =
3438
case repo().__adapter__() do

0 commit comments

Comments
 (0)