add: Publish GHC runtime metrics to Prometheus metrics endpoint
This commit is contained in:
committed by
Wolfgang Walther
parent
c09394517d
commit
85d91e5c0a
@@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file. From versio
|
|||||||
- Add `Vary` header to responses by @develop7 in #4609
|
- Add `Vary` header to responses by @develop7 in #4609
|
||||||
- Add config `db-timezone-enabled` for optional querying of timezones by @taimoorzaeem in #4751
|
- Add config `db-timezone-enabled` for optional querying of timezones by @taimoorzaeem in #4751
|
||||||
- Log schema cache queries timings on `log-level=debug` by @steve-chavez in #4805
|
- Log schema cache queries timings on `log-level=debug` by @steve-chavez in #4805
|
||||||
|
- Add GHC runtime metrics to the metrics endpoint by @mkleczek in #4862
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,9 @@ filename
|
|||||||
FreeBSD
|
FreeBSD
|
||||||
fts
|
fts
|
||||||
fullstack
|
fullstack
|
||||||
|
GC
|
||||||
GeoJSON
|
GeoJSON
|
||||||
|
GHC
|
||||||
Github
|
Github
|
||||||
Google
|
Google
|
||||||
grantor
|
grantor
|
||||||
@@ -147,6 +149,7 @@ RESTful
|
|||||||
RLS
|
RLS
|
||||||
RPC
|
RPC
|
||||||
RSA
|
RSA
|
||||||
|
RTS
|
||||||
safeupdate
|
safeupdate
|
||||||
savepoint
|
savepoint
|
||||||
schemas
|
schemas
|
||||||
|
|||||||
@@ -238,6 +238,45 @@ pgrst_jwt_cache_evictions_total
|
|||||||
|
|
||||||
The total number of JWT cache evictions.
|
The total number of JWT cache evictions.
|
||||||
|
|
||||||
|
GHC Runtime Metrics
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
PostgREST can also expose GHC runtime system metrics. These use the ``ghc_*``
|
||||||
|
prefix and include
|
||||||
|
`GHC RTS statistics <https://ghc.gitlab.haskell.org/ghc/doc/libraries/base-4.22.0.0-inplace/GHC-Stats.html#g:1>`_
|
||||||
|
for runtime allocation, garbage collection, memory, and CPU/elapsed time.
|
||||||
|
|
||||||
|
These are useful for monitoring PostgREST process health and diagnosing memory
|
||||||
|
pressure or GC behavior.
|
||||||
|
|
||||||
|
To expose these metrics, enable GHC RTS statistics when starting PostgREST:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
postgrest +RTS -T -RTS
|
||||||
|
|
||||||
|
When enabled, the admin ``/metrics`` endpoint includes samples such as:
|
||||||
|
|
||||||
|
.. code-block:: text
|
||||||
|
|
||||||
|
# HELP ghc_gcs_total Total number of GCs
|
||||||
|
# TYPE ghc_gcs_total counter
|
||||||
|
ghc_gcs_total 1
|
||||||
|
# HELP ghc_allocated_bytes_total Total bytes allocated
|
||||||
|
# TYPE ghc_allocated_bytes_total counter
|
||||||
|
ghc_allocated_bytes_total 12345678
|
||||||
|
|
||||||
|
Other available GHC runtime metrics include:
|
||||||
|
|
||||||
|
- ``ghc_gcs_total``
|
||||||
|
- ``ghc_major_gcs_total``
|
||||||
|
- ``ghc_allocated_bytes_total``
|
||||||
|
- ``ghc_max_live_bytes``
|
||||||
|
- ``ghc_max_mem_in_use_bytes``
|
||||||
|
- ``ghc_mutator_cpu_seconds_total``
|
||||||
|
- ``ghc_gc_cpu_seconds_total``
|
||||||
|
- ``ghc_elapsed_seconds_total``
|
||||||
|
|
||||||
Traces
|
Traces
|
||||||
======
|
======
|
||||||
|
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ library
|
|||||||
, parsec >= 3.1.11 && < 3.2
|
, parsec >= 3.1.11 && < 3.2
|
||||||
, postgresql-libpq >= 0.10
|
, postgresql-libpq >= 0.10
|
||||||
, prometheus-client >= 1.1.1 && < 1.2.0
|
, prometheus-client >= 1.1.1 && < 1.2.0
|
||||||
|
, prometheus-metrics-ghc >= 1.0.1.2 && < 1.2
|
||||||
, protolude >= 0.3.1 && < 0.4
|
, protolude >= 0.3.1 && < 0.4
|
||||||
, regex-tdfa >= 1.2.2 && < 1.4
|
, regex-tdfa >= 1.2.2 && < 1.4
|
||||||
, retry >= 0.7.4 && < 0.10
|
, retry >= 0.7.4 && < 0.10
|
||||||
|
|||||||
@@ -13,10 +13,13 @@ module PostgREST.Metrics
|
|||||||
import qualified Data.ByteString.Lazy as LBS
|
import qualified Data.ByteString.Lazy as LBS
|
||||||
import qualified Hasql.Pool.Observation as SQL
|
import qualified Hasql.Pool.Observation as SQL
|
||||||
|
|
||||||
|
import GHC.Stats (getRTSStatsEnabled)
|
||||||
import Prometheus
|
import Prometheus
|
||||||
|
import qualified Prometheus.Metric.GHC as PMG
|
||||||
|
|
||||||
import PostgREST.Observation
|
import PostgREST.Observation
|
||||||
|
|
||||||
|
|
||||||
import Protolude
|
import Protolude
|
||||||
|
|
||||||
data MetricsState =
|
data MetricsState =
|
||||||
@@ -34,6 +37,7 @@ data MetricsState =
|
|||||||
|
|
||||||
init :: Int -> IO MetricsState
|
init :: Int -> IO MetricsState
|
||||||
init configDbPoolSize = do
|
init configDbPoolSize = do
|
||||||
|
whenM getRTSStatsEnabled $ void $ register PMG.ghcMetrics
|
||||||
metricState <- MetricsState <$>
|
metricState <- MetricsState <$>
|
||||||
register (counter (Info "pgrst_db_pool_timeouts_total" "The total number of pool connection timeouts")) <*>
|
register (counter (Info "pgrst_db_pool_timeouts_total" "The total number of pool connection timeouts")) <*>
|
||||||
register (gauge (Info "pgrst_db_pool_available" "Available connections in the pool")) <*>
|
register (gauge (Info "pgrst_db_pool_available" "Available connections in the pool")) <*>
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ def run(
|
|||||||
configpath=None,
|
configpath=None,
|
||||||
stdin=None,
|
stdin=None,
|
||||||
env=None,
|
env=None,
|
||||||
|
args=None,
|
||||||
port=None,
|
port=None,
|
||||||
admin_port=None,
|
admin_port=None,
|
||||||
host=None,
|
host=None,
|
||||||
@@ -122,6 +123,9 @@ def run(
|
|||||||
command = [POSTGREST_BIN]
|
command = [POSTGREST_BIN]
|
||||||
env["HPCTIXFILE"] = hpctixfile()
|
env["HPCTIXFILE"] = hpctixfile()
|
||||||
|
|
||||||
|
if args:
|
||||||
|
command.extend(args)
|
||||||
|
|
||||||
if configpath:
|
if configpath:
|
||||||
command.append(configpath)
|
command.append(configpath)
|
||||||
|
|
||||||
|
|||||||
@@ -1693,6 +1693,30 @@ def test_admin_metrics(defaultenv):
|
|||||||
assert "pgrst_db_pool_timeouts_total" in response.text
|
assert "pgrst_db_pool_timeouts_total" in response.text
|
||||||
|
|
||||||
|
|
||||||
|
def test_admin_metrics_include_ghc_runtime_metrics(defaultenv):
|
||||||
|
"Should get GHC runtime metrics from the admin endpoint when RTS stats are enabled"
|
||||||
|
|
||||||
|
with run(env=defaultenv, args=["+RTS", "-T", "-RTS"], port=freeport()) as postgrest:
|
||||||
|
response = postgrest.admin.get("/metrics")
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert "# HELP ghc_gcs_total Total number of GCs" in response.text
|
||||||
|
assert "# TYPE ghc_gcs_total counter" in response.text
|
||||||
|
assert re.search(r"^ghc_gcs_total \d+(?:\.\d+)?$", response.text, re.MULTILINE)
|
||||||
|
assert re.search(
|
||||||
|
r"^ghc_allocated_bytes_total \d+(?:\.\d+)?$", response.text, re.MULTILINE
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_admin_metrics_exclude_ghc_runtime_metrics_by_default(defaultenv):
|
||||||
|
"Should not get GHC runtime metrics unless RTS stats are enabled"
|
||||||
|
|
||||||
|
with run(env=defaultenv, port=freeport()) as postgrest:
|
||||||
|
response = postgrest.admin.get("/metrics")
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert "ghc_gcs_total" not in response.text
|
||||||
|
assert "ghc_allocated_bytes_total" not in response.text
|
||||||
|
|
||||||
|
|
||||||
def test_schema_cache_startup_load_with_in_db_config(defaultenv, metapostgrest):
|
def test_schema_cache_startup_load_with_in_db_config(defaultenv, metapostgrest):
|
||||||
"verify that the Schema Cache loads correctly at startup, using the in-db `pgrst.db_schemas` config"
|
"verify that the Schema Cache loads correctly at startup, using the in-db `pgrst.db_schemas` config"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user