From e51054a72fd91444f71f9f660556a52480c02967 Mon Sep 17 00:00:00 2001 From: Jiri Podivin Date: Fri, 4 Sep 2026 10:08:25 +0200 Subject: [PATCH] Add sentry to sweep workflows Signed-off-by: Jiri Podivin --- Containerfile.sweep | 1 + openshift/cronjob-sweep-dependency.yml | 2 ++ openshift/cronjob-sweep-no-patch.yml | 2 ++ openshift/cronjob-sweep-pr-pending.yml | 2 ++ openshift/cronjob-sweep-y-stream.yml | 2 ++ ymir/agents/backport_agent.py | 3 +-- ymir/agents/mr_consolidation_agent.py | 3 +-- ymir/agents/rebase_agent.py | 3 +-- ymir/agents/rebuild_agent.py | 2 +- ymir/agents/reproducer_agent.py | 2 +- ymir/agents/triage_agent.py | 2 +- ymir/agents/utils.py | 36 ------------------------- ymir/common/utils.py | 37 ++++++++++++++++++++++++++ ymir/sweep/__main__.py | 14 +++++----- 14 files changed, 60 insertions(+), 51 deletions(-) diff --git a/Containerfile.sweep b/Containerfile.sweep index f7ac781b4..9a638b85b 100644 --- a/Containerfile.sweep +++ b/Containerfile.sweep @@ -26,6 +26,7 @@ RUN pip3 install -v --no-cache-dir \ jinja2 \ redis \ specfile \ + sentry-sdk>=2.13.0 \ && dnf -y remove gcc gcc-c++ python3-devel \ && dnf clean all diff --git a/openshift/cronjob-sweep-dependency.yml b/openshift/cronjob-sweep-dependency.yml index 9e6e67de2..f1529f9a5 100644 --- a/openshift/cronjob-sweep-dependency.yml +++ b/openshift/cronjob-sweep-dependency.yml @@ -38,6 +38,8 @@ spec: name: jira-env - secretRef: name: jira-env + - secretRef: + name: sentry-env resources: limits: cpu: "200m" diff --git a/openshift/cronjob-sweep-no-patch.yml b/openshift/cronjob-sweep-no-patch.yml index 7b4caf01c..5e08f0050 100644 --- a/openshift/cronjob-sweep-no-patch.yml +++ b/openshift/cronjob-sweep-no-patch.yml @@ -43,6 +43,8 @@ spec: name: jira-env - secretRef: name: jira-env + - secretRef: + name: sentry-env resources: limits: cpu: "200m" diff --git a/openshift/cronjob-sweep-pr-pending.yml b/openshift/cronjob-sweep-pr-pending.yml index 29717e694..cc4b4e16b 100644 --- a/openshift/cronjob-sweep-pr-pending.yml +++ b/openshift/cronjob-sweep-pr-pending.yml @@ -40,6 +40,8 @@ spec: name: jira-env - secretRef: name: gitlab-env + - secretRef: + name: sentry-env resources: limits: cpu: "200m" diff --git a/openshift/cronjob-sweep-y-stream.yml b/openshift/cronjob-sweep-y-stream.yml index 349ee9c8c..b8ef1aac7 100644 --- a/openshift/cronjob-sweep-y-stream.yml +++ b/openshift/cronjob-sweep-y-stream.yml @@ -38,6 +38,8 @@ spec: name: jira-env - secretRef: name: jira-env + - secretRef: + name: sentry-env resources: limits: cpu: "200m" diff --git a/ymir/agents/backport_agent.py b/ymir/agents/backport_agent.py index 1651279ff..feec0db83 100644 --- a/ymir/agents/backport_agent.py +++ b/ymir/agents/backport_agent.py @@ -42,7 +42,6 @@ get_agent_execution_config, get_chat_model, get_tool_call_checker_config, - init_sentry, is_reasoning_enabled, mcp_tools, render_template, @@ -95,7 +94,7 @@ ShippedZStreamCandidate, Task, ) -from ymir.common.utils import get_all_patches +from ymir.common.utils import get_all_patches, init_sentry from ymir.common.version_utils import is_older_zstream, parse_rhel_version from ymir.tools.unprivileged.commands import RunShellCommandTool from ymir.tools.unprivileged.distgit_detector import DistgitDetectorTool diff --git a/ymir/agents/mr_consolidation_agent.py b/ymir/agents/mr_consolidation_agent.py index db8ea5a31..815fe50c9 100644 --- a/ymir/agents/mr_consolidation_agent.py +++ b/ymir/agents/mr_consolidation_agent.py @@ -41,7 +41,6 @@ get_agent_execution_config, get_chat_model, get_tool_call_checker_config, - init_sentry, is_reasoning_enabled, mcp_tools, render_template, @@ -62,7 +61,7 @@ MRConsolidationInputSchema, MRConsolidationOutputSchema, ) -from ymir.common.utils import get_all_patches +from ymir.common.utils import get_all_patches, init_sentry from ymir.tools.unprivileged.commands import RunShellCommandTool from ymir.tools.unprivileged.filesystem import GetCWDTool, RemoveTool from ymir.tools.unprivileged.specfile import GetPackageInfoTool diff --git a/ymir/agents/rebase_agent.py b/ymir/agents/rebase_agent.py index d111dec4f..f1951ad0d 100644 --- a/ymir/agents/rebase_agent.py +++ b/ymir/agents/rebase_agent.py @@ -37,7 +37,6 @@ get_agent_execution_config, get_chat_model, get_tool_call_checker_config, - init_sentry, is_reasoning_enabled, mcp_tools, render_template, @@ -63,7 +62,7 @@ RebaseOutputSchema, Task, ) -from ymir.common.utils import extract_text_from_adf +from ymir.common.utils import extract_text_from_adf, init_sentry from ymir.tools.unprivileged.commands import RunShellCommandTool from ymir.tools.unprivileged.filesystem import GetCWDTool, RemoveTool from ymir.tools.unprivileged.text import ( diff --git a/ymir/agents/rebuild_agent.py b/ymir/agents/rebuild_agent.py index 72edafcd7..f6125c226 100644 --- a/ymir/agents/rebuild_agent.py +++ b/ymir/agents/rebuild_agent.py @@ -24,7 +24,6 @@ from ymir.agents.utils import ( format_mr_triage_details, get_agent_execution_config, - init_sentry, mcp_tools, render_template, resolve_chat_model_override, @@ -45,6 +44,7 @@ RebuildOutputSchema, Task, ) +from ymir.common.utils import init_sentry logger = logging.getLogger(__file__) redis_logger = logging.getLogger("agent.redis") diff --git a/ymir/agents/reproducer_agent.py b/ymir/agents/reproducer_agent.py index 2a807ab74..46113909c 100644 --- a/ymir/agents/reproducer_agent.py +++ b/ymir/agents/reproducer_agent.py @@ -29,7 +29,6 @@ get_agent_execution_config, get_chat_model, get_tool_call_checker_config, - init_sentry, is_reasoning_enabled, mcp_tools, render_template, @@ -61,6 +60,7 @@ sweep_stale_reproducer_locks, try_acquire_reproducer_lock, ) +from ymir.common.utils import init_sentry from ymir.common.version_utils import construct_internal_branch_name, parse_rhel_version from ymir.tools.privileged.jira import fetch_jira_issue_issuelinks from ymir.tools.unprivileged.commands import RunShellCommandTool diff --git a/ymir/agents/triage_agent.py b/ymir/agents/triage_agent.py index 26a97ad3c..0dd0a2681 100644 --- a/ymir/agents/triage_agent.py +++ b/ymir/agents/triage_agent.py @@ -33,7 +33,6 @@ get_agent_execution_config, get_chat_model, get_tool_call_checker_config, - init_sentry, is_reasoning_enabled, mcp_tools, render_template, @@ -74,6 +73,7 @@ check_build_in_buildroot, extract_text_from_adf, get_latest_candidate_build, + init_sentry, ) from ymir.common.version_utils import ( construct_internal_branch_name, diff --git a/ymir/agents/utils.py b/ymir/agents/utils.py index 93c282b15..a5fbc7dda 100644 --- a/ymir/agents/utils.py +++ b/ymir/agents/utils.py @@ -209,39 +209,3 @@ def format_mr_triage_details( body = "\n\n".join(parts) return wrap_details("Triage Details", body) + "\n\n" return "" - - -def init_sentry() -> None: - """Initialize Sentry, if the DSN is set.""" - if not (dsn := os.getenv("SENTRY_DSN")): - # no DSN, no reporting - return - - import sentry_sdk - from sentry_sdk.integrations.asyncio import AsyncioIntegration - from sentry_sdk.integrations.litellm import LiteLLMIntegration - from sentry_sdk.integrations.logging import ( - ignore_logger, - ignore_logger_for_sentry_logs, - ) - - sentry_sdk.init( - dsn=dsn, - environment=os.getenv("SENTRY_ENVIRONMENT"), - enable_logs=True, - # Set traces_sample_rate to 1.0 to capture 100% - # of transactions for tracing. - traces_sample_rate=1.0, - # Add data like inputs and responses; - # see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info - stream_gen_ai_spans=True, - send_default_pii=True, - integrations=[ - AsyncioIntegration(), - LiteLLMIntegration(), - ], - ) - - for ignored_logger in ("agent.redis", "agent.task_loop", "agent.trajectory"): - ignore_logger(ignored_logger) - ignore_logger_for_sentry_logs(ignored_logger) diff --git a/ymir/common/utils.py b/ymir/common/utils.py index 7bd074cce..53fca8aae 100644 --- a/ymir/common/utils.py +++ b/ymir/common/utils.py @@ -4,6 +4,7 @@ import asyncio import logging +import os from collections.abc import AsyncGenerator, Callable from contextlib import asynccontextmanager from datetime import timedelta @@ -401,3 +402,39 @@ def extract_text_from_adf(adf_body) -> str: if isinstance(adf_body, list): return " ".join(extract_text_from_adf(item) for item in adf_body) return "" + + +def init_sentry() -> None: + """Initialize Sentry, if the DSN is set.""" + if not (dsn := os.getenv("SENTRY_DSN")): + # no DSN, no reporting + return + + import sentry_sdk + from sentry_sdk.integrations.asyncio import AsyncioIntegration + from sentry_sdk.integrations.litellm import LiteLLMIntegration + from sentry_sdk.integrations.logging import ( + ignore_logger, + ignore_logger_for_sentry_logs, + ) + + sentry_sdk.init( + dsn=dsn, + environment=os.getenv("SENTRY_ENVIRONMENT"), + enable_logs=True, + # Set traces_sample_rate to 1.0 to capture 100% + # of transactions for tracing. + traces_sample_rate=1.0, + # Add data like inputs and responses; + # see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info + stream_gen_ai_spans=True, + send_default_pii=True, + integrations=[ + AsyncioIntegration(), + LiteLLMIntegration(), + ], + ) + + for ignored_logger in ("agent.redis", "agent.task_loop", "agent.trajectory"): + ignore_logger(ignored_logger) + ignore_logger_for_sentry_logs(ignored_logger) diff --git a/ymir/sweep/__main__.py b/ymir/sweep/__main__.py index 3fae78ac4..cd87d2e91 100644 --- a/ymir/sweep/__main__.py +++ b/ymir/sweep/__main__.py @@ -16,18 +16,13 @@ import sys from ymir.common.base_utils import redis_client +from ymir.common.utils import init_sentry from ymir.supervisor.http_utils import with_requests_session from ymir.sweep.dependency import DependencySweep from ymir.sweep.no_patch import NoPatchSweep from ymir.sweep.pr_pending import PRPendingSweep from ymir.sweep.y_stream import YStreamSweep -logging.basicConfig( - level=logging.INFO, - format="%(asctime)s [%(levelname)s] %(name)s %(message)s", - stream=sys.stdout, -) - logger = logging.getLogger(__name__) STRATEGIES: dict = { @@ -59,6 +54,13 @@ async def run_sweep(strategy_names: list[str]) -> None: if __name__ == "__main__": + logging.basicConfig( + level=logging.INFO, + format="%(asctime)s [%(levelname)s] %(name)s %(message)s", + stream=sys.stdout, + ) + init_sentry() + parser = argparse.ArgumentParser(description="Run postponed-issue sweep") group = parser.add_mutually_exclusive_group(required=True) group.add_argument(