You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently it's difficult to process exceptions in logger plugins. There are mostly two main issues:
Exception details not provided in log event
The ERROR event seems to be intended to have more details about the exception (the planned ErrorEvent dataclass has multiple different attributes). Currently this is emitted from snakemake.exceptions.print_exception(). This formats the exception using format_exception_to_string() for the log message, but the only additional information attached is the name of the exception type. This makes it hard for plugins to do anything with the error other than display the preformatted message provided.
A quick and easy solution is to attach the exception instance to the log record for the ERROR event in the standard way, using the exc_info argument to the logging method. This makes everything accessible to loggers, including the source file and line number. The linemaps argument to print_exception() could also be included in the extra dict, so that loggers can set the correct line numbers in tracebacks.
Multiple error events
If an error occurs during a job, two separate events are emitted: ERROR and JOB_ERROR. Details about the exception itself can be attached to ERROR because the function that creates the event is passed the exception instance. However it is not possible to know which job the error corresponds to. JOB_ERROR is the opposite, it indicates which job had an error but does not have the exception details attached to it.
Solving this might be a lot more complicated. JOB_ERROR is emitted from Job.log_error(), but there are multiple different code paths leading to it. Here's what I found from my analysis:
Based on this, it might be possible to add an optional job_id or job_ids argument to print_exception that could be attached to the event, which could be provided in local.Excutor._callback(). There would still be two events, but it would be possible to match them with each other.
This doesn't cover the paths from JobScheduler.schedule
Caveats
I don't know how any of this changes with remote executors.
Currently it's difficult to process exceptions in logger plugins. There are mostly two main issues:
Exception details not provided in log event
The
ERRORevent seems to be intended to have more details about the exception (the plannedErrorEventdataclass has multiple different attributes). Currently this is emitted fromsnakemake.exceptions.print_exception(). This formats the exception usingformat_exception_to_string()for the log message, but the only additional information attached is the name of the exception type. This makes it hard for plugins to do anything with the error other than display the preformatted message provided.A quick and easy solution is to attach the exception instance to the log record for the
ERRORevent in the standard way, using theexc_infoargument to the logging method. This makes everything accessible to loggers, including the source file and line number. Thelinemapsargument toprint_exception()could also be included in theextradict, so that loggers can set the correct line numbers in tracebacks.Multiple error events
If an error occurs during a job, two separate events are emitted:
ERRORandJOB_ERROR. Details about the exception itself can be attached toERRORbecause the function that creates the event is passed the exception instance. However it is not possible to know which job the error corresponds to.JOB_ERRORis the opposite, it indicates which job had an error but does not have the exception details attached to it.Solving this might be a lot more complicated.
JOB_ERRORis emitted fromJob.log_error(), but there are multiple different code paths leading to it. Here's what I found from my analysis:Based on this, it might be possible to add an optional
job_idorjob_idsargument toprint_exceptionthat could be attached to the event, which could be provided inlocal.Excutor._callback(). There would still be two events, but it would be possible to match them with each other.This doesn't cover the paths from
JobScheduler.scheduleCaveats
I don't know how any of this changes with remote executors.