diff options
-rw-r--r-- | .github/workflows/main.yaml | 6 | ||||
-rw-r--r-- | .github/workflows/sentry_release.yaml | 23 | ||||
-rw-r--r-- | arthur/__init__.py | 4 | ||||
-rw-r--r-- | arthur/__main__.py | 5 | ||||
-rw-r--r-- | arthur/bot.py | 13 | ||||
-rw-r--r-- | arthur/config.py | 6 | ||||
-rw-r--r-- | arthur/exts/grafana/team_sync.py | 2 | ||||
-rw-r--r-- | arthur/log.py | 27 | ||||
-rw-r--r-- | poetry.lock | 48 | ||||
-rw-r--r-- | pyproject.toml | 1 |
10 files changed, 126 insertions, 9 deletions
diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 72afbde..3ae64f6 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -33,3 +33,9 @@ jobs: with: sha-tag: ${{ needs.generate-sha-tag.outputs.sha-tag }} secrets: inherit + + sentry-release: + if: github.ref == 'refs/heads/main' + uses: ./.github/workflows/sentry_release.yaml + needs: build-deploy + secrets: inherit diff --git a/.github/workflows/sentry_release.yaml b/.github/workflows/sentry_release.yaml new file mode 100644 index 0000000..9a8513b --- /dev/null +++ b/.github/workflows/sentry_release.yaml @@ -0,0 +1,23 @@ +name: Create Sentry release + +on: + workflow_call + + +jobs: + create_sentry_release: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Create a Sentry.io release + uses: tclindner/[email protected] + env: + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_ORG: python-discord + SENTRY_PROJECT: king-arthur + with: + tagName: ${{ github.sha }} + environment: production + releaseNamePrefix: king-arthur@ diff --git a/arthur/__init__.py b/arthur/__init__.py index 269a320..a163be5 100644 --- a/arthur/__init__.py +++ b/arthur/__init__.py @@ -2,17 +2,13 @@ import asyncio import os -from functools import partial from typing import TYPE_CHECKING -import loguru from pydis_core.utils import apply_monkey_patches if TYPE_CHECKING: from arthur.bot import KingArthur -logger = loguru.logger.opt(colors=True) -logger.opt = partial(logger.opt, colors=True) apply_monkey_patches() diff --git a/arthur/__main__.py b/arthur/__main__.py index 53e1fb3..041399b 100644 --- a/arthur/__main__.py +++ b/arthur/__main__.py @@ -9,6 +9,7 @@ from discord.ext import commands import arthur from arthur.bot import KingArthur from arthur.config import CONFIG +from arthur.log import logger, setup_sentry async def main() -> None: @@ -34,5 +35,7 @@ async def main() -> None: await bot.start(CONFIG.token.get_secret_value()) -with arthur.logger.catch(): +setup_sentry() + +with logger.catch(): asyncio.run(main()) diff --git a/arthur/bot.py b/arthur/bot.py index 8acf6fe..9a51298 100644 --- a/arthur/bot.py +++ b/arthur/bot.py @@ -8,9 +8,11 @@ from discord.ext import commands from kubernetes_asyncio import config from kubernetes_asyncio.config.kube_config import KUBE_CONFIG_DEFAULT_LOCATION from pydis_core import BotBase +from sentry_sdk import push_scope -from arthur import exts, logger +from arthur import exts from arthur.config import CONFIG +from arthur.log import logger class KingArthur(BotBase): @@ -60,3 +62,12 @@ class KingArthur(BotBase): return False return CONFIG.devops_role in [r.id for r in user.roles] + + async def on_error(self, event_name: str, *args: Any, **kwargs: Any) -> None: + """Log errors raised in event listeners.""" + with push_scope() as scope: + scope.set_tag("event", event_name) + scope.set_extra("args", args) + scope.set_extra("kwargs", kwargs) + + logger.exception(f"Unhandled exception during event: {event_name}.") diff --git a/arthur/config.py b/arthur/config.py index e9f80d9..c4f7e1a 100644 --- a/arthur/config.py +++ b/arthur/config.py @@ -1,5 +1,7 @@ """Utilities for interacting with the config for King Arthur.""" +from os import environ + import pydantic from pydantic_settings import BaseSettings @@ -23,6 +25,10 @@ class Config( devops_role: int = 409416496733880320 guild_id: int = 267624335836053506 + sentry_dsn: str = "" + + +GIT_SHA = environ.get("GIT_SHA", "development") CONFIG = Config() diff --git a/arthur/exts/grafana/team_sync.py b/arthur/exts/grafana/team_sync.py index 289cebd..20e059e 100644 --- a/arthur/exts/grafana/team_sync.py +++ b/arthur/exts/grafana/team_sync.py @@ -4,9 +4,9 @@ import aiohttp import discord from discord.ext import commands, tasks -from arthur import logger from arthur.apis import github, grafana from arthur.bot import KingArthur +from arthur.log import logger @dataclass(frozen=True) diff --git a/arthur/log.py b/arthur/log.py new file mode 100644 index 0000000..c382479 --- /dev/null +++ b/arthur/log.py @@ -0,0 +1,27 @@ +from functools import partial + +import loguru +import sentry_sdk +from sentry_sdk.integrations.loguru import LoggingLevels, LoguruIntegration + +from arthur.config import CONFIG, GIT_SHA + +logger = loguru.logger.opt(colors=True) +logger.opt = partial(logger.opt, colors=True) + + +def setup_sentry() -> None: + """Set up the Sentry logging integrations.""" + loguru_integration = LoguruIntegration( + level=LoggingLevels.DEBUG.value, event_level=LoggingLevels.WARNING.value + ) + + sentry_sdk.init( + dsn=CONFIG.sentry_dsn, + integrations=[ + loguru_integration, + ], + release=f"king-arthur@{GIT_SHA}", + traces_sample_rate=0.5, + profiles_sample_rate=0.5, + ) diff --git a/poetry.lock b/poetry.lock index 4c412c2..476c522 100644 --- a/poetry.lock +++ b/poetry.lock @@ -988,7 +988,6 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, - {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -1050,6 +1049,51 @@ files = [ ] [[package]] +name = "sentry-sdk" +version = "1.40.4" +description = "Python client for Sentry (https://sentry.io)" +optional = false +python-versions = "*" +files = [ + {file = "sentry-sdk-1.40.4.tar.gz", hash = "sha256:657abae98b0050a0316f0873d7149f951574ae6212f71d2e3a1c4c88f62d6456"}, + {file = "sentry_sdk-1.40.4-py2.py3-none-any.whl", hash = "sha256:ac5cf56bb897ec47135d239ddeedf7c1c12d406fb031a4c0caa07399ed014d7e"}, +] + +[package.dependencies] +certifi = "*" +urllib3 = {version = ">=1.26.11", markers = "python_version >= \"3.6\""} + +[package.extras] +aiohttp = ["aiohttp (>=3.5)"] +arq = ["arq (>=0.23)"] +asyncpg = ["asyncpg (>=0.23)"] +beam = ["apache-beam (>=2.12)"] +bottle = ["bottle (>=0.12.13)"] +celery = ["celery (>=3)"] +chalice = ["chalice (>=1.16.0)"] +clickhouse-driver = ["clickhouse-driver (>=0.2.0)"] +django = ["django (>=1.8)"] +falcon = ["falcon (>=1.4)"] +fastapi = ["fastapi (>=0.79.0)"] +flask = ["blinker (>=1.1)", "flask (>=0.11)", "markupsafe"] +grpcio = ["grpcio (>=1.21.1)"] +httpx = ["httpx (>=0.16.0)"] +huey = ["huey (>=2)"] +loguru = ["loguru (>=0.5)"] +opentelemetry = ["opentelemetry-distro (>=0.35b0)"] +opentelemetry-experimental = ["opentelemetry-distro (>=0.40b0,<1.0)", "opentelemetry-instrumentation-aiohttp-client (>=0.40b0,<1.0)", "opentelemetry-instrumentation-django (>=0.40b0,<1.0)", "opentelemetry-instrumentation-fastapi (>=0.40b0,<1.0)", "opentelemetry-instrumentation-flask (>=0.40b0,<1.0)", "opentelemetry-instrumentation-requests (>=0.40b0,<1.0)", "opentelemetry-instrumentation-sqlite3 (>=0.40b0,<1.0)", "opentelemetry-instrumentation-urllib (>=0.40b0,<1.0)"] +pure-eval = ["asttokens", "executing", "pure_eval"] +pymongo = ["pymongo (>=3.1)"] +pyspark = ["pyspark (>=2.4.4)"] +quart = ["blinker (>=1.1)", "quart (>=0.16.1)"] +rq = ["rq (>=0.6)"] +sanic = ["sanic (>=0.8)"] +sqlalchemy = ["sqlalchemy (>=1.2)"] +starlette = ["starlette (>=0.19.1)"] +starlite = ["starlite (>=1.48)"] +tornado = ["tornado (>=5)"] + +[[package]] name = "setuptools" version = "69.0.3" description = "Easily download, build, install, upgrade, and uninstall Python packages" @@ -1325,4 +1369,4 @@ multidict = ">=4.0" [metadata] lock-version = "2.0" python-versions = "3.11.*" -content-hash = "1131ecf2c4f2e722a189599434e233d1c9239cf179abbba382af5de6d1530aac" +content-hash = "83ca6e244ddd3f2a95f919d25b9c4e8a77207ffbcf7ef3b0a483c99b4ac7f68c" diff --git a/pyproject.toml b/pyproject.toml index ef51b2d..1fa3dbe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,7 @@ loguru = "0.7.2" kubernetes_asyncio = "29.0.0" tabulate = { extras = ["widechars"], version = "0.9.0" } jishaku = "2.5.2" +sentry-sdk = "1.40.4" [tool.poetry.dev-dependencies] pre-commit = "3.6.1" |