Expose system metrics #4

Merged
joao.dubas merged 9 commits from jpd-add-prom-ex into main 2022-05-03 16:19:40 +00:00
10 changed files with 126 additions and 17 deletions

View File

@ -36,6 +36,10 @@ compose_up: ## start containers for this service
compose_test: ## run tests in containers
@$(COMPOSE) run -e MIX_ENV=test --entrypoint make app test
.PHONY: compose_ps
compose_ps: ## status of containers
@$(COMPOSE) ps
.PHONY: help
help:
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

View File

@ -14,6 +14,13 @@ config :wabanex, Wabanex.Repo,
migration_primary_key: [type: :binary_id],
migration_foreign_key: [type: :binary_id]
config :wabanex, Wabanex.PromEx,
disabled: false,
manual_metrics_start_delay: :no_delay,
drop_metrics_groups: [],
grafana: :disabled,
metrics_server: :disabled
# Configures the endpoint
config :wabanex, WabanexWeb.Endpoint,
url: [host: "localhost"],

View File

@ -30,23 +30,9 @@ services:
- 'app_build:/opt/app/_build'
- 'app_deps:/opt/app/deps'
working_dir: /opt/app
entrypoint: sleep
command: infinity
pgcli:
image: 'joaodubas/pgcli:latest'
hostname: development
depends_on:
- db
environment:
PGUSER: *db_user
PGPASSWORD: *db_pass
PGHOST: *db_host
PGDATABASE: wabanex_dev
volumes:
- './priv/docker/pgcli:/root/.config/pgcli'
restart: unless-stopped
entrypoint: sleep
command: 3650d
command: infinity
volumes:
db_data: {}

View File

@ -7,6 +7,8 @@ defmodule Wabanex.Application do
def start(_type, _args) do
children = [
# Start the PromEx supervisor
Wabanex.PromEx,
# Start the Ecto repository
Wabanex.Repo,
# Start the Telemetry supervisor

102
lib/wabanex/prom_ex.ex Normal file
View File

@ -0,0 +1,102 @@
defmodule Wabanex.PromEx do
@moduledoc """
Be sure to add the following to finish setting up PromEx:
1. Update your configuration (config.exs, dev.exs, prod.exs, releases.exs, etc) to
configure the necessary bit of PromEx. Be sure to check out `PromEx.Config` for
more details regarding configuring PromEx:
```
config :wabanex, Wabanex.PromEx,
disabled: false,
manual_metrics_start_delay: :no_delay,
drop_metrics_groups: [],
grafana: :disabled,
metrics_server: :disabled
```
2. Add this module to your application supervision tree. It should be one of the first
things that is started so that no Telemetry events are missed. For example, if PromEx
is started after your Repo module, you will miss Ecto's init events and the dashboards
will be missing some data points:
```
def start(_type, _args) do
children = [
Wabanex.PromEx,
...
]
...
end
```
3. Update your `endpoint.ex` file to expose your metrics (or configure a standalone
server using the `:metrics_server` config options). Be sure to put this plug before
your `Plug.Telemetry` entry so that you can avoid having calls to your `/metrics`
endpoint create their own metrics and logs which can pollute your logs/metrics given
that Prometheus will scrape at a regular interval and that can get noisy:
```
defmodule WabanexWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :wabanex
...
plug PromEx.Plug, prom_ex_module: Wabanex.PromEx
...
end
```
4. Update the list of plugins in the `plugins/0` function return list to reflect your
application's dependencies. Also update the list of dashboards that are to be uploaded
to Grafana in the `dashboards/0` function.
"""
use PromEx, otp_app: :wabanex
alias PromEx.Plugins
@impl true
def plugins do
[
# PromEx built in plugins
Plugins.Application,
Plugins.Beam,
# {Plugins.Phoenix, router: WabanexWeb.Router, endpoint: WabanexWeb.Endpoint},
Plugins.Ecto,
# Plugins.Oban,
# Plugins.PhoenixLiveView,
Plugins.Absinthe
# Plugins.Broadway,
# Add your own PromEx metrics plugins
# Wabanex.Users.PromExPlugin
]
end
@impl true
def dashboard_assigns do
[
datasource_id: "prometheus",
default_selected_interval: "30s"
]
end
@impl true
def dashboards do
[
# PromEx built in Grafana dashboards
{:prom_ex, "application.json"},
{:prom_ex, "beam.json"},
# {:prom_ex, "phoenix.json"},
{:prom_ex, "ecto.json"},
# {:prom_ex, "oban.json"},
# {:prom_ex, "phoenix_live_view.json"},
{:prom_ex, "absinthe.json"}
# {:prom_ex, "broadway.json"},
# Add your dashboard definitions here with the format: {:otp_app, "path_in_priv"}
# {:wabanex, "/grafana_dashboards/user_metrics.json"}
]
end
end

View File

@ -16,6 +16,8 @@ defmodule WabanexWeb.Endpoint do
socket "/live", Phoenix.LiveView.Socket, websocket: [connect_info: [session: @session_options]]
plug PromEx.Plug, prom_ex_module: Wabanex.PromEx
# Serve at "/" the static files from "priv/static" directory.
#
# You should set gzip to true if you are running phx.digest

View File

@ -17,10 +17,11 @@ defmodule WabanexWeb.Schema.Types.Custom.DateRange do
end
@spec serialize_range(PgRanges.DateRange.t()) :: String.t()
@spec serialize_range(list(DateTime.t() | nil)) :: String.t()
@spec serialize_range(list(DateTime.t() | nil | atom)) :: String.t()
defp serialize_range(%PgRanges.DateRange{lower: start_range, upper: end_range}),
do: serialize_range([start_range, end_range])
defp serialize_range([start_range, :unbound]), do: serialize_range([start_range, nil])
defp serialize_range([start_range, nil]), do: "#{Date.to_iso8601(start_range)},"
defp serialize_range([start_range, end_range]),

View File

@ -45,6 +45,7 @@ defmodule Wabanex.MixProject do
{:phoenix_live_dashboard, "~> 0.6"},
{:plug_cowboy, "~> 2.0"},
{:postgrex, ">= 0.0.0"},
{:prom_ex, "~> 1.7"},
{:telemetry_metrics, "~> 0.6"},
{:telemetry_poller, "~> 1.0"}
]

View File

@ -39,8 +39,10 @@
"plug_cowboy": {:hex, :plug_cowboy, "2.5.2", "62894ccd601cf9597e2c23911ff12798a8a18d237e9739f58a6b04e4988899fe", [: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]}], "hexpm", "ea6e87f774c8608d60c8d34022a7d073bd7680a0a013f049fc62bf35efea1044"},
"plug_crypto": {:hex, :plug_crypto, "1.2.2", "05654514ac717ff3a1843204b424477d9e60c143406aa94daf2274fdd280794d", [:mix], [], "hexpm", "87631c7ad914a5a445f0a3809f99b079113ae4ed4b867348dd9eec288cecb6db"},
"postgrex": {:hex, :postgrex, "0.16.2", "0f83198d0e73a36e8d716b90f45f3bde75b5eebf4ade4f43fa1f88c90a812f74", [:mix], [{:connection, "~> 1.1", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "a9ea589754d9d4d076121090662b7afe155b374897a6550eb288f11d755acfa0"},
"prom_ex": {:hex, :prom_ex, "1.7.1", "39331ee3fe6f9a8587d8208bf9274a253bb80281700e127dd18786cda5e08c37", [:mix], [{:absinthe, ">= 1.6.0", [hex: :absinthe, repo: "hexpm", optional: true]}, {:broadway, ">= 1.0.2", [hex: :broadway, repo: "hexpm", optional: true]}, {:ecto, ">= 3.5.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:finch, "~> 0.10.2", [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.12.1", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, "~> 2.5.1", [hex: :plug_cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6.1", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}, {:telemetry_metrics_prometheus_core, "~> 1.0.2", [hex: :telemetry_metrics_prometheus_core, repo: "hexpm", optional: false]}, {:telemetry_poller, "~> 1.0.0", [hex: :telemetry_poller, repo: "hexpm", optional: false]}], "hexpm", "4c978872b88a929833925a0f4d0561824804c671fdd04581e765509ed0a6ed08"},
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
"telemetry": {:hex, :telemetry, "1.1.0", "a589817034a27eab11144ad24d5c0f9fab1f58173274b1e9bae7074af9cbee51", [:rebar3], [], "hexpm", "b727b2a1f75614774cff2d7565b64d0dfa5bd52ba517f16543e6fc7efcc0df48"},
"telemetry": {:hex, :telemetry, "1.0.0", "0f453a102cdf13d506b7c0ab158324c337c41f1cc7548f0bc0e130bbf0ae9452", [:rebar3], [], "hexpm", "73bc09fa59b4a0284efb4624335583c528e07ec9ae76aca96ea0673850aec57a"},
"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.2", "c98b1c580de637bfeac00db41b9fb91fb4c3548ee3d512a8ed7299172312eaf3", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "48351a0d56f80e38c997b44232b1043e0a081670d16766eee920e6254175b730"},
"telemetry_poller": {:hex, :telemetry_poller, "1.0.0", "db91bb424e07f2bb6e73926fcafbfcbcb295f0193e0a00e825e589a0a47e8453", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b3a24eafd66c3f42da30fc3ca7dda1e9d546c12250a2d60d7b81d264fbec4f6e"},
}

View File

@ -28,6 +28,7 @@ defmodule WabanexWeb.Schema.Types.Custom.DateRangeTest do
test "serialize a list of dates as a list of ISO8601 date strings" do
assert "1978-12-15,1980-02-13" == serialize(:date_range, [~D[1978-12-15], ~D[1980-02-13]])
assert "1978-12-15," == serialize(:date_range, [~D[1978-12-15], nil])
assert "1978-12-15," == serialize(:date_range, [~D[1978-12-15], :unbound])
end
test "serialize a postgres range as a list of ISO8601 date strings" do
@ -35,6 +36,7 @@ defmodule WabanexWeb.Schema.Types.Custom.DateRangeTest do
serialize(:date_range, DateRange.new(~D[1978-12-15], ~D[1980-02-13]))
assert "1978-12-15," == serialize(:date_range, DateRange.new(~D[1978-12-15], nil))
assert "1978-12-15," == serialize(:date_range, DateRange.new(~D[1978-12-15], :unbound))
end
test "can be parsed from a string of ISO8601" do