Skip to content

Add PromEx. #180

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ services:
dockerfile: Dockerfile
args:
# Elixir Version: 1.9, 1.10, 1.10.4, ...
VARIANT: '1.15.4'
VARIANT: '1.15.5'
# Phoenix Version: 1.4.17, 1.5.4, ...
PHOENIX_VERSION: '1.7.7'
# Node Version: 12, 14, ...
@@ -22,7 +22,7 @@ services:
command: sleep infinity

db:
image: postgres:15.3-bullseye
image: postgres:15.4-bullseye
restart: unless-stopped
volumes:
- postgres-data:/var/lib/postgresql/data
25 changes: 25 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
@@ -48,6 +48,31 @@ if Mix.env() == :dev do
]
end

# Configures prom_ex
config :zero_phoenix, ZeroPhoenix.PromEx,
disabled: false,
manual_metrics_start_delay: :no_delay,
drop_metrics_groups: [],
grafana: [
host: System.get_env("GRAFANA_HOST", "http://localhost:3000"),
username: System.get_env("GF_SECURITY_ADMIN_USER", "admin"),
password: System.get_env("GF_SECURITY_ADMIN_PASSWORD", "admin"),
folder_name: "zero-to-graphql-using-elixir",
upload_dashboards_on_start: true,
annotate_app_lifecycle: true
],
metrics_server: [
protocol: :http,
path: "/metrics",
port: 4021,
pool_size: 5,
cowboy_opts: [],
auth_strategy: :none
]

# config :zero_phoenix, ZeroPhoenix.PromEx,
# grafana_datasource_id: System.get_env("GRAFANA_DATASOURCE_ID", "Local Prometheus")

# Import environment specific config. This must remain at the bottom
# of this file so it overrides the configuration defined above.
import_config "#{config_env()}.exs"
22 changes: 22 additions & 0 deletions config/prod.exs
Original file line number Diff line number Diff line change
@@ -12,3 +12,25 @@ config :logger, level: :info

# Runtime production configuration, including reading
# of environment variables, is done on config/runtime.exs.

# Configures prom_ex
config :zero_phoenix, ZeroPhoenix.PromEx,
disabled: false,
manual_metrics_start_delay: :no_delay,
drop_metrics_groups: [],
grafana: [
host: System.get_env("GRAFANA_HOST", raise("GRAFANA_HOST is required")),
auth_token: System.get_env("GRAFANA_TOKEN", raise("GRAFANA_TOKEN is required")),
folder_name: "zero-to-graphql-using-elixir",
upload_dashboards_on_start: true,
annotate_app_lifecycle: true
],
metrics_server: [
protocol: :http,
path: "/metrics",
port: 4021,
pool_size: 5,
cowboy_opts: []
auth_strategy: :bearer,
auth_token: "<YOUR_AUTH_TOKEN_HERE>",
]
12 changes: 7 additions & 5 deletions lib/zero_phoenix/application.ex
Original file line number Diff line number Diff line change
@@ -7,16 +7,18 @@ defmodule ZeroPhoenix.Application do

def start(_type, _args) do
children = [
# Start the Ecto repository
ZeroPhoenix.Repo,
# Start the PromEx
ZeroPhoenix.PromEx,
# Start the Telemetry supervisor
ZeroPhoenixWeb.Telemetry,
# Start the Ecto repository
ZeroPhoenix.Repo,
# Start the PubSub system
{Phoenix.PubSub, name: ZeroPhoenix.PubSub},
# Start the endpoint when the application starts
# Start Finch
{Finch, name: ZeroPhoenix.Finch},
# Start the Endpoint (http/https)
ZeroPhoenixWeb.Endpoint
# Start your own worker by calling: ZeroPhoenix.Worker.start_link(arg1, arg2, arg3)
# worker(ZeroPhoenix.Worker, [arg1, arg2, arg3]),
]

# See https://hexdocs.pm/elixir/Supervisor.html
103 changes: 103 additions & 0 deletions lib/zero_phoenix/prom_ex.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
defmodule ZeroPhoenix.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 :zero_phoenix, ZeroPhoenix.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 = [
ZeroPhoenix.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 ZeroPhoenixWeb.Endpoint do
use Phoenix.Endpoint, otp_app: :zero_phoenix

...

plug PromEx.Plug, prom_ex_module: ZeroPhoenix.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: :zero_phoenix

alias PromEx.Plugins

@impl true
def plugins do
[
# PromEx built in plugins
Plugins.Application,
Plugins.Beam,
{Plugins.Phoenix, router: ZeroPhoenixWeb.Router, endpoint: ZeroPhoenixWeb.Endpoint},
Plugins.Ecto,
# Plugins.Oban,
Plugins.PhoenixLiveView,
Plugins.Absinthe
# Plugins.Broadway,

# Add your own PromEx metrics plugins
# ZeroPhoenix.Users.PromExPlugin
]
end

@impl true
def dashboard_assigns do
[
datasource_id: "Local Prometheus",
# datasource_id: Application.get_env(:zero_phoenix, :grafana_datasource_id),
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"}
# {:zero_phoenix, "/grafana_dashboards/user_metrics.json"}
]
end
end
1 change: 1 addition & 0 deletions lib/zero_phoenix_web/endpoint.ex
Original file line number Diff line number Diff line change
@@ -35,6 +35,7 @@ defmodule ZeroPhoenixWeb.Endpoint do
cookie_key: "request_logger"

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

plug Plug.Parsers,