Created
May 12, 2021 22:06
-
-
Save ivanovv/6290e9178e0229a689a21c3e2a62d280 to your computer and use it in GitHub Desktop.
socket_connected events
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| defmodule WebinarGeek.PromEx.Plugins.Phoenix do | |
| @moduledoc false | |
| use PromEx.Plugin | |
| require Logger | |
| alias Phoenix.Socket | |
| alias Plug.Conn | |
| @impl true | |
| def event_metrics(opts) do | |
| otp_app = Keyword.fetch!(opts, :otp_app) | |
| metric_prefix = PromEx.metric_prefix(otp_app, :phoenix) | |
| # Event metrics definitions | |
| [ | |
| http_events(metric_prefix, opts), | |
| channel_events(metric_prefix), | |
| socket_events(metric_prefix), | |
| ] | |
| end | |
| defp http_events(metric_prefix, opts) do | |
| # Fetch user options | |
| phoenix_router = Keyword.fetch!(opts, :router) | |
| event_prefix = Keyword.get(opts, :event_prefix, [:phoenix, :endpoint]) | |
| # Shared configuration | |
| phoenix_stop_event = event_prefix ++ [:stop] | |
| http_metrics_tags = [:status, :method, :path, :controller, :action] | |
| Event.build( | |
| :phoenix_http_event_metrics, | |
| [ | |
| # Capture request duration information | |
| distribution( | |
| metric_prefix ++ [:http, :request, :duration, :milliseconds], | |
| event_name: phoenix_stop_event, | |
| measurement: :duration, | |
| description: "The time it takes for the application to respond to HTTP requests.", | |
| reporter_options: [ | |
| buckets: exponential!(1, 2, 12) | |
| ], | |
| tag_values: get_conn_tags(phoenix_router), | |
| tags: http_metrics_tags, | |
| unit: {:native, :millisecond} | |
| ), | |
| # Capture response payload size information | |
| distribution( | |
| metric_prefix ++ [:http, :response, :size, :bytes], | |
| event_name: phoenix_stop_event, | |
| description: "The size of the HTTP response payload.", | |
| reporter_options: [ | |
| buckets: exponential!(1, 4, 12) | |
| ], | |
| measurement: fn _measurements, metadata -> | |
| case metadata.conn.resp_body do | |
| nil -> 0 | |
| _ -> :erlang.iolist_size(metadata.conn.resp_body) | |
| end | |
| end, | |
| tag_values: get_conn_tags(phoenix_router), | |
| tags: http_metrics_tags, | |
| unit: :byte | |
| ), | |
| # Capture the number of requests that have been serviced | |
| counter( | |
| metric_prefix ++ [:http, :requests, :total], | |
| event_name: phoenix_stop_event, | |
| description: "The number of requests have been serviced.", | |
| tag_values: get_conn_tags(phoenix_router), | |
| tags: http_metrics_tags | |
| ) | |
| ] | |
| ) | |
| end | |
| defp channel_events(metric_prefix) do | |
| Event.build( | |
| :phoenix_channel_event_metrics, | |
| [ | |
| # Capture the number of channel joins that have occured | |
| counter( | |
| metric_prefix ++ [:channel, :joined, :total], | |
| event_name: [:phoenix, :channel_joined], | |
| description: "The number of channel joins that have occured.", | |
| tag_values: fn %{result: result, socket: %Socket{transport: transport}} -> | |
| %{ | |
| transport: transport, | |
| result: result | |
| } | |
| end, | |
| tags: [:result, :transport] | |
| ), | |
| # Capture channel handle_in duration | |
| distribution( | |
| metric_prefix ++ [:channel, :handled_in, :duration, :milliseconds], | |
| event_name: [:phoenix, :channel_handled_in], | |
| measurement: :duration, | |
| description: "The time it takes for the application to respond to channel messages.", | |
| reporter_options: [ | |
| buckets: exponential!(1, 2, 12) | |
| ], | |
| unit: {:native, :millisecond} | |
| ) | |
| ] | |
| ) | |
| end | |
| defp socket_events(metric_prefix) do | |
| Event.build( | |
| :phoenix_socket_event_metrics, | |
| [ | |
| # Capture the number of channel joins that have occurred | |
| counter( | |
| metric_prefix ++ [:socket, :connected, :total], | |
| event_name: [:phoenix, :socket_connected], | |
| description: "The number of socket connects that have occurred.", | |
| tag_values: fn %{result: result, transport: transport} -> | |
| %{ | |
| transport: transport, | |
| result: result | |
| } | |
| end, | |
| tags: [:result, :transport] | |
| ), | |
| # Capture socket_connected duration | |
| distribution( | |
| metric_prefix ++ [:socket, :connected, :duration, :milliseconds], | |
| event_name: [:phoenix, :socket_connected], | |
| measurement: :duration, | |
| description: "The time it takes for the application to accept websocket connection.", | |
| reporter_options: [ | |
| buckets: exponential!(1, 2, 12) | |
| ], | |
| unit: {:native, :millisecond} | |
| ) | |
| ] | |
| ) | |
| end | |
| defp get_conn_tags(router) do | |
| fn | |
| %{conn: %Conn{} = conn} -> | |
| router | |
| |> Phoenix.Router.route_info(conn.method, conn.request_path, "") | |
| |> case do | |
| %{route: path, plug: controller, plug_opts: action} -> | |
| %{ | |
| path: path, | |
| controller: normalize_module_name(controller), | |
| action: action | |
| } | |
| _ -> | |
| %{ | |
| path: "Unknown", | |
| controller: "Unknown", | |
| action: "Unknown" | |
| } | |
| end | |
| |> Map.merge(%{ | |
| status: conn.status, | |
| method: conn.method | |
| }) | |
| _ -> | |
| # TODO: Change this to warning as warn is deprecated as of Elixir 1.11 | |
| Logger.warn("Could not resolve path for request") | |
| end | |
| end | |
| defp normalize_module_name(name) when is_atom(name) do | |
| name | |
| |> Atom.to_string() | |
| |> String.trim_leading("Elixir.") | |
| end | |
| defp normalize_module_name(name), do: name | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment