Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ config :sentry,
| `hackney_pool_timeout` | False | 5000 | |
| `before_send_event` | False | | |
| `after_send_event` | False | | |
| `sample_rate` | False | 1.0 | |
| `enable_source_code_context` | True | | |
| `root_source_code_path` | Required if `enable_source_code_context` is enabled | | Should generally be set to `File.cwd!`|
| `context_lines` | False | 3 | |
Expand Down
4 changes: 4 additions & 0 deletions docs/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ Optional settings

This option allows performing arbitrary operations after attempting to send an event. Accepts an anonymous function or a {module, function} tuple, and the event will be passed as the first argument, and the result of sending the event will be passed as the second argument.

.. describe:: sample_rate

The sampling factor to apply to events. A value of 0.0 will deny sending any events, and a value of 1.0 will send 100% of events.

.. describe:: context_lines

The number of lines of source code before and after the line that caused the exception to be included. Defaults to ``3``.
Expand Down
22 changes: 21 additions & 1 deletion lib/sentry/client.ex
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ defmodule Sentry.Client do
@type get_dsn :: {String.t, String.t, Integer.t}
@sentry_version 5
@max_attempts 4
@default_sample_rate 1.0
@hackney_pool_name :sentry_pool

quote do
Expand All @@ -54,12 +55,23 @@ defmodule Sentry.Client do

### Options
* `:result` - Allows specifying how the result should be returned. Options include `:sync`, `:none`, and `:async`. `:sync` will make the API call synchronously, and return `{:ok, event_id}` if successful. `:none` sends the event from an unlinked child process under `Sentry.TaskSupervisor` and will return `{:ok, ""}` regardless of the result. `:async` will start an unlinked task and return a tuple of `{:ok, Task.t}` on success where the Task can be awaited upon to receive the result asynchronously. When used in an OTP behaviour like GenServer, the task will send a message that needs to be matched with `GenServer.handle_info/2`. See `Task.Supervisor.async_nolink/2` for more information. `:async` is the default.
* `:sample_rate` - The sampling factor to apply to events. A value of 0.0 will deny sending any events, and a value of 1.0 will send 100% of events.
"""
@spec send_event(Event.t) :: {:ok, Task.t | String.t} | :error
@spec send_event(Event.t) :: {:ok, Task.t | String.t} | :error | :unsampled
def send_event(%Event{} = event, opts \\ []) do
result = Keyword.get(opts, :result, :async)
sample_rate = Keyword.get(opts, :sample_rate) || Application.get_env(:sentry, :sample_rate, @default_sample_rate)

event = maybe_call_before_send_event(event)

if sample_event?(sample_rate) do
encode_and_send(event, result)
else
:unsampled
end
end

defp encode_and_send(event, result) do
case Poison.encode(event) do
{:ok, body} ->
do_send_event(event, body, result)
Expand Down Expand Up @@ -225,4 +237,12 @@ defmodule Sentry.Client do
|> Kernel.round()
|> :timer.sleep()
end

defp sample_event?(1), do: true
defp sample_event?(1.0), do: true
defp sample_event?(0), do: false
defp sample_event?(0.0), do: false
defp sample_event?(sample_rate) do
:rand.uniform < sample_rate
end
end
42 changes: 42 additions & 0 deletions test/client_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -156,4 +156,46 @@ defmodule Sentry.ClientTest do
end) =~ "AFTER_SEND_EVENT"
end
end

test "sends event with sample_rate of 1" do
bypass = Bypass.open
Bypass.expect bypass, fn conn ->
{:ok, _body, conn} = Plug.Conn.read_body(conn)
Plug.Conn.resp(conn, 200, ~s<{"id": "340"}>)
end

modify_env(:sentry, [dsn: "http://public:secret@localhost:#{bypass.port}/1",
client: Sentry.Client
]
)

try do
Event.not_a_function
rescue
e ->
{:ok, _} = Sentry.capture_exception(e, result: :sync, sample_rate: 1)
end
end

test "does not send event with sample_rate of 0" do
bypass = Bypass.open
Bypass.expect bypass, fn conn ->
{:ok, _body, conn} = Plug.Conn.read_body(conn)
Plug.Conn.resp(conn, 200, ~s<{"id": "340"}>)
end

modify_env(:sentry, [dsn: "http://public:secret@localhost:#{bypass.port}/1",
client: Sentry.Client
]
)

try do
Event.not_a_function
rescue
e ->
{:ok, _} = Sentry.capture_exception(e, result: :sync, sample_rate: 1)
Bypass.down(bypass)
:unsampled = Sentry.capture_exception(e, result: :sync, sample_rate: 0.0)
end
end
end