Skip to content

Commit 03003b4

Browse files
Merge pull request #130 from getsentry/sentry-hackney-pool
separate hackney pool
2 parents ea05387 + 341e88b commit 03003b4

File tree

6 files changed

+47
-5
lines changed

6 files changed

+47
-5
lines changed

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,9 @@ config :sentry,
6767
| `release` | False | None | |
6868
| `server_name` | False | None | |
6969
| `use_error_logger` | False | False | |
70-
| hackney_opts | False | [] | |
70+
| hackney_opts | False | `[pool: :sentry_pool]` | |
71+
| hackney_pool_max_connections | False | 50 | |
72+
| hackney_pool_timeout | False | 5000 | |
7173

7274
An example production config might look like this:
7375

@@ -113,7 +115,7 @@ Now, on our servers, we can set the environment variable appropriately. On
113115
our local development machines, exceptions will never be sent, because the
114116
default value is not in the list of `included_environments`.
115117

116-
Sentry uses the [hackney HTTP client](https://github.com/benoitc/hackney) for HTTP requests. If you need to set [hackney configurations](https://github.com/benoitc/hackney/blob/master/doc/hackney.md#request5) for things like a proxy or different pool, the `hackney_opts` configuration is passed directly to hackney.
118+
Sentry uses the [hackney HTTP client](https://github.com/benoitc/hackney) for HTTP requests. Sentry starts its own hackney pool named `:sentry_pool` with a default connection pool of 50, and a connection timeout of 5000 milliseconds. The pool can be configured with the `hackney_pool_max_connections` and `hackney_pool_timeout` configuration keys. If you need to set other [hackney configurations](https://github.com/benoitc/hackney/blob/master/doc/hackney.md#request5) for things like a proxy, using your own pool or response timeouts, the `hackney_opts` configuration is passed directly to hackney for each request.
117119

118120
## Testing Your Configuration
119121

config/test.exs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ use Mix.Config
22

33
config :sentry,
44
environment_name: :test,
5-
client: Sentry.TestClient
5+
client: Sentry.TestClient,
6+
hackney_opts: [recv_timeout: 50]

docs/config.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,17 @@ Optional settings
5757
Set this to a module that implements the ``Sentry.EventFilter`` behaviour if you would like to prevent
5858
certain exceptions from being sent. See below for further documentation.
5959

60+
.. describe:: hackney_pool_max_connections
61+
62+
Number of connections for Sentry's hackney pool. This defaults to 50.
63+
64+
.. describe:: hackney_pool_timeout
65+
66+
Timeout for Sentry's hackney pool. This defaults to 5000 milliseconds.
67+
6068
.. describe:: hackney_opts
6169

62-
Sentry uses `hackney <https://github.com/benoitc/hackney>`_. If you would like to set `options <https://github.com/benoitc/hackney/blob/master/doc/hackney.md#request5>`_ for hackney requests, they can be provided via this configuration.
70+
Sentry starts its own hackney pool named ``:sentry_pool``, and defaults to using it. Hackney's ``pool`` configuration as well others like proxy or response timeout can be set through this configuration as it is passed directly to hackney when making a request.
6371

6472
Testing Your Configuration
6573
--------------------------

lib/sentry.ex

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,13 @@ defmodule Sentry do
9494
@client Application.get_env(:sentry, :client, Sentry.Client)
9595
@use_error_logger Application.get_env(:sentry, :use_error_logger, false)
9696
@default_environment_name Mix.env
97+
@max_hackney_connections Application.get_env(:sentry, :hackney_pool_max_connections, 50)
98+
@hackney_timeout Application.get_env(:sentry, :hackney_pool_timeout, 5000)
9799

98100
def start(_type, _opts) do
99101
children = [
100102
supervisor(Task.Supervisor, [[name: Sentry.TaskSupervisor]]),
103+
:hackney_pool.child_spec(Sentry.Client.hackney_pool_name(), [timeout: @hackney_timeout, max_connections: @max_hackney_connections])
101104
]
102105
opts = [strategy: :one_for_one, name: Sentry.Supervisor]
103106

lib/sentry/client.ex

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ defmodule Sentry.Client do
44
@type get_dsn :: {String.t, String.t, Integer.t}
55
@sentry_version 5
66
@max_attempts 4
7+
@hackney_pool_name :sentry_pool
78

89
quote do
910
unquote(@sentry_client "sentry-elixir/#{Mix.Project.config[:version]}")
@@ -59,6 +60,7 @@ defmodule Sentry.Client do
5960
"""
6061
def request(method, url, headers, body) do
6162
hackney_opts = Application.get_env(:sentry, :hackney_opts, [])
63+
|> Keyword.put_new(:pool, @hackney_pool_name)
6264
case :hackney.request(method, url, headers, body, hackney_opts) do
6365
{:ok, 200, _headers, client} ->
6466
case :hackney.body(client) do
@@ -112,6 +114,10 @@ defmodule Sentry.Client do
112114
{endpoint, public_key, secret_key}
113115
end
114116

117+
def hackney_pool_name do
118+
@hackney_pool_name
119+
end
120+
115121
defp fetch_dsn do
116122
case Application.fetch_env!(:sentry, :dsn) do
117123
{:system, env_var} -> System.get_env(env_var)
@@ -121,7 +127,7 @@ defmodule Sentry.Client do
121127

122128
defp log_api_error(body) do
123129
Logger.warn(fn ->
124-
["Failed to send sentry event.", ?\n, body]
130+
["Failed to send Sentry event.", ?\n, body]
125131
end)
126132
end
127133

test/sentry_test.exs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
defmodule SentryTest do
22
use ExUnit.Case
3+
import ExUnit.CaptureLog
34

45
test "excludes events properly" do
56
Application.put_env(:sentry, :filter, Sentry.TestFilter)
@@ -22,4 +23,25 @@ defmodule SentryTest do
2223
assert :excluded = Sentry.capture_exception(%ArithmeticError{message: "error"}, [event_source: :plug])
2324
assert {:ok, _} = Sentry.capture_message("RuntimeError: error", [event_source: :plug])
2425
end
26+
27+
test "errors when taking too long to receive response" do
28+
Application.put_env(:sentry, :filter, Sentry.TestFilter)
29+
30+
bypass = Bypass.open
31+
Bypass.expect bypass, fn conn ->
32+
:timer.sleep(100)
33+
assert conn.request_path == "/api/1/store/"
34+
assert conn.method == "POST"
35+
Plug.Conn.send_resp(conn, 200, ~s<{"id": "340"}>)
36+
end
37+
Bypass.pass(bypass)
38+
39+
Application.put_env(:sentry, :dsn, "http://public:secret@localhost:#{bypass.port}/1")
40+
Application.put_env(:sentry, :included_environments, [:test])
41+
Application.put_env(:sentry, :environment_name, :test)
42+
43+
assert capture_log(fn ->
44+
assert :error = Sentry.capture_message("error", [])
45+
end) =~ "Failed to send Sentry event"
46+
end
2547
end

0 commit comments

Comments
 (0)