healthckeck improvements
All checks were successful
CI/CD Pipeline / build (push) Successful in 52s

This commit is contained in:
2026-03-09 15:30:47 -06:00
parent 3fd64aa2f8
commit 6acb01d335
7 changed files with 45 additions and 44 deletions

View File

@@ -23,7 +23,7 @@ jobs:
- name: Build and push backend image - name: Build and push backend image
run: | run: |
docker build -t alexmickelson/ai-liveview:$GITHUB_RUN_NUMBER . docker build -q -t alexmickelson/ai-liveview:$GITHUB_RUN_NUMBER .
docker push -q alexmickelson/ai-liveview:$GITHUB_RUN_NUMBER docker push -q alexmickelson/ai-liveview:$GITHUB_RUN_NUMBER
- name: Deploy to Kubernetes - name: Deploy to Kubernetes

View File

@@ -20,7 +20,8 @@ config :elixir_ai, ElixirAiWeb.Endpoint,
layout: false layout: false
], ],
pubsub_server: ElixirAi.PubSub, pubsub_server: ElixirAi.PubSub,
live_view: [signing_salt: "4UG1IVt+"] live_view: [signing_salt: "4UG1IVt+"],
log: false
# Configure esbuild (the version is required) # Configure esbuild (the version is required)
config :esbuild, config :esbuild,
@@ -46,12 +47,7 @@ config :tailwind,
# Configures Elixir's Logger # Configures Elixir's Logger
config :logger, :console, config :logger, :console,
format: "$time $metadata[$level] $message\n", format: "$time $metadata[$level] $message\n",
metadata: [:request_id], metadata: [:request_id]
filters: [:health_check_filter]
config :logger, :health_check_filter,
module: ElixirAiWeb.HealthCheckFilter,
function: :filter
# Use Jason for JSON parsing in Phoenix # Use Jason for JSON parsing in Phoenix
config :phoenix, :json_library, Jason config :phoenix, :json_library, Jason
@@ -59,7 +55,9 @@ config :phoenix, :json_library, Jason
# Lower the BEAM node-down detection window from the default 60s. # Lower the BEAM node-down detection window from the default 60s.
# Nodes send ticks every (net_ticktime / 4)s; a node is declared down # Nodes send ticks every (net_ticktime / 4)s; a node is declared down
# after 4 missed ticks (net_ticktime total). 5s means detection in ≤5s. # after 4 missed ticks (net_ticktime total). 5s means detection in ≤5s.
if System.get_env("RELEASE_MODE") do
config :kernel, net_ticktime: 2 config :kernel, net_ticktime: 2
end
# Libcluster — Gossip strategy works for local dev and Docker Compose # Libcluster — Gossip strategy works for local dev and Docker Compose
# (UDP multicast, zero config). Overridden to Kubernetes.DNS in runtime.exs for prod. # (UDP multicast, zero config). Overridden to Kubernetes.DNS in runtime.exs for prod.

View File

@@ -4,6 +4,14 @@ defmodule ElixirAi.Application do
@impl true @impl true
def start(_type, _args) do def start(_type, _args) do
# Attach custom logger that filters health checks
:telemetry.attach(
"phoenix-endpoint-logger",
[:phoenix, :endpoint, :stop],
&__MODULE__.log_request/4,
%{}
)
children = [ children = [
ElixirAiWeb.Telemetry, ElixirAiWeb.Telemetry,
ElixirAi.Repo, ElixirAi.Repo,
@@ -39,4 +47,32 @@ defmodule ElixirAi.Application do
ElixirAiWeb.Endpoint.config_change(changed, removed) ElixirAiWeb.Endpoint.config_change(changed, removed)
:ok :ok
end end
# Custom request logger that filters health check endpoint
require Logger
def log_request(_event, measurements, %{conn: conn}, _config) do
# Skip logging for health check endpoint
if conn.request_path != "/health" do
duration = System.convert_time_unit(measurements.duration, :native, :microsecond)
Logger.info(
fn ->
[conn.method, " ", conn.request_path]
end,
request_id: conn.assigns[:request_id]
)
Logger.info(
fn ->
["Sent ", to_string(conn.status), " in ", format_duration(duration)]
end,
request_id: conn.assigns[:request_id]
)
end
end
defp format_duration(μs) when μs < 1000, do: "#{μs}µs"
defp format_duration(μs) when μs < 1_000_000, do: "#{div(μs, 1000)}ms"
defp format_duration(μs), do: "#{Float.round(μs / 1_000_000, 2)}s"
end end

View File

@@ -38,7 +38,6 @@ defmodule ElixirAiWeb.Endpoint do
cookie_key: "request_logger" cookie_key: "request_logger"
plug Plug.RequestId plug Plug.RequestId
plug ElixirAiWeb.Plugs.HealthCheckLogger
plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint] plug Plug.Telemetry, event_prefix: [:phoenix, :endpoint]
plug Plug.Parsers, plug Plug.Parsers,

View File

@@ -1,15 +0,0 @@
defmodule ElixirAiWeb.HealthCheckFilter do
@moduledoc """
Logger filter to suppress health check endpoint logs.
"""
def filter(%{meta: meta}, _config) when is_map(meta) do
if Map.get(meta, :health_check) == true do
:stop
else
:ignore
end
end
def filter(_log_event, _config), do: :ignore
end

View File

@@ -1,19 +0,0 @@
defmodule ElixirAiWeb.Plugs.HealthCheckLogger do
@moduledoc """
Plug that marks health check requests for filtering.
"""
@behaviour Plug
require Logger
@impl true
def init(opts), do: opts
@impl true
def call(%Plug.Conn{path_info: ["health"]} = conn, _opts) do
# Mark this as a health check for logger filtering
Logger.metadata(health_check: true)
conn
end
def call(conn, _opts), do: conn
end

View File

@@ -1,8 +1,10 @@
%{ %{
"acceptor_pool": {:hex, :acceptor_pool, "1.0.1", "d88c2e8a0be9216cf513fbcd3e5a4beb36bee3ff4168e85d6152c6f899359cdb", [:rebar3], [], "hexpm", "f172f3d74513e8edd445c257d596fc84dbdd56d2c6fa287434269648ae5a421e"}, "acceptor_pool": {:hex, :acceptor_pool, "1.0.1", "d88c2e8a0be9216cf513fbcd3e5a4beb36bee3ff4168e85d6152c6f899359cdb", [:rebar3], [], "hexpm", "f172f3d74513e8edd445c257d596fc84dbdd56d2c6fa287434269648ae5a421e"},
"bandit": {:hex, :bandit, "1.10.3", "1e5d168fa79ec8de2860d1b4d878d97d4fbbe2fdbe7b0a7d9315a4359d1d4bb9", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "99a52d909c48db65ca598e1962797659e3c0f1d06e825a50c3d75b74a5e2db18"}, "bandit": {:hex, :bandit, "1.10.3", "1e5d168fa79ec8de2860d1b4d878d97d4fbbe2fdbe7b0a7d9315a4359d1d4bb9", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.0", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "99a52d909c48db65ca598e1962797659e3c0f1d06e825a50c3d75b74a5e2db18"},
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
"castore": {:hex, :castore, "1.0.17", "4f9770d2d45fbd91dcf6bd404cf64e7e58fed04fadda0923dc32acca0badffa2", [:mix], [], "hexpm", "12d24b9d80b910dd3953e165636d68f147a31db945d2dcb9365e441f8b5351e5"}, "castore": {:hex, :castore, "1.0.17", "4f9770d2d45fbd91dcf6bd404cf64e7e58fed04fadda0923dc32acca0badffa2", [:mix], [], "hexpm", "12d24b9d80b910dd3953e165636d68f147a31db945d2dcb9365e441f8b5351e5"},
"chatterbox": {:hex, :ts_chatterbox, "0.15.1", "5cac4d15dd7ad61fc3c4415ce4826fc563d4643dee897a558ec4ea0b1c835c9c", [:rebar3], [{:hpack, "~> 0.3.0", [hex: :hpack_erl, repo: "hexpm", optional: false]}], "hexpm", "4f75b91451338bc0da5f52f3480fa6ef6e3a2aeecfc33686d6b3d0a0948f31aa"}, "chatterbox": {:hex, :ts_chatterbox, "0.15.1", "5cac4d15dd7ad61fc3c4415ce4826fc563d4643dee897a558ec4ea0b1c835c9c", [:rebar3], [{:hpack, "~> 0.3.0", [hex: :hpack_erl, repo: "hexpm", optional: false]}], "hexpm", "4f75b91451338bc0da5f52f3480fa6ef6e3a2aeecfc33686d6b3d0a0948f31aa"},
"credo": {:hex, :credo, "1.7.17", "f92b6aa5b26301eaa5a35e4d48ebf5aa1e7094ac00ae38f87086c562caf8a22f", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "1eb5645c835f0b6c9b5410f94b5a185057bcf6d62a9c2b476da971cde8749645"},
"ctx": {:hex, :ctx, "0.6.0", "8ff88b70e6400c4df90142e7f130625b82086077a45364a78d208ed3ed53c7fe", [:rebar3], [], "hexpm", "a14ed2d1b67723dbebbe423b28d7615eb0bdcba6ff28f2d1f1b0a7e1d4aa5fc2"}, "ctx": {:hex, :ctx, "0.6.0", "8ff88b70e6400c4df90142e7f130625b82086077a45364a78d208ed3ed53c7fe", [:rebar3], [], "hexpm", "a14ed2d1b67723dbebbe423b28d7615eb0bdcba6ff28f2d1f1b0a7e1d4aa5fc2"},
"db_connection": {:hex, :db_connection, "2.9.0", "a6a97c5c958a2d7091a58a9be40caf41ab496b0701d21e1d1abff3fa27a7f371", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "17d502eacaf61829db98facf6f20808ed33da6ccf495354a41e64fe42f9c509c"}, "db_connection": {:hex, :db_connection, "2.9.0", "a6a97c5c958a2d7091a58a9be40caf41ab496b0701d21e1d1abff3fa27a7f371", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "17d502eacaf61829db98facf6f20808ed33da6ccf495354a41e64fe42f9c509c"},
"decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"}, "decimal": {:hex, :decimal, "2.3.0", "3ad6255aa77b4a3c4f818171b12d237500e63525c2fd056699967a3e7ea20f62", [:mix], [], "hexpm", "a4d66355cb29cb47c3cf30e71329e58361cfcb37c34235ef3bf1d7bf3773aeac"},