Packages
hackney
3.0.0
4.7.2
4.7.1
4.7.0
4.6.1
4.6.0
4.5.2
4.5.1
4.5.0
4.4.5
4.4.3
4.4.2
4.4.1
4.4.0
4.3.0
4.2.3
4.2.2
4.2.1
4.2.0
4.1.0
4.0.3
4.0.2
4.0.1
4.0.0
3.2.1
3.2.0
3.1.2
3.1.1
3.1.0
3.0.3
3.0.2
3.0.1
3.0.0
retired
2.0.1
2.0.0
2.0.0-beta.1
1.25.0
1.24.1
1.24.0
1.23.0
1.22.0
1.21.0
1.20.1
1.20.0
1.19.1
1.19.0
1.18.2
1.18.1
1.18.0
1.17.4
1.17.3
1.17.2
1.17.1
1.17.0
1.16.0
1.15.2
1.15.1
1.15.0
1.14.3
1.14.2
1.14.0
1.13.0
1.12.1
1.12.0
1.11.0
1.10.1
1.10.0
1.9.0
1.8.6
1.8.5
1.8.4
1.8.3
1.8.2
1.8.0
1.7.1
1.7.0
1.6.6
retired
1.6.5
1.6.4
retired
1.6.3
1.6.2
1.6.1
1.6.0
1.5.7
1.5.6
1.5.5
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.4.10
1.4.8
1.4.7
1.4.6
1.4.5
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.2
1.3.1
1.3.0
1.2.0
1.1.0
1.0.6
1.0.5
1.0.2
1.0.1
0.15.2
0.15.0
0.14.3
0.14.2
0.14.1
0.14.0
0.13.1
Simple HTTP client with HTTP/1.1, HTTP/2, and HTTP/3 support
Retired package: Release invalid - Use 3.0.1 instead
Security advisory:
This version has known vulnerabilities.
View advisories
Current section
Files
Jump to
Current section
Files
src/hackney_manager.erl
%%% -*- erlang -*-
%%%
%%% This file is part of hackney released under the Apache 2 license.
%%% See the NOTICE for more information.
%%%
%%% Simplified manager that only handles metrics.
%%% Request tracking is no longer needed - hackney_conn processes
%%% manage their own lifecycle and monitor their owners.
-module(hackney_manager).
-behaviour(gen_server).
%% Metrics API
-export([start_request/1,
finish_request/2]).
%% Backward compatibility API
-export([get_state/1, async_response_pid/1]).
%% gen_server API
-export([start_link/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
terminate/2, code_change/3]).
-record(state, {}).
%%====================================================================
%% API
%%====================================================================
%% @doc Called when a new request starts. Updates request counters.
-spec start_request(Host :: string() | binary()) -> ok.
start_request(Host) ->
gen_server:cast(?MODULE, {start_request, Host}).
%% @doc Called when a request finishes. Updates metrics.
-spec finish_request(Host :: string() | binary(), StartTime :: erlang:timestamp()) -> ok.
finish_request(Host, StartTime) ->
gen_server:cast(?MODULE, {finish_request, Host, StartTime}).
%% @doc Check the state of a connection (backward compatibility).
%% In the old architecture, this tracked request state.
%% In the new architecture, we simply check if the connection process is alive.
%% Returns `req_not_found' if the process is dead, or the connection state name.
-spec get_state(pid() | term()) -> req_not_found | atom().
get_state(ConnPid) when is_pid(ConnPid) ->
case is_process_alive(ConnPid) of
false -> req_not_found;
true ->
case hackney_conn:get_state(ConnPid) of
{ok, State} -> State;
_ -> req_not_found
end
end;
get_state(_) ->
req_not_found.
%% @doc Get the async response pid (backward compatibility).
%% In the new architecture, all streaming connections are considered "async".
-spec async_response_pid(pid()) -> {ok, pid()} | {error, req_not_found | req_not_async}.
async_response_pid(Ref) when is_pid(Ref) ->
case get_state(Ref) of
req_not_found -> {error, req_not_found};
streaming -> {ok, Ref};
streaming_once -> {ok, Ref};
_ -> {error, req_not_async}
end;
async_response_pid(_) ->
{error, req_not_async}.
%%====================================================================
%% gen_server callbacks
%%====================================================================
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
init([]) ->
{ok, #state{}}.
handle_call(_Request, _From, State) ->
{reply, ok, State}.
handle_cast({start_request, Host}, State) ->
HostBin = to_binary(Host),
Labels = #{host => HostBin},
_ = hackney_metrics:counter_inc(hackney_requests_total, Labels),
_ = hackney_metrics:gauge_inc(hackney_requests_active, Labels),
{noreply, State};
handle_cast({finish_request, Host, StartTime}, State) ->
HostBin = to_binary(Host),
Labels = #{host => HostBin},
%% Calculate duration in seconds (Prometheus convention)
DurationMicros = timer:now_diff(os:timestamp(), StartTime),
DurationSeconds = DurationMicros / 1000000,
_ = hackney_metrics:histogram_observe(hackney_request_duration_seconds, Labels, DurationSeconds),
_ = hackney_metrics:gauge_dec(hackney_requests_active, Labels),
_ = hackney_metrics:counter_inc(hackney_requests_finished_total, Labels),
{noreply, State};
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info(_Info, State) ->
{noreply, State}.
terminate(_Reason, _State) ->
ok.
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%====================================================================
%% Internal functions
%%====================================================================
to_binary(Host) when is_binary(Host) -> Host;
to_binary(Host) when is_list(Host) -> list_to_binary(Host);
to_binary(Host) when is_atom(Host) -> atom_to_binary(Host, utf8).