diff --git a/README.md b/README.md
index 14af9890..42540a1f 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ __Version:__ 1.6.1
**hackney** is an HTTP client library for Erlang.
-[![Build Status](https://secure.travis-ci.org/benoitc/hackney.svg?branch=master)](https://travis-ci.org/benoitc/hackney)
+[![Build Status](https://travis-ci.org/benoitc/hackney.png?branch=master)](https://travis-ci.org/benoitc/hackney)
[![Hex pm](http://img.shields.io/hexpm/v/hackney.svg?style=flat)](https://hex.pm/packages/hackney)
## Main features:
@@ -172,6 +172,8 @@ read_body(MaxLength, Ref, Acc) when MaxLength > byte_size(Acc) ->
> Note: you can also fetch a multipart response using the functions
> `hackney:stream_multipart/1` and `hackney:skip_multipart/1`.
+> Note 2: using the `with_body` option will return the body directy instead of a reference.
+
### Reuse a connection
By default all connections are created and closed dynamically by
@@ -214,7 +216,7 @@ NextReq = {NextMethod, NextPath, ReqHeaders, ReqBody}
Here we are posting a JSON payload to '/' on the friendpaste service to
create a paste. Then we close the client connection.
-> If your connection supports keepalive the connection will be simply :
+> If your connection supports keepalive the connection will be kept open until you close it exclusively.
### Send a body
@@ -222,7 +224,7 @@ hackney helps you send different payloads by passing different terms as
the request body:
- `{form, PropList}` : To send a form
-- `{multipart, Parts}` : to send you body using the multipart API. Parts
+- `{multipart, Parts}` : to send your body using the multipart API. Parts
follow this format:
- `eof`: end the multipart request
- `{file, Path}`: to stream a file
@@ -316,7 +318,7 @@ LoopFun(LoopFun, ClientRef).
> synchronously using the function `hackney:stop_async/1` See the
> example [test_async_once2](https://github.com/benoitc/hackney/blob/master/examples/test_async_once2.erl) for the usage.
-> **Note 4**: When the option `{following_redirect, true}` is passed to
+> **Note 4**: When the option `{follow_redirect, true}` is passed to
> the request, you will receive the folllowing messages on valid
> redirection:
> - `{redirect, To, Headers}`
@@ -436,15 +438,21 @@ automatically upgrading to an SSL connection if needed.
Hackney offers the following metrics
-You can enable metrics collection by adding a `mod_metrics` entry to hackney's
-app config. Metrics are disabled by default. The module specified must have an
-API matching that of the hackney metrics module.
+You can enable metrics collection by adding a `metrics` entry to the config.
setopts/2<
### body/1 ###
-body(Ref::client_ref()) -> {ok, binary()} | {error, atom()}
+body(Ref::client_ref()) -> {ok, binary()} | {error, atom()} | {error, {closed, binary()}}
@@ -94,7 +94,7 @@ Return the full body sent with the response.
### body/2 ###
-body(Ref::client_ref(), MaxLength::non_neg_integer() | infinity) -> {ok, binary()} | {error, atom()}
+body(Ref::client_ref(), MaxLength::non_neg_integer() | infinity) -> {ok, binary()} | {error, atom()} | {error, {closed, binary()}}
diff --git a/doc/hackney_connect.md b/doc/hackney_connect.md
index 96df8eb5..11f24950 100644
--- a/doc/hackney_connect.md
+++ b/doc/hackney_connect.md
@@ -9,7 +9,7 @@
## Function Index ##
-
+
@@ -78,6 +78,12 @@ get current pool pid or name used by a client if needed
connect a socket and create a client state.
+
+
+### partial_chain/1 ###
+
+`partial_chain(Certs) -> any()`
+
### reconnect/4 ###
diff --git a/doc/hackney_local_tcp.md b/doc/hackney_local_tcp.md
new file mode 100644
index 00000000..75abec07
--- /dev/null
+++ b/doc/hackney_local_tcp.md
@@ -0,0 +1,148 @@
+
+
+# Module hackney_local_tcp #
+* [Function Index](#index)
+* [Function Details](#functions)
+
+
+
+## Function Index ##
+
+
+
+
+
+
+
+## Function Details ##
+
+
+
+### close/1 ###
+
+
+close(Socket::inet:socket()) -> ok
+
+
+
+Close a TCP socket.
+
+__See also:__ [gen_tcp:close/1](gen_tcp.md#close-1).
+
+
+
+### connect/3 ###
+
+`connect(Host, Port, Opts) -> any()`
+
+
+
+### connect/4 ###
+
+`connect(Host, Port, Opts, Timeout) -> any()`
+
+
+
+### controlling_process/2 ###
+
+
+controlling_process(Socket::inet:socket(), Pid::pid()) -> ok | {error, closed | not_owner | atom()}
+
+
+
+Assign a new controlling process _Pid_ to _Socket_.
+
+__See also:__ [gen_tcp:controlling_process/2](gen_tcp.md#controlling_process-2).
+
+
+
+### messages/1 ###
+
+`messages(X1) -> any()`
+
+Atoms used to identify messages in {active, once | true} mode.
+
+
+
+### peername/1 ###
+
+
+peername(Socket::inet:socket()) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, atom()}
+
+
+
+Return the address and port for the other end of a connection.
+
+__See also:__ [inet:peername/1](inet.md#peername-1).
+
+
+
+### recv/2 ###
+
+`recv(Socket, Length) -> any()`
+
+
+
+### recv/3 ###
+
+
+recv(Socket::inet:socket(), Length::non_neg_integer(), Timeout::timeout()) -> {ok, any()} | {error, closed | atom()}
+
+
+
+Receive a packet from a socket in passive mode.
+
+__See also:__ [gen_tcp:recv/3](gen_tcp.md#recv-3).
+
+
+
+### send/2 ###
+
+
+send(Socket::inet:socket(), Packet::iolist()) -> ok | {error, atom()}
+
+
+
+Send a packet on a socket.
+
+__See also:__ [gen_tcp:send/2](gen_tcp.md#send-2).
+
+
+
+### setopts/2 ###
+
+
+setopts(Socket::inet:socket(), Opts::list()) -> ok | {error, atom()}
+
+
+
+Set one or more options for a socket.
+
+__See also:__ [inet:setopts/2](inet.md#setopts-2).
+
+
+
+### shutdown/2 ###
+
+
+shutdown(Socket::inet:socket(), How::read | write | read_write) -> ok
+
+
+
+Immediately close a socket in one or two directions.
+
+__See also:__ [gen_tcp:shutdown/2](gen_tcp.md#shutdown-2).
+
+
+
+### sockname/1 ###
+
+
+sockname(Socket::inet:socket()) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, atom()}
+
+
+
+Get the local address and port of a socket
+
+__See also:__ [inet:sockname/1](inet.md#sockname-1).
+
diff --git a/doc/hackney_ssl.md b/doc/hackney_ssl.md
new file mode 100644
index 00000000..15a29279
--- /dev/null
+++ b/doc/hackney_ssl.md
@@ -0,0 +1,148 @@
+
+
+# Module hackney_ssl #
+* [Function Index](#index)
+* [Function Details](#functions)
+
+
+
+## Function Index ##
+
+
+
+
+
+
+
+## Function Details ##
+
+
+
+### close/1 ###
+
+
+close(Socket::ssl:sslsocket()) -> ok
+
+
+
+Close a TCP socket.
+
+__See also:__ [ssl:close/1](ssl.md#close-1).
+
+
+
+### connect/3 ###
+
+`connect(Host, Port, Opts) -> any()`
+
+
+
+### connect/4 ###
+
+`connect(Host, Port, Opts, Timeout) -> any()`
+
+
+
+### controlling_process/2 ###
+
+
+controlling_process(Socket::ssl:sslsocket(), Pid::pid()) -> ok | {error, closed | not_owner | atom()}
+
+
+
+Assign a new controlling process _Pid_ to _Socket_.
+
+__See also:__ [ssl:controlling_process/2](ssl.md#controlling_process-2).
+
+
+
+### messages/1 ###
+
+`messages(X1) -> any()`
+
+Atoms used to identify messages in {active, once | true} mode.
+
+
+
+### peername/1 ###
+
+
+peername(Socket::ssl:sslsocket()) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, atom()}
+
+
+
+Return the address and port for the other end of a connection.
+
+__See also:__ [ssl:peername/1](ssl.md#peername-1).
+
+
+
+### recv/2 ###
+
+`recv(Socket, Length) -> any()`
+
+
+
+### recv/3 ###
+
+
+recv(Socket::ssl:sslsocket(), Length::non_neg_integer(), Timeout::timeout()) -> {ok, any()} | {error, closed | atom()}
+
+
+
+Receive a packet from a socket in passive mode.
+
+__See also:__ [ssl:recv/3](ssl.md#recv-3).
+
+
+
+### send/2 ###
+
+
+send(Socket::ssl:sslsocket(), Packet::iolist()) -> ok | {error, atom()}
+
+
+
+Send a packet on a socket.
+
+__See also:__ [ssl:send/2](ssl.md#send-2).
+
+
+
+### setopts/2 ###
+
+
+setopts(Socket::ssl:sslsocket(), Opts::list()) -> ok | {error, atom()}
+
+
+
+Set one or more options for a socket.
+
+__See also:__ [ssl:setopts/2](ssl.md#setopts-2).
+
+
+
+### shutdown/2 ###
+
+
+shutdown(Socket::ssl:socket(), How::read | write | read_write) -> ok
+
+
+
+Immediately close a socket in one or two directions.
+
+__See also:__ [ssl:shutdown/2](ssl.md#shutdown-2).
+
+
+
+### sockname/1 ###
+
+
+sockname(Socket::ssl:sslsocket()) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, atom()}
+
+
+
+Get the local address and port of a socket
+
+__See also:__ [ssl:sockname/1](ssl.md#sockname-1).
+
diff --git a/doc/hackney_tcp.md b/doc/hackney_tcp.md
new file mode 100644
index 00000000..ef5764fd
--- /dev/null
+++ b/doc/hackney_tcp.md
@@ -0,0 +1,148 @@
+
+
+# Module hackney_tcp #
+* [Function Index](#index)
+* [Function Details](#functions)
+
+
+
+## Function Index ##
+
+
+
+
+
+
+
+## Function Details ##
+
+
+
+### close/1 ###
+
+
+close(Socket::inet:socket()) -> ok
+
+
+
+Close a TCP socket.
+
+__See also:__ [gen_tcp:close/1](gen_tcp.md#close-1).
+
+
+
+### connect/3 ###
+
+`connect(Host, Port, Opts) -> any()`
+
+
+
+### connect/4 ###
+
+`connect(Host, Port, Opts, Timeout) -> any()`
+
+
+
+### controlling_process/2 ###
+
+
+controlling_process(Socket::inet:socket(), Pid::pid()) -> ok | {error, closed | not_owner | atom()}
+
+
+
+Assign a new controlling process _Pid_ to _Socket_.
+
+__See also:__ [gen_tcp:controlling_process/2](gen_tcp.md#controlling_process-2).
+
+
+
+### messages/1 ###
+
+`messages(X1) -> any()`
+
+Atoms used to identify messages in {active, once | true} mode.
+
+
+
+### peername/1 ###
+
+
+peername(Socket::inet:socket()) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, atom()}
+
+
+
+Return the address and port for the other end of a connection.
+
+__See also:__ [inet:peername/1](inet.md#peername-1).
+
+
+
+### recv/2 ###
+
+`recv(Socket, Length) -> any()`
+
+
+
+### recv/3 ###
+
+
+recv(Socket::inet:socket(), Length::non_neg_integer(), Timeout::timeout()) -> {ok, any()} | {error, closed | atom()}
+
+
+
+Receive a packet from a socket in passive mode.
+
+__See also:__ [gen_tcp:recv/3](gen_tcp.md#recv-3).
+
+
+
+### send/2 ###
+
+
+send(Socket::inet:socket(), Packet::iolist()) -> ok | {error, atom()}
+
+
+
+Send a packet on a socket.
+
+__See also:__ [gen_tcp:send/2](gen_tcp.md#send-2).
+
+
+
+### setopts/2 ###
+
+
+setopts(Socket::inet:socket(), Opts::list()) -> ok | {error, atom()}
+
+
+
+Set one or more options for a socket.
+
+__See also:__ [inet:setopts/2](inet.md#setopts-2).
+
+
+
+### shutdown/2 ###
+
+
+shutdown(Socket::inet:socket(), How::read | write | read_write) -> ok
+
+
+
+Immediately close a socket in one or two directions.
+
+__See also:__ [gen_tcp:shutdown/2](gen_tcp.md#shutdown-2).
+
+
+
+### sockname/1 ###
+
+
+sockname(Socket::inet:socket()) -> {ok, {inet:ip_address(), inet:port_number()}} | {error, atom()}
+
+
+
+Get the local address and port of a socket
+
+__See also:__ [inet:sockname/1](inet.md#sockname-1).
+
diff --git a/doc/hackney_util.md b/doc/hackney_util.md
index 0c92d417..35cc12cf 100644
--- a/doc/hackney_util.md
+++ b/doc/hackney_util.md
@@ -9,7 +9,7 @@
## Function Index ##
-
+
@@ -40,11 +40,11 @@ filter a proplists and only keep allowed keys
`maybe_apply_defaults(Rest, Options) -> any()`
-
+
-### mod_metrics/0 ###
+### merge_opts/2 ###
-`mod_metrics() -> any()`
+`merge_opts(Rest, Options) -> any()`
@@ -81,3 +81,9 @@ set the default options in a proplists if not defined
`to_atom(V) -> any()`
+
+
+### uniform/1 ###
+
+`uniform(N) -> any()`
+
diff --git a/doc/overview.edoc b/doc/overview.edoc
index 69900546..b74b86c7 100644
--- a/doc/overview.edoc
+++ b/doc/overview.edoc
@@ -229,7 +229,7 @@ hackney helps you send different payloads by passing different terms as
the request body:
- `{form, PropList}' : To send a form
-- `{multipart, Parts}' : to send you body using the multipart API. Parts
+- `{multipart, Parts}' : to send your body using the multipart API. Parts
follow this format:
- `eof': end the multipart request
- `{file, Path}': to stream a file
@@ -438,16 +438,24 @@ automatically upgrading to an SSL connection if needed.
Hackney offers the following metrics
-You can enable metrics collection by adding a `mod_metrics' entry to hackney's
-app config. Metrics are disabled by default. The module specified must have an
-API matching that of the hackney metrics module.
+You can enable metrics collection by adding a `metrics` entry to the config.
-To use [folsom](https://github.com/boundary/folsom), specify `{mod_metrics,
-folsom}', or if you want to use
-[exometer](https://github.com/feuerlabs/exometer), specify `{mod_metrics,
-exometer}' and ensure that folsom or exometer is in your code path and has
-been started.
+
+{metrics, [
+ {mod_metrics, metrics_folsom}
+]}
+
+Metrics are disabled by default. The module specified must have an API
+matching that of the hackney metrics module.
+
+To use [folsom](https://github.com/boundary/folsom), specify `{mod_metrics,
+metrics_folsom}`, if you want to use
+[exometer](https://github.com/feuerlabs/exometer), specify`{mod_metrics,
+metrics_exometer}`, or if you want to use
+[grapherl](https://github.com/processone/grapherl), specify `{mod_metrics,
+metrics_grapherl}` and ensure that folsom, exometer or grapherl is in your
+code path and has been started.
#### Generic Hackney metrics
@@ -508,8 +516,8 @@ $ pip install gunicorn httpbin
Running the tests:
```
-$ gunicorn --daemon --pid httpbin.pid httpbin:app
-$ make test
+$ gunicorn -b 127.0.0.1:8000 -b unix:httpbin.sock --daemon --pid httpbin.pid httpbin:app
+$ rebar3 as test eunit
$ kill `cat httpbin.pid`
'''
diff --git a/include/hackney.hrl b/include/hackney.hrl
index 2cb3cfd9..8d1b12fe 100644
--- a/include/hackney.hrl
+++ b/include/hackney.hrl
@@ -2,7 +2,6 @@
-record(client, {
start_time,
- mod_metrics = nil,
transport,
host,
port,
@@ -42,4 +41,4 @@
connection = nil,
method = nil,
path,
- ctype = nil}).
\ No newline at end of file
+ ctype = nil}).
diff --git a/mix.exs b/mix.exs
index da71a9e3..93c3e635 100644
--- a/mix.exs
+++ b/mix.exs
@@ -46,7 +46,7 @@ use Mix.Project
{:idna, "~> 1.2.0"},
{:mimerl, "~> 1.0.2"},
{:certifi, "~> 0.7.0"},
- {:metrics, "~> 1.0.1"},
+ {:metrics, "~> 2.2.0"},
{:ssl_verify_fun, "1.1.1"}
]
end
diff --git a/mix.lock b/mix.lock
index 79a49796..2968b3a9 100644
--- a/mix.lock
+++ b/mix.lock
@@ -1,5 +1,5 @@
-%{"certifi": {:hex, :certifi, "0.5.0", "17b5a3561228434bb66ee8de6a0563d5a03724616896087d854ac9840f1e7778", [:rebar3], []},
+%{"certifi": {:hex, :certifi, "0.7.0", "861a57f3808f7eb0c2d1802afeaae0fa5de813b0df0979153cbafcd853ababaf", [:rebar3], []},
"idna": {:hex, :idna, "1.2.0", "ac62ee99da068f43c50dc69acf700e03a62a348360126260e87f2b54eced86b2", [:rebar3], []},
- "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []},
+ "metrics": {:hex, :metrics, "2.2.0", "709b45a275fde02c9f2950ceab38b29b46d05687de33299e02c03a71be336545", [:rebar3], []},
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], []},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:rebar, :make], []}}
diff --git a/rebar.config b/rebar.config
index 7a183925..d3b6e395 100644
--- a/rebar.config
+++ b/rebar.config
@@ -17,7 +17,7 @@
{idna, "1.2.0"},
{mimerl, "1.0.2"},
{certifi, "0.7.0"},
- {metrics, "1.0.1"},
+ {metrics, "2.2.0"},
{ssl_verify_fun, "1.1.1"}
]}.
diff --git a/rebar.config.script b/rebar.config.script
index 72f49093..5f9d5e64 100644
--- a/rebar.config.script
+++ b/rebar.config.script
@@ -14,7 +14,7 @@ Rebar2Deps0 = [{idna, ".*",
{metrics, ".*",
{git, "https://github.com/benoitc/erlang-metrics",
- {tag, "1.0.1"}}},
+ {tag, "2.1.0"}}},
{ssl_verify_fun, ".*",
{git, "https://github.com/deadtrickster/ssl_verify_fun.erl",
diff --git a/rebar.lock b/rebar.lock
index 561f1c7c..556e7292 100644
--- a/rebar.lock
+++ b/rebar.lock
@@ -1,5 +1,5 @@
[{<<"certifi">>,{pkg,<<"certifi">>,<<"0.7.0">>},0},
{<<"idna">>,{pkg,<<"idna">>,<<"1.2.0">>},0},
- {<<"metrics">>,{pkg,<<"metrics">>,<<"1.0.1">>},0},
+ {<<"metrics">>,{pkg,<<"metrics">>,<<"2.2.0">>},0},
{<<"mimerl">>,{pkg,<<"mimerl">>,<<"1.0.2">>},0},
{<<"ssl_verify_fun">>,{pkg,<<"ssl_verify_fun">>,<<"1.1.1">>},0}].
diff --git a/src/hackney_connect.erl b/src/hackney_connect.erl
index fe436e7b..6b6b3569 100644
--- a/src/hackney_connect.erl
+++ b/src/hackney_connect.erl
@@ -65,12 +65,8 @@ create_connection(Transport, Host, Port, Options, Dynamic)
WithBody = proplists:get_value(with_body, Options, false),
MaxBody = proplists:get_value(max_body, Options),
- %% get mod metrics
- Engine = metrics:init(hackney_util:mod_metrics()),
-
%% initial state
- InitialState = #client{mod_metrics=Engine,
- transport=Transport,
+ InitialState = #client{transport=Transport,
host=Host,
port=Port,
netloc=Netloc,
@@ -109,7 +105,7 @@ maybe_connect(#client{state=closed, redirect=Redirect}=Client) ->
redirect=nil},
reconnect(Host, Port, Transport, Client1);
maybe_connect(#client{redirect=nil}=Client) ->
- {ok, check_mod_metrics(Client)};
+ {ok, Client};
maybe_connect(#client{redirect=Redirect}=Client) ->
%% reinit the options and reconnect the client
{Transport, Host, Port, Options} = Redirect,
@@ -167,9 +163,9 @@ reconnect(Host, Port, Transport, State) ->
case is_pool(State) of
false ->
%% the client won't use any pool
- do_connect(Host, Port, Transport, check_mod_metrics(State));
+ do_connect(Host, Port, Transport, State);
true ->
- socket_from_pool(Host, Port, Transport, check_mod_metrics(State))
+ socket_from_pool(Host, Port, Transport, State)
end.
%%
@@ -179,7 +175,6 @@ reconnect(Host, Port, Transport, State) ->
socket_from_pool(Host, Port, Transport, Client0) ->
PoolHandler = hackney_app:get_app_env(pool_handler, hackney_pool),
PoolName = proplists:get_value(pool, Client0#client.options, default),
- Metrics = Client0#client.mod_metrics,
%% new request
{_RequestRef, Client} = hackney_manager:new_request(Client0),
@@ -187,8 +182,8 @@ socket_from_pool(Host, Port, Transport, Client0) ->
case PoolHandler:checkout(Host, Port, Transport, Client) of
{ok, Ref, Skt} ->
?report_debug("reuse a connection", [{pool, PoolName}]),
- metrics:update_meter(Metrics, [hackney_pool, PoolName, take_rate], 1),
- metrics:increment_counter(Metrics, [hackney_pool, Host, reuse_connection]),
+ metrics:update([hackney_pool, PoolName, take_rate], 1),
+ metrics:update([hackney_pool, Host, reuse_connection]),
Client1 = Client#client{socket=Skt,
socket_ref=Ref,
pool_handler=PoolHandler,
@@ -198,7 +193,7 @@ socket_from_pool(Host, Port, Transport, Client0) ->
{ok, Client1};
{error, no_socket, Ref} ->
?report_trace("no socket in the pool", [{pool, PoolName}]),
- metrics:increment_counter(Metrics, [hackney_pool, PoolName, no_socket]),
+ metrics:update([hackney_pool, PoolName, no_socket]),
do_connect(Host, Port, Transport, Client#client{socket_ref=Ref},
pool);
Error ->
@@ -210,8 +205,7 @@ do_connect(Host, Port, Transport, Client) ->
-do_connect(Host, Port, Transport, #client{mod_metrics=Metrics,
- options=Opts}=Client0, Type) ->
+do_connect(Host, Port, Transport, #client{options=Opts}=Client0, Type) ->
Begin = os:timestamp(),
{_RequestRef, Client} = case Type of
pool ->
@@ -247,20 +241,20 @@ do_connect(Host, Port, Transport, #client{mod_metrics=Metrics,
{ok, Skt} ->
?report_trace("new connection", []),
ConnectTime = timer:now_diff(os:timestamp(), Begin)/1000,
- metrics:update_histogram(Metrics, [hackney, Host, connect_time], ConnectTime),
- metrics:increment_counter(Metrics, [hackney_pool, Host, new_connection]),
+ metrics:update([hackney, Host, connect_time], ConnectTime),
+ metrics:update([hackney_pool, Host, new_connection]),
Client1 = Client#client{socket=Skt,
state = connected},
hackney_manager:update_state(Client1),
{ok, Client1};
{error, timeout} ->
?report_trace("connect timeout", []),
- metrics:increment_counter(Metrics, [hackney, Host, connect_timeout]),
+ metrics:update([hackney, Host, connect_timeout]),
hackney_manager:cancel_request(Client),
{error, connect_timeout};
Error ->
?report_trace("connect error", []),
- metrics:increment_counter(Metrics, [hackney, Host, connect_error]),
+ metrics:update([hackney, Host, connect_error]),
hackney_manager:cancel_request(Client),
Error
end.
@@ -274,12 +268,6 @@ use_default_pool() ->
true
end.
-check_mod_metrics(#client{mod_metrics=Mod}=State)
- when Mod /= nil, Mod /= undefined ->
- State;
-check_mod_metrics(State) ->
- State#client{mod_metrics=metrics:init(hackney_util:mod_metrics())}.
-
ssl_opts(Host, Options) ->
case proplists:get_value(ssl_options, Options) of
undefined ->
diff --git a/src/hackney_manager.erl b/src/hackney_manager.erl
index 23555bf1..d1eab05d 100644
--- a/src/hackney_manager.erl
+++ b/src/hackney_manager.erl
@@ -44,8 +44,7 @@
-define(REFS, hackney_manager_refs).
--record(mstate, {pids=dict:new(),
- metrics}).
+-record(mstate, {pids=dict:new()}).
new_request(#client{request_ref=Ref}=Client)
@@ -283,14 +282,13 @@ init(_) ->
ets:new(?REFS, [named_table, set, protected]),
%% initialize metrics
- Metrics = init_metrics(),
+ init_metrics(),
process_flag(trap_exit, true),
%% return {ok, {Pids, Refs}}
%% Pids are the managed pids
%% Refs are the managed requests
- {ok, #mstate{pids=dict:new(),
- metrics=Metrics}}.
+ {ok, #mstate{pids=dict:new()}}.
handle_call({new_request, Pid, Ref, Client}, _From, #mstate{pids=Pids}=State) ->
@@ -303,7 +301,7 @@ handle_call({new_request, Pid, Ref, Client}, _From, #mstate{pids=Pids}=State) ->
host=Client#client.host},
%% start the request
- start_request(ReqInfo, State),
+ start_request(ReqInfo),
%% link the request owner
link(Pid),
@@ -323,7 +321,7 @@ handle_call({take_control, Ref, Client}, _From, State) ->
NInfo = Info#request_info{start_time=StartTime,
host=Client#client.host},
%% start the request
- start_request(NInfo, State),
+ start_request(NInfo),
ets:insert(?REFS, {Ref, {Owner, Stream, NInfo}}),
{reply, {ok, StartTime}, State}
@@ -405,7 +403,7 @@ handle_cast({cancel_request, Ref}, State) ->
%% notify the pool that the request have been canceled
PoolHandler:notify(Pool, {'DOWN', Ref, request, Owner, cancel}),
%% update metrics
- finish_request(Info, State),
+ finish_request(Info),
{noreply, State#mstate{pids=Pids2}};
[{Ref, {Owner, Stream, #request_info{pool=Pool}=Info}}]
when is_pid(Stream) ->
@@ -416,7 +414,7 @@ handle_cast({cancel_request, Ref}, State) ->
%% notify the pool that the request have been canceled
PoolHandler:notify(Pool, {'DOWN', Ref, request, Owner, cancel}),
%% update metrics
- finish_request(Info, State),
+ finish_request(Info),
%% terminate the async response
terminate_async_response(Stream),
{noreply, State#mstate{pids=Pids2}}
@@ -507,7 +505,7 @@ handle_exit(Pid, {Ref, stream}, Reason, State) ->
PoolHandler:notify(Pool, {'DOWN', Ref, request, Owner, Reason}),
%% update metrics
- finish_request(Info, State),
+ finish_request(Info),
%% reply
{noreply, State#mstate{pids=Pids2}}
@@ -529,7 +527,7 @@ handle_exit(Pid, {Ref, owner}, Reason, State) ->
%% notify the pool that the request have been canceled
PoolHandler:notify(Pool, {'DOWN', Ref, request, Pid, Reason}),
%% update metrics
- finish_request(Info, State),
+ finish_request(Info),
%% reply
{noreply, State#mstate{pids=Pids1}};
[{Ref, {Pid, Stream, #request_info{pool=Pool}=Info}}] ->
@@ -543,7 +541,7 @@ handle_exit(Pid, {Ref, owner}, Reason, State) ->
%% notify the pool that the request have been canceled
PoolHandler:notify(Pool, {'DOWN', Ref, request, Pid, Reason}),
%% update metrics
- finish_request(Info, State),
+ finish_request(Info),
{noreply, State#mstate{pids=Pids2}}
end.
@@ -580,25 +578,20 @@ wait_async_response(Stream) ->
end.
init_metrics() ->
- %% get metrics module
- Engine = metrics:init(hackney_util:mod_metrics()),
-
%% initialise metrics
- metrics:new(Engine, counter, [hackney, nb_requests]),
- metrics:new(Engine, counter, [hackney, total_requests]),
- metrics:new(Engine, counter, [hackney, finished_requests]),
- Engine.
+ metrics:new(counter, [hackney, nb_requests]),
+ metrics:new(counter, [hackney, total_requests]),
+ metrics:new(counter, [hackney, finished_requests]).
-start_request(#request_info{host=Host}, #mstate{metrics=Engine}) ->
- metrics:increment_counter(Engine, [hackney, Host, nb_requests]),
- metrics:increment_counter(Engine, [hackney, nb_requests]),
- metrics:increment_counter(Engine, [hackney, total_requests]).
+start_request(#request_info{host=Host}) ->
+ metrics:update([hackney, Host, nb_requests]),
+ metrics:update([hackney, nb_requests]),
+ metrics:update([hackney, total_requests]).
-finish_request(#request_info{start_time=Begin, host=Host},
- #mstate{metrics=Engine}) ->
+finish_request(#request_info{start_time=Begin, host=Host}) ->
RequestTime = timer:now_diff(os:timestamp(), Begin)/1000,
- metrics:update_histogram(Engine, [hackney, Host, request_time], RequestTime),
- metrics:decrement_counter(Engine, [hackney, Host, nb_requests]),
- metrics:decrement_counter(Engine, [hackney, nb_requests]),
- metrics:increment_counter(Engine, [hackney, finished_requests]).
+ metrics:update([hackney, Host, request_time], RequestTime),
+ metrics:update([hackney, Host, nb_requests], {c, -1}),
+ metrics:update([hackney, nb_requests], {c, -1}),
+ metrics:update([hackney, finished_requests]).
diff --git a/src/hackney_pool.erl b/src/hackney_pool.erl
index 8707c26d..f6ee8854 100644
--- a/src/hackney_pool.erl
+++ b/src/hackney_pool.erl
@@ -41,7 +41,6 @@
-record(state, {
name,
- metrics,
max_connections,
timeout,
clients = dict:new(),
@@ -227,9 +226,9 @@ init([Name, Options]) ->
ets:insert(?MODULE, {Name, self()}),
%% initialize metrics
- Engine = init_metrics(Name),
+ init_metrics(Name),
- {ok, #state{name=Name, metrics=Engine, max_connections=MaxConn,
+ {ok, #state{name=Name, max_connections=MaxConn,
timeout=Timeout}}.
handle_call(count, _From, #state{sockets=Sockets}=State) ->
@@ -240,7 +239,6 @@ handle_call(max_connections, _From, #state{max_connections=MaxConn}=State) ->
{reply, MaxConn, State};
handle_call({checkout, Dest, Pid, RequestRef}, From, State) ->
#state{name=PoolName,
- metrics = Engine,
max_connections=MaxConn,
clients=Clients,
queues = Queues,
@@ -257,9 +255,8 @@ handle_call({checkout, Dest, Pid, RequestRef}, From, State) ->
true ->
Queues2 = add_to_queue(Dest, From, RequestRef, Queues),
NbWaiters2 = NbWaiters + 1,
- metrics:update_histogram(Engine,
- [hackney_pool, PoolName, queue_count],
- NbWaiters2),
+ metrics:update([hackney_pool, PoolName, queue_count],
+ NbWaiters2),
{noreply, State2#state{queues = Queues2,
nb_waiters=NbWaiters2}};
false ->
@@ -329,8 +326,7 @@ handle_info({'DOWN', Ref, request, _Pid, _Reason}, State) ->
{noreply, State#state{clients = Clients2}};
{ok, {From, Ref2}, Queues2} ->
NbWaiters = State#state.nb_waiters - 1,
- metrics:update_histogram(State#state.metrics,
- [hackney_pool, State#state.name, queue_count], NbWaiters),
+ metrics:update([hackney_pool, State#state.name, queue_count], NbWaiters),
gen_server:reply(From, {error, no_socket, self()}),
State2 = State#state{queues = Queues2, clients = Clients2,
nb_waiters=NbWaiters},
@@ -345,7 +341,7 @@ handle_info(_, State) ->
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
-terminate(_Reason, #state{name=PoolName, metrics=Engine, sockets=Sockets}) ->
+terminate(_Reason, #state{name=PoolName, sockets=Sockets}) ->
%% close any sockets in the pool
lists:foreach(fun({Socket, {{_, _, Transport}, Timer}}) ->
cancel_timer(Socket, Timer),
@@ -353,7 +349,7 @@ terminate(_Reason, #state{name=PoolName, metrics=Engine, sockets=Sockets}) ->
end, dict:to_list(Sockets)),
%% delete pool metrics
- delete_metrics(Engine, PoolName),
+ delete_metrics(PoolName),
ok.
%% internals
@@ -394,9 +390,8 @@ find_connection({_Host, _Port, Transport}=Dest, Pid,
end.
remove_socket(Socket, #state{connections=Conns, sockets=Sockets}=State) ->
- metrics:update_histogram(State#state.metrics,
- [hackney, State#state.name, free_count],
- dict:size(Sockets)),
+ metrics:update([hackney, State#state.name, free_count],
+ dict:size(Sockets)),
case dict:find(Socket, Sockets) of
{ok, {{_Host, _Port, Transport}=Key, Timer}} ->
cancel_timer(Socket, Timer),
@@ -479,9 +474,8 @@ deliver_socket(Socket, {_, _, Transport} = Dest, State) ->
store_socket(Dest, Socket, State);
{ok, {{PidWaiter, _} = FromWaiter, Ref}, Queues2} ->
NbWaiters = State#state.nb_waiters - 1,
- metrics:update_histogram(State#state.metrics,
- [hackney_pool, State#state.name, queue_count],
- NbWaiters),
+ metrics:update([hackney_pool, State#state.name, queue_count],
+ NbWaiters),
case Transport:controlling_process(Socket, PidWaiter) of
ok ->
gen_server:reply(FromWaiter, {ok, Socket, self()}),
@@ -518,28 +512,24 @@ monitor_client(Dest, Ref, State) ->
init_metrics(PoolName) ->
- %% get metrics module
- Engine = metrics:init(hackney_util:mod_metrics()),
-
%% initialise metrics
- metrics:new(Engine, histogram, [hackney_pool, PoolName, take_rate]),
- metrics:new(Engine, counter, [hackney_pool, PoolName, no_socket]),
- metrics:new(Engine, histogram, [hackney_pool, PoolName, in_use_count]),
- metrics:new(Engine, histogram, [hackney_pool, PoolName, free_count]),
- metrics:new(Engine, histogram, [hackney_pool, PoolName, queue_counter]),
- Engine.
-
-delete_metrics(Engine, PoolName) ->
- metrics:delete(Engine, [hackney_pool, PoolName, take_rate]),
- metrics:delete(Engine, [hackney_pool, PoolName, no_socket]),
- metrics:delete(Engine, [hackney_pool, PoolName, in_use_count]),
- metrics:delete(Engine, [hackney_pool, PoolName, free_count]),
- metrics:delete(Engine, [hackney_pool, PoolName, queue_counter]).
-
-
-update_usage(#state{name=PoolName, metrics=Engine, sockets=Sockets,
+ metrics:new(histogram, [hackney_pool, PoolName, take_rate]),
+ metrics:new(counter, [hackney_pool, PoolName, no_socket]),
+ metrics:new(histogram, [hackney_pool, PoolName, in_use_count]),
+ metrics:new(histogram, [hackney_pool, PoolName, free_count]),
+ metrics:new(histogram, [hackney_pool, PoolName, queue_counter]).
+
+delete_metrics(PoolName) ->
+ metrics:delete([hackney_pool, PoolName, take_rate]),
+ metrics:delete([hackney_pool, PoolName, no_socket]),
+ metrics:delete([hackney_pool, PoolName, in_use_count]),
+ metrics:delete([hackney_pool, PoolName, free_count]),
+ metrics:delete([hackney_pool, PoolName, queue_counter]).
+
+
+update_usage(#state{name=PoolName, sockets=Sockets,
clients=Clients}) ->
- metrics:update_histogram(Engine, [hackney_pool, PoolName,in_use_count],
- dict:size(Clients) - 1),
- metrics:update_histogram(Engine, [hackney_pool, PoolName, free_count],
- dict:size(Sockets) - 1).
+ metrics:update([hackney_pool, PoolName,in_use_count],
+ dict:size(Clients) - 1),
+ metrics:update([hackney_pool, PoolName, free_count],
+ dict:size(Sockets) - 1).
diff --git a/src/hackney_response.erl b/src/hackney_response.erl
index bfc798ba..34986b8d 100644
--- a/src/hackney_response.erl
+++ b/src/hackney_response.erl
@@ -122,9 +122,8 @@ wait_headers({header, {Key, Value}=KV, Parser}, Client, Status, Headers) ->
wait_headers({headers_complete, Parser}, Client, Status, Headers) ->
ResponseTime = timer:now_diff(os:timestamp(),
Client#client.start_time)/1000,
- metrics:update_histogram(Client#client.mod_metrics,
- [hackney, Client#client.host, response_time],
- ResponseTime),
+ metrics:update([hackney, Client#client.host, response_time],
+ ResponseTime),
{ok, Status, lists:reverse(Headers), Client#client{parser=Parser}}.
stream_body(Client=#client{response_state=done}) ->
diff --git a/src/hackney_util.erl b/src/hackney_util.erl
index 8f5f249f..723c7810 100644
--- a/src/hackney_util.erl
+++ b/src/hackney_util.erl
@@ -11,7 +11,6 @@
-export([maybe_apply_defaults/2]).
-export([is_ipv6/1]).
-export([privdir/0]).
--export([mod_metrics/0]).
-export([to_atom/1]).
%% random compatibility
@@ -105,16 +104,6 @@ privdir() ->
end.
-mod_metrics() ->
- case application:get_env(hackney, mod_metrics) of
- {ok, folsom} -> metrics_folsom;
- {ok, exometer} -> metrics_exometer;
- {ok, dummy} -> metrics_dummy;
- {ok, Mod} -> Mod;
- _ -> metrics_dummy
- end.
-
-
to_atom(V) when is_list(V) ->
try
list_to_existing_atom(V)
|