Skip to content

Commit

Permalink
feat: add Prometheus metrics for active ws conn and topic sub totals
Browse files Browse the repository at this point in the history
  • Loading branch information
w3b6x9 committed Jul 28, 2021
1 parent d376d5b commit eaf8180
Show file tree
Hide file tree
Showing 12 changed files with 168 additions and 3 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ SECURE_CHANNELS # {string} (options: 'true'/'false') Enable/Disable
JWT_SECRET # {string} HS algorithm octet key (e.g. "95x0oR8jq9unl9pOIx"). Only required if SECURE_CHANNELS is set to true.
JWT_CLAIM_VALIDATORS # {string} Expected claim key/value pairs compared to JWT claims via equality checks in order to validate JWT. e.g. '{"iss": "Issuer", "nbf": 1610078130}'. This is optional but encouraged.
MAX_REPLICATION_LAG_MB # {number} If set, when the replication lag exceeds MAX_REPLICATION_LAG_MB (value must be a positive integer in megabytes), then replication slot is dropped, Realtime is restarted, and a new slot is created. Warning: setting MAX_REPLICATION_SLOT_MB could cause database changes to be lost when the replication slot is dropped.
EXPOSE_METRICS # {string} (options: 'true'/'false') Expose Prometheus metrics at '/metrics' endpoint. Currently supports active websocket connection and active topic subscription totals. Defaults to 'true' in development and 'false' in production.
```

**EXAMPLE: RUNNING SERVER WITH ALL OPTIONS**
Expand Down
10 changes: 9 additions & 1 deletion server/config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ db_ip_version =
%{"ipv4" => :inet, "ipv6" => :inet6}
|> Map.fetch(System.get_env("DB_IP_VERSION", "") |> String.downcase())

# Expose Prometheus metrics
# Defaults to true in development and false in production
expose_metrics = System.get_env("EXPOSE_METRICS", "true") == "true"

config :realtime,
app_port: app_port,
db_host: db_host,
Expand All @@ -73,7 +77,8 @@ config :realtime,
secure_channels: secure_channels,
jwt_secret: jwt_secret,
jwt_claim_validators: jwt_claim_validators,
max_replication_lag_in_mb: max_replication_lag_in_mb
max_replication_lag_in_mb: max_replication_lag_in_mb,
expose_metrics: expose_metrics

# Configures the endpoint
config :realtime, RealtimeWeb.Endpoint,
Expand All @@ -90,6 +95,9 @@ config :logger, :console,
# Use Jason for JSON parsing in Phoenix
config :phoenix, :json_library, Jason

config :realtime, Realtime.Metrics.PromEx,
disabled: !expose_metrics

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{Mix.env()}.exs"
10 changes: 9 additions & 1 deletion server/config/releases.exs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ db_ip_version =
%{"ipv4" => :inet, "ipv6" => :inet6}
|> Map.fetch(System.get_env("DB_IP_VERSION", "") |> String.downcase())

# Expose Prometheus metrics
# Defaults to true in development and false in production
expose_metrics = System.get_env("EXPOSE_METRICS", "false") == "true"

config :realtime,
app_port: app_port,
db_host: db_host,
Expand All @@ -66,9 +70,13 @@ config :realtime,
secure_channels: secure_channels,
jwt_secret: jwt_secret,
jwt_claim_validators: jwt_claim_validators,
max_replication_lag_in_mb: max_replication_lag_in_mb
max_replication_lag_in_mb: max_replication_lag_in_mb,
expose_metrics: expose_metrics

config :realtime, RealtimeWeb.Endpoint,
http: [:inet6, port: app_port],
pubsub_server: Realtime.PubSub,
secret_key_base: session_secret_key_base

config :realtime, Realtime.Metrics.PromEx,
disabled: !expose_metrics
2 changes: 2 additions & 0 deletions server/lib/realtime/application.ex
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ defmodule Realtime.Application do

# List all child processes to be supervised
children = [
Realtime.Metrics.PromEx,
Realtime.Metrics.SocketMonitor,
# Start the endpoint when the application starts
RealtimeWeb.Endpoint,
{
Expand Down
8 changes: 8 additions & 0 deletions server/lib/realtime/metrics/prom_ex.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
defmodule Realtime.Metrics.PromEx do
use PromEx, otp_app: :realtime

@impl true
def plugins do
[Realtime.Metrics.PromEx.Plugins.Realtime]
end
end
29 changes: 29 additions & 0 deletions server/lib/realtime/metrics/prom_ex_plugins/realtime_plugin.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
defmodule Realtime.Metrics.PromEx.Plugins.Realtime do
use PromEx.Plugin

@event_prefix [:realtime, :prom_ex, :plugin, :socket]

@impl true
def event_metrics(_opts) do
Event.build(
:realtime_socket_event_metrics,
[
last_value(
[:realtime, :active, :websocket, :connection, :total],
event_name: socket_event(),
measurement: :active_socket_total,
description: "The total number of active websocket connections."
),
last_value(
[:realtime, :active, :websocket, :topic, :total],
event_name: channel_event(),
measurement: :active_channel_total,
description: "The total number of active topic subscriptions."
)
]
)
end

def socket_event, do: @event_prefix ++ [:connection]
def channel_event, do: @event_prefix ++ [:channel]
end
81 changes: 81 additions & 0 deletions server/lib/realtime/metrics/socket_monitor.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# This file draws from https://github.com/pushex-project/pushex
# License: https://github.com/pushex-project/pushex/blob/master/LICENSE

defmodule Realtime.Metrics.SocketMonitor do
use GenServer
alias Realtime.Metrics.PromEx.Plugins.Realtime

def start_link(_) do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end

def init(_) do
{:ok, %{transport_pids: %{}, channel_pids: %{}}}
end

def track_socket(socket = %Phoenix.Socket{}) do
GenServer.call(__MODULE__, {:track_socket, socket})
end

def track_channel(socket = %Phoenix.Socket{}) do
GenServer.call(__MODULE__, {:track_channel, socket})
end

## Callbacks

def handle_call(
{:track_socket, %Phoenix.Socket{transport_pid: transport_pid}},
_from,
state = %{transport_pids: transport_pids}
) do
Process.monitor(transport_pid)

new_transport_pids =
Map.put(transport_pids, transport_pid, %{
online_at: unix_ms_now()
})

execute_socket_telemetry(new_transport_pids)

{:reply, :ok, %{state | transport_pids: new_transport_pids}}
end

def handle_call(
{:track_channel, %Phoenix.Socket{channel_pid: channel_pid, topic: topic}},
_from,
state = %{channel_pids: channel_pids}
) do
Process.monitor(channel_pid)

new_channel_pids =
Map.put(channel_pids, channel_pid, %{
channel: topic,
online_at: unix_ms_now()
})

execute_channel_telemetry(new_channel_pids)

{:reply, :ok, %{state | channel_pids: new_channel_pids}}
end

def handle_info(
{:DOWN, _ref, :process, pid, _reason},
state = %{transport_pids: transport_pids, channel_pids: channel_pids}
) do
new_transport_pids = Map.delete(transport_pids, pid)
new_channel_pids = Map.delete(channel_pids, pid)

execute_socket_telemetry(new_transport_pids)
execute_channel_telemetry(new_channel_pids)

{:noreply, %{state | transport_pids: new_transport_pids, channel_pids: new_channel_pids}}
end

defp execute_socket_telemetry(pids),
do: :telemetry.execute(Realtime.socket_event(), %{active_socket_total: map_size(pids)})

defp execute_channel_telemetry(pids),
do: :telemetry.execute(Realtime.channel_event(), %{active_channel_total: map_size(pids)})

defp unix_ms_now(), do: :erlang.system_time(:millisecond)
end
6 changes: 6 additions & 0 deletions server/lib/realtime_web/channels/realtime_channel.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ defmodule RealtimeWeb.RealtimeChannel do
require Logger, warn: false

def join("realtime:" <> _topic, _payload, socket) do
send(self(), :after_join)
{:ok, %{}, socket}
end

Expand All @@ -21,4 +22,9 @@ defmodule RealtimeWeb.RealtimeChannel do
def handle_realtime_transaction(topic, txn) do
RealtimeWeb.Endpoint.broadcast_from!(self(), topic, txn.type, txn)
end

def handle_info(:after_join, socket) do
Realtime.Metrics.SocketMonitor.track_channel(socket)
{:noreply, socket}
end
end
8 changes: 8 additions & 0 deletions server/lib/realtime_web/channels/user_socket.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@ defmodule RealtimeWeb.UserSocket do

alias RealtimeWeb.ChannelsAuthorization

defoverridable init: 1

def init(state) do
res = {:ok, {_, socket}} = super(state)
Realtime.Metrics.SocketMonitor.track_socket(socket)
res
end

## Channels
channel "realtime:*", RealtimeWeb.RealtimeChannel

Expand Down
4 changes: 4 additions & 0 deletions server/lib/realtime_web/endpoint.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ defmodule RealtimeWeb.Endpoint do
plug Phoenix.CodeReloader
end

if Application.fetch_env!(:realtime, :expose_metrics) do
plug PromEx.Plug, prom_ex_module: Realtime.Metrics.PromEx
end

plug Plug.RequestId
plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint]

Expand Down
3 changes: 2 additions & 1 deletion server/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ defmodule Realtime.MixProject do
{:epgsql, "~> 4.5"},
{:timex, "~> 3.0"},
{:retry, "~> 0.14.1"},
{:mock, "~> 0.3.0", only: :test}
{:mock, "~> 0.3.0", only: :test},
{:prom_ex, "~> 1.3.0"}
]
end
end
9 changes: 9 additions & 0 deletions server/mix.lock
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
%{
"castore": {:hex, :castore, "0.1.11", "c0665858e0e1c3e8c27178e73dffea699a5b28eb72239a3b2642d208e8594914", [:mix], [], "hexpm", "91b009ba61973b532b84f7c09ce441cba7aa15cb8b006cf06c6f4bba18220081"},
"certifi": {:hex, :certifi, "2.5.3", "70bdd7e7188c804f3a30ee0e7c99655bc35d8ac41c23e12325f36ab449b70651", [:rebar3], [{:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}], "hexpm", "ed516acb3929b101208a9d700062d520f3953da3b6b918d866106ffa980e1c10"},
"combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"},
"cowboy": {:hex, :cowboy, "2.8.0", "f3dc62e35797ecd9ac1b50db74611193c29815401e53bac9a5c0577bd7bc667d", [:rebar3], [{:cowlib, "~> 2.9.1", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "~> 1.7.1", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "4643e4fba74ac96d4d152c75803de6fad0b3fa5df354c71afdd6cbeeb15fac8a"},
"cowboy_telemetry": {:hex, :cowboy_telemetry, "0.3.1", "ebd1a1d7aff97f27c66654e78ece187abdc646992714164380d8a041eda16754", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a6efd3366130eab84ca372cbd4a7d3c3a97bdfcfb4911233b035d117063f0af"},
"cowlib": {:hex, :cowlib, "2.9.1", "61a6c7c50cf07fdd24b2f45b89500bb93b6686579b069a89f88cb211e1125c78", [:rebar3], [], "hexpm", "e4175dc240a70d996156160891e1c62238ede1729e45740bdd38064dad476170"},
"epgsql": {:hex, :epgsql, "4.5.0", "ca863ee3a771e7696ae58ec924a29df8435cdaffa64dba70c02dd2571ad2122d", [:rebar3], [], "hexpm", "0a02d338cc1426c5873b412fed9d694f7b5143933c5f85f244655a5e77b23078"},
"file_system": {:hex, :file_system, "0.2.10", "fb082005a9cd1711c05b5248710f8826b02d7d1784e7c3451f9c1231d4fc162d", [:mix], [], "hexpm", "41195edbfb562a593726eda3b3e8b103a309b733ad25f3d642ba49696bf715dc"},
"finch": {:hex, :finch, "0.7.0", "2352962c81fd54952788d66e5eed436a7b734745e0c1cdd5b28a28184fe3e5cd", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: false]}, {:mint, "~> 1.3", [hex: :mint, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.3.5", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:nimble_pool, "~> 0.2", [hex: :nimble_pool, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4e046b6a4f010898a036244d680ae212331aab2f0a1005bcded3e3e3364f0025"},
"gettext": {:hex, :gettext, "0.18.2", "7df3ea191bb56c0309c00a783334b288d08a879f53a7014341284635850a6e55", [:mix], [], "hexpm", "f9f537b13d4fdd30f3039d33cb80144c3aa1f8d9698e47d7bcbcc8df93b1f5c5"},
"hackney": {:hex, :hackney, "1.17.0", "717ea195fd2f898d9fe9f1ce0afcc2621a41ecfe137fae57e7fe6e9484b9aa99", [:rebar3], [{:certifi, "~>2.5", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "~>3.3", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "64c22225f1ea8855f584720c0e5b3cd14095703af1c9fbc845ba042811dc671c"},
"httpoison": {:hex, :httpoison, "1.8.0", "6b85dea15820b7804ef607ff78406ab449dd78bed923a49c7160e1886e987a3d", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "28089eaa98cf90c66265b6b5ad87c59a3729bea2e74e9d08f9b51eb9729b3c3a"},
Expand All @@ -17,7 +19,10 @@
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
"mime": {:hex, :mime, "1.5.0", "203ef35ef3389aae6d361918bf3f952fa17a09e8e43b5aa592b93eba05d0fb8d", [:mix], [], "hexpm", "55a94c0f552249fc1a3dd9cd2d3ab9de9d3c89b559c2bd01121f824834f24746"},
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
"mint": {:hex, :mint, "1.3.0", "396b3301102f7b775e103da5a20494b25753aed818d6d6f0ad222a3a018c3600", [:mix], [{:castore, "~> 0.1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "a9aac960562e43ca69a77e5176576abfa78b8398cec5543dd4fb4ab0131d5c1e"},
"mock": {:hex, :mock, "0.3.6", "e810a91fabc7adf63ab5fdbec5d9d3b492413b8cda5131a2a8aa34b4185eb9b4", [:mix], [{:meck, "~> 0.8.13", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "bcf1d0a6826fb5aee01bae3d74474669a3fa8b2df274d094af54a25266a1ebd2"},
"nimble_options": {:hex, :nimble_options, "0.3.5", "a4f6820cdcb4ee444afd78635f323e58e8a5ddf2fbbe9b9d283a99f972034bae", [:mix], [], "hexpm", "f5507cc90033a8d12769522009c80aa9164af6bab245dbd4ad421d008455f1e1"},
"nimble_pool": {:hex, :nimble_pool, "0.2.4", "1db8e9f8a53d967d595e0b32a17030cdb6c0dc4a451b8ac787bf601d3f7704c3", [:mix], [], "hexpm", "367e8071e137b787764e6a9992ccb57b276dc2282535f767a07d881951ebeac6"},
"parse_trans": {:hex, :parse_trans, "3.3.1", "16328ab840cc09919bd10dab29e431da3af9e9e7e7e6f0089dd5a2d2820011d8", [:rebar3], [], "hexpm", "07cd9577885f56362d414e8c4c4e6bdf10d43a8767abb92d24cbe8b24c54888b"},
"phoenix": {:hex, :phoenix, "1.5.8", "71cfa7a9bb9a37af4df98939790642f210e35f696b935ca6d9d9c55a884621a4", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "35ded0a32f4836168c7ab6c33b88822eccd201bcd9492125a9bea4c54332d955"},
"phoenix_html": {:hex, :phoenix_html, "2.14.3", "51f720d0d543e4e157ff06b65de38e13303d5778a7919bcc696599e5934271b8", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "efd697a7fff35a13eeeb6b43db884705cba353a1a41d127d118fda5f90c8e80f"},
Expand All @@ -26,10 +31,14 @@
"plug": {:hex, :plug, "1.11.0", "f17217525597628298998bc3baed9f8ea1fa3f1160aa9871aee6df47a6e4d38e", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "2d9c633f0499f9dc5c2fd069161af4e2e7756890b81adcbb2ceaa074e8308876"},
"plug_cowboy": {:hex, :plug_cowboy, "2.4.1", "779ba386c0915027f22e14a48919a9545714f849505fa15af2631a0d298abf0f", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "d72113b6dff7b37a7d9b2a5b68892808e3a9a752f2bf7e503240945385b70507"},
"plug_crypto": {:hex, :plug_crypto, "1.2.1", "5c854427528bf61d159855cedddffc0625e2228b5f30eff76d5a4de42d896ef4", [:mix], [], "hexpm", "6961c0e17febd9d0bfa89632d391d2545d2e0eb73768f5f50305a23961d8782c"},
"prom_ex": {:hex, :prom_ex, "1.3.0", "7949d45af8a8da7258ed0575997473f6937473819a382be1582a89146c206745", [:mix], [{:absinthe, ">= 1.6.0", [hex: :absinthe, repo: "hexpm", optional: true]}, {:ecto, ">= 3.5.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:finch, "~> 0.7.0", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}, {:oban, ">= 2.4.0", [hex: :oban, repo: "hexpm", optional: true]}, {:phoenix, ">= 1.5.0", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, ">= 0.14.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, ">= 1.10.0", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, "~> 2.1", [hex: :plug_cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}, {:telemetry_metrics_prometheus_core, "~> 1.0.1", [hex: :telemetry_metrics_prometheus_core, repo: "hexpm", optional: false]}, {:telemetry_poller, "~> 0.5.1", [hex: :telemetry_poller, repo: "hexpm", optional: false]}], "hexpm", "9ca9e796b0d766d9a7f216faeb78cbfd5943c70c8c94b4b88436c2fde0900af3"},
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"},
"retry": {:hex, :retry, "0.14.1", "722d1b0cf87096b71213f5801d99fface7ca76adc83fc9dbf3e1daee952aef10", [:mix], [], "hexpm", "b3a609f286f6fe4f6b2c15f32cd4a8a60427d78d05d7b68c2dd9110981111ae0"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
"telemetry": {:hex, :telemetry, "0.4.2", "2808c992455e08d6177322f14d3bdb6b625fbcfd233a73505870d8738a2f4599", [:rebar3], [], "hexpm", "2d1419bd9dda6a206d7b5852179511722e2b18812310d304620c7bd92a13fcef"},
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.1", "315d9163a1d4660aedc3fee73f33f1d355dcc76c5c3ab3d59e76e3edf80eef1f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7be9e0871c41732c233be71e4be11b96e56177bf15dde64a8ac9ce72ac9834c6"},
"telemetry_metrics_prometheus_core": {:hex, :telemetry_metrics_prometheus_core, "1.0.1", "cebf3c8892f5dc40eb057375e5c1c2077c155ed46654d5af35a2ad48a3f48749", [:mix], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "112a9d5a6facf34fb0dda8426c18432ffb9e8abe38f394f3417cb589ecaeb674"},
"telemetry_poller": {:hex, :telemetry_poller, "0.5.1", "21071cc2e536810bac5628b935521ff3e28f0303e770951158c73eaaa01e962a", [:rebar3], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4cab72069210bc6e7a080cec9afffad1b33370149ed5d379b81c7c5f0c663fd4"},
"timex": {:hex, :timex, "3.6.3", "58ce6c9eda8ed47fc80c24dde09d481465838d3bcfc230949287fc1b0b0041c1", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "6d69f4f95fcf5684102a9cb3cf92c5ba6545bd60ed8d8a6a93cd2a4a4fb0d9ec"},
"tzdata": {:hex, :tzdata, "1.0.5", "69f1ee029a49afa04ad77801febaf69385f3d3e3d1e4b56b9469025677b89a28", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "55519aa2a99e5d2095c1e61cc74c9be69688f8ab75c27da724eb8279ff402a5a"},
"unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"},
Expand Down

0 comments on commit eaf8180

Please sign in to comment.