diff --git a/CHANGELOG.md b/CHANGELOG.md index 65e562e..1c043f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,18 +1,11 @@ # Changelog - All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## In development - -- Added per-host telemetry metrics (https://github.com/TheRealReal/hackney_telemetry/pull/7) - ## [0.1.2] - 2022-09-19 - ### Changed - - Update docs - Build docs with ex_doc - Update specs to successfully run Dialyzer @@ -21,16 +14,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.1.1] - 2021-12-10 ### Changed - Minor update. ### Fixed - - Fix histogram values shift for `in_use_count` and `free_count metrics` ## [0.1.0] - 2021-12-08 ## Added - - First version! - Metrics collector for hackney global and pool metrics diff --git a/README.md b/README.md index 36cd8a8..d58bc1d 100644 --- a/README.md +++ b/README.md @@ -18,22 +18,16 @@ so we need to transform the metrics data before reporting it. The following metrics are exported by this library to telemetry. -| Metric | Tags | Meaning | -| ------------------------------ | ---- | ----------------------------------------------------- | -| `hackney.nb_requests` | - | Current number of requests | -| `hackney.finished_requests` | - | Total number of finished requests | -| `hackney.total_requests` | - | Total number of requests | -| `hackney_pool.free_count` | pool | Number of free sockets in a connection pool | -| `hackney_pool.in_use_count` | pool | Number of busy sockets in a connection pool | -| `hackney_pool.no_socket` | pool | Count of new connections | -| `hackney_pool.queue_count` | pool | Number of requests waiting for a connection in a pool | -| `hackney_pool.take_rate` | pool | Rate at which a connection is retrieved from the pool | -| `hackney_host.nb_requests` | host | Number of running requests per host | -| `hackney_host.request_time` | host | Request time per host | -| `hackney_host.connect_time` | host | Connect time per host | -| `hackney_host.response_time` | host | Response time per host | -| `hackney_host.connect_timeout` | host | Number of connect timeout per host | -| `hackney_host.connect_error` | host | Number of timeout errors per host | +| Metric | Tags | Meaning | +| --------------------------- | ---- | ----------------------------------------------------- | +| `hackney.nb_requests` | - | Current number of requests | +| `hackney.finished_requests` | - | Total number of finished requests | +| `hackney.total_requests` | - | Total number of requests | +| `hackney_pool.free_count` | pool | Number of free sockets in a connection pool | +| `hackney_pool.in_use_count` | pool | Number of busy sockets in a connection pool | +| `hackney_pool.no_socket` | pool | Count of new connections | +| `hackney_pool.queue_count` | pool | Number of requests waiting for a connection in a pool | +| `hackney_pool.take_rate` | pool | Rate at which a connection is retrieved from the pool | This module implements all the callbacks required by `hackney_metrics` but it does not support host metrics. @@ -132,13 +126,7 @@ defmodule YourApplcation.Telemetry do last_value("hackney_pool.in_use_count", tags: [:pool]), last_value("hackney_pool.no_socket", tags: [:pool]), last_value("hackney_pool.queue_count", tags: [:pool]), - last_value("hackney_pool.take_rate", tags: [:pool]), - last_value("hackney_host.nb_requests", tags: [:host]), - last_value("hackney_host.request_time", tags: [:host]), - last_value("hackney_host.connect_time", tags: [:host]), - last_value("hackney_host.response_time", tags: [:host]), - last_value("hackney_host.connect_timeout", tags: [:host]), - last_value("hackney_host.connect_error", tags: [:host]) + last_value("hackney_pool.take_rate", tags: [:pool]) ] end end @@ -172,7 +160,7 @@ rebar3 steamroll ## Code of Conduct -This project Contributor Covenant version 2.1. Check [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) file for more information. +This project Contributor Covenant version 2.1. Check [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) file for more information. ## License diff --git a/include/hackney_telemetry_worker.hrl b/include/hackney_telemetry_worker.hrl index f696113..6f65e31 100644 --- a/include/hackney_telemetry_worker.hrl +++ b/include/hackney_telemetry_worker.hrl @@ -1,7 +1,7 @@ -record( worker_state, { - value :: map(), + value :: any(), report_interval :: non_neg_integer(), telemetry_settings :: {[atom(), ...], atom(), map()} } diff --git a/src/hackney_telemetry_sup.erl b/src/hackney_telemetry_sup.erl index 1e2a303..dfa772d 100644 --- a/src/hackney_telemetry_sup.erl +++ b/src/hackney_telemetry_sup.erl @@ -17,17 +17,14 @@ start_link() -> supervisor:start_link({local, ?SERVER}, ?MODULE, []). --define(PER_HOST, [nb_requests, request_time, connect_time, response_time, connect_timeout, connect_error]). - init([]) -> SupFlags = #{strategy => one_for_one, intensity => 0, period => 1}, ChildSpecs = [ - hackney_telemetry_worker:child_spec([{metric, [hackney, Sub]}]) - || Sub <- [nb_requests, total_requests, finished_requests]] - ++ [ - hackney_telemetry_worker:child_spec([{metric, [hackney_host, Sub]}]) - || Sub <- ?PER_HOST], + hackney_telemetry_worker:child_spec([{metric, [hackney, nb_requests]}]), + hackney_telemetry_worker:child_spec([{metric, [hackney, total_requests]}]), + hackney_telemetry_worker:child_spec([{metric, [hackney, finished_requests]}]) + ], {ok, {SupFlags, ChildSpecs}}. %%% @doc Start worker for the given metric under this supervisor. diff --git a/src/hackney_telemetry_worker.erl b/src/hackney_telemetry_worker.erl index 107309c..24bf36d 100644 --- a/src/hackney_telemetry_worker.erl +++ b/src/hackney_telemetry_worker.erl @@ -58,9 +58,6 @@ child_spec(Args) -> %% @doc Return name of the worker process -spec worker_name(hackney_metric()) -> {global, {atom(), hackney_metric()}}. -worker_name([hackney, Host, Key]) when is_list(Host) -> - worker_name([hackney_host, Key]); - worker_name(Metric) -> {global, {node(), Metric}}. %% @doc Update metric @@ -68,7 +65,7 @@ worker_name(Metric) -> {global, {node(), Metric}}. -spec update(hackney_metric(), any(), transform_fun()) -> ok. update(Metric, EventValue, TransformFun) -> ProcessName = worker_name(Metric), - gen_server:cast(ProcessName, {update_event, Metric, EventValue, TransformFun}). + gen_server:cast(ProcessName, {update_event, EventValue, TransformFun}). %% @doc Start server @@ -84,7 +81,7 @@ init(Args) -> {ok, TelemetrySettings} -> State = #worker_state{ - value = #{}, + value = 0, report_interval = fetch_report_interval(Args), telemetry_settings = TelemetrySettings }, @@ -100,8 +97,6 @@ telemetry_settings(Args) -> case Metric of [hackney, MeasurementKey] -> {ok, {[hackney], MeasurementKey, #{}}}; - [hackney_host, MeasurementKey] -> {ok, {[hackney_host], MeasurementKey, #{}}}; - [hackney_pool, PoolName, MeasurementKey] -> {ok, {[hackney_pool], MeasurementKey, #{pool => PoolName}}}; @@ -114,29 +109,21 @@ handle_call(_Message, _From, State) -> {reply, ok, State}. %% @doc Handle update event -handle_cast({update_event, Metric, EventValue, TransformFun}, State) -> - MetadataKey = metadata_key(Metric), - OldValue = maps:get(MetadataKey, State#worker_state.value, 0), - NewValue = TransformFun(OldValue, EventValue), - - UpdatedState = State#worker_state{value = maps:put(MetadataKey, NewValue, State#worker_state.value)}, +handle_cast({update_event, EventValue, TransformFun}, State) -> + NewValue = TransformFun(State#worker_state.value, EventValue), + UpdatedState = State#worker_state{value = NewValue}, if - UpdatedState#worker_state.report_interval == 0 -> - {noreply, report(UpdatedState)}; - true -> - {noreply, UpdatedState} - end. - -metadata_key([hackney, Host, _]) when is_list(Host) -> #{host => Host}; -metadata_key([hackney_pool, Pool, _]) -> #{pool => Pool}; -metadata_key(_Metric) -> #{}. + UpdatedState#worker_state.report_interval == 0 -> report(UpdatedState); + true -> ok + end, + {noreply, UpdatedState}. %% @doc Handle report events handle_info(report, State) -> - State1 = report(State), - maybe_schedule_report(State1), - {noreply, State1}. + report(State), + maybe_schedule_report(State), + {noreply, State}. %% @doc gen_server terminate callback @@ -151,11 +138,9 @@ code_change(_OldVersion, State, _Extra) -> {ok, State}. -spec report(#worker_state{}) -> ok. report(State) -> {Metric, MeasurementKey, Metadata} = State#worker_state.telemetry_settings, - [begin - Measurement = #{MeasurementKey => Value}, - telemetry:execute(Metric, Measurement, maps:merge(ExtraMetadata, Metadata)) - end || {ExtraMetadata, Value} <- maps:to_list(State#worker_state.value)], - State#worker_state{value = #{}}. + Measurement = #{MeasurementKey => State#worker_state.value}, + telemetry:execute(Metric, Measurement, Metadata), + ok. %% @doc Report events to telemetry. %%