From a27be9aa5fff96754399553f40754f10abb3ce46 Mon Sep 17 00:00:00 2001 From: "David H. Irving" Date: Mon, 18 Nov 2024 14:21:24 -0700 Subject: [PATCH] Add Sentry telemetry Add the Sentry SDK and use it to capture traces for debugging performance problems. --- Makefile | 12 +++++----- requirements/dev.txt | 4 ++++ requirements/main.in | 1 + requirements/main.txt | 8 ++++++- src/sia/main.py | 2 ++ src/sia/telemetry.py | 53 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 src/sia/telemetry.py diff --git a/Makefile b/Makefile index 47d05fa..0384250 100644 --- a/Makefile +++ b/Makefile @@ -36,14 +36,14 @@ update: update-deps init .PHONY: update-deps update-deps: - pip install --upgrade uv - uv pip install --upgrade pre-commit - pre-commit autoupdate - uv pip compile --upgrade --generate-hashes \ +# pip install --upgrade uv +# uv pip install --upgrade pre-commit +# pre-commit autoupdate + uv pip compile --generate-hashes \ --output-file requirements/main.txt requirements/main.in - uv pip compile --upgrade --generate-hashes \ + uv pip compile --generate-hashes \ --output-file requirements/dev.txt requirements/dev.in - uv pip compile --upgrade --generate-hashes \ + uv pip compile --generate-hashes \ --output-file requirements/tox.txt requirements/tox.in # Useful for testing against a Git version of Safir. diff --git a/requirements/dev.txt b/requirements/dev.txt index b14b411..76744f4 100644 --- a/requirements/dev.txt +++ b/requirements/dev.txt @@ -16,6 +16,10 @@ anyio==4.6.2.post1 \ # via # -c requirements/main.txt # httpx +appnope==0.1.4 \ + --hash=sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee \ + --hash=sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c + # via ipykernel asgi-lifespan==2.1.0 \ --hash=sha256:5e2effaf0bfe39829cf2d64e7ecc47c7d86d676a6599f7afba378c31f5e3a308 \ --hash=sha256:ed840706680e28428c01e14afb3875d7d76d3206f3d5b2f2294e059b5c23804f diff --git a/requirements/main.in b/requirements/main.in index 1a90f9c..da4b99f 100644 --- a/requirements/main.in +++ b/requirements/main.in @@ -27,3 +27,4 @@ vo-models defusedxml lsst-daf-butler[postgres, remote] lsst-dax-obscore @ git+https://github.com/lsst-dm/dax_obscore@main#egg=lsst-dax-obscore +sentry-sdk diff --git a/requirements/main.txt b/requirements/main.txt index 1ae6478..74c2621 100644 --- a/requirements/main.txt +++ b/requirements/main.txt @@ -72,6 +72,7 @@ certifi==2024.8.30 \ # httpcore # httpx # requests + # sentry-sdk cffi==1.17.1 \ --hash=sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8 \ --hash=sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2 \ @@ -553,7 +554,7 @@ lsst-daf-relation==27.2024.4300 \ --hash=sha256:26cf7d4583adfcd03d708a5ffc80c18c52c78e54607cad7b104f4dcf30f3a9ff \ --hash=sha256:cae56b91e3fc44626c4fbc2aeb432817baa1084b43b0ff386e9f1e44498dd12d # via lsst-daf-butler -lsst-dax-obscore @ git+https://github.com/lsst-dm/dax_obscore@5919c78c29630b1c9ed7544a1e075d8cc7ebda22#egg=lsst-dax-obscore +lsst-dax-obscore @ git+https://github.com/lsst-dm/dax_obscore@9897f02c276698048087a91c4e0e36c808d66fdf#egg=lsst-dax-obscore # via -r requirements/main.in lsst-felis==27.2024.4300 \ --hash=sha256:5584317179c191c632233408f4a972d51165d0ef48420b2d374360a2f3d0fe37 \ @@ -1214,6 +1215,10 @@ safir-logging==6.5.1 \ --hash=sha256:b056306de26627e29bd6a6d04b1144456a1319ec0e15a67ebbc12b43362a27cd \ --hash=sha256:ff591f0247fda10842835e714a6dbf601a894432d33d6d98e20fe035a5ad952c # via safir +sentry-sdk==2.18.0 \ + --hash=sha256:0dc21febd1ab35c648391c664df96f5f79fb0d92d7d4225cd9832e53a617cafd \ + --hash=sha256:ee70e27d1bbe4cd52a38e1bd28a5fadb9b17bc29d91b5f2b97ae29c0a7610442 + # via -r requirements/main.in six==1.16.0 \ --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \ --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 @@ -1323,6 +1328,7 @@ urllib3==2.2.3 \ # botocore # lsst-resources # requests + # sentry-sdk uvicorn==0.32.0 \ --hash=sha256:60b8f3a5ac027dcd31448f411ced12b5ef452c646f76f02f8cc3f25d8d26fd82 \ --hash=sha256:f78b36b143c16f54ccdb8190d0a26b5f1901fe5a3c777e1ab29f26391af8551e diff --git a/src/sia/main.py b/src/sia/main.py index 11edcdc..aa8896d 100644 --- a/src/sia/main.py +++ b/src/sia/main.py @@ -33,6 +33,7 @@ from .handlers.external import external_router from .handlers.internal import internal_router from .middleware.ivoa import CaseInsensitiveFormMiddleware +from .telemetry import enable_telemetry __all__ = ["app"] @@ -63,6 +64,7 @@ async def lifespan(app: FastAPI) -> AsyncIterator[None]: name="sia", ) configure_uvicorn_logging(config.log_level) +enable_telemetry() app = FastAPI( title="sia", diff --git a/src/sia/telemetry.py b/src/sia/telemetry.py new file mode 100644 index 0000000..22a067e --- /dev/null +++ b/src/sia/telemetry.py @@ -0,0 +1,53 @@ +# This file is part of daf_butler. +# +# Developed for the LSST Data Management System. +# This product includes software developed by the LSST Project +# (http://www.lsst.org). +# See the COPYRIGHT file at the top-level directory of this distribution +# for details of code ownership. +# +# This software is dual licensed under the GNU General Public License and also +# under a 3-clause BSD license. Recipients may choose which of these licenses +# to use; please see the files gpl-3.0.txt and/or bsd_license.txt, +# respectively. If you choose the GPL option then the following text applies +# (but note that there is still no warranty even if you opt for BSD instead): +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from typing import Any + + +def enable_telemetry() -> None: + """Turn on upload of trace telemetry to Sentry, to allow performance + debugging of deployed server. + """ + try: + import sentry_sdk + except ImportError: + return + + # Configuration will be pulled from SENTRY_* environment variables + # (see https://docs.sentry.io/platforms/python/configuration/options/). + # If SENTRY_DSN is not present, telemetry is disabled. + sentry_sdk.init(enable_tracing=True, traces_sampler=_decide_whether_to_sample_trace) + + +def _decide_whether_to_sample_trace(context: dict[str, Any]) -> float: + asgi_scope = context.get("asgi_scope") + if asgi_scope is not None: + # Do not log health check endpoint. + if asgi_scope.get("path") == "/": + return 0 + + return 1