From 401e6f94b639616ee85fe9b46d07d50210abfa87 Mon Sep 17 00:00:00 2001 From: Anthony Shull Date: Thu, 9 May 2024 15:43:46 -0500 Subject: [PATCH] Adds telemetry metrics to dotcom (#2039) * trying out metrics * rearrange config * change port * this is the right url * nebulex and req stats being sent * vm stats are coming through * phoenix telemetry * docs and tests * credo * ignore files for coverage * missing docs * remove logger from helper * mix lock file --- config/runtime.exs | 4 + coveralls.json | 5 + lib/dotcom/application.ex | 4 +- lib/dotcom/cache/telemetry.ex | 45 +++---- lib/dotcom/cache/telemetry/reporter.ex | 126 ------------------ lib/dotcom/telemetry.ex | 46 +++++++ lib/dotcom_web/stats.ex | 74 ++++++++++ lib/dotcom_web/telemetry.ex | 55 ++++++++ lib/mbta/api/stats.ex | 77 ----------- .../behaviours => lib}/req/behaviour.ex | 0 lib/req/stats.ex | 75 +++++++++++ lib/req/telemetry.ex | 55 ++++++++ lib/telemetry/helper.ex | 59 ++++++++ mix.exs | 2 +- mix.lock | 16 +-- test/dotcom/cache/telemetry/reporter_test.exs | 37 ----- test/dotcom_web/stats_test.exs | 49 +++++++ test/{mbta/api => req}/stats_test.exs | 16 +-- 18 files changed, 460 insertions(+), 285 deletions(-) delete mode 100644 lib/dotcom/cache/telemetry/reporter.ex create mode 100644 lib/dotcom/telemetry.ex create mode 100644 lib/dotcom_web/stats.ex create mode 100644 lib/dotcom_web/telemetry.ex delete mode 100644 lib/mbta/api/stats.ex rename {test/support/behaviours => lib}/req/behaviour.ex (100%) create mode 100644 lib/req/stats.ex create mode 100644 lib/req/telemetry.ex create mode 100644 lib/telemetry/helper.ex delete mode 100644 test/dotcom/cache/telemetry/reporter_test.exs create mode 100644 test/dotcom_web/stats_test.exs rename test/{mbta/api => req}/stats_test.exs (67%) diff --git a/config/runtime.exs b/config/runtime.exs index 95583cf106..76528d8c3b 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -115,6 +115,10 @@ config :dotcom, :mbta_api, {"x-enable-experimental-features", "true"} ] +config :dotcom, :telemetry_metrics_splunk, + token: System.get_env("TELEMETRY_METRICS_SPLUNK_TOKEN"), + url: "https://http-inputs-mbta.splunkcloud.com/services/collector" + config :dotcom, aws_index_prefix: System.get_env("AWS_PLACE_INDEX_PREFIX") || "dotcom-dev" if config_env() != :test do diff --git a/coveralls.json b/coveralls.json index a06860dd4f..a26f385d4e 100644 --- a/coveralls.json +++ b/coveralls.json @@ -9,13 +9,16 @@ "skip_files": [ "lib/alerts/supervisor.ex", "lib/cms/custom_html5_scrubber.ex", + "lib/dotcom/cache/telemetry.ex", "lib/dotcom/redis/behaviour.ex", "lib/dotcom/redix/behaviour.ex", "lib/dotcom/redix/pub_sub/behaviour.ex", + "lib/dotcom/telemetry.ex", "lib/dotcom_web.ex", "lib/dotcom_web/live/admin", "lib/dotcom_web/controllers/bus_stop_change_controller.ex", "lib/dotcom_web/views/bus_stop_change_view.ex", + "lib/dotcom_web/telemetry.ex", "lib/feedback/test.ex", "lib/feedback/fake_date_time.ex", "lib/feedback/mock_aws.ex", @@ -23,9 +26,11 @@ "lib/green_line/cache_supervisor.ex", "lib/mbta/api/behaviour.ex", "lib/mix/tasks", + "lib/req/telemetry.ex", "lib/route_patterns/mock_repo.ex", "lib/routes/routes.ex", "lib/routes/mock_repo_api.ex", + "lib/telemetry/helper.ex", "lib/trip_plan/api/mock_planner.ex", "lib/trip_plan/geocode/mock_geocode.ex", "test/algolia/support", diff --git a/lib/dotcom/application.ex b/lib/dotcom/application.ex index c799c90bb1..07b829afcb 100644 --- a/lib/dotcom/application.ex +++ b/lib/dotcom/application.ex @@ -30,8 +30,10 @@ defmodule Dotcom.Application do ] ++ if Application.get_env(:dotcom, :env) != :test do [ - # We can't run telemetry in the test environment because none of the levels are running + {Dotcom.Telemetry, []}, {Dotcom.Cache.Telemetry, []}, + {DotcomWeb.Telemetry, []}, + {Req.Telemetry, []}, # We don't need to run this cache because we are using the local cache for tests {Dotcom.Cache.TripPlanFeedback.Cache, []} ] diff --git a/lib/dotcom/cache/telemetry.ex b/lib/dotcom/cache/telemetry.ex index e4f643373c..9e296d1211 100644 --- a/lib/dotcom/cache/telemetry.ex +++ b/lib/dotcom/cache/telemetry.ex @@ -1,16 +1,8 @@ defmodule Dotcom.Cache.Telemetry do @moduledoc """ - This supervisor establishes a connection between the telemetry_poller and our telemetry reporters. + This supervisor establishes a connection between the telemetry_poller and the `TelemetryMetricsSplunk` reporter. Cache stats are emitted by every level of `Dotcom.Cache.Multilevel`. We poll for them every minute. - - Currently, they are passed to two reporters: - - The Statsd reporter will eventually be hooked up to Splunk metrics. - For now, it does no harm to emit them even though nothing is listening. - - The custom reporter logs in a format that can be picked up in Splunk logs. - Eventually, this should be removed. """ use Supervisor @@ -22,24 +14,35 @@ defmodule Dotcom.Cache.Telemetry do end def init(_arg) do + telemetry_metrics_splunk_config = Application.get_env(:dotcom, :telemetry_metrics_splunk) + children = [ - {:telemetry_poller, measurements: periodic_measurements(), period: 60_000}, - {Dotcom.Cache.Telemetry.Reporter, metrics: reporter_metrics()}, - {TelemetryMetricsStatsd, metrics: statsd_metrics()} + { + TelemetryMetricsSplunk, + [ + metrics: metrics(), + token: telemetry_metrics_splunk_config[:token], + url: telemetry_metrics_splunk_config[:url] + ] + }, + { + :telemetry_poller, + measurements: measurements(), period: :timer.seconds(60), init_delay: :timer.seconds(5) + } ] Supervisor.init(children, strategy: :one_for_one) end - defp reporter_metrics do + defp measurements do [ - Metrics.last_value("dotcom.cache.multilevel.l1.stats.updates"), - Metrics.last_value("dotcom.cache.multilevel.l2.stats.updates"), - Metrics.last_value("dotcom.cache.multilevel.l3.stats.updates") + {Dotcom.Cache.Multilevel.Local, :dispatch_stats, []}, + {Dotcom.Cache.Multilevel.Publisher, :dispatch_stats, []}, + {Dotcom.Cache.Multilevel.Redis, :dispatch_stats, []} ] end - defp statsd_metrics do + defp metrics do [ Metrics.last_value("dotcom.cache.multilevel.l1.stats.hits"), Metrics.last_value("dotcom.cache.multilevel.l1.stats.misses"), @@ -48,12 +51,4 @@ defmodule Dotcom.Cache.Telemetry do Metrics.last_value("dotcom.cache.multilevel.l3.stats.evictions") ] end - - defp periodic_measurements do - [ - {Dotcom.Cache.Multilevel.Local, :dispatch_stats, []}, - {Dotcom.Cache.Multilevel.Publisher, :dispatch_stats, []}, - {Dotcom.Cache.Multilevel.Redis, :dispatch_stats, []} - ] - end end diff --git a/lib/dotcom/cache/telemetry/reporter.ex b/lib/dotcom/cache/telemetry/reporter.ex deleted file mode 100644 index bf5ff6ea79..0000000000 --- a/lib/dotcom/cache/telemetry/reporter.ex +++ /dev/null @@ -1,126 +0,0 @@ -defmodule Dotcom.Cache.Telemetry.Reporter do - @moduledoc """ - This custom Telemetry Reporter logs hit rate information for `Dotom.Cache.Multilevel`. - It also logs exceptions for `Redix.ConnectionError`, `Redix.Error`, and `ArgumentError`. - And, finally, it logs evictions for `Dotcom.Cache.Multilevel.Publisher`. - - See https://blog.miguelcoba.com/telemetry-and-metrics-in-elixir#heading-customreporter for more on writing custom reporters. - """ - - use GenServer - - require Logger - - alias Telemetry.Metrics - - def start_link(metrics: metrics) do - GenServer.start_link(__MODULE__, metrics) - end - - @impl true - def init(metrics) do - Process.flag(:trap_exit, true) - - groups = Enum.group_by(metrics, & &1.event_name) - - for {event, metrics} <- groups do - :telemetry.attach({__MODULE__, event, self()}, event, &__MODULE__.handle_event/4, metrics) - end - - :telemetry.attach( - "cache-command-exception", - [:dotcom, :cache, :multilevel, :l2, :command, :exception], - &__MODULE__.handle_exception/4, - nil - ) - - {:ok, Map.keys(groups)} - end - - @impl true - def terminate(_, events) do - for event <- events do - :telemetry.detach({__MODULE__, event, self()}) - end - - :ok - end - - def handle_event(_event_name, measurements, metadata, metrics) do - metrics - |> Enum.map(&handle_metric(&1, measurements, metadata)) - end - - def handle_exception( - event_name, - _measurements, - %{kind: kind, reason: %Redix.ConnectionError{reason: reason}}, - _config - ) do - name = event_name(event_name) - - Logger.warning("#{name} kind=#{kind} reason=#{reason}") - end - - def handle_exception( - event_name, - _measurements, - %{kind: kind, reason: %Redix.Error{message: message}}, - _config - ) do - name = event_name(event_name) - - Logger.warning("#{name} kind=#{kind} reason=#{message}") - end - - def handle_exception( - event_name, - _measurements, - %{kind: kind, reason: %ArgumentError{message: message}}, - _config - ) do - name = event_name(event_name) - - Logger.warning("#{name} kind=#{kind} reason=#{message}") - end - - defp handle_metric(%Metrics.LastValue{}, %{evictions: evictions}, %{ - cache: Dotcom.Cache.Multilevel.Publisher - }) do - name = module_name(Dotcom.Cache.Multilevel.Publisher) - - Logger.notice("#{name}.stats evictions=#{evictions}") - end - - defp handle_metric(%Metrics.LastValue{}, %{hits: hits, misses: misses}, metadata) do - name = module_name(metadata.cache) - - total = hits + misses - rate = if total > 0, do: Float.ceil(hits / total, 4), else: 0 - - if rate > 0 do - Logger.notice("#{name}.stats hits=#{hits} misses=#{misses} total=#{total} hit_rate=#{rate}") - end - end - - defp handle_metric(metric, _measurements, metadata) do - name = module_name(metadata.cache) - - Logger.warning("#{name}.unsupported_metric metric=#{metric.__struct__}") - end - - defp event_name(event) do - event - |> Enum.map_join(".", &Atom.to_string/1) - |> String.downcase() - end - - defp module_name(module) do - module - |> Kernel.to_string() - |> String.split(".") - |> (fn [_ | tail] -> tail end).() - |> Enum.join(".") - |> String.downcase() - end -end diff --git a/lib/dotcom/telemetry.ex b/lib/dotcom/telemetry.ex new file mode 100644 index 0000000000..456a94e914 --- /dev/null +++ b/lib/dotcom/telemetry.ex @@ -0,0 +1,46 @@ +defmodule Dotcom.Telemetry do + @moduledoc """ + This Supervisor establishes sends vm stats to the `TelemetryMetricsSplunk` reporter. + No polling occurs as these metrics are emitted regularly anyway. + """ + + use Supervisor + + alias Telemetry.Metrics + + @doc """ + Starts the supervisor. + """ + def start_link(arg) do + Supervisor.start_link(__MODULE__, arg, name: __MODULE__) + end + + @doc """ + Initializes the supervisor. + """ + def init(_arg) do + telemetry_metrics_splunk_config = Application.get_env(:dotcom, :telemetry_metrics_splunk) + + children = [ + { + TelemetryMetricsSplunk, + [ + metrics: metrics(), + token: telemetry_metrics_splunk_config[:token], + url: telemetry_metrics_splunk_config[:url] + ] + } + ] + + Supervisor.init(children, strategy: :one_for_one) + end + + defp metrics do + [ + Metrics.last_value("vm.memory.total", unit: :byte), + Metrics.last_value("vm.total_run_queue_lengths.total"), + Metrics.last_value("vm.total_run_queue_lengths.cpu"), + Metrics.last_value("vm.system_counts.process_count") + ] + end +end diff --git a/lib/dotcom_web/stats.ex b/lib/dotcom_web/stats.ex new file mode 100644 index 0000000000..caf30da98c --- /dev/null +++ b/lib/dotcom_web/stats.ex @@ -0,0 +1,74 @@ +defmodule DotcomWeb.Stats do + @moduledoc """ + This Agent attaches to telemetry events emitted by Phoenix and aggregates them. + """ + + use Agent + + @doc """ + Starts the Agent and attaches to `[:phoenix, :router_dispatch, :stop]` telemetry events. + """ + def start_link(initial_value \\ %{}) do + :telemetry.attach( + "phoenix-router_dispatch-stop", + [:phoenix, :router_dispatch, :stop], + &__MODULE__.handle_event/4, + nil + ) + + Agent.start_link(fn -> initial_value end, name: __MODULE__) + end + + @doc """ + Handles telemetry events and aggregates them by path and status. + """ + def handle_event(_name, measurement, metadata, _config) do + method = metadata.conn.method + path = metadata.route + status = metadata.conn.status + duration = measurement[:duration] + + Agent.update(__MODULE__, fn state -> + if Kernel.get_in(state, [method, path, status]) do + Kernel.update_in(state, [method, path, status], &(&1 ++ [duration])) + else + Kernel.put_in(state, [Access.key(method, %{}), Access.key(path, %{}), status], [duration]) + end + end) + end + + @doc """ + Dispatches the aggregated stats to the `[:phoenix, :router_dispatch, :stop]` telemetry event. + + Resets the Agent state after dispatching the stats. + """ + def dispatch_stats() do + Enum.each(Agent.get(__MODULE__, & &1), &dispatch_method/1) + + Agent.update(__MODULE__, fn _ -> %{} end) + end + + defp dispatch_method({method, stats}) do + Enum.each(stats, fn {path, statuses} -> + Enum.each(statuses, fn {status, durations} -> + dispatch_stat(method, path, status, durations) + end) + end) + end + + defp dispatch_stat(method, path, status, durations) do + count = Enum.count(durations) + + avg = + durations + |> Enum.sum() + |> Kernel.div(count) + |> System.convert_time_unit(:native, :millisecond) + + :telemetry.execute([:dotcom_web, :request], %{count: count, avg: avg}, %{ + method: method, + path: path, + status: status + }) + end +end diff --git a/lib/dotcom_web/telemetry.ex b/lib/dotcom_web/telemetry.ex new file mode 100644 index 0000000000..ff640e5af8 --- /dev/null +++ b/lib/dotcom_web/telemetry.ex @@ -0,0 +1,55 @@ +defmodule DotcomWeb.Telemetry do + @moduledoc """ + This Supervisor is responsible for starting the Telemetry poller and defining the metrics to be collected for Phoenix. + We poll the metrics every 60 seconds and send them to the `TelemetryMetricsSplunk` reporter. + """ + + use Supervisor + + alias Telemetry.Metrics + + @doc """ + Starts the supervisor. + """ + def start_link(arg) do + Supervisor.start_link(__MODULE__, arg, name: __MODULE__) + end + + @doc """ + Initializes the supervisor. + """ + def init(_arg) do + telemetry_metrics_splunk_config = Application.get_env(:dotcom, :telemetry_metrics_splunk) + + children = [ + { + TelemetryMetricsSplunk, + [ + metrics: metrics(), + token: telemetry_metrics_splunk_config[:token], + url: telemetry_metrics_splunk_config[:url] + ] + }, + { + :telemetry_poller, + measurements: measurements(), period: :timer.seconds(60), init_delay: :timer.seconds(5) + }, + {DotcomWeb.Stats, %{}} + ] + + Supervisor.init(children, strategy: :one_for_one) + end + + defp measurements do + [ + {DotcomWeb.Stats, :dispatch_stats, []} + ] + end + + defp metrics do + [ + Metrics.last_value("dotcom_web.request.count"), + Metrics.last_value("dotcom_web.request.avg") + ] + end +end diff --git a/lib/mbta/api/stats.ex b/lib/mbta/api/stats.ex deleted file mode 100644 index 990b589fbd..0000000000 --- a/lib/mbta/api/stats.ex +++ /dev/null @@ -1,77 +0,0 @@ -defmodule MBTA.Api.Stats do - @moduledoc """ - This Agent attaches to telemetry events emitted by Finch and aggregates them by path and status. - """ - - use Agent - - @doc """ - Starts the Agent and attaches to `[:finch, :recv, :stop]` telemetry events. - """ - def start_link(initial_value \\ %{}) do - :telemetry.attach("finch-recv-stop", [:finch, :recv, :stop], &__MODULE__.handle_event/4, nil) - - Agent.start_link(fn -> initial_value end, name: __MODULE__) - end - - @doc """ - Handles telemetry events and aggregates them by path and status. - """ - def handle_event(_name, measurement, metadata, _config) do - path = path_to_atom(metadata.request.path) - status = status_to_atom(metadata.status) - duration = measurement[:duration] - - Agent.update(__MODULE__, fn state -> - if Kernel.get_in(state, [path, status]) do - Kernel.update_in(state, [path, status], &(&1 ++ [duration])) - else - Kernel.put_in(state, [Access.key(path, %{}), status], [duration]) - end - end) - end - - @doc """ - Dispatches the aggregated stats to the `[:mbta_api, :request]` telemetry event. - - Resets the Agent state after dispatching the stats. - """ - def dispatch_stats() do - Enum.each(Agent.get(__MODULE__, & &1), &dispatch_path/1) - - Agent.update(__MODULE__, fn _ -> %{} end) - end - - defp dispatch_path({path, stats}) do - Enum.each(stats, fn {status, durations} -> - dispatch_stat(path, status, durations) - end) - end - - defp dispatch_stat(path, status, durations) do - count = Enum.count(durations) - - avg = - durations - |> Enum.sum() - |> Kernel.div(count) - - :telemetry.execute([:mbta_api, :request], %{count: count, avg: avg}, %{ - path: path, - status: status - }) - end - - defp path_to_atom(path) do - path - |> String.replace(~r{^/|/$}, "") - |> String.replace(~r{/}, "_") - |> String.to_atom() - end - - defp status_to_atom(status) do - status - |> Integer.to_string() - |> String.to_atom() - end -end diff --git a/test/support/behaviours/req/behaviour.ex b/lib/req/behaviour.ex similarity index 100% rename from test/support/behaviours/req/behaviour.ex rename to lib/req/behaviour.ex diff --git a/lib/req/stats.ex b/lib/req/stats.ex new file mode 100644 index 0000000000..b04ad29c33 --- /dev/null +++ b/lib/req/stats.ex @@ -0,0 +1,75 @@ +defmodule Req.Stats do + @moduledoc """ + This Agent attaches to telemetry events emitted by Finch (used by Req) and aggregates them by host, path, and status. + """ + + use Agent + + @doc """ + Starts the Agent and attaches to `[:finch, :recv, :stop]` telemetry events. + """ + def start_link(initial_value \\ %{}) do + :telemetry.attach("finch-recv-stop", [:finch, :recv, :stop], &__MODULE__.handle_event/4, nil) + + Agent.start_link(fn -> initial_value end, name: __MODULE__) + end + + @doc """ + Handles telemetry events and aggregates them by host, path, and status. + """ + def handle_event(_name, measurement, metadata, _config) do + host = metadata.request.host + path = strip_filename(metadata.request.path) + status = metadata.status + duration = measurement[:duration] + + Agent.update(__MODULE__, fn state -> + if Kernel.get_in(state, [host, path, status]) do + Kernel.update_in(state, [host, path, status], &(&1 ++ [duration])) + else + Kernel.put_in(state, [Access.key(host, %{}), Access.key(path, %{}), status], [duration]) + end + end) + end + + @doc """ + Dispatches the aggregated stats to the `[:req, :request]` telemetry event. + + Resets the Agent state after dispatching the stats. + """ + def dispatch_stats() do + Enum.each(Agent.get(__MODULE__, & &1), &dispatch_host/1) + + Agent.update(__MODULE__, fn _ -> %{} end) + end + + defp dispatch_host({host, stats}) do + Enum.each(stats, fn {path, statuses} -> + Enum.each(statuses, fn {status, durations} -> + dispatch_stat(host, path, status, durations) + end) + end) + end + + defp dispatch_stat(host, path, status, durations) do + count = Enum.count(durations) + + avg = + durations + |> Enum.sum() + |> Kernel.div(count) + |> System.convert_time_unit(:native, :millisecond) + + :telemetry.execute([:req, :request], %{count: count, avg: avg}, %{ + host: host, + path: path, + status: status + }) + end + + defp strip_filename(path) do + path + |> (&Regex.replace(~r/\/$/, &1, "")).() + |> (&Regex.replace(~r/[\w|-]+\.\w+/, &1, "")).() + end +end diff --git a/lib/req/telemetry.ex b/lib/req/telemetry.ex new file mode 100644 index 0000000000..b18a2fa2bf --- /dev/null +++ b/lib/req/telemetry.ex @@ -0,0 +1,55 @@ +defmodule Req.Telemetry do + @moduledoc """ + This Supervisor is responsible for starting the Telemetry poller and defining the metrics to be collected for Req (finch). + We poll the metrics every 60 seconds and send them to the `TelemetryMetricsSplunk` reporter. + """ + + use Supervisor + + alias Telemetry.Metrics + + @doc """ + Starts the supervisor. + """ + def start_link(arg) do + Supervisor.start_link(__MODULE__, arg, name: __MODULE__) + end + + @doc """ + Initializes the supervisor. + """ + def init(_arg) do + telemetry_metrics_splunk_config = Application.get_env(:dotcom, :telemetry_metrics_splunk) + + children = [ + { + TelemetryMetricsSplunk, + [ + metrics: metrics(), + token: telemetry_metrics_splunk_config[:token], + url: telemetry_metrics_splunk_config[:url] + ] + }, + { + :telemetry_poller, + measurements: measurements(), period: :timer.seconds(60), init_delay: :timer.seconds(5) + }, + {Req.Stats, %{}} + ] + + Supervisor.init(children, strategy: :one_for_one) + end + + defp measurements do + [ + {Req.Stats, :dispatch_stats, []} + ] + end + + defp metrics do + [ + Metrics.last_value("req.request.count"), + Metrics.last_value("req.request.avg") + ] + end +end diff --git a/lib/telemetry/helper.ex b/lib/telemetry/helper.ex new file mode 100644 index 0000000000..55ee501d7f --- /dev/null +++ b/lib/telemetry/helper.ex @@ -0,0 +1,59 @@ +defmodule Telemetry.Helper do + @moduledoc """ + Helper functions for seeing all telemetry events. + + Only for use in development. + """ + + @doc """ + Attach to all telemetry events and log them. + + You can pass in a filter so that you only see telemetry events for a specific module. + E.g., if you want to see all telemetry events for Phoenix you can pass in `[:phoenix]`. + For more specific events you can pass in more specific names like `[:phoenix, :router_dispatch]` or `[:phoenix, :router_dispatch, :stop]`. + """ + def attach(filter \\ nil) do + # Start the tracer + :dbg.start() + + # Create tracer process with a function that pattern matches out the three arguments the telemetry calls are made with. + :dbg.tracer( + :process, + { + fn + {_, _, _, {_mod, :execute, [name, measurement, metadata]}}, _state -> + handler(name, metadata, measurement, filter) + end, + nil + } + ) + + # Trace all processes + :dbg.p(:all, :c) + + # Trace calls to the functions used to emit telemetry events + :dbg.tp(:telemetry, :execute, 3, []) + end + + @doc """ + Stop the tracer and therefore stop listening for telemetry events. + """ + def stop do + :dbg.stop() + end + + defp handler(name, metadata, measure, filter) do + unless filtered?(name, filter) do + # credo:disable-for-next-line Credo.Check.Warning.IoInspect + IO.inspect(%{name: name, metadata: metadata, measure: measure}) + end + end + + defp filtered?(name, filter) when is_atom(name), do: name == filter + + defp filtered?(_, nil), do: false + + defp filtered?(name, filter) do + not Enum.all?(filter, fn entry -> Enum.member?(name, entry) end) + end +end diff --git a/mix.exs b/mix.exs index 239a841d79..26cdc2de3a 100644 --- a/mix.exs +++ b/mix.exs @@ -143,7 +143,7 @@ defmodule DotCom.Mixfile do {:sweet_xml, "0.7.4", only: [:prod, :dev]}, {:telemetry, "1.2.1", override: true}, {:telemetry_metrics, "1.0.0", override: true}, - {:telemetry_metrics_statsd, "0.7.0"}, + {:telemetry_metrics_splunk, "0.0.2-alpha"}, {:telemetry_poller, "1.1.0"}, {:telemetry_test, "0.1.2", only: [:test]}, # latest version is 3.7.11; cannot upgrade because tests fail diff --git a/mix.lock b/mix.lock index e9631a702e..c724868249 100644 --- a/mix.lock +++ b/mix.lock @@ -2,11 +2,9 @@ "absinthe_client": {:hex, :absinthe_client, "0.1.0", "a3bafc1dff141073a2a7fd926942fb10afb4d45295f0b6df46f6f1955ececaac", [:mix], [{:castore, ">= 0.0.0", [hex: :castore, repo: "hexpm", optional: false]}, {:req, "~> 0.3.0", [hex: :req, repo: "hexpm", optional: false]}, {:slipstream, "~> 1.0", [hex: :slipstream, repo: "hexpm", optional: false]}], "hexpm", "a7ec3e13da9b463cb024dba4733c2fa31a0690a3bfa897b9df6bdd544a4d6f91"}, "benchfella": {:hex, :benchfella, "0.3.5", "b2122c234117b3f91ed7b43b6e915e19e1ab216971154acd0a80ce0e9b8c05f5", [:mix], [], "hexpm", "23f27cbc482cbac03fc8926441eb60a5e111759c17642bac005c3225f5eb809d"}, "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, - "bypass": {:hex, :bypass, "1.0.0", "b78b3dcb832a71aca5259c1a704b2e14b55fd4e1327ff942598b4e7d1a7ad83d", [:mix], [{:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: false]}], "hexpm", "5a1dc855dfcc86160458c7a70d25f65d498bd8012bd4c06a8d3baa368dda3c45"}, "castore": {:hex, :castore, "0.1.22", "4127549e411bedd012ca3a308dede574f43819fe9394254ca55ab4895abfa1a2", [:mix], [], "hexpm", "c17576df47eb5aa1ee40cc4134316a99f5cad3e215d5c77b8dd3cfef12a22cac"}, "certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"}, "combine": {:hex, :combine, "0.10.0", "eff8224eeb56498a2af13011d142c5e7997a80c8f5b97c499f84c841032e429f", [:mix], [], "hexpm", "1b1dbc1790073076580d0d1d64e42eae2366583e7aecd455d1215b0d16f2451b"}, - "con_cache": {:hex, :con_cache, "0.12.1", "7553dcd51ee86fd52bd9ea9aa4b33e71bebf0b5fc5ab60e63d2e0bcaa260f937", [:mix], [{:exactor, "~> 2.2.0", [hex: :exactor, repo: "hexpm", optional: false]}], "hexpm", "e72ea94da0ad5d651fe4fa5e6c9b85e16b3583f0690af7fc4de191eac370bcae"}, "cowboy": {:hex, :cowboy, "2.12.0", "f276d521a1ff88b2b9b4c54d0e753da6c66dd7be6c9fca3d9418b561828a3731", [:make, :rebar3], [{:cowlib, "2.13.0", [hex: :cowlib, repo: "hexpm", optional: false]}, {:ranch, "1.8.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "8a7abe6d183372ceb21caa2709bec928ab2b72e18a3911aa1771639bef82651e"}, "cowboy_telemetry": {:hex, :cowboy_telemetry, "0.4.0", "f239f68b588efa7707abce16a84d0d2acf3a0f50571f8bb7f56a15865aae820c", [:rebar3], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7d98bac1ee4565d31b62d59f8823dfd8356a169e7fcbb83831b8a5397404c9de"}, "cowlib": {:hex, :cowlib, "2.13.0", "db8f7505d8332d98ef50a3ef34b34c1afddec7506e4ee4dd4a3a266285d282ca", [:make, :rebar3], [], "hexpm", "e1e1284dc3fc030a64b1ad0d8382ae7e99da46c3246b815318a4b848873800a4"}, @@ -19,7 +17,7 @@ "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, "eflame": {:hex, :eflame, "1.0.1", "0664d287e39eef3c413749254b3af5f4f8b00be71c1af67d325331c4890be0fc", [:mix], [], "hexpm", "e0b08854a66f9013129de0b008488f3411ae9b69b902187837f994d7a99cf04e"}, "ehmon": {:git, "https://github.com/mbta/ehmon.git", "1fb603262bd02d74a16183bd8f344dcace9d7561", []}, - "elixir_make": {:hex, :elixir_make, "0.7.8", "505026f266552ee5aabca0b9f9c229cbb496c689537c9f922f3eb5431157efc7", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "7a71945b913d37ea89b06966e1342c85cfe549b15e6d6d081e8081c493062c07"}, + "elixir_make": {:hex, :elixir_make, "0.8.3", "d38d7ee1578d722d89b4d452a3e36bcfdc644c618f0d063b874661876e708683", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "5c99a18571a756d4af7a4d89ca75c28ac899e6103af6f223982f09ce44942cc9"}, "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, "ex_aws": {:hex, :ex_aws, "2.5.3", "9c2d05ba0c057395b12c7b5ca6267d14cdaec1d8e65bdf6481fe1fd245accfb4", [:mix], [{:configparser_ex, "~> 4.0", [hex: :configparser_ex, repo: "hexpm", optional: true]}, {:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:jsx, "~> 2.8 or ~> 3.0", [hex: :jsx, repo: "hexpm", optional: true]}, {:mime, "~> 1.2 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:sweet_xml, "~> 0.7", [hex: :sweet_xml, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "67115f1d399d7ec4d191812ee565c6106cb4b1bbf19a9d4db06f265fd87da97e"}, "ex_aws_s3": {:hex, :ex_aws_s3, "2.5.3", "422468e5c3e1a4da5298e66c3468b465cfd354b842e512cb1f6fbbe4e2f5bdaf", [:mix], [{:ex_aws, "~> 2.0", [hex: :ex_aws, repo: "hexpm", optional: false]}, {:sweet_xml, ">= 0.0.0", [hex: :sweet_xml, repo: "hexpm", optional: true]}], "hexpm", "4f09dd372cc386550e484808c5ac5027766c8d0cd8271ccc578b82ee6ef4f3b8"}, @@ -27,7 +25,6 @@ "ex_doc": {:hex, :ex_doc, "0.32.1", "21e40f939515373bcdc9cffe65f3b3543f05015ac6c3d01d991874129d173420", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.1", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "5142c9db521f106d61ff33250f779807ed2a88620e472ac95dc7d59c380113da"}, "ex_machina": {:hex, :ex_machina, "2.7.0", "b792cc3127fd0680fecdb6299235b4727a4944a09ff0fa904cc639272cd92dc7", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "419aa7a39bde11894c87a615c4ecaa52d8f107bbdd81d810465186f783245bf8"}, "ex_unit_summary": {:hex, :ex_unit_summary, "0.1.0", "7b0352afc5e6a933c805df0a539b66b392ac12ba74d8b208db7d83f77cb57049", [:mix], [], "hexpm", "8c87d0deade3657102902251d2ec60b5b94560004ce0e2c2fa5b466232716bd6"}, - "exactor": {:hex, :exactor, "2.2.4", "5efb4ddeb2c48d9a1d7c9b465a6fffdd82300eb9618ece5d34c3334d5d7245b1", [:mix], [], "hexpm", "1222419f706e01bfa1095aec9acf6421367dcfab798a6f67c54cf784733cd6b5"}, "excoveralls": {:hex, :excoveralls, "0.16.1", "0bd42ed05c7d2f4d180331a20113ec537be509da31fed5c8f7047ce59ee5a7c5", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "dae763468e2008cf7075a64cb1249c97cb4bc71e236c5c2b5e5cdf1cfa2bf138"}, "expo": {:hex, :expo, "0.5.2", "beba786aab8e3c5431813d7a44b828e7b922bfa431d6bfbada0904535342efe2", [:mix], [], "hexpm", "8c9bfa06ca017c9cb4020fabe980bc7fdb1aaec059fd004c2ab3bff03b1c599c"}, "faker": {:hex, :faker, "0.18.0", "943e479319a22ea4e8e39e8e076b81c02827d9302f3d32726c5bf82f430e6e14", [:mix], [], "hexpm", "bfbdd83958d78e2788e99ec9317c4816e651ad05e24cfd1196ce5db5b3e81797"}, @@ -39,10 +36,9 @@ "hackney": {:hex, :hackney, "1.20.1", "8d97aec62ddddd757d128bfd1df6c5861093419f8f7a4223823537bad5d064e2", [:rebar3], [{:certifi, "~> 2.12.0", [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.4.1", [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", "fe9094e5f1a2a2c0a7d10918fee36bfec0ec2a979994cff8cfe8058cd9af38e3"}, "hammer": {:hex, :hammer, "6.2.1", "5ae9c33e3dceaeb42de0db46bf505bd9c35f259c8defb03390cd7556fea67ee2", [:mix], [{:poolboy, "~> 1.5", [hex: :poolboy, repo: "hexpm", optional: false]}], "hexpm", "b9476d0c13883d2dc0cc72e786bac6ac28911fba7cc2e04b70ce6a6d9c4b2bdc"}, "hpax": {:hex, :hpax, "0.2.0", "5a58219adcb75977b2edce5eb22051de9362f08236220c9e859a47111c194ff5", [:mix], [], "hexpm", "bea06558cdae85bed075e6c036993d43cd54d447f76d8190a8db0dc5893fa2f1"}, - "html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"}, "html_sanitize_ex": {:hex, :html_sanitize_ex, "1.3.0", "f005ad692b717691203f940c686208aa3d8ffd9dd4bb3699240096a51fa9564e", [:mix], [{:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm", "abfb393ad888d57700f4d0f119c2643c8a9d98856f9b8a92001be7efad1419d6"}, "httpoison": {:hex, :httpoison, "1.8.2", "9eb9c63ae289296a544842ef816a85d881d4a31f518a0fec089aaa744beae290", [:mix], [{:hackney, "~> 1.17", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "2bb350d26972e30c96e2ca74a1aaf8293d61d0742ff17f01e0279fef11599921"}, - "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, + "idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~> 0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"}, "inflex": {:hex, :inflex, "2.1.0", "a365cf0821a9dacb65067abd95008ca1b0bb7dcdd85ae59965deef2aa062924c", [:mix], [], "hexpm", "14c17d05db4ee9b6d319b0bff1bdf22aa389a25398d1952c7a0b5f3d93162dd8"}, "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, "logster": {:hex, :logster, "1.1.1", "d6fddac540dd46adde0c894024500867fe63b0043713f842c62da5815e21db10", [:mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "d18e852c430812ad1c9756998ebe46ec814c724e6eb551a512d7e3f8dee24cef"}, @@ -83,7 +79,7 @@ "pollution": {:hex, :pollution, "0.9.2", "3f67542631071c99f807d2a8f9da799c07cd983c902f5357b9e1569c20a26e76", [:mix], [], "hexpm", "6399fd8ffd97dcc3d9d277f60542a234d644d7bcc0d48c8fda93d6be4801bac2"}, "polyline": {:hex, :polyline, "1.4.0", "36666a3d010692d91d89501e13d385b6b136ef446f05814fb2e90149349d5a14", [:mix], [{:vector, "~> 1.0", [hex: :vector, repo: "hexpm", optional: false]}], "hexpm", "0e1e57497ba05f0355e23d722b03d5dc9a68d5d0c17c9f2dd5efefaa96f8960d"}, "poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"}, - "proper": {:hex, :proper, "1.3.0", "c1acd51c51da17a2fe91d7a6fc6a0c25a6a9849d8dc77093533109d1218d8457", [:make, :mix, :rebar3], [], "hexpm", "4aa192fccddd03fdbe50fef620be9d4d2f92635b54f55fb83aec185994403cbc"}, + "proper": {:hex, :proper, "1.4.0", "89a44b8c39d28bb9b4be8e4d715d534905b325470f2e0ec5e004d12484a79434", [:rebar3], [], "hexpm", "18285842185bd33efbda97d134a5cb5a0884384db36119fee0e3cfa488568cbb"}, "quixir": {:hex, :quixir, "0.9.3", "f01c37386b9e1d0526f01a8734a6d7884af294a0ec360f05c24c7171d74632bd", [:mix], [{:pollution, "~> 0.9.2", [hex: :pollution, repo: "hexpm", optional: false]}], "hexpm", "4f3a1fe7c82b767d935b3f7b94cf34b91ef78bb487ef256b303d77417fc7d589"}, "ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"}, "recaptcha": {:git, "https://github.com/samueljseay/recaptcha.git", "8ea13f63990ca18725ac006d30e55d42c3a58457", [ref: "8ea13f63990ca18725ac006d30e55d42c3a58457"]}, @@ -95,15 +91,15 @@ "sentry": {:hex, :sentry, "7.2.5", "570db92c3bbacd6ad02ac81cba8ac5af11235a55d65ac4375e3ec833975b83d3", [:mix], [{:hackney, "1.6.5 or ~> 1.8", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.3", [hex: :phoenix, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, "~> 1.0 or ~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "ea84ed6848505ff2a246567df562f465d2b34c317d3ecba7c7df58daa56e5e5d"}, "server_sent_event_stage": {:hex, :server_sent_event_stage, "1.2.0", "3baa30e046714880e8cf0155db0820ad1b32bdd00ee7e94332167f91bf4891c3", [:mix], [{:castore, "~> 0.1", [hex: :castore, repo: "hexpm", optional: true]}, {:ex_doc, "~> 0.22", [hex: :ex_doc, repo: "hexpm", optional: true]}, {:gen_stage, "~> 1.1", [hex: :gen_stage, repo: "hexpm", optional: false]}, {:mint, "~> 1.4", [hex: :mint, repo: "hexpm", optional: false]}], "hexpm", "8c886ee46c3a63f0f1df48a0d3392fd996741dd3ba000b828d0ebcfbf1ccb264"}, "sizeable": {:hex, :sizeable, "1.0.2", "625fe06a5dad188b52121a140286f1a6ae1adf350a942cf419499ecd8a11ee29", [:mix], [], "hexpm", "4bab548e6dfba777b400ca50830a9e3a4128e73df77ab1582540cf5860601762"}, - "slipstream": {:hex, :slipstream, "1.1.0", "e3581e9bc73036e4283b33447475499d18c813c7662aa6b86e131633a7e912f3", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mint_web_socket, "~> 0.2 or ~> 1.0", [hex: :mint_web_socket, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.1 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "66eb1ac7c43573511b5bad90c24c128bb4e69f588bff65d0c409adf4c7eb02e6"}, + "slipstream": {:hex, :slipstream, "1.1.1", "7e56f62f1a9ee81351e3c36f57b9b187e00dc2f470e70ba46ea7ad16e80b061f", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mint_web_socket, "~> 0.2 or ~> 1.0", [hex: :mint_web_socket, repo: "hexpm", optional: false]}, {:nimble_options, "~> 0.1 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c20e420cde1654329d38ec3aa1c0e4debbd4c91ca421491e7984ad4644e638a6"}, "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"}, "sweet_xml": {:hex, :sweet_xml, "0.7.4", "a8b7e1ce7ecd775c7e8a65d501bc2cd933bff3a9c41ab763f5105688ef485d08", [:mix], [], "hexpm", "e7c4b0bdbf460c928234951def54fe87edf1a170f6896675443279e2dbeba167"}, "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, "telemetry_metrics": {:hex, :telemetry_metrics, "1.0.0", "29f5f84991ca98b8eb02fc208b2e6de7c95f8bb2294ef244a176675adc7775df", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f23713b3847286a534e005126d4c959ebcca68ae9582118ce436b521d1d47d5d"}, - "telemetry_metrics_statsd": {:hex, :telemetry_metrics_statsd, "0.7.0", "92732fae63db31ef2508df6faee7d81401883e33f2976715a82f296a33a45cee", [:mix], [{:nimble_options, "~> 0.4 or ~> 1.0", [hex: :nimble_options, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "797e34a856376dfd4e96347da0f747fcff4e0cadf6e6f0f989598f563cad05ff"}, + "telemetry_metrics_splunk": {:hex, :telemetry_metrics_splunk, "0.0.2-alpha", "f0a25d582b4315b5461840a55c77f2b0ad625c8afceaec56ce0b198f6c87f741", [:mix], [{:jason, "1.4.1", [hex: :jason, repo: "hexpm", optional: false]}, {:recase, "0.7.0", [hex: :recase, repo: "hexpm", optional: false]}, {:telemetry, "1.2.1", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "1.0.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "c6ea80ee987a19df3c5d3bb87a5b94c3acf4a8d4df778e0f3ede2987426eba8f"}, "telemetry_poller": {:hex, :telemetry_poller, "1.1.0", "58fa7c216257291caaf8d05678c8d01bd45f4bdbc1286838a28c4bb62ef32999", [:rebar3], [{:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "9eb9d9cbfd81cbd7cdd24682f8711b6e2b691289a0de6826e58452f28c103c8f"}, "telemetry_test": {:hex, :telemetry_test, "0.1.2", "122d927567c563cf57773105fa8104ae4299718ec2cbdddcf6776562c7488072", [:mix], [{:telemetry, "~> 1.2", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7bd41a49ecfd33ecd82d2c7edae19a5736f0d2150206d0ee290dcf3885d0e14d"}, - "tesla": {:hex, :tesla, "1.8.0", "d511a4f5c5e42538d97eef7c40ec4f3e44effdc5068206f42ed859e09e51d1fd", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "10501f360cd926a309501287470372af1a6e1cbed0f43949203a4c13300bc79f"}, + "tesla": {:hex, :tesla, "1.9.0", "8c22db6a826e56a087eeb8cdef56889731287f53feeb3f361dec5d4c8efb6f14", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:exjsx, ">= 3.0.0", [hex: :exjsx, repo: "hexpm", optional: true]}, {:finch, "~> 0.13", [hex: :finch, repo: "hexpm", optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, repo: "hexpm", optional: true]}, {:gun, ">= 1.0.0", [hex: :gun, repo: "hexpm", optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, repo: "hexpm", optional: true]}, {:ibrowse, "4.4.2", [hex: :ibrowse, repo: "hexpm", optional: true]}, {:jason, ">= 1.0.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: true]}, {:msgpax, "~> 2.3", [hex: :msgpax, repo: "hexpm", optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "7c240c67e855f7e63e795bf16d6b3f5115a81d1f44b7fe4eadbf656bae0fef8a"}, "timex": {:hex, :timex, "3.1.24", "d198ae9783ac807721cca0c5535384ebdf99da4976be8cefb9665a9262a1e9e3", [:mix], [{:combine, "~> 0.7", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "ca852258d788542c263b12dbf55375fe2ccf5674e7b20995e3d84d2d4412bc0f"}, "tzdata": {:hex, :tzdata, "0.5.22", "f2ba9105117ee0360eae2eca389783ef7db36d533899b2e84559404dbc77ebb8", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "cd66c8a1e6a9e121d1f538b01bef459334bb4029a1ffb4eeeb5e4eae0337e7b6"}, "unicode_util_compat": {:hex, :unicode_util_compat, "0.7.0", "bc84380c9ab48177092f43ac89e4dfa2c6d62b40b8bd132b1059ecc7232f9a78", [:rebar3], [], "hexpm", "25eee6d67df61960cf6a794239566599b09e17e668d3700247bc498638152521"}, diff --git a/test/dotcom/cache/telemetry/reporter_test.exs b/test/dotcom/cache/telemetry/reporter_test.exs deleted file mode 100644 index 61ad3a00e4..0000000000 --- a/test/dotcom/cache/telemetry/reporter_test.exs +++ /dev/null @@ -1,37 +0,0 @@ -defmodule Dotcom.Cache.Telemetry.ReporterTest do - use ExUnit.Case, async: true - - import ExUnit.CaptureLog - - alias Dotcom.Cache.Multilevel.Local - alias Dotcom.Cache.Telemetry.Reporter - - test "the hit rate gets logged" do - Reporter.start_link( - metrics: [Telemetry.Metrics.last_value("dotcom.cache.multilevel.l1.stats.updates")] - ) - - assert capture_log(fn -> - :telemetry.execute( - [:dotcom, :cache, :multilevel, :l1, :stats], - %{hits: 99, misses: 1}, - %{cache: Local} - ) - end) =~ "hit_rate=0.99" - end - - test "cache command exceptions get logged" do - Reporter.start_link(metrics: []) - - assert capture_log(fn -> - :telemetry.execute( - [:dotcom, :cache, :multilevel, :l2, :command, :exception], - %{duration: 0}, - %{ - kind: :error, - reason: %Redix.ConnectionError{reason: :closed} - } - ) - end) =~ "dotcom.cache.multilevel.l2.command.exception kind=error reason=closed" - end -end diff --git a/test/dotcom_web/stats_test.exs b/test/dotcom_web/stats_test.exs new file mode 100644 index 0000000000..f246cb1e35 --- /dev/null +++ b/test/dotcom_web/stats_test.exs @@ -0,0 +1,49 @@ +defmodule DotcomWeb.StatsTest do + use ExUnit.Case + + import TelemetryTest + + alias DotcomWeb.Stats + + setup [:telemetry_listen] + + setup do + {:ok, _} = Stats.start_link() + + :ok + end + + @tag telemetry_listen: [:dotcom_web, :request] + test "aggregates and dispatches stats" do + # Setup + duration = :rand.uniform(1_000_000_000) + + measurement = %{ + duration: duration + } + + metadata = %{ + conn: %{ + method: Enum.random(["GET", "POST", "PUT", "DELETE"]), + status: Enum.random([200, 404, 500]) + }, + route: "/#{Faker.Internet.slug()}/" + } + + # Exercise + :telemetry.execute([:phoenix, :router_dispatch, :stop], measurement, metadata) + :telemetry.execute([:phoenix, :router_dispatch, :stop], measurement, metadata) + + Stats.dispatch_stats() + + # Verify + assert_receive { + :telemetry_event, + %{ + event: [:dotcom_web, :request], + measurements: %{avg: _duration, count: 2}, + metadata: %{method: _host, path: _path, status: _status} + } + } + end +end diff --git a/test/mbta/api/stats_test.exs b/test/req/stats_test.exs similarity index 67% rename from test/mbta/api/stats_test.exs rename to test/req/stats_test.exs index 49b1caae4c..d8cdb23730 100644 --- a/test/mbta/api/stats_test.exs +++ b/test/req/stats_test.exs @@ -1,9 +1,9 @@ -defmodule MBTA.Api.StatsTest do +defmodule Req.StatsTest do use ExUnit.Case import TelemetryTest - alias MBTA.Api.Stats + alias Req.Stats setup [:telemetry_listen] @@ -13,10 +13,9 @@ defmodule MBTA.Api.StatsTest do :ok end - @tag telemetry_listen: [:mbta_api, :request] + @tag telemetry_listen: [:req, :request] test "aggregates and dispatches stats" do # Setup - # 1 second in nanoseconds duration = :rand.uniform(1_000_000_000) measurement = %{ @@ -25,7 +24,8 @@ defmodule MBTA.Api.StatsTest do metadata = %{ request: %{ - path: "/#{Faker.Team.creature()}/" + host: Faker.Internet.domain_name(), + path: "/#{Faker.Internet.slug()}/" }, status: Enum.random([200, 404, 500]) } @@ -40,9 +40,9 @@ defmodule MBTA.Api.StatsTest do assert_receive { :telemetry_event, %{ - event: [:mbta_api, :request], - measurements: %{avg: ^duration, count: 2}, - metadata: %{path: _path, status: _status} + event: [:req, :request], + measurements: %{avg: _duration, count: 2}, + metadata: %{host: _host, path: _path, status: _status} } } end