diff --git a/judoscale/asgi/middleware.py b/judoscale/asgi/middleware.py index 7106061..d3c2c56 100644 --- a/judoscale/asgi/middleware.py +++ b/judoscale/asgi/middleware.py @@ -3,6 +3,7 @@ from judoscale.core.adapter import Adapter, AdapterInfo from judoscale.core.config import config as judoconfig +from judoscale.core.logger import logger from judoscale.core.metric import Metric from judoscale.core.metrics_collectors import WebMetricsCollector from judoscale.core.reporter import reporter @@ -14,6 +15,11 @@ class RequestQueueTimeMiddleware: def __init__(self, app, extra_config: Mapping = {}, **kwargs): self.app = app judoconfig.update(extra_config) + + if not judoconfig.is_enabled: + logger.info("Not activated - no API URL provivded") + return + self.collector = WebMetricsCollector(judoconfig) adapter = Adapter( identifier=f"judoscale-{self.platform}", @@ -28,14 +34,15 @@ async def __call__(self, scope, receive, send): await self.app(scope, receive, send) return - for header, value in scope["headers"]: - if header.lower() == b"x-request-start": - request_start = value.decode() - if metric := Metric.for_web(request_start): - self.collector.add(metric) - break + if judoconfig.is_enabled: + for header, value in scope["headers"]: + if header.lower() == b"x-request-start": + request_start = value.decode() + if metric := Metric.for_web(request_start): + self.collector.add(metric) + break - reporter.ensure_running() + reporter.ensure_running() await self.app(scope, receive, send) diff --git a/judoscale/celery/__init__.py b/judoscale/celery/__init__.py index ddcdd3d..5f36405 100644 --- a/judoscale/celery/__init__.py +++ b/judoscale/celery/__init__.py @@ -8,6 +8,7 @@ from judoscale.celery.collector import CeleryMetricsCollector from judoscale.core.adapter import Adapter, AdapterInfo from judoscale.core.config import config as judoconfig +from judoscale.core.logger import logger from judoscale.core.reporter import reporter @@ -20,6 +21,11 @@ def judoscale_celery(celery: Celery, extra_config: Mapping = {}) -> None: celery.conf.task_send_sent_event = True judoconfig.update(extra_config) + + if not judoconfig.is_enabled: + logger.info("Not activated - no API URL provivded") + return + collector = CeleryMetricsCollector(config=judoconfig, broker=celery) adapter = Adapter( identifier="judoscale-celery", diff --git a/judoscale/core/config.py b/judoscale/core/config.py index bd121e5..7215755 100644 --- a/judoscale/core/config.py +++ b/judoscale/core/config.py @@ -71,6 +71,10 @@ def for_render(cls, env: Mapping): api_base_url = f"https://adapter.judoscale.com/api/{service_id}" return cls(runtime_container, api_base_url, env) + @property + def is_enabled(self) -> bool: + return bool(self["API_BASE_URL"]) + def update(self, new_config: Mapping): for k, v in new_config.items(): k = k.upper() diff --git a/judoscale/django/apps.py b/judoscale/django/apps.py index 55d0218..56115f3 100644 --- a/judoscale/django/apps.py +++ b/judoscale/django/apps.py @@ -17,7 +17,7 @@ class JudoscaleDjangoConfig(AppConfig): def ready(self): judoconfig.update(getattr(settings, "JUDOSCALE", {})) - if judoconfig["API_BASE_URL"] is None: + if not judoconfig.is_enabled: logger.info("Not activated - No API URL provided") return diff --git a/judoscale/flask/judoscale.py b/judoscale/flask/judoscale.py index 1894e16..87b7a57 100644 --- a/judoscale/flask/judoscale.py +++ b/judoscale/flask/judoscale.py @@ -5,6 +5,7 @@ from judoscale.core.adapter import Adapter, AdapterInfo from judoscale.core.config import config as judoconfig +from judoscale.core.logger import logger from judoscale.core.metric import Metric from judoscale.core.metrics_collectors import WebMetricsCollector from judoscale.core.reporter import reporter @@ -28,6 +29,11 @@ def __init__(self, app: Optional[Flask] = None): def init_app(self, app: Flask): judoconfig.update(app.config.get("JUDOSCALE", {})) + + if not judoconfig.is_enabled: + logger.info("Not activated - no API URL provivded") + return + collector = WebMetricsCollector(judoconfig) adapter = Adapter( identifier="judoscale-flask", diff --git a/judoscale/rq/__init__.py b/judoscale/rq/__init__.py index e9af414..14ef574 100644 --- a/judoscale/rq/__init__.py +++ b/judoscale/rq/__init__.py @@ -5,12 +5,18 @@ from judoscale.core.adapter import Adapter, AdapterInfo from judoscale.core.config import config as judoconfig +from judoscale.core.logger import logger from judoscale.core.reporter import reporter from judoscale.rq.collector import RQMetricsCollector def judoscale_rq(redis: Redis, extra_config: Mapping = {}) -> None: judoconfig.update(extra_config) + + if not judoconfig.is_enabled: + logger.info("Not activated - no API URL provivded") + return + collector = RQMetricsCollector(config=judoconfig, redis=redis) adapter = Adapter( identifier="judoscale-rq", diff --git a/judoscale/rq/apps.py b/judoscale/rq/apps.py index 7b0b09f..254e8e4 100644 --- a/judoscale/rq/apps.py +++ b/judoscale/rq/apps.py @@ -20,7 +20,7 @@ class JudoscaleRQConfig(AppConfig): def ready(self): judoconfig.update(getattr(settings, "JUDOSCALE", {})) - if judoconfig["API_BASE_URL"] is None: + if not judoconfig.is_enabled: logger.info("Not activated - No API URL provided") return diff --git a/sample-apps/django_celery_sample/blog/views.py b/sample-apps/django_celery_sample/blog/views.py index ec59762..554979c 100644 --- a/sample-apps/django_celery_sample/blog/views.py +++ b/sample-apps/django_celery_sample/blog/views.py @@ -32,14 +32,17 @@ def many_tasks(request): def index(request): # Log message in level warning as this is Django's default logging level logger.warning("Hello, world") - catcher_url = settings.JUDOSCALE["API_BASE_URL"].replace("/inspect/", "/p/") - return HttpResponse( - "Judoscale Django Celery Sample App. " - f"Metrics" - "
" - "" - ) + if url := settings.JUDOSCALE.get("API_BASE_URL"): + catcher_url = url.replace("/inspect/", "/p/") + return HttpResponse( + "Judoscale Django Celery Sample App. " + f"Metrics" + "" + "" + ) + else: + return HttpResponse("Judoscale Django Celery Sample App. No API URL provided.") diff --git a/sample-apps/django_rq_sample/blog/views.py b/sample-apps/django_rq_sample/blog/views.py index ce41d69..48394b2 100644 --- a/sample-apps/django_rq_sample/blog/views.py +++ b/sample-apps/django_rq_sample/blog/views.py @@ -38,14 +38,17 @@ def many_tasks(request): def index(request): # Log message in level warning as this is Django's default logging level logger.warning("Hello, world") - catcher_url = settings.JUDOSCALE["API_BASE_URL"].replace("/inspect/", "/p/") - return HttpResponse( - "Judoscale Django RQ Sample App. " - f"Metrics" - "" - "" - ) + if url := settings.JUDOSCALE.get("API_BASE_URL"): + catcher_url = url.replace("/inspect/", "/p/") + return HttpResponse( + "Judoscale Django RQ Sample App. " + f"Metrics" + "" + "" + ) + else: + return HttpResponse("Judoscale Django RQ Sample App. No API URL provided.") diff --git a/sample-apps/django_sample/blog/views.py b/sample-apps/django_sample/blog/views.py index 61a6ad8..13eec15 100644 --- a/sample-apps/django_sample/blog/views.py +++ b/sample-apps/django_sample/blog/views.py @@ -9,8 +9,11 @@ def index(request): # Log message in level warning as this is Django's default logging level logger.warning("Hello, world") - catcher_url = settings.JUDOSCALE["API_BASE_URL"].replace("/inspect/", "/p/") - return HttpResponse( - "Judoscale Django Sample App. " - f"Metrics" - ) + if url := settings.JUDOSCALE.get("API_BASE_URL"): + catcher_url = url.replace("/inspect/", "/p/") + return HttpResponse( + "Judoscale Django Sample App. " + f"Metrics" + ) + else: + return HttpResponse("Judoscale Django Sample App. No API URL provided.") diff --git a/sample-apps/fastapi_celery_sample/app/main.py b/sample-apps/fastapi_celery_sample/app/main.py index ee2a590..541ccd4 100644 --- a/sample-apps/fastapi_celery_sample/app/main.py +++ b/sample-apps/fastapi_celery_sample/app/main.py @@ -24,17 +24,22 @@ def create_app(): @app.get("/") async def index(): logger.warning("Hello, world") - catcher_url = settings.JUDOSCALE["API_BASE_URL"].replace("/inspect/", "/p/") - return HTMLResponse( - "Judoscale FastAPI Celery Sample App. " - f"Metrics" - "" - "" - ) + if url := settings.JUDOSCALE.get("API_BASE_URL"): + catcher_url = url.replace("/inspect/", "/p/") + return HTMLResponse( + "Judoscale FastAPI Celery Sample App. " + f"Metrics" + "" + "" + ) + else: + return HTMLResponse( + "Judoscale FastAPI Celery Sample App. No API URL provided." + ) @app.post("/task") async def task(): diff --git a/sample-apps/fastapi_sample/app/main.py b/sample-apps/fastapi_sample/app/main.py index 8dedaf3..30c016c 100644 --- a/sample-apps/fastapi_sample/app/main.py +++ b/sample-apps/fastapi_sample/app/main.py @@ -15,10 +15,13 @@ def create_app() -> FastAPI: @app.get("/") async def index(): - catcher_url = judoconfig["API_BASE_URL"].replace("/inspect/", "/p/") - return HTMLResponse( - "Judoscale FastAPI Sample App. " - f"Metrics" - ) + if url := judoconfig.get("API_BASE_URL"): + catcher_url = url.replace("/inspect/", "/p/") + return HTMLResponse( + "Judoscale FastAPI Sample App. " + f"Metrics" + ) + else: + return HTMLResponse("Judoscale FastAPI Sample App. No API URL provided.") return app diff --git a/sample-apps/flask_celery_sample/app/app.py b/sample-apps/flask_celery_sample/app/app.py index 628f17c..4aa0400 100644 --- a/sample-apps/flask_celery_sample/app/app.py +++ b/sample-apps/flask_celery_sample/app/app.py @@ -23,19 +23,20 @@ def create_app(): @app.get("/") def index(): current_app.logger.warning("Hello, world") - catcher_url = current_app.config["JUDOSCALE"]["API_BASE_URL"].replace( - "/inspect/", "/p/" - ) - return ( - "Judoscale Flask Celery Sample App. " - f"Metrics" - "" - "" - ) + if url := current_app.config["JUDOSCALE"].get("API_BASE_URL"): + catcher_url = url.replace("/inspect/", "/p/") + return ( + "Judoscale Flask Celery Sample App. " + f"Metrics" + "" + "" + ) + else: + return "Judoscale Flask Celery Sample App. No API URL provided." @app.post("/task") def task(): diff --git a/sample-apps/flask_rq_sample/app/app.py b/sample-apps/flask_rq_sample/app/app.py index 884da08..ab55349 100644 --- a/sample-apps/flask_rq_sample/app/app.py +++ b/sample-apps/flask_rq_sample/app/app.py @@ -29,19 +29,20 @@ def create_app(): @app.get("/") def index(): current_app.logger.warning("Hello, world") - catcher_url = current_app.config["JUDOSCALE"]["API_BASE_URL"].replace( - "/inspect/", "/p/" - ) - return ( - "Judoscale Flask RQ Sample App. " - f"Metrics" - "" - "" - ) + if url := current_app.config["JUDOSCALE"].get("API_BASE_URL"): + catcher_url = url.replace("/inspect/", "/p/") + return ( + "Judoscale Flask RQ Sample App. " + f"Metrics" + "" + "" + ) + else: + return "Judoscale Flask RQ Sample App. No API URL provided." @app.post("/task") def task(): diff --git a/sample-apps/flask_sample/app.py b/sample-apps/flask_sample/app.py index e31268b..f239054 100644 --- a/sample-apps/flask_sample/app.py +++ b/sample-apps/flask_sample/app.py @@ -15,13 +15,14 @@ def create_app(): @app.route("/", methods=["GET"]) def index(): current_app.logger.warning("Hello, world") - catcher_url = current_app.config["JUDOSCALE"]["API_BASE_URL"].replace( - "/inspect/", "/p/" - ) - return ( - "Judoscale Flask Sample App. " - f"Metrics" - ) + if url := current_app.config["JUDOSCALE"].get("API_BASE_URL"): + catcher_url = url.replace("/inspect/", "/p/") + return ( + "Judoscale Flask Sample App. " + f"Metrics" + ) + else: + return "Judoscale Flask Sample App. No API URL provided." return app diff --git a/tests/test_config.py b/tests/test_config.py index 8f16ec5..03882b1 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -31,6 +31,16 @@ def test_on_render(self): assert config["LOG_LEVEL"] == "WARN" assert config["API_BASE_URL"] == "https://adapter.judoscale.com/api/srv-123" + def test_is_enabled(self): + config = Config(None, "", {}) + assert not config.is_enabled + + config = Config(None, None, {}) + assert not config.is_enabled + + config = Config(None, "https://some-url.com", {}) + assert config.is_enabled + def test_for_report(self): fake_env = { "DYNO": "web.1",