diff --git a/.env.example b/.env.example index 2300b588..fae3fbe1 100644 --- a/.env.example +++ b/.env.example @@ -48,4 +48,12 @@ NEXT_PUBLIC_PLAUSIBLE_HOST=https://plausible.io # Python Microservice # ------------------------------------------------------------------------------------ -ENGINE_BASE_URL=http://localhost:8000 \ No newline at end of file +ENGINE_BASE_URL=http://localhost:8000 + +# Frontend URL for CORS +FRONTEND_URL=http://localhost:3000 + +# Optional: API authentication +API_SECRET_KEY=VSbk6svpu3uwhU9e + +SENTRY_DSN=https://xxx.ingest.de.sentry.io/ \ No newline at end of file diff --git a/engine/README.md b/engine/README.md index 84259a5c..c66c1d31 100644 --- a/engine/README.md +++ b/engine/README.md @@ -13,6 +13,7 @@ This service provides a simple health check endpoint and can be extended with ad - **UV Dependency Management**: Fast, reliable Python package management - **Auto Scaling**: Scales to zero when not in use on Fly.io - **Docker Support**: Containerized for easy deployment +- **Sentry Integration**: Error tracking and performance monitoring with FastAPI integration ## File Structure @@ -179,6 +180,7 @@ Quick deploy: ```bash fly launch +fly secrets set SENTRY_DSN= fly secrets set FRONTEND_URL=https://your-app.vercel.app fly deploy ``` @@ -194,7 +196,9 @@ fly deploy ## Environment Variables ```bash -PORT=8000 # Optional, defaults to 8000 +PORT=8000 # Optional, defaults to 8000 +SENTRY_DSN= # Optional, enables error tracking when set +ENVIRONMENT=development # development, staging, or production ``` ## Future Enhancements diff --git a/engine/fly.toml b/engine/fly.toml index 9d05640d..e2cedcaa 100644 --- a/engine/fly.toml +++ b/engine/fly.toml @@ -10,6 +10,7 @@ primary_region = 'fra' [env] PORT = '8000' + ENVIRONMENT = 'production' [http_service] internal_port = 8000 diff --git a/engine/main.py b/engine/main.py index ce383a1c..5580fdfd 100644 --- a/engine/main.py +++ b/engine/main.py @@ -1,13 +1,32 @@ +import os from datetime import UTC from datetime import datetime +import sentry_sdk from dotenv import load_dotenv from fastapi import FastAPI +from sentry_sdk.integrations.fastapi import FastApiIntegration from models import HealthResponse load_dotenv() +# Initialize Sentry with FastAPI integration +sentry_dsn = os.getenv("SENTRY_DSN") +if sentry_dsn: + sentry_sdk.init( + dsn=sentry_dsn, + environment=os.getenv("ENVIRONMENT", "development"), + traces_sample_rate=0.1, + profiles_sample_rate=0.1, + enable_tracing=True, + integrations=[ + FastApiIntegration( + transaction_style="endpoint", + ), + ], + ) + app = FastAPI( title="Engine Service", description="Core engine service for Kosuke Template", version="1.0.0" ) diff --git a/engine/pyproject.toml b/engine/pyproject.toml index 3c1b4fa4..60a4a5d5 100644 --- a/engine/pyproject.toml +++ b/engine/pyproject.toml @@ -9,6 +9,7 @@ dependencies = [ "uvicorn==0.34.0", "pydantic==2.10.6", "python-dotenv==1.0.1", + "sentry-sdk[fastapi]==2.19.2", ] [project.optional-dependencies] diff --git a/engine/uv.lock b/engine/uv.lock index 66321477..e7ff8322 100644 --- a/engine/uv.lock +++ b/engine/uv.lock @@ -137,6 +137,7 @@ dependencies = [ { name = "fastapi" }, { name = "pydantic" }, { name = "python-dotenv" }, + { name = "sentry-sdk", extra = ["fastapi"] }, { name = "uvicorn" }, ] @@ -161,6 +162,7 @@ requires-dist = [ { name = "pytest-cov", marker = "extra == 'dev'", specifier = "==6.0.0" }, { name = "python-dotenv", specifier = "==1.0.1" }, { name = "ruff", marker = "extra == 'dev'", specifier = "==0.9.1" }, + { name = "sentry-sdk", extras = ["fastapi"], specifier = "==2.19.2" }, { name = "uvicorn", specifier = "==0.34.0" }, ] provides-extras = ["dev"] @@ -413,6 +415,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b2/94/0498cdb7316ed67a1928300dd87d659c933479f44dec51b4f62bfd1f8028/ruff-0.9.1-py3-none-win_arm64.whl", hash = "sha256:1cd76c7f9c679e6e8f2af8f778367dca82b95009bc7b1a85a47f1521ae524fa7", size = 9145708, upload-time = "2025-01-10T18:57:51.308Z" }, ] +[[package]] +name = "sentry-sdk" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "certifi" }, + { name = "urllib3" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/36/4a/eccdcb8c2649d53440ae1902447b86e2e2ad1bc84207c80af9696fa07614/sentry_sdk-2.19.2.tar.gz", hash = "sha256:467df6e126ba242d39952375dd816fbee0f217d119bf454a8ce74cf1e7909e8d", size = 299047, upload-time = "2024-12-06T08:23:30.762Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/31/4d/74597bb6bcc23abc774b8901277652c61331a9d4d0a8d1bdb20679b9bbcb/sentry_sdk-2.19.2-py2.py3-none-any.whl", hash = "sha256:ebdc08228b4d131128e568d696c210d846e5b9d70aa0327dec6b1272d9d40b84", size = 322942, upload-time = "2024-12-06T08:23:28.842Z" }, +] + +[package.optional-dependencies] +fastapi = [ + { name = "fastapi" }, +] + [[package]] name = "sniffio" version = "1.3.1" @@ -443,6 +463,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, ] +[[package]] +name = "urllib3" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, +] + [[package]] name = "uvicorn" version = "0.34.0"