fix(admin): metrics endpoint not responding with Content-Type header

The prometheus metrics text format requires `Content-Type` header
for correct scraping which fails otherwise. Closes #4271.

Signed-off-by: Taimoor Zaeem <taimoorzaeem@gmail.com>
This commit is contained in:
Taimoor Zaeem
2025-08-20 16:13:55 -05:00
committed by Steve Chavez
parent 7657607ca5
commit dfe5ba3863
4 changed files with 9 additions and 1 deletions
+1
View File
@@ -18,6 +18,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Fix OpenAPI broken docs link by @taimoorzaeem in #4080 - Fix OpenAPI broken docs link by @taimoorzaeem in #4080
- Fix OpenAPI specification incorrectly exposing GET methods for volatile functions by @joelonsql in #4174 - Fix OpenAPI specification incorrectly exposing GET methods for volatile functions by @joelonsql in #4174
- Fix empty spread embeddings return unexpected SQL error by @taimoorzaeem in #3887 - Fix empty spread embeddings return unexpected SQL error by @taimoorzaeem in #3887
- Fix `/metrics` endpoint not responding with `Content-Type` header by @taimoorzaeem in #4271
### Changed ### Changed
+5
View File
@@ -128,6 +128,11 @@ The ``metrics`` endpoint on the :ref:`admin_server` endpoint provides metrics in
curl "http://localhost:3001/metrics" curl "http://localhost:3001/metrics"
.. code-block:: http
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
# HELP pgrst_schema_cache_query_time_seconds The query time in seconds of the last schema cache load # HELP pgrst_schema_cache_query_time_seconds The query time in seconds of the last schema cache load
# TYPE pgrst_schema_cache_query_time_seconds gauge # TYPE pgrst_schema_cache_query_time_seconds gauge
pgrst_schema_cache_query_time_seconds 1.5937927e-2 pgrst_schema_cache_query_time_seconds 1.5937927e-2
+2 -1
View File
@@ -16,6 +16,7 @@ import Network.Socket.ByteString
import PostgREST.AppState (AppState) import PostgREST.AppState (AppState)
import PostgREST.Config (AppConfig (..)) import PostgREST.Config (AppConfig (..))
import PostgREST.MediaType (MediaType (..), toContentType)
import PostgREST.Metrics (metricsToText) import PostgREST.Metrics (metricsToText)
import PostgREST.Network (resolveHost) import PostgREST.Network (resolveHost)
import PostgREST.Observation (Observation (..)) import PostgREST.Observation (Observation (..))
@@ -58,7 +59,7 @@ admin appState req respond = do
respond $ Wai.responseLBS HTTP.status200 [] (maybe mempty JSON.encode sCache) respond $ Wai.responseLBS HTTP.status200 [] (maybe mempty JSON.encode sCache)
["metrics"] -> do ["metrics"] -> do
mets <- metricsToText mets <- metricsToText
respond $ Wai.responseLBS HTTP.status200 [] mets respond $ Wai.responseLBS HTTP.status200 [toContentType MTTextPlain] mets -- Content-Type is required for prometheus compliance
_ -> _ ->
respond $ Wai.responseLBS HTTP.status404 [] mempty respond $ Wai.responseLBS HTTP.status404 [] mempty
+1
View File
@@ -1730,6 +1730,7 @@ def test_admin_metrics(defaultenv):
with run(env=defaultenv, port=freeport()) as postgrest: with run(env=defaultenv, port=freeport()) as postgrest:
response = postgrest.admin.get("/metrics") response = postgrest.admin.get("/metrics")
assert response.status_code == 200 assert response.status_code == 200
assert response.headers["Content-Type"] == "text/plain; charset=utf-8"
assert "pgrst_schema_cache_query_time_seconds" in response.text assert "pgrst_schema_cache_query_time_seconds" in response.text
assert 'pgrst_schema_cache_loads_total{status="SUCCESS"}' in response.text assert 'pgrst_schema_cache_loads_total{status="SUCCESS"}' in response.text
assert "pgrst_db_pool_max" in response.text assert "pgrst_db_pool_max" in response.text