Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement pool telemetry #248

Merged
merged 15 commits into from
Jan 7, 2024
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
docs: add docs
oliveigah committed Nov 26, 2023
commit ef7dd23fc7e4d4aa442e061551d3d98ec672b1e3
50 changes: 48 additions & 2 deletions lib/finch.ex
Original file line number Diff line number Diff line change
@@ -100,6 +100,10 @@ defmodule Finch do
"""
@type name() :: atom()

@type scheme() :: :http | :https

@type shp() :: {scheme(), host :: String.t(), port :: pos_integer()}

@type request_opt() :: {:pool_timeout, pos_integer()} | {:receive_timeout, pos_integer()}

@typedoc """
@@ -577,13 +581,55 @@ defmodule Finch do
PoolManager.get_pool(name, {scheme, host, port})
end

@doc """
Get pool metrics list.
The number of items present on the metrics list depends on the `:count` option
each metric will have a `pool_index` going from 1 to `:count`.
The metrics struct depends on the pool scheme defined on the `:protocols` option
`Finch.HTTP1.PoolMetrics` for `:http1` and `Finch.HTTP2.PoolMetrics` for `:http2`.
See the `Finch.HTTP1.PoolMetrics` and `Finch.HTTP2.PoolMetrics` for more details.
`{:error, :not_found}` may return on 2 scenarios. There is no pool on the
given finch instance regarding the given url or the pool is configured with
`start_pool_metrics?` option false (the default).
## Example
iex> Finch.get_pool_status(MyFinch, "https://httpbin.org")
{:ok, [
%Finch.HTTP1.PoolMetrics{
pool_index: 1,
pool_size: 50,
available_connections: 43,
in_use_connections: 7
},
%Finch.HTTP1.PoolMetrics{
pool_index: 2,
pool_size: 50,
available_connections: 37,
in_use_connections: 13
}]
}
"""
@spec get_pool_status(name(), url :: String.t() | shp()) ::
{:ok, list(Finch.HTTP1.PoolMetrics.t())}
| {:ok, list(Finch.HTTP2.PoolMetrics.t())}
| {:error, :not_found}
def get_pool_status(finch_name, url) when is_binary(url) do
{s, h, p, _, _} = Request.parse_url(url)
get_pool_status(finch_name, {s, h, p})
end

def get_pool_status(finch_name, shp) when is_tuple(shp) do
{_pool, pool_mod} = PoolManager.get_pool(finch_name, shp)
pool_mod.get_pool_status(finch_name, shp)
case PoolManager.get_pool(finch_name, shp, auto_start?: false) do
{_pool, pool_mod} ->
pool_mod.get_pool_status(finch_name, shp)

:not_found ->
{:error, :not_found}
end
end
end
21 changes: 20 additions & 1 deletion lib/finch/http1/pool_metrics.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
defmodule Finch.HTTP1.PoolMetrics do
@moduledoc """
HTTP1 Pool metrics. TODO: Add more description
HTTP1 Pool metrics.
Available metrics:
* `:pool_index` - Index of the pool
* `:pool_size` - Total number of connections of the pool
* `:available_connections` - Number of avaialable connections
* `:in_use_connections` - Number of connections currently in use
Caveats:
* A given number X of `available_connections` does not mean that currently
exists X connections to the server sitting on the pool. Because Finch uses
a lazy strategy for workers initialization, every pool starts with it's
size as available connections even if they are not started yet. In practice
this means that `available_connections` may be connections sitting on the pool
or available space on the pool for a new one if required.
"""
@type t :: %__MODULE__{}

defstruct [
:pool_index,
:pool_size,
1 change: 0 additions & 1 deletion lib/finch/http2/pool.ex
Original file line number Diff line number Diff line change
@@ -206,7 +206,6 @@ defmodule Finch.HTTP2.Pool do
@impl true
def init({{scheme, host, port} = shp, registry, pool_opts, metrics_ref, pool_idx}) do
{:ok, _} = Registry.register(registry, shp, __MODULE__)

data = %{
conn: nil,
finch_name: registry,
15 changes: 14 additions & 1 deletion lib/finch/http2/pool_metrics.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
defmodule Finch.HTTP2.PoolMetrics do
@moduledoc """
HTTP2 Pool metrics. TODO: Add more description
HTTP2 Pool metrics.
Available metrics:
* `:pool_index` - Index of the pool
* `:in_flight_requests` - Number of requests currently on the connection
Caveats:
* HTTP2 pools have only one connection and leverage the multiplex nature
of the protocol. That's why we only keep the in flight requests, representing
the number of streams currently running on the connection.
"""
@type t :: %__MODULE__{}

defstruct [
:pool_index,
:in_flight_requests
6 changes: 3 additions & 3 deletions test/finch/http2/pool_metrics_test.exs
Original file line number Diff line number Diff line change
@@ -67,7 +67,7 @@ defmodule Finch.HTTP2.PoolMetricsTest do
ref
end)

Process.sleep(300)
Process.sleep(400)

assert {:ok,
[
@@ -115,7 +115,7 @@ defmodule Finch.HTTP2.PoolMetricsTest do
end)
end)

Process.sleep(300)
Process.sleep(400)

assert {:ok,
[
@@ -169,7 +169,7 @@ defmodule Finch.HTTP2.PoolMetricsTest do
ref
end)

Process.sleep(300)
Process.sleep(400)

assert {:ok,
[