From 61a706eeecbd250ac66a21005779a1910bf55889 Mon Sep 17 00:00:00 2001 From: Armen Date: Wed, 17 Mar 2021 15:57:11 -0400 Subject: [PATCH 1/6] devenv(feat): Report sentry issues encountered in development environment If the developer uses `direnv` it will load the `SENTRY_DEVENV_DSN` env variable. When using the `sentry` CLI, this will enable reporting development environment issues to Sentry.io --- .envrc | 5 +++-- src/sentry/utils/sdk.py | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.envrc b/.envrc index e4c06e445710ce..2b88f659004759 100644 --- a/.envrc +++ b/.envrc @@ -41,7 +41,8 @@ report_to_sentry() { if ! require sentry-cli; then curl -sL https://sentry.io/get-cli/ | bash fi - sentry-cli send-event -m "$error_message" --logfile "$_SENTRY_LOG_FILE" --level $log_level + SENTRY_DSN=${SENTRY_DEVENV_DSN} \ + sentry-cli send-event -m "$error_message" --logfile "$_SENTRY_LOG_FILE" --level $log_level rm "$_SENTRY_LOG_FILE" } @@ -128,7 +129,7 @@ if [ "$SENTRY_DEVENV_NO_REPORT" ]; then info "No development environment errors will be reported (since you've defined SENTRY_DEVENV_NO_REPORT)." else info "Development errors will be reported to Sentry.io."$'\n'" If you wish to opt-out, set SENTRY_DEVENV_NO_REPORT as an env variable." - export SENTRY_DSN=https://23670f54c6254bfd9b7de106637808e9@o1.ingest.sentry.io/1492057 + export SENTRY_DEVENV_DSN=https://23670f54c6254bfd9b7de106637808e9@o1.ingest.sentry.io/1492057 fi ### System ### diff --git a/src/sentry/utils/sdk.py b/src/sentry/utils/sdk.py index e9f85099f28928..1c1563befb0015 100644 --- a/src/sentry/utils/sdk.py +++ b/src/sentry/utils/sdk.py @@ -1,5 +1,6 @@ import inspect import random +import os from django.conf import settings from django.urls import resolve @@ -215,6 +216,10 @@ def configure_sdk(): upstream_dsn = sdk_options.pop("dsn", None) sdk_options["traces_sampler"] = traces_sampler + # This allows reporting issues from the development environment + if not upstream_dsn and os.environ.get("SENTRY_DEVENV_DSN"): + upstream_dsn = os.environ["SENTRY_DEVENV_DSN"] + if upstream_dsn: upstream_transport = make_transport(get_options(dsn=upstream_dsn, **sdk_options)) else: From 99d8b441757eea5a48b64ec975964aab0e2101a9 Mon Sep 17 00:00:00 2001 From: Armen Date: Wed, 17 Mar 2021 16:34:44 -0400 Subject: [PATCH 2/6] sentry_runner(feat): Report development issues If the developer has SENTRY_DEVENV_DSN set we can report issues faced by the Sentry runner. --- src/sentry/runner/__init__.py | 24 +++++++++++++++++++++++- src/sentry/utils/sdk.py | 7 +++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/sentry/runner/__init__.py b/src/sentry/runner/__init__.py index 622c1f3f4dab89..594b42d4efe344 100644 --- a/src/sentry/runner/__init__.py +++ b/src/sentry/runner/__init__.py @@ -1,11 +1,15 @@ +import logging import os import click import sys import sentry import datetime +import sentry_sdk from sentry.utils.imports import import_string from sentry.utils.compat import map +logger = logging.getLogger("sentry.runner") + # We need to run this here because of a concurrency bug in Python's locale # with the lazy initialization. datetime.datetime.strptime("", "") @@ -161,4 +165,22 @@ def call_command(name, obj=None, **kwargs): def main(): - cli(prog_name=get_prog(), obj={}, max_content_width=100) + try: + if os.environ.get("SENTRY_DEVENV_DSN"): + logger.warning( + "The Sentry runner will report development issues to Sentry.io." + "Use SENTRY_DEVENV_NO_REPORT to avoid reporting issues." + ) + cli(prog_name=get_prog(), obj={}, max_content_width=100) + except Exception as e: + if os.environ.get("SENTRY_DEVENV_DSN"): + # This reports to the project sentry-dev-env + sentry_sdk.init( + dsn=os.environ["SENTRY_DEVENV_DSN"], + ) + if os.environ.get("USER"): + sentry_sdk.set_user({"username": os.environ.get("USER")}) + sentry_sdk.capture_exception(e) + logger.info("We have reported the error below to Sentry") + + raise (e) diff --git a/src/sentry/utils/sdk.py b/src/sentry/utils/sdk.py index 1c1563befb0015..6b53a8c78ccdfe 100644 --- a/src/sentry/utils/sdk.py +++ b/src/sentry/utils/sdk.py @@ -1,3 +1,4 @@ +import logging import inspect import random import os @@ -15,6 +16,8 @@ from sentry.utils import metrics from sentry.utils.rust import RustInfoIntegration +logger = logging.getLogger("sentry.utils.sdk") + UNSAFE_FILES = ( "sentry/event_manager.py", "sentry/tasks/process_buffer.py", @@ -218,6 +221,10 @@ def configure_sdk(): # This allows reporting issues from the development environment if not upstream_dsn and os.environ.get("SENTRY_DEVENV_DSN"): + logger.warning( + "The Sentry runner will report development issues to Sentry.io." + "Use SENTRY_DEVENV_NO_REPORT to avoid reporting issues." + ) upstream_dsn = os.environ["SENTRY_DEVENV_DSN"] if upstream_dsn: From 6d7fafbbfc7b5d582d9e812ca9e1cf42ad6659fc Mon Sep 17 00:00:00 2001 From: Armen Date: Fri, 19 Mar 2021 10:19:18 -0400 Subject: [PATCH 3/6] Revert changes to sdk --- src/sentry/runner/__init__.py | 20 +++++++++----------- src/sentry/utils/sdk.py | 12 ------------ 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/sentry/runner/__init__.py b/src/sentry/runner/__init__.py index 594b42d4efe344..f64be5511f923f 100644 --- a/src/sentry/runner/__init__.py +++ b/src/sentry/runner/__init__.py @@ -8,7 +8,8 @@ from sentry.utils.imports import import_string from sentry.utils.compat import map -logger = logging.getLogger("sentry.runner") +logging.basicConfig(format="%(asctime)s [%(levelname)s] %(message)s", level=logging.INFO) +logger = logging.getLogger(__name__) # We need to run this here because of a concurrency bug in Python's locale # with the lazy initialization. @@ -168,19 +169,16 @@ def main(): try: if os.environ.get("SENTRY_DEVENV_DSN"): logger.warning( - "The Sentry runner will report development issues to Sentry.io." + "The Sentry runner will report development issues to Sentry.io. " "Use SENTRY_DEVENV_NO_REPORT to avoid reporting issues." ) cli(prog_name=get_prog(), obj={}, max_content_width=100) except Exception as e: if os.environ.get("SENTRY_DEVENV_DSN"): # This reports to the project sentry-dev-env - sentry_sdk.init( - dsn=os.environ["SENTRY_DEVENV_DSN"], - ) - if os.environ.get("USER"): - sentry_sdk.set_user({"username": os.environ.get("USER")}) - sentry_sdk.capture_exception(e) - logger.info("We have reported the error below to Sentry") - - raise (e) + with sentry_sdk.init(dsn=os.environ["SENTRY_DEVENV_DSN"]): + if os.environ.get("USER"): + sentry_sdk.set_user({"username": os.environ.get("USER")}) + sentry_sdk.capture_exception(e) + logger.info("We have reported the error below to Sentry") + raise e diff --git a/src/sentry/utils/sdk.py b/src/sentry/utils/sdk.py index 6b53a8c78ccdfe..e9f85099f28928 100644 --- a/src/sentry/utils/sdk.py +++ b/src/sentry/utils/sdk.py @@ -1,7 +1,5 @@ -import logging import inspect import random -import os from django.conf import settings from django.urls import resolve @@ -16,8 +14,6 @@ from sentry.utils import metrics from sentry.utils.rust import RustInfoIntegration -logger = logging.getLogger("sentry.utils.sdk") - UNSAFE_FILES = ( "sentry/event_manager.py", "sentry/tasks/process_buffer.py", @@ -219,14 +215,6 @@ def configure_sdk(): upstream_dsn = sdk_options.pop("dsn", None) sdk_options["traces_sampler"] = traces_sampler - # This allows reporting issues from the development environment - if not upstream_dsn and os.environ.get("SENTRY_DEVENV_DSN"): - logger.warning( - "The Sentry runner will report development issues to Sentry.io." - "Use SENTRY_DEVENV_NO_REPORT to avoid reporting issues." - ) - upstream_dsn = os.environ["SENTRY_DEVENV_DSN"] - if upstream_dsn: upstream_transport = make_transport(get_options(dsn=upstream_dsn, **sdk_options)) else: From e72a6126cfbd7638d416141cc89d5b98288b0ff6 Mon Sep 17 00:00:00 2001 From: Armen Date: Mon, 22 Mar 2021 14:26:56 -0400 Subject: [PATCH 4/6] Better location for loading values from .env file --- .envrc | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.envrc b/.envrc index c7f8f6785de202..633e510061bb28 100644 --- a/.envrc +++ b/.envrc @@ -126,6 +126,13 @@ export NODE_OPTIONS=--max-old-space-size=4096 # Enable this by default for development envs (CI/deploys do not use envrc) export SENTRY_UI_HOT_RELOAD=1 +### You can override the exported variables with a .env file +# All exports should happen before here unless they're safeguarded (see devenv error reporting below) +if [ -f '.env' ]; then + info ".env found. Reading it..." + dotenv .env +fi + ## Notify of reporting to Sentry if [ -n "${SENTRY_DEVENV_NO_REPORT+x}" ]; then info "No development environment errors will be reported (since you've defined SENTRY_DEVENV_NO_REPORT)." @@ -218,11 +225,6 @@ PATH_add node_modules/.bin ### Overrides ### -if [ -f '.env' ]; then - info ".env found. Reading it..." - dotenv .env -fi - cat < Date: Mon, 22 Mar 2021 15:45:57 -0400 Subject: [PATCH 5/6] Clean up logging block --- src/sentry/runner/__init__.py | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/sentry/runner/__init__.py b/src/sentry/runner/__init__.py index f64be5511f923f..6522718a7d2fb0 100644 --- a/src/sentry/runner/__init__.py +++ b/src/sentry/runner/__init__.py @@ -8,9 +8,6 @@ from sentry.utils.imports import import_string from sentry.utils.compat import map -logging.basicConfig(format="%(asctime)s [%(levelname)s] %(message)s", level=logging.INFO) -logger = logging.getLogger(__name__) - # We need to run this here because of a concurrency bug in Python's locale # with the lazy initialization. datetime.datetime.strptime("", "") @@ -166,19 +163,26 @@ def call_command(name, obj=None, **kwargs): def main(): - try: - if os.environ.get("SENTRY_DEVENV_DSN"): - logger.warning( - "The Sentry runner will report development issues to Sentry.io. " - "Use SENTRY_DEVENV_NO_REPORT to avoid reporting issues." - ) - cli(prog_name=get_prog(), obj={}, max_content_width=100) - except Exception as e: - if os.environ.get("SENTRY_DEVENV_DSN"): + # This variable is *only* set as part of direnv/.envrc, thus, we cannot affect production + if os.environ.get("SENTRY_DEVENV_DSN"): + # We do this here because `configure_structlog` executes later + logging.basicConfig(format="%(levelname)s:%(message)s", level=logging.INFO) + logger = logging.getLogger(__name__) + + logger.info( + "The Sentry runner will report development issues to Sentry.io. " + "Use SENTRY_DEVENV_NO_REPORT to avoid reporting issues." + ) + try: + cli(prog_name=get_prog(), obj={}, max_content_width=100) + except Exception as e: # This reports to the project sentry-dev-env with sentry_sdk.init(dsn=os.environ["SENTRY_DEVENV_DSN"]): if os.environ.get("USER"): sentry_sdk.set_user({"username": os.environ.get("USER")}) sentry_sdk.capture_exception(e) logger.info("We have reported the error below to Sentry") - raise e + raise e + else: + # If you change this command here make sure to also change it in the block above + cli(prog_name=get_prog(), obj={}, max_content_width=100) From c61c05fd41160d9916ca48a363775477e45aa5ac Mon Sep 17 00:00:00 2001 From: Armen Date: Tue, 23 Mar 2021 09:54:49 -0400 Subject: [PATCH 6/6] Use func/kwargs --- src/sentry/runner/__init__.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/sentry/runner/__init__.py b/src/sentry/runner/__init__.py index 6522718a7d2fb0..436c5b1e0a44d0 100644 --- a/src/sentry/runner/__init__.py +++ b/src/sentry/runner/__init__.py @@ -163,6 +163,12 @@ def call_command(name, obj=None, **kwargs): def main(): + func = cli + kwargs = { + "prog_name": get_prog(), + "obj": {}, + "max_content_width": 100, + } # This variable is *only* set as part of direnv/.envrc, thus, we cannot affect production if os.environ.get("SENTRY_DEVENV_DSN"): # We do this here because `configure_structlog` executes later @@ -174,7 +180,7 @@ def main(): "Use SENTRY_DEVENV_NO_REPORT to avoid reporting issues." ) try: - cli(prog_name=get_prog(), obj={}, max_content_width=100) + func(**kwargs) except Exception as e: # This reports to the project sentry-dev-env with sentry_sdk.init(dsn=os.environ["SENTRY_DEVENV_DSN"]): @@ -184,5 +190,4 @@ def main(): logger.info("We have reported the error below to Sentry") raise e else: - # If you change this command here make sure to also change it in the block above - cli(prog_name=get_prog(), obj={}, max_content_width=100) + func(**kwargs)