From 92c2119c8ef976184356eeeb20c846d8da823f58 Mon Sep 17 00:00:00 2001 From: Kris Knigga Date: Thu, 18 Jul 2024 15:38:27 -0500 Subject: [PATCH] Add Sentry support and logging controls. Bump version to 0.3.0. --- .env.example | 5 ++++ README.md | 6 ++++ poetry.lock | 52 ++++++++++++++++++++++++++++++++- pyproject.toml | 3 +- requirements.txt | 1 + rflying_tower_bot/__init__.py | 2 +- rflying_tower_bot/__main__.py | 4 --- rflying_tower_bot/config.py | 27 +++++++++++++++++ tests/test_rflying_tower_bot.py | 2 +- 9 files changed, 94 insertions(+), 8 deletions(-) diff --git a/.env.example b/.env.example index 7477218..7c8eb5d 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,11 @@ +RFTB_ENVIRONMENT="development" RFTB_PRAW_CLIENT_ID="" RFTB_PRAW_CLIENT_SECRET="" RFTB_PRAW_USERNAME="" RFTB_PRAW_PASSWORD="" RFTB_SUBREDDIT="" RFTB_DB_CONNECTION_STRING="sqlite+aiosqlite:///:memory:" +RFTB_LOG_LEVEL="debug" +RFTB_SENTRY_DSN="" +RFTB_SENTRY_TRACE_RATE="0.00001" +RFTB_SENTRY_PROFILE_RATE="0.00001" diff --git a/README.md b/README.md index f3e548e..310d3ca 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,12 @@ $ export RFTB_PRAW_CLIENT_SECRET="your_client_secret_here" $ export RFTB_PRAW_USERNAME="your_reddit_username_here" $ export RFTB_PRAW_PASSWORD="your_reddit_password_here" $ export RFTB_SUBREDDIT="the_name_of_a_subreddit_here" +$ export RFTB_DB_CONNECTION_STRING="sqlite+aiosqlite:///:memory:" # Optional. It keeps track of what actions have been done so they don't accidently get repeated. +$ export RFTB_LOG_LEVEL="info" # Optional. Can be debug, info, warning, error, or critical. +$ export RFTB_SENTRY_DSN="your_sentry_dsn" # Optional. Enables Sentry logging +$ export RFTB_SENTRY_TRACE_RATE="0.1" # Optional. +$ export RFTB_SENTRY_PROFILE_RATE="0.1" # Optional. +$ export RFTB_ENVIRONMENT="development" # Optional. This is for Sentry, mostly, currently ``` or, put the secrets in a file called .env (see .env.example) diff --git a/poetry.lock b/poetry.lock index 510c96b..305b927 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1678,6 +1678,56 @@ files = [ {file = "semver-3.0.2.tar.gz", hash = "sha256:6253adb39c70f6e51afed2fa7152bcd414c411286088fb4b9effb133885ab4cc"}, ] +[[package]] +name = "sentry-sdk" +version = "2.10.0" +description = "Python client for Sentry (https://sentry.io)" +optional = false +python-versions = ">=3.6" +files = [ + {file = "sentry_sdk-2.10.0-py2.py3-none-any.whl", hash = "sha256:87b3d413c87d8e7f816cc9334bff255a83d8b577db2b22042651c30c19c09190"}, + {file = "sentry_sdk-2.10.0.tar.gz", hash = "sha256:545fcc6e36c335faa6d6cda84669b6e17025f31efbf3b2211ec14efe008b75d1"}, +] + +[package.dependencies] +certifi = "*" +urllib3 = ">=1.26.11" + +[package.extras] +aiohttp = ["aiohttp (>=3.5)"] +anthropic = ["anthropic (>=0.16)"] +arq = ["arq (>=0.23)"] +asyncpg = ["asyncpg (>=0.23)"] +beam = ["apache-beam (>=2.12)"] +bottle = ["bottle (>=0.12.13)"] +celery = ["celery (>=3)"] +celery-redbeat = ["celery-redbeat (>=2)"] +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)", "protobuf (>=3.8.0)"] +httpx = ["httpx (>=0.16.0)"] +huey = ["huey (>=2)"] +huggingface-hub = ["huggingface-hub (>=0.22)"] +langchain = ["langchain (>=0.0.210)"] +loguru = ["loguru (>=0.5)"] +openai = ["openai (>=1.0.0)", "tiktoken (>=0.3.0)"] +opentelemetry = ["opentelemetry-distro (>=0.35b0)"] +opentelemetry-experimental = ["opentelemetry-instrumentation-aio-pika (==0.46b0)", "opentelemetry-instrumentation-aiohttp-client (==0.46b0)", "opentelemetry-instrumentation-aiopg (==0.46b0)", "opentelemetry-instrumentation-asgi (==0.46b0)", "opentelemetry-instrumentation-asyncio (==0.46b0)", "opentelemetry-instrumentation-asyncpg (==0.46b0)", "opentelemetry-instrumentation-aws-lambda (==0.46b0)", "opentelemetry-instrumentation-boto (==0.46b0)", "opentelemetry-instrumentation-boto3sqs (==0.46b0)", "opentelemetry-instrumentation-botocore (==0.46b0)", "opentelemetry-instrumentation-cassandra (==0.46b0)", "opentelemetry-instrumentation-celery (==0.46b0)", "opentelemetry-instrumentation-confluent-kafka (==0.46b0)", "opentelemetry-instrumentation-dbapi (==0.46b0)", "opentelemetry-instrumentation-django (==0.46b0)", "opentelemetry-instrumentation-elasticsearch (==0.46b0)", "opentelemetry-instrumentation-falcon (==0.46b0)", "opentelemetry-instrumentation-fastapi (==0.46b0)", "opentelemetry-instrumentation-flask (==0.46b0)", "opentelemetry-instrumentation-grpc (==0.46b0)", "opentelemetry-instrumentation-httpx (==0.46b0)", "opentelemetry-instrumentation-jinja2 (==0.46b0)", "opentelemetry-instrumentation-kafka-python (==0.46b0)", "opentelemetry-instrumentation-logging (==0.46b0)", "opentelemetry-instrumentation-mysql (==0.46b0)", "opentelemetry-instrumentation-mysqlclient (==0.46b0)", "opentelemetry-instrumentation-pika (==0.46b0)", "opentelemetry-instrumentation-psycopg (==0.46b0)", "opentelemetry-instrumentation-psycopg2 (==0.46b0)", "opentelemetry-instrumentation-pymemcache (==0.46b0)", "opentelemetry-instrumentation-pymongo (==0.46b0)", "opentelemetry-instrumentation-pymysql (==0.46b0)", "opentelemetry-instrumentation-pyramid (==0.46b0)", "opentelemetry-instrumentation-redis (==0.46b0)", "opentelemetry-instrumentation-remoulade (==0.46b0)", "opentelemetry-instrumentation-requests (==0.46b0)", "opentelemetry-instrumentation-sklearn (==0.46b0)", "opentelemetry-instrumentation-sqlalchemy (==0.46b0)", "opentelemetry-instrumentation-sqlite3 (==0.46b0)", "opentelemetry-instrumentation-starlette (==0.46b0)", "opentelemetry-instrumentation-system-metrics (==0.46b0)", "opentelemetry-instrumentation-threading (==0.46b0)", "opentelemetry-instrumentation-tornado (==0.46b0)", "opentelemetry-instrumentation-tortoiseorm (==0.46b0)", "opentelemetry-instrumentation-urllib (==0.46b0)", "opentelemetry-instrumentation-urllib3 (==0.46b0)", "opentelemetry-instrumentation-wsgi (==0.46b0)"] +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 (>=6)"] + [[package]] name = "setoptconf-tmp" version = "0.3.1" @@ -2115,4 +2165,4 @@ test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "1dd5644b64c8d3875d3101432581bf2c0a159e6daeab37ed683a4a7e6da25c34" +content-hash = "4046a43423870b21205a3e46c2555cf313f0c0dbfe6dfb414f813eeeb4e0030f" diff --git a/pyproject.toml b/pyproject.toml index 0b51626..84d12d7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "rflying_tower_bot" -version = "0.2.1" +version = "0.3.0" description = "" authors = ["Kris Knigga "] @@ -12,6 +12,7 @@ aiohttp = "^3.9.5" pydantic = "^2.8.2" python-dotenv = "^1.0.1" sqlalchemy = {extras = ["asyncio"], version = "^2.0.31"} +sentry-sdk = "^2.10.0" [tool.poetry.group.dev.dependencies] pre-commit = "^3.7.1" diff --git a/requirements.txt b/requirements.txt index e53116a..b98a221 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,6 +20,7 @@ python-dotenv==1.0.1 ; python_version >= "3.12" and python_version < "4.0" requests==2.32.3 ; python_version >= "3.12" and python_version < "4.0" ruamel-yaml-clib==0.2.8 ; platform_python_implementation == "CPython" and python_version < "3.13" and python_version >= "3.12" ruamel-yaml==0.18.6 ; python_version >= "3.12" and python_version < "4.0" +sentry-sdk==2.10.0 ; python_version >= "3.12" and python_version < "4.0" sqlalchemy[asyncio]==2.0.31 ; python_version >= "3.12" and python_version < "4.0" typing-extensions==4.12.2 ; python_version >= "3.12" and python_version < "4.0" update-checker==0.18.0 ; python_version >= "3.12" and python_version < "4.0" diff --git a/rflying_tower_bot/__init__.py b/rflying_tower_bot/__init__.py index 3f4c040..1a45a6d 100644 --- a/rflying_tower_bot/__init__.py +++ b/rflying_tower_bot/__init__.py @@ -1,3 +1,3 @@ """rflying_tower_bot package.""" -__version__ = "0.2.1" +__version__ = "0.3.0" diff --git a/rflying_tower_bot/__main__.py b/rflying_tower_bot/__main__.py index 4e5e37a..92a3ce1 100644 --- a/rflying_tower_bot/__main__.py +++ b/rflying_tower_bot/__main__.py @@ -9,10 +9,6 @@ from rflying_tower_bot.modlog import ModLog from rflying_tower_bot.post_stream import PostStream -logging.basicConfig( - format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO -) - log: logging.Logger = logging.getLogger(f"{__name__}") praw_config = PRAWConfig() diff --git a/rflying_tower_bot/config.py b/rflying_tower_bot/config.py index 176f85b..7fc8c46 100644 --- a/rflying_tower_bot/config.py +++ b/rflying_tower_bot/config.py @@ -3,6 +3,7 @@ import logging import os +import sentry_sdk from asyncpraw import Reddit from asyncpraw.models import Subreddit from asyncpraw.models.reddit.removal_reasons import RemovalReason @@ -22,6 +23,32 @@ load_dotenv() +log_level_map: dict[str, int] = { + "debug": logging.DEBUG, + "info": logging.INFO, + "warning": logging.WARNING, + "error": logging.ERROR, + "critical": logging.CRITICAL, +} + +log_level = os.getenv("RFTB_LOG_LEVEL", "info") +logging.basicConfig( + format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", + level=log_level_map.get(log_level, logging.INFO), +) + +sentry_dsn = os.getenv("RFTB_SENTRY_DSN") +if sentry_dsn is not None: + sentry_sdk.init( + dsn=sentry_dsn, + release=bot_version, + environment=os.getenv("RFTB_ENVIRONMENT", "development"), + debug=log_level == "debug", + enable_tracing=True, + traces_sample_rate=float(os.getenv("RFTB_SENTRY_TRACE_RATE", 0.00001)), + profiles_sample_rate=float(os.getenv("RFTB_SENTRY_PROFILE_RATE", 0.00001)), + ) + class BotConfig: """General configuration for the bot, as well as a shared asyncpraw.Reddit instance.""" diff --git a/tests/test_rflying_tower_bot.py b/tests/test_rflying_tower_bot.py index 03b96de..01817d5 100644 --- a/tests/test_rflying_tower_bot.py +++ b/tests/test_rflying_tower_bot.py @@ -5,4 +5,4 @@ def test_version(): """Test the version of the rflying_tower_bot package.""" - assert __version__ == "0.2.0" + assert __version__ == "0.3.0"