From a38d6de4e59a243befce92ebeaee5a656e06df16 Mon Sep 17 00:00:00 2001 From: Diogo Scudelletti Date: Fri, 3 Jan 2025 16:17:46 +0100 Subject: [PATCH] Avoid compiling `Peep.Plug` when Plug module is not present. --- lib/plug.ex | 200 ++++++++++++++++++++++++++-------------------------- 1 file changed, 101 insertions(+), 99 deletions(-) diff --git a/lib/plug.ex b/lib/plug.ex index 8ff4cf1..f72fa7d 100644 --- a/lib/plug.ex +++ b/lib/plug.ex @@ -1,109 +1,111 @@ -defmodule Peep.Plug do - @moduledoc """ - Use this plug to expose your metrics on an endpoint for scraping. This is useful if you are using Prometheus. +if Code.ensure_loaded?(Plug) do + defmodule Peep.Plug do + @moduledoc """ + Use this plug to expose your metrics on an endpoint for scraping. This is useful if you are using Prometheus. + + This plug accepts the following options: + + * `:peep_worker` - The name of the Peep worker to use. This is required. + * `:path` - The path to expose the metrics on. Defaults to `"/metrics"`. + * `:on_unmatched_path` - The intended behavior of this plug when handling a + request to a different path. There are two possible values: + - `:continue` (default) - This allows for subsequent Plugs in a router to + be executed. This option is useful when Peep.Plug is part of a router + for a Phoenix application, or a router that matches other paths after + Peep.Plug. + + - `:halt` - Responds to requests with 404. This option is useful when + Peep.Plug is used for serving metrics on a separate port, which is a + practice that is encouraged by other libraries that export Prometheus + metrics. + + ## Usage + + You can use this plug in your Phoenix endpoint like this: + + ```elixir + plug Peep.Plug, peep_worker: :my_peep_worker + ``` + + Or if you'd rather use a different path: + + ```elixir + plug Peep.Plug, path: "/my-metrics" + ``` + + If you are not using Phoenix, you can use it directly with Cowboy by adding this to your applications's supervision tree: + + ```elixir + {Plug.Cowboy, scheme: :http, plug: Peep.Plug, options: [port: 9000]} + ``` + + Similarly, if you are using Bandit, you can use it like so: + + ```elixir + {Bandit, [ + scheme: :http, + plug: {Peep.Plug, peep_worker: :my_app}, + port: 9000 + ]} + ``` + """ + + @behaviour Plug + + import Plug.Conn + alias Plug.Conn + require Logger + + @default_metrics_path "/metrics" + + @impl Plug + def init(opts) do + %{ + metrics_path: Keyword.get(opts, :path, @default_metrics_path), + peep_worker: Keyword.fetch!(opts, :peep_worker), + on_unmatched_path: Keyword.get(opts, :on_unmatched_path, :continue) + } + end + + @impl Plug + def call(%Conn{request_path: metrics_path, method: "GET"} = conn, %{ + metrics_path: metrics_path, + peep_worker: peep_worker + }) do + metrics = + Peep.get_all_metrics(peep_worker) + |> Peep.Prometheus.export() - This plug accepts the following options: - - * `:peep_worker` - The name of the Peep worker to use. This is required. - * `:path` - The path to expose the metrics on. Defaults to `"/metrics"`. - * `:on_unmatched_path` - The intended behavior of this plug when handling a - request to a different path. There are two possible values: - - `:continue` (default) - This allows for subsequent Plugs in a router to - be executed. This option is useful when Peep.Plug is part of a router - for a Phoenix application, or a router that matches other paths after - Peep.Plug. - - - `:halt` - Responds to requests with 404. This option is useful when - Peep.Plug is used for serving metrics on a separate port, which is a - practice that is encouraged by other libraries that export Prometheus - metrics. - - ## Usage - - You can use this plug in your Phoenix endpoint like this: - - ```elixir - plug Peep.Plug, peep_worker: :my_peep_worker - ``` - - Or if you'd rather use a different path: - - ```elixir - plug Peep.Plug, path: "/my-metrics" - ``` - - If you are not using Phoenix, you can use it directly with Cowboy by adding this to your applications's supervision tree: - - ```elixir - {Plug.Cowboy, scheme: :http, plug: Peep.Plug, options: [port: 9000]} - ``` - - Similarly, if you are using Bandit, you can use it like so: - - ```elixir - {Bandit, [ - scheme: :http, - plug: {Peep.Plug, peep_worker: :my_app}, - port: 9000 - ]} - ``` - """ - - @behaviour Plug - - import Plug.Conn - alias Plug.Conn - require Logger - - @default_metrics_path "/metrics" - - @impl Plug - def init(opts) do - %{ - metrics_path: Keyword.get(opts, :path, @default_metrics_path), - peep_worker: Keyword.fetch!(opts, :peep_worker), - on_unmatched_path: Keyword.get(opts, :on_unmatched_path, :continue) - } - end + conn + |> put_resp_content_type("text/plain") + |> send_resp(200, metrics) + |> halt() + rescue + error -> + Logger.error(Exception.format(:error, error, __STACKTRACE__)) - @impl Plug - def call(%Conn{request_path: metrics_path, method: "GET"} = conn, %{ - metrics_path: metrics_path, - peep_worker: peep_worker - }) do - metrics = - Peep.get_all_metrics(peep_worker) - |> Peep.Prometheus.export() - - conn - |> put_resp_content_type("text/plain") - |> send_resp(200, metrics) - |> halt() - rescue - error -> - Logger.error(Exception.format(:error, error, __STACKTRACE__)) + conn + |> put_resp_content_type("text/plain") + |> send_resp(503, "Service Unavailable") + |> halt() + end + def call(%Conn{request_path: metrics_path} = conn, %{metrics_path: metrics_path}) do conn |> put_resp_content_type("text/plain") - |> send_resp(503, "Service Unavailable") + |> send_resp(400, "Invalid Request") |> halt() - end + end - def call(%Conn{request_path: metrics_path} = conn, %{metrics_path: metrics_path}) do - conn - |> put_resp_content_type("text/plain") - |> send_resp(400, "Invalid Request") - |> halt() - end - - def call(%Conn{} = conn, %{on_unmatched_path: :continue}) do - conn - end + def call(%Conn{} = conn, %{on_unmatched_path: :continue}) do + conn + end - def call(%Conn{} = conn, %{on_unmatched_path: :halt}) do - conn - |> put_resp_content_type("text/plain") - |> send_resp(404, "Not Found") - |> halt() + def call(%Conn{} = conn, %{on_unmatched_path: :halt}) do + conn + |> put_resp_content_type("text/plain") + |> send_resp(404, "Not Found") + |> halt() + end end end