mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
Group tool templating exceptions in sentry
This will properly group tool templating exceptions.
The added tags should make it easy to prioritize and distribute fixes.
Also improves the exception if not using sentry:
```
...
Cheetah.Parser.ParseError:
Some #directives are missing their corresponding #end ___ tag: for
Line 3, column 4
Line|Cheetah Code
----|-------------------------------------------------------------
2 | moo
3 |
^
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/Users/mvandenb/src/galaxy/lib/galaxy/jobs/runners/__init__.py", line 297, in prepare_job
job_wrapper.prepare()
File "/Users/mvandenb/src/galaxy/lib/galaxy/jobs/__init__.py", line 1260, in prepare
) = tool_evaluator.build()
File "/Users/mvandenb/src/galaxy/lib/galaxy/tools/evaluation.py", line 611, in build
global_tool_logs(self._build_command_line, config_file, "Building Command Line", self.tool)
File "/Users/mvandenb/src/galaxy/lib/galaxy/tools/evaluation.py", line 111, in global_tool_logs
raise ToolTemplatingException(
galaxy.tools.evaluation.ToolTemplatingException: Error occurred while building command line for tool 'cheetah_problem_syntax_error'
```
This commit is contained in:
@@ -147,6 +147,7 @@ from galaxy.tools.cache import ToolCache
|
||||
from galaxy.tools.data import ToolDataTableManager
|
||||
from galaxy.tools.data_manager.manager import DataManagers
|
||||
from galaxy.tools.error_reports import ErrorReports
|
||||
from galaxy.tools.evaluation import ToolTemplatingException
|
||||
from galaxy.tools.search import ToolBoxSearch
|
||||
from galaxy.tools.special_tools import load_lib_tools
|
||||
from galaxy.tours import (
|
||||
@@ -227,12 +228,34 @@ class SentryClientMixin:
|
||||
level=logging.INFO, # Capture info and above as breadcrumbs
|
||||
event_level=getattr(logging, event_level), # Send errors as events
|
||||
)
|
||||
|
||||
def before_send(event, hint):
|
||||
if "exc_info" in hint:
|
||||
exc_type, exc_value, tb = hint["exc_info"]
|
||||
if isinstance(exc_value, ToolTemplatingException):
|
||||
# We set a custom fingerprint that may look like:
|
||||
# ["Error occurred while {action_str.lower()} for tool '{tool.id}'",
|
||||
# "1.0",
|
||||
# "cannot find 'file_name' while searching for 'species_chromosomes.file_name'"]
|
||||
# If we don't do this issues are never properly grouped since by default the calling stack is inspected,
|
||||
# and that is always unique in cheetah as it is dynamically generated.
|
||||
event["fingerprint"] = [str(exc_value), str(exc_value.tool_version), str(exc_value.__cause__)]
|
||||
event.setdefault("tags", {}).update(
|
||||
{
|
||||
"tool_is_latest": exc_value.is_latest,
|
||||
"tool_id": str(exc_value.tool_id),
|
||||
"tool_version": exc_value.tool_version,
|
||||
}
|
||||
)
|
||||
return event
|
||||
|
||||
self.sentry_client = sentry_sdk.init(
|
||||
self.config.sentry_dsn,
|
||||
release=f"{self.config.version_major}.{self.config.version_minor}",
|
||||
integrations=[sentry_logging],
|
||||
traces_sample_rate=self.config.sentry_traces_sample_rate,
|
||||
ca_certs=self.config.sentry_ca_certs,
|
||||
before_send=before_send,
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ from typing import (
|
||||
Dict,
|
||||
List,
|
||||
Optional,
|
||||
TYPE_CHECKING,
|
||||
Union,
|
||||
)
|
||||
|
||||
@@ -70,6 +71,9 @@ from galaxy.util.template import (
|
||||
from galaxy.util.tree_dict import TreeDict
|
||||
from galaxy.work.context import WorkRequestContext
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from galaxy.tools import Tool
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -89,13 +93,27 @@ class ToolErrorLog:
|
||||
global_tool_errors = ToolErrorLog()
|
||||
|
||||
|
||||
def global_tool_logs(func, config_file, action_str):
|
||||
class ToolTemplatingException(Exception):
|
||||
|
||||
def __init__(self, *args: object, tool_id: Optional[str], tool_version: str, is_latest: bool) -> None:
|
||||
super().__init__(*args)
|
||||
self.tool_id = tool_id
|
||||
self.tool_version = tool_version
|
||||
self.is_latest = is_latest
|
||||
|
||||
|
||||
def global_tool_logs(func, config_file: str, action_str: str, tool: "Tool"):
|
||||
try:
|
||||
return func()
|
||||
except Exception as e:
|
||||
# capture and log parsing errors
|
||||
global_tool_errors.add_error(config_file, action_str, e)
|
||||
raise e
|
||||
raise ToolTemplatingException(
|
||||
f"Error occurred while {action_str.lower()} for tool '{tool.id}'",
|
||||
tool_id=tool.id,
|
||||
tool_version=tool.version,
|
||||
is_latest=tool.is_latest_version,
|
||||
) from e
|
||||
|
||||
|
||||
DeferrableObjectsT = Union[
|
||||
@@ -581,13 +599,18 @@ class ToolEvaluator:
|
||||
"""
|
||||
config_file = self.tool.config_file
|
||||
global_tool_logs(
|
||||
self._create_interactivetools_entry_points, config_file, "Building Interactive Tool Entry Points"
|
||||
self._create_interactivetools_entry_points, config_file, "Building Interactive Tool Entry Points", self.tool
|
||||
)
|
||||
global_tool_logs(self._build_config_files, config_file, "Building Config Files")
|
||||
global_tool_logs(self._build_param_file, config_file, "Building Param File")
|
||||
global_tool_logs(self._build_command_line, config_file, "Building Command Line")
|
||||
global_tool_logs(self._build_version_command, config_file, "Building Version Command Line")
|
||||
global_tool_logs(self._build_environment_variables, config_file, "Building Environment Variables")
|
||||
global_tool_logs(
|
||||
self._build_config_files,
|
||||
config_file,
|
||||
"Building Config Files",
|
||||
self.tool,
|
||||
)
|
||||
global_tool_logs(self._build_param_file, config_file, "Building Param File", self.tool)
|
||||
global_tool_logs(self._build_command_line, config_file, "Building Command Line", self.tool)
|
||||
global_tool_logs(self._build_version_command, config_file, "Building Version Command Line", self.tool)
|
||||
global_tool_logs(self._build_environment_variables, config_file, "Building Environment Variables", self.tool)
|
||||
return (
|
||||
self.command_line,
|
||||
self.version_command_line,
|
||||
@@ -836,7 +859,7 @@ class PartialToolEvaluator(ToolEvaluator):
|
||||
|
||||
def build(self):
|
||||
config_file = self.tool.config_file
|
||||
global_tool_logs(self._build_environment_variables, config_file, "Building Environment Variables")
|
||||
global_tool_logs(self._build_environment_variables, config_file, "Building Environment Variables", self.tool)
|
||||
return (
|
||||
self.command_line,
|
||||
self.version_command_line,
|
||||
@@ -857,10 +880,10 @@ class RemoteToolEvaluator(ToolEvaluator):
|
||||
|
||||
def build(self):
|
||||
config_file = self.tool.config_file
|
||||
global_tool_logs(self._build_config_files, config_file, "Building Config Files")
|
||||
global_tool_logs(self._build_param_file, config_file, "Building Param File")
|
||||
global_tool_logs(self._build_command_line, config_file, "Building Command Line")
|
||||
global_tool_logs(self._build_version_command, config_file, "Building Version Command Line")
|
||||
global_tool_logs(self._build_config_files, config_file, "Building Config Files", self.tool)
|
||||
global_tool_logs(self._build_param_file, config_file, "Building Param File", self.tool)
|
||||
global_tool_logs(self._build_command_line, config_file, "Building Command Line", self.tool)
|
||||
global_tool_logs(self._build_version_command, config_file, "Building Version Command Line", self.tool)
|
||||
return (
|
||||
self.command_line,
|
||||
self.version_command_line,
|
||||
|
||||
Reference in New Issue
Block a user