惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
B
Blog RSS Feed
Microsoft Security Blog
Microsoft Security Blog
Y
Y Combinator Blog
N
Netflix TechBlog - Medium
M
MIT News - Artificial intelligence
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
B
Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
C
Check Point Blog
The GitHub Blog
The GitHub Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
P
Proofpoint News Feed
Martin Fowler
Martin Fowler
大猫的无限游戏
大猫的无限游戏
GbyAI
GbyAI
博客园_首页
A
About on SuperTechFans
Blog — PlanetScale
Blog — PlanetScale
人人都是产品经理
人人都是产品经理
T
Tailwind CSS Blog
aimingoo的专栏
aimingoo的专栏
T
The Blog of Author Tim Ferriss
The Cloudflare Blog

jola.dev

Migrating your Bluesky account the hard way | jola.dev Cluster singleton pattern | jola.dev cove.town, atproto self-hosted self-hosting | jola.dev Speeding up a Phoenix LiveView web app with a CDN | jola.dev Self-hosting an atproto container registry | jola.dev Migrating to the new Tangled knot2 | jola.dev Self-hosting and Tangled | jola.dev Self-hosting your PDS | jola.dev Taking control of your atproto account | jola.dev No cost, no value | jola.dev Latch - an Elixir atproto OAuth library | jola.dev Limited output is a feature | jola.dev Distributed rate limiter with HRW in Elixir | jola.dev A computer can never be held accountable | jola.dev Elixir Cluster 101 | jola.dev How to stop Claude from saying load-bearing | jola.dev Let libraries be libraries | jola.dev CI workflows on Tangled for Elixir | jola.dev Automatically syncing your blog to atproto and standard.site | jola.dev Appreciation for the small web | jola.dev Treating LLMs as programming books Publishing your blog to standard.site in Elixir Generating OG images in Elixir The social contract of writing Highest Random Weight in Elixir bunnyx: a bunny.net Elixir client library Building for the joy of building Running local models on an M4 with 24GB memory How to hit your Claude weekly limit so you can go outside and touch grass Dropping Cloudflare for bunny.net
Health checks for Plug and Phoenix
Johanna Larsson · 2019-06-01 · via jola.dev

I want to share a simple pattern for setting up HTTP based health checks for Plug/Phoenix applications. Health checks can be used for anything from uptime measuring to readiness/liveness probes for platforms like Kubernetes och ECS. The most simple version of one accepts requests on some specific path and responds with a 200. Another consideration is that it might run very frequently (ECS by default checks around 6 times a second) so it’s also ideal to run it as light as possible, and not generate logs. Finally, personally, I prefer having it out of the way of routing and controllers because I see it as separate from the functionality of the application. Skip to the bottom for a suggestion on how to avoid logging health checks in Phoenix while still using Phoenix.Router.

This code example works even if you don’t use Phoenix since it’s just a plug.

defmodule HealthCheck do

import Plug.Conn

def init(opts), do: opts

def call(%Plug.Conn{request_path: "/health_check"} = conn, _opts) do

conn

|> send_resp(200, "")

|> halt()

end

def call(conn, _opts), do: conn

end

To just briefly explain it, it will grab any request with the specified request_path and immediately respond with an empty 200. All other requests are passed through untouched.

You use it by adding it to the top of your plugs. Here’s an example based on the default Phoenix project, in the Endpoint.ex file:

# hello_web/Endpoint.ex

defmodule HelloWeb.Endpoint do

use Phoenix.Endpoint, otp_app: :hello

# Put the health check here, before anything else

plug HealthCheck

socket "/socket", HelloWeb.UserSocket,

websocket: true,

longpoll: false

# Serve at "/" the static files from "priv/static" directory.

#

# You should set gzip to true if you are running phx.digest

# when deploying your static files in production.

plug Plug.Static,

at: "/",

from: :hello,

gzip: false,

only: ~w(css fonts images js favicon.ico robots.txt)

...

The reason you want it first is that it short circuits any requests to the path /health_check, meaning no other plugs are executed. This has two primary benefits: the first one being that you avoid unnecessary CPU cycles (no router etc). And the other being that it doesn’t get logged because it runs before Plug.Logger.

If you now try going to /health_check you’ll see that no request is logged and you get an empty successful response.

So there you are, a very simple pattern for handling health checks in Plug and Phoenix. You don’t have to limit yourself to just responding 200, you can do any checks in that function clause and return anything, so feel free to adjust and improve for your use case.

If you’re not like me, and you feel strongly that the health check should be in your router (and you’re using Phoenix), but you don’t want those requests to be logged, take a look at scope/2. It supports setting the log level for requests for a specific scope, or even turning request logging off completely for them. Here’s an example:

scope "/health_check", log: false do

forward "/", HealthCheck

end

Enjoy!

Written by Johanna Larsson. Thoughts on this post? Find me on Bluesky at @jola.dev or why not give it a vote on Bubbles.