Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build_api/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ runs:
shell: bash
run: >
docker build ${{ inputs.docker_build_context }}
--build-arg SENTRY_RELEASE="opensensor-api@${GITHUB_SHA}"
-f ${{ inputs.dockerfile }}
-t ${{ steps.image_tags.outputs.sha }}
-t ${{ steps.image_tags.outputs.latest }}
Expand Down
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,10 @@ USER opensensor-api
ENV TZ=UTC

# Start opensensor API
# Public Sentry ingestion key; upload credentials are never part of the image.
ARG SENTRY_RELEASE
ENV SENTRY_DSN=https://f342f997ac7c582759f18b6d46a71956@o4512337837686784.ingest.us.sentry.io/4512337894637568 \
SENTRY_ENVIRONMENT=production \
SENTRY_RELEASE=${SENTRY_RELEASE}

CMD ["/usr/src/.venv/bin/uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8010", "--timeout-keep-alive", "30", "--log-level", "info"]
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ verify_ssl = true
name = "pypi"

[packages]
sentry-sdk = "==2.73.0"
fastapi = "*"
uvicorn = "*"
pydantic = "*"
Expand Down
19 changes: 18 additions & 1 deletion Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
from opensensor.app import app
from opensensor.collection_apis import router as collection_apis_router
from opensensor.devices import router as device_apis_router
from opensensor.observability import init_sentry

init_sentry()


@app.get("/")
Expand Down
46 changes: 46 additions & 0 deletions opensensor/observability.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""Opt-in Sentry error and trace capture; no request payloads or local variables."""

import os
from urllib.parse import urlsplit, urlunsplit

import sentry_sdk


def scrub_event(event, hint):
request = event.get("request")
if request:
for key in ("data", "cookies", "headers", "query_string"):
request.pop(key, None)
if request.get("url"):
parts = urlsplit(request["url"])
request["url"] = urlunsplit((parts.scheme, parts.netloc, parts.path, "", ""))
event.pop("user", None)
event.pop("extra", None)
event["breadcrumbs"] = {"values": []}
return event


def init_sentry() -> None:
dsn = os.environ.get("SENTRY_DSN")
if not dsn or os.environ.get("SENTRY_ENABLED", "true").lower() == "false":
return
sentry_sdk.init(
dsn=dsn,
environment=os.environ.get("SENTRY_ENVIRONMENT", "production"),
release=os.environ.get("SENTRY_RELEASE") or None,
traces_sample_rate=0.1,
data_collection={
"user_info": False,
"cookies": {"mode": "off"},
"http_headers": {"request": {"mode": "off"}},
"http_bodies": [],
"url_query_params": {"mode": "off"},
"database_query_data": False,
"queues": False,
"stack_frame_variables": False,
"gen_ai": {"inputs": False, "outputs": False},
"graphql": {"document": False, "variables": False},
},
before_send=scrub_event,
before_send_transaction=scrub_event,
)
Loading