Skip to content

Commit 79e0c61

Browse files
Slightly re-haul how we document options (#778)
Co-authored-by: Andrea Leopardi <[email protected]>
1 parent d79919f commit 79e0c61

File tree

5 files changed

+278
-232
lines changed

5 files changed

+278
-232
lines changed

lib/sentry.ex

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ defmodule Sentry do
1616
[*Setup with Plug and Phoenix* guide](setup-with-plug-and-phoenix.html), and the
1717
`Sentry.PlugCapture` and `Sentry.PlugContext` modules.
1818
19+
* Through integrations for various ecosystem tools, like [Oban](oban-integration.html)
20+
or [Quantum](quantum-integration.html).
21+
1922
## Usage
2023
2124
Add the following to your production configuration:
@@ -65,9 +68,11 @@ defmodule Sentry do
6568
6669
## Configuration
6770
68-
You can configure Sentry through the application environment. Configure
69-
the following keys under the `:sentry` application. For example, you can
70-
do this in `config/config.exs`:
71+
*See also the [official Sentry
72+
documentation](https://docs.sentry.io/platforms/elixir/configuration/).*
73+
74+
You can configure Sentry through the application environment, under the `:sentry` application.
75+
For example, you can do this in `config/config.exs`:
7176
7277
# config/config.exs
7378
config :sentry,
@@ -174,7 +179,7 @@ defmodule Sentry do
174179
> with `:source_code_exclude_patterns`.
175180
"""
176181

177-
alias Sentry.{CheckIn, Client, ClientError, Config, Event, LoggerUtils}
182+
alias Sentry.{CheckIn, Client, ClientError, Config, Event, LoggerUtils, Options}
178183

179184
require Logger
180185

@@ -224,13 +229,15 @@ defmodule Sentry do
224229
and is not `nil`. See the [*Configuration* section](#module-configuration)
225230
in the module documentation.
226231
227-
The `opts` argument is passed as the second argument to `send_event/2`.
232+
## Options
233+
234+
#{Options.docs_for(:capture_exception)}
228235
"""
229-
@spec capture_exception(Exception.t(), keyword()) :: send_result
230-
def capture_exception(exception, opts \\ []) do
236+
@spec capture_exception(Exception.t(), keyword()) :: send_result()
237+
def capture_exception(exception, options \\ []) do
231238
filter_module = Config.filter()
232-
event_source = Keyword.get(opts, :event_source)
233-
{send_opts, create_event_opts} = Client.split_send_event_opts(opts)
239+
event_source = Keyword.get(options, :event_source)
240+
{send_opts, create_event_opts} = Options.split_send_event_options(options)
234241

235242
if filter_module.exclude_exception?(exception, event_source) do
236243
:excluded
@@ -263,7 +270,9 @@ defmodule Sentry do
263270
@doc """
264271
Reports a message to Sentry.
265272
266-
`opts` argument is passed as the second argument to `send_event/2`.
273+
## Options
274+
275+
#{Options.docs_for(:capture_message)}
267276
268277
## Interpolation (since v10.1.0)
269278
@@ -289,7 +298,7 @@ defmodule Sentry do
289298
{send_opts, create_event_opts} =
290299
opts
291300
|> Keyword.put(:message, message)
292-
|> Client.split_send_event_opts()
301+
|> Options.split_send_event_options()
293302

294303
event = Event.create_event(create_event_opts)
295304
send_event(event, send_opts)
@@ -302,9 +311,13 @@ defmodule Sentry do
302311
information about an exception, a message, or any other event that you want to
303312
report. To manually build events, see the functions in `Sentry.Event`.
304313
314+
This function doesn't build the event for you, it only *sends* it. Most of the time,
315+
you'll want to use `capture_exception/2` or `capture_message/2`. To manually create events,
316+
see `Sentry.Event.create_event/1`.
317+
305318
## Options
306319
307-
#{NimbleOptions.docs(Client.send_events_opts_schema())}
320+
#{Options.docs_for(:send_event)}
308321
309322
> #### Async Send {: .error}
310323
>
@@ -321,7 +334,7 @@ defmodule Sentry do
321334
> use cases, use `capture_exception/2` or `capture_message/2`.
322335
"""
323336
@spec send_event(Event.t(), keyword()) :: send_result
324-
def send_event(event, opts \\ []) do
337+
def send_event(event, options \\ []) do
325338
# TODO: remove on v11.0.0, :included_environments was deprecated in 10.0.0.
326339
included_envs = Config.included_environments()
327340

@@ -332,14 +345,16 @@ defmodule Sentry do
332345

333346
# If we're in test mode, let's send the event down the pipeline anyway.
334347
Config.test_mode?() ->
335-
Client.send_event(event, opts)
348+
Client.send_event(event, options)
336349

337350
!Config.dsn() ->
338-
_opts = Client.validate_options!(opts)
351+
# We still validate options even if we're not sending the event. This aims at catching
352+
# configuration issues during development instead of only when deploying to production.
353+
_options = NimbleOptions.validate!(options, Options.send_event_schema())
339354
:ignored
340355

341356
included_envs == :all or to_string(Config.environment_name()) in included_envs ->
342-
Client.send_event(event, opts)
357+
Client.send_event(event, options)
343358

344359
true ->
345360
:ignored
@@ -366,10 +381,6 @@ defmodule Sentry do
366381
> to Sentry and will instead return `:ignored`. This behaviour is consistent with
367382
> the rest of the SDK (such as `capture_exception/2`).
368383
369-
## Options
370-
371-
This functions supports all the options mentioned in `Sentry.CheckIn.new/1`.
372-
373384
## Examples
374385
375386
Say you have a GenServer which periodically sends a message to itself to execute some

lib/sentry/client.ex

Lines changed: 3 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -14,80 +14,15 @@ defmodule Sentry.Client do
1414
Event,
1515
Interfaces,
1616
LoggerUtils,
17-
Transport
17+
Transport,
18+
Options
1819
}
1920

2021
require Logger
2122

2223
# Max message length per https://github.com/getsentry/sentry/blob/0fcec33ac94ad81a205f86f208072b0f57b39ff4/src/sentry/conf/server.py#L1021
2324
@max_message_length 8_192
2425

25-
# The docs for the options here are generated in the Sentry module, so you can refer to types
26-
# and functions and so on like if you were writing these docs in the Sentry module itself.
27-
send_event_opts_schema = [
28-
result: [
29-
type: {:in, [:sync, :none]},
30-
doc: """
31-
Allows specifying how the result should be returned. The possible values are:
32-
33-
* `:sync` - Sentry will make an API call synchronously (including retries) and will
34-
return `{:ok, event_id}` if successful.
35-
36-
* `:none` - Sentry will send the event in the background, in a *fire-and-forget*
37-
fashion. The function will return `{:ok, ""}` regardless of whether the API
38-
call ends up being successful or not.
39-
"""
40-
],
41-
sample_rate: [
42-
type: :float,
43-
doc: """
44-
Same as the global `:sample_rate` configuration, but applied only to
45-
this call. See the module documentation. *Available since v10.0.0*.
46-
"""
47-
],
48-
before_send: [
49-
type: {:or, [{:fun, 1}, {:tuple, [:atom, :atom]}]},
50-
type_doc: "`t:before_send_event_callback/0`",
51-
doc: """
52-
Same as the global `:before_send` configuration, but
53-
applied only to this call. See the module documentation. *Available since v10.0.0*.
54-
"""
55-
],
56-
after_send_event: [
57-
type: {:or, [{:fun, 2}, {:tuple, [:atom, :atom]}]},
58-
type_doc: "`t:after_send_event_callback/1`",
59-
doc: """
60-
Same as the global `:after_send_event` configuration, but
61-
applied only to this call. See the module documentation. *Available since v10.0.0*.
62-
"""
63-
],
64-
client: [
65-
type: :atom,
66-
type_doc: "`t:module/0`",
67-
doc: """
68-
Same as the global `:client` configuration, but
69-
applied only to this call. See the module documentation. *Available since v10.0.0*.
70-
"""
71-
],
72-
73-
# Private options, only used in testing.
74-
request_retries: [
75-
type: {:list, :integer},
76-
doc: false
77-
]
78-
]
79-
80-
@send_event_opts_schema NimbleOptions.new!(send_event_opts_schema)
81-
@send_event_opts_keys Keyword.keys(send_event_opts_schema)
82-
83-
@spec send_events_opts_schema() :: NimbleOptions.t()
84-
def send_events_opts_schema, do: @send_event_opts_schema
85-
86-
@spec split_send_event_opts(keyword()) :: {keyword(), keyword()}
87-
def split_send_event_opts(options) when is_list(options) do
88-
Keyword.split(options, @send_event_opts_keys)
89-
end
90-
9126
@spec send_check_in(CheckIn.t(), keyword()) ::
9227
{:ok, check_in_id :: String.t()} | {:error, term()}
9328
def send_check_in(%CheckIn{} = check_in, opts) when is_list(opts) do
@@ -116,7 +51,7 @@ defmodule Sentry.Client do
11651
| :unsampled
11752
| :excluded
11853
def send_event(%Event{} = event, opts) when is_list(opts) do
119-
opts = validate_options!(opts)
54+
opts = NimbleOptions.validate!(opts, Options.send_event_schema())
12055

12156
result_type = Keyword.get_lazy(opts, :result, &Config.send_result/0)
12257
sample_rate = Keyword.get_lazy(opts, :sample_rate, &Config.sample_rate/0)
@@ -160,11 +95,6 @@ defmodule Sentry.Client do
16095
end
16196
end
16297

163-
@spec validate_options!(keyword()) :: keyword()
164-
def validate_options!(opts) when is_list(opts) do
165-
NimbleOptions.validate!(opts, @send_event_opts_schema)
166-
end
167-
16898
defp sample_event(sample_rate) do
16999
cond do
170100
sample_rate == 1 -> :ok

lib/sentry/event.ex

Lines changed: 4 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ defmodule Sentry.Event do
88
See <https://develop.sentry.dev/sdk/event-payloads>.
99
"""
1010

11-
alias Sentry.{Attachment, Config, Interfaces, Sources, UUID}
11+
alias Sentry.{Attachment, Config, Interfaces, Sources, UUID, Options}
1212

1313
@sdk %Interfaces.SDK{
1414
name: "sentry-elixir",
@@ -147,139 +147,7 @@ defmodule Sentry.Event do
147147
|> Map.drop([:original_exception, :source, :attachments, :integration_meta])
148148
end
149149

150-
create_event_opts_schema = [
151-
exception: [
152-
type: {:custom, __MODULE__, :__validate_exception__, [:exception]},
153-
type_doc: "`t:Exception.t/0`",
154-
doc: """
155-
This is the exception that gets reported in the
156-
`:exception` field of `t:t/0`. The term passed here also ends up unchanged in the
157-
`:original_exception` field of `t:t/0`. This option is **required** unless the
158-
`:message` option is present. Not present by default.
159-
"""
160-
],
161-
stacktrace: [
162-
type:
163-
{:list,
164-
{:or,
165-
[
166-
{:tuple, [:atom, :atom, :any, :keyword_list]},
167-
{:tuple, [:any, :any, :keyword_list]}
168-
]}},
169-
type_doc: "`t:Exception.stacktrace/0`",
170-
doc: """
171-
The exception's stacktrace. This can also be used with messages (`:message`). Not
172-
present by default.
173-
"""
174-
],
175-
message: [
176-
type: :string,
177-
doc: """
178-
A message to report. The string can contain interpolation markers (`%s`). In that
179-
case, you can pass the `:interpolation_parameters` option as well to fill
180-
in those parameters. See `Sentry.capture_message/2` for more information on
181-
message interpolation. Not present by default.
182-
"""
183-
],
184-
extra: [
185-
type: {:map, {:or, [:atom, :string]}, :any},
186-
type_doc: "`t:Sentry.Context.extra/0`",
187-
default: %{},
188-
doc: """
189-
Map of extra context, which gets merged with the current context
190-
(see `Sentry.Context.set_extra_context/1`). If fields collide, the ones
191-
in the map passed through this option have precedence over the ones in
192-
the context.
193-
"""
194-
],
195-
user: [
196-
type: :map,
197-
type_doc: "`t:Sentry.Context.user_context/0`",
198-
default: %{},
199-
doc: """
200-
Map of user context, which gets merged with the current context
201-
(see `Sentry.Context.set_user_context/1`). If fields collide, the ones
202-
in the map passed through this option have precedence over the ones in
203-
the context.
204-
"""
205-
],
206-
tags: [
207-
type: {:map, {:or, [:atom, :string]}, :any},
208-
type_doc: "`t:Sentry.Context.tags/0`",
209-
default: %{},
210-
doc: """
211-
Map of tags context, which gets merged with the current context (see
212-
`Sentry.Context.set_tags_context/1`) and with the `:tags` option in the global
213-
Sentry configuration. If fields collide, the ones in the map passed through
214-
this option have precedence over the ones in the context, which have precedence
215-
over the ones in the configuration.
216-
"""
217-
],
218-
request: [
219-
type: :map,
220-
type_doc: "`t:Sentry.Context.request_context/0`",
221-
default: %{},
222-
doc: """
223-
Map of request context, which gets merged with the current context
224-
(see `Sentry.Context.set_request_context/1`). If fields collide, the ones
225-
in the map passed through this option have precedence over the ones in
226-
the context.
227-
"""
228-
],
229-
breadcrumbs: [
230-
type: {:list, {:or, [:keyword_list, :map]}},
231-
type_doc: "list of `t:keyword/0` or `t:Sentry.Context.breadcrumb/0`",
232-
default: [],
233-
doc: """
234-
List of breadcrumbs. This list gets **prepended** to the list
235-
in the context (see `Sentry.Context.add_breadcrumb/1`).
236-
"""
237-
],
238-
level: [
239-
type: {:in, [:fatal, :error, :warning, :info, :debug]},
240-
type_doc: "`t:level/0`",
241-
default: :error,
242-
doc: """
243-
The level of the event.
244-
"""
245-
],
246-
fingerprint: [
247-
type: {:list, :string},
248-
default: ["{{ default }}"],
249-
doc: """
250-
List of the fingerprint for grouping this event.
251-
"""
252-
],
253-
event_source: [
254-
type: :atom,
255-
doc: """
256-
The source of the event. This fills in the `:source` field of the
257-
returned struct. This is not present by default.
258-
"""
259-
],
260-
interpolation_parameters: [
261-
type: {:list, :any},
262-
doc: """
263-
The parameters to use for message interpolation. This is only used if the
264-
`:message` option is present. This is not present by default. See
265-
`Sentry.capture_message/2`. *Available since v10.1.0*.
266-
"""
267-
],
268-
integration_meta: [
269-
type: :map,
270-
default: %{},
271-
doc: false
272-
],
273-
274-
## Internal options
275-
handled: [
276-
type: :boolean,
277-
default: true,
278-
doc: false
279-
]
280-
]
281-
282-
@create_event_opts_schema NimbleOptions.new!(create_event_opts_schema)
150+
@create_event_opts_schema Options.create_event_schema()
283151

284152
@doc """
285153
Creates an event struct out of collected context and options.
@@ -461,12 +329,11 @@ defmodule Sentry.Event do
461329
@doc """
462330
Transforms an exception to a Sentry event.
463331
464-
This essentially defers to `create_event/1`, inferring some options from
465-
the given `exception`.
332+
This essentially defers to `create_event/1`.
466333
467334
## Options
468335
469-
This function takes the same options as `create_event/1`.
336+
This function takes the same options as `create_event/1`, except for the `:exception` option.
470337
"""
471338
@spec transform_exception(Exception.t(), keyword()) :: t()
472339
def transform_exception(exception, opts) when is_exception(exception) and is_list(opts) do

0 commit comments

Comments
 (0)