diff --git a/lib/towerops_web/endpoint.ex b/lib/towerops_web/endpoint.ex index 6c2dd12a..cbefd4e4 100644 --- a/lib/towerops_web/endpoint.ex +++ b/lib/towerops_web/endpoint.ex @@ -94,5 +94,7 @@ defmodule ToweropsWeb.Endpoint do # Disable logging for health check endpoint to reduce log noise from K8s probes def log_level(%{path_info: ["health"]}), do: false + # Disable logging for HEAD requests to root path (external uptime monitors) + def log_level(%{method: "HEAD", path_info: []}), do: false def log_level(_), do: :info end diff --git a/mix.exs b/mix.exs index 6fdab8d4..3af4f2ea 100644 --- a/mix.exs +++ b/mix.exs @@ -70,9 +70,9 @@ defmodule Towerops.MixProject do {:jason, "~> 1.2"}, {:dns_cluster, "~> 0.2.0"}, {:libcluster, "~> 3.4"}, - {:oban_pro, "~> 1.6", path: "vendor/oban_pro"}, + {:oban_pro, "~> 1.6", repo: "oban"}, {:oban_met, "~> 1.0", path: "vendor/oban_met", override: true}, - {:oban_web, "~> 2.11", path: "vendor/oban_web"}, + {:oban_web, "~> 2.11"}, {:bandit, "~> 1.5"}, {:phoenix_pubsub_redis, "~> 3.0"}, {:ecto_psql_extras, "~> 0.6"}, diff --git a/mix.lock b/mix.lock index 1079373c..1d107571 100644 --- a/mix.lock +++ b/mix.lock @@ -56,8 +56,7 @@ "nimble_pool": {:hex, :nimble_pool, "1.1.0", "bf9c29fbdcba3564a8b800d1eeb5a3c58f36e1e11d7b7fb2e084a643f645f06b", [:mix], [], "hexpm", "af2e4e6b34197db81f7aad230c1118eac993acc0dae6bc83bac0126d4ae0813a"}, "nimble_totp": {:hex, :nimble_totp, "1.0.0", "79753bae6ce59fd7cacdb21501a1dbac249e53a51c4cd22b34fa8438ee067283", [:mix], [], "hexpm", "6ce5e4c068feecdb782e85b18237f86f66541523e6bad123e02ee1adbe48eda9"}, "oban": {:hex, :oban, "2.20.3", "e4d27336941955886cc7113420c32c63b70b64f10b27e08e3cf2b001153953cd", [:mix], [{:ecto_sql, "~> 3.10", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:ecto_sqlite3, "~> 0.9", [hex: :ecto_sqlite3, repo: "hexpm", optional: true]}, {:igniter, "~> 0.5", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.20", [hex: :postgrex, repo: "hexpm", optional: true]}, {:telemetry, "~> 1.3", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "075ffbf1279a96bec495bc63d647b08929837d70bcc0427249ffe4d1dddaec33"}, - "oban_met": {:hex, :oban_met, "1.0.5", "bb633ab06448dab2ef9194f6688d33b3d07fc3f2ad793a1a08f4dfbb2cc9fe50", [:mix], [{:oban, "~> 2.19", [hex: :oban, repo: "hexpm", optional: false]}], "hexpm", "64664d50805bbfd3903aeada1f3c39634652a87844797ee400b0bcc95a28f5ea"}, - "oban_web": {:hex, :oban_web, "2.11.8", "be6521b5b1eb6d4182f40f5acc948ea65d243451b94c26f06a7329575748f695", [:mix], [{:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}, {:oban, "~> 2.19", [hex: :oban, repo: "hexpm", optional: false]}, {:oban_met, "~> 1.0", [hex: :oban_met, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.7", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}], "hexpm", "d0c04a836d929ef037e96be142285238275aabbafe62543bbdcc3f541d29ec30"}, + "oban_met": {:hex, :oban_met, "1.0.6", "2a5500aff496b7ac4b830b0b03b08e920625a051bb6890981fbb53b15f1cbdc0", [:mix], [{:oban, "~> 2.19", [hex: :oban, repo: "hexpm", optional: false]}], "hexpm", "15ea3303de76225878a8e6c25a9d62bd1e2e9dd1c46ac8487d873b9f99e8dcee"}, "parse_trans": {:hex, :parse_trans, "3.4.1", "6e6aa8167cb44cc8f39441d05193be6e6f4e7c2946cb2759f015f8c56b76e5ff", [:rebar3], [], "hexpm", "620a406ce75dada827b82e453c19cf06776be266f5a67cff34e1ef2cbb60e49a"}, "phoenix": {:hex, :phoenix, "1.8.4", "0387f84f00071cba8d71d930b9121b2fb3645197a9206c31b908d2e7902a4851", [:mix], [{:bandit, "~> 1.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.1", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.7", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:websock_adapter, "~> 0.5.3", [hex: :websock_adapter, repo: "hexpm", optional: false]}], "hexpm", "c988b1cd3b084eebb13e6676d572597d387fa607dab258526637b4e6c4c08543"}, "phoenix_ecto": {:hex, :phoenix_ecto, "4.7.0", "75c4b9dfb3efdc42aec2bd5f8bccd978aca0651dbcbc7a3f362ea5d9d43153c6", [:mix], [{:ecto, "~> 3.5", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.1", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: false]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}], "hexpm", "1d75011e4254cb4ddf823e81823a9629559a1be93b4321a6a5f11a5306fbf4cc"}, diff --git a/vendor/README.md b/vendor/README.md index 9e5fb2a4..6ccfbd59 100644 --- a/vendor/README.md +++ b/vendor/README.md @@ -60,7 +60,7 @@ end ### Oban Met -**Version**: 1.0.5 +**Version**: 1.0.6 **Source**: https://hex.pm/packages/oban_met **License**: Apache-2.0 diff --git a/vendor/oban_met/.hex b/vendor/oban_met/.hex index 45983a56..78a6f8cb 100644 Binary files a/vendor/oban_met/.hex and b/vendor/oban_met/.hex differ diff --git a/vendor/oban_met/CHANGELOG.md b/vendor/oban_met/CHANGELOG.md index ccf7023c..6b9dea94 100644 --- a/vendor/oban_met/CHANGELOG.md +++ b/vendor/oban_met/CHANGELOG.md @@ -1,5 +1,24 @@ # Changelog for Oban Met v1.0 +## v1.0.6 — 2026-02-19 + +### Enhancements + +- Add configurable time unit for timing metrics + + Metrics stored in sketches now support configurable time units via the `:sketch_time_unit` + compile-time option. By default, timing values remain in `:native` units for backward + compatibility. + + Setting `config :oban_met, sketch_time_unit: :millisecond` reduces sketch storage size by ~20% + and consolidates timing values into fewer bins by eliminating nanosecond-level measurement + noise. + +- Share crontab options as a map rather than nested lists + + For compatibility with entries shared by python, we convert options to a + map structure rather than a list of lists. + ## v1.0.5 — 2025-12-10 ### Bug Fixes diff --git a/vendor/oban_met/README.md b/vendor/oban_met/README.md index 59e524fd..f9031c0a 100644 --- a/vendor/oban_met/README.md +++ b/vendor/oban_met/README.md @@ -135,6 +135,29 @@ explicit migration: {Oban.Met, reporter: [auto_migrate: false]} ``` +### Sketch Time Unit + +Timing metrics (execution time, queue time) are stored in space-efficient quantile sketches. By +default, values are recorded in `:native` time units (nanoseconds on most systems), which provides +maximum precision but uses more space. + +For reduced storage size (~20% smaller) and better bin consolidation, you can configure sketches to +store timing in milliseconds: + +```elixir +config :oban_met, sketch_time_unit: :millisecond +``` + +This is a compile-time option that affects how timing values are binned in sketches. + +> #### Cluster Consistency {: .warning} +> +> All nodes in a cluster **must** use the same `sketch_time_unit` setting. Mixing units between +> nodes will produce incorrect aggregated metrics. +> +> After changing this setting, existing metrics will be invalid until compaction ages them out +> (approximately 2 hours with default compaction periods). + ## Contributing diff --git a/vendor/oban_met/hex_metadata.config b/vendor/oban_met/hex_metadata.config index fb388b4e..8ee7678c 100644 --- a/vendor/oban_met/hex_metadata.config +++ b/vendor/oban_met/hex_metadata.config @@ -4,7 +4,7 @@ <<"https://github.com/oban-bg/oban_met/blob/main/CHANGELOG.md">>}, {<<"GitHub">>,<<"https://github.com/oban-bg/oban_met">>}]}. {<<"name">>,<<"oban_met">>}. -{<<"version">>,<<"1.0.5">>}. +{<<"version">>,<<"1.0.6">>}. {<<"description">>, <<"A distributed, compacting, multidimensional, telemetry-powered time series datastore">>}. {<<"elixir">>,<<"~> 1.15">>}. diff --git a/vendor/oban_met/lib/oban/met/cronitor.ex b/vendor/oban_met/lib/oban/met/cronitor.ex index 08fe36b8..ecabb58f 100644 --- a/vendor/oban_met/lib/oban/met/cronitor.ex +++ b/vendor/oban_met/lib/oban/met/cronitor.ex @@ -83,8 +83,8 @@ defmodule Oban.Met.Cronitor do |> Keyword.get(Oban.Plugins.Cron, []) |> Keyword.get(:crontab, []) |> Enum.map(fn - {expr, work} -> {expr, inspect(work), []} - {expr, work, opts} -> {expr, inspect(work), opts} + {expr, work} -> {expr, inspect(work), %{}} + {expr, work, opts} -> {expr, inspect(work), Map.new(opts)} end) payload = %{crontab: crontab, name: inspect(name), node: node} @@ -103,12 +103,7 @@ defmodule Oban.Met.Cronitor do %{"crontab" => crontab, "name" => name, "node" => node} = payload ts = System.system_time(:millisecond) - - crontab = - Enum.map(crontab, fn [expr, work, opts] -> - {expr, work, Map.new(opts, &List.to_tuple/1)} - end) - + crontab = Enum.map(crontab, &List.to_tuple/1) crontabs = Map.put(state.crontabs, {node, name}, {ts, crontab}) {:noreply, %{state | crontabs: crontabs}} diff --git a/vendor/oban_met/lib/oban/met/listener.ex b/vendor/oban_met/lib/oban/met/listener.ex index 4d994272..c1b86671 100644 --- a/vendor/oban_met/lib/oban/met/listener.ex +++ b/vendor/oban_met/lib/oban/met/listener.ex @@ -9,6 +9,8 @@ defmodule Oban.Met.Listener do alias Oban.Met.Values.{Gauge, Sketch} alias Oban.Notifier + @time_unit Application.compile_env(:oban_met, :sketch_time_unit, :native) + defstruct [ :conf, :name, @@ -116,9 +118,10 @@ defmodule Oban.Met.Listener do trst = trans_state(state) # Sketches don't support negative times (caused when the VM wakes from sleep), or zero values - # (infrequently caused by the same situation). - exec_time = exec_time |> abs() |> max(1) - wait_time = wait_time |> abs() |> max(1) + # (infrequently caused by the same situation). Times are converted to the configured unit + # before clamping. + exec_time = exec_time |> convert_time() |> abs() |> max(1) + wait_time = wait_time |> convert_time() |> abs() |> max(1) :ets.insert(tab, [ {{:exec_time, trst, queue, worker}, time, exec_time}, @@ -129,6 +132,12 @@ defmodule Oban.Met.Listener do def handle_event(_event, _measure, _meta, _conf), do: :ok + if @time_unit == :native do + defp convert_time(value), do: value + else + defp convert_time(value), do: System.convert_time_unit(value, :native, @time_unit) + end + # Scheduling defp schedule_report(state) do diff --git a/vendor/oban_met/mix.exs b/vendor/oban_met/mix.exs index f184c9d3..9b17ae36 100644 --- a/vendor/oban_met/mix.exs +++ b/vendor/oban_met/mix.exs @@ -2,7 +2,7 @@ defmodule Oban.Met.MixProject do use Mix.Project @source_url "https://github.com/oban-bg/oban_met" - @version "1.0.5" + @version "1.0.6" def project do [