From ee4a8e593dbc95b0a83cb42897640a405460ea7a Mon Sep 17 00:00:00 2001 From: kireetb Date: Mon, 3 Feb 2025 22:50:58 -0500 Subject: [PATCH] simpler custom spawn bucket sizes for prometheus --- docs/source/reference/monitoring.md | 10 +++++++++ jupyterhub/metrics.py | 32 +++++++---------------------- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/docs/source/reference/monitoring.md b/docs/source/reference/monitoring.md index 622f52aa..8208d799 100644 --- a/docs/source/reference/monitoring.md +++ b/docs/source/reference/monitoring.md @@ -33,6 +33,16 @@ export JUPYTERHUB_METRICS_PREFIX=jupyterhub_prod would result in the metric `jupyterhub_prod_active_users`, etc. +## Customizing spawn bucket sizes + +As of JupyterHub >= 5.2.1, override `JUPYTERHUB_SERVER_SPAWN_DURATION_SECONDS_BUCKETS` env variable in Hub's environment to allow custom bucket sizes. Otherwise default to, [0.5, 1, 2.5, 5, 10, 15, 30, 60, 120, 180, 300, 600, float("inf")] + +For example, + +```bash +export JUPYTERHUB_SERVER_SPAWN_DURATION_SECONDS_BUCKETS="1,2,4,6,12,30,60,120" +``` + ## Configuring metrics ```{eval-rst} diff --git a/jupyterhub/metrics.py b/jupyterhub/metrics.py index adf6efd1..90bb41d4 100644 --- a/jupyterhub/metrics.py +++ b/jupyterhub/metrics.py @@ -36,31 +36,13 @@ from traitlets.config import LoggingConfigurable from . import orm from .utils import utcnow +metrics_prefix = os.getenv('JUPYTERHUB_METRICS_PREFIX', 'jupyterhub') +_env_buckets = os.environ.get('JUPYTERHUB_SERVER_SPAWN_DURATION_SECONDS_BUCKETS', "").strip() -class CustomEnvVars(HasTraits): - bucket_sizes = List().tag(config=True) - metrics_prefix = os.getenv('JUPYTERHUB_METRICS_PREFIX', 'jupyterhub') - - def load_from_env(self): - env_var_bucket_sizes = os.getenv( - 'JUPYTERHUB_SERVER_SPAWN_DURATION_SECONDS_BUCKET_SIZES', - '[0.5, 1, 2.5, 5, 10, 15, 30, 60, 120, 180, 300, 600]', - ) - - try: - # Manually convert the string to a list - # Here we assume the string is in the format '[1, 2, 3]' - cleaned = env_var_bucket_sizes.strip('[]').replace(' ', '') - self.bucket_sizes = [str(i) for i in cleaned.split(',')] - except (ValueError, AttributeError): - # Handle if conversion fails - raise TraitError("Failed to convert environment variable to list.") - - -custom_env = CustomEnvVars() -custom_env.load_from_env() -metrics_prefix = custom_env.metrics_prefix -bucket_sizes = custom_env.bucket_sizes +if _env_buckets: + spawn_duration_buckets = [float(_s) for _s in _env_buckets.split(",")] +else: + spawn_duration_buckets = [0.5, 1, 2.5, 5, 10, 15, 30, 60, 120, 180, 300, 600, float("inf")] REQUEST_DURATION_SECONDS = Histogram( 'request_duration_seconds', @@ -75,7 +57,7 @@ SERVER_SPAWN_DURATION_SECONDS = Histogram( ['status'], # Use custom bucket sizes, since the default bucket ranges # are meant for quick running processes. Spawns can take a while! - buckets=bucket_sizes, + buckets=spawn_duration_buckets, namespace=metrics_prefix, )