Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • calibration/pycalibration
1 result
Show changes
Commits on Source (3)
%% Cell type:code id:98e38fec tags:
``` python
in_folder = "./" # input folder
out_folder = "./" # output folder
```
%% Cell type:code id:7fbce574 tags:
``` python
import logging
```
%% Cell type:markdown id:ba0663ca tags:
## INFO/DEBUG
%% Cell type:code id:a3b5e455 tags:
``` python
# This wont be logged
logging.info("Logging some (INFO)rmation")
```
%% Cell type:markdown id:1bf72c57 tags:
## WARNINGS
%% Cell type:code id:c0d290a1 tags:
``` python
import warnings
from cal_tools.warnings import CalWarning
from cal_tools.warnings import CalibrationWarning
class TestCalWarning(CalWarning):
class TestCalWarning(CalibrationWarning):
"""Base class for custom user warnings"""
pass
def warn_user(message, warning_class):
warnings.warn(message, warning_class)
if 1 < 2:
warn_user('This inequality is true!', TestCalWarning)
```
%% Cell type:code id:9b79ea47 tags:
``` python
# This wont be logged
logging.warning("This is a warning message using logging standard library.")
```
%% Cell type:markdown id:2b22e2e0 tags:
## ERRORS
%% Cell type:code id:0f3bfeb7 tags:
``` python
# This wont be logged
logging.error("Logging some (ERROR) without failing the notebook")
```
%% Cell type:code id:c3b87719 tags:
``` python
from cal_tools.exceptions import CalError
from cal_tools.exceptions import CalibrationError
raise CalError('Calibration Failure')
raise CalibrationError('Calibration Failure')
```
......
class CalibrationError(Exception):
pass
class CalWarning(UserWarning):
pass
\ No newline at end of file
class CalibrationWarning(UserWarning):
pass
......@@ -6,15 +6,30 @@ import warnings
import IPython
from pythonjsonlogger import jsonlogger
from cal_tools.warnings import CalibrationWarning
NOTEBOOK_NAME = os.getenv('CAL_NOTEBOOK_NAME', 'Unknown notebook')
JOB_ID = os.getenv('SLURM_JOB_ID', 'local')
class ContextFilter(logging.Filter):
def filter(self, record):
record.notebook = NOTEBOOK_NAME
record.job_id = JOB_ID
return True
# Only allow records that come from exception handlers
if getattr(record, 'from_exception_handler', False):
record.notebook = NOTEBOOK_NAME
record.job_id = JOB_ID
return True
return False
def get_class_hierarchy(cls):
"""Helper function to get the full class hierarchy"""
class_hierarchy = []
current_class = cls
while current_class and current_class != object:
class_hierarchy.append(current_class.__name__)
current_class = current_class.__base__
return '.'.join(reversed(class_hierarchy))
class CustomJsonFormatter(jsonlogger.JsonFormatter):
......@@ -25,23 +40,15 @@ class CustomJsonFormatter(jsonlogger.JsonFormatter):
log_record['level'] = record.levelname
log_record['filename'] = record.filename
log_record['lineno'] = record.lineno
log_record['class'] = getattr(record, 'class', 'DefaultClass')
exc_info = getattr(record, 'exc_info', None)
if exc_info and exc_info[0]:
exc_class = exc_info[0]
class_hierarchy = []
current_class = exc_class
while current_class and current_class != Exception:
class_hierarchy.append(current_class.__name__)
current_class = current_class.__base__
class_hierarchy.append('Exception')
log_record['class'] = '.'.join(reversed(class_hierarchy))
else:
log_record['class'] = getattr(record, 'class', 'DefaultClass')
# Get log_class from extra parameters (set in our warning/error handlers)
if hasattr(record, 'log_class'):
log_record['log_class'] = record.log_class
if record.exc_info:
log_record['exc_info'] = self.formatException(record.exc_info)
exc_class = record.exc_info[0]
log_record['class'] = get_class_hierarchy(exc_class)
# Create a logger
......@@ -51,7 +58,7 @@ logger.setLevel(logging.INFO)
# Define a custom JSON format
formatter = CustomJsonFormatter(
'%(timestamp)s %(level)s %(filename)s %(lineno)d '
'%(notebook)s %(job_id)s %(class)s %(message)s')
'%(notebook)s %(job_id)s %(log_class)s %(message)s')
# Function to create a file handler with job-specific JSON log file
......@@ -70,15 +77,14 @@ warning_handler = create_job_specific_handler(logging.WARNING, 'warnings')
# Keep console handler for notebook and slurm.out stdout
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
# Avoid errors being logged in warnings.json
warning_handler.addFilter(lambda record: record.levelno < logging.ERROR)
console_formatter = logging.Formatter('%(levelname)s: %(message)s')
console_handler.setFormatter(console_formatter)
# Add the custom filter to handlers
context_filter = ContextFilter()
error_handler.addFilter(context_filter)
warning_handler.addFilter(context_filter)
warning_handler.addFilter(lambda record: record.levelno < logging.ERROR)
console_handler.addFilter(context_filter)
# Add handlers to logger
......@@ -91,6 +97,12 @@ handling_error = False
def safe_handle_error(exc_type, exc_value, exc_traceback):
global handling_error
# Added this block to skip sys.exit()
if exc_type in (SystemExit, KeyboardInterrupt):
sys.__excepthook__(exc_type, exc_value, exc_traceback)
return
if handling_error: # Avoid infinite loop of errors.
sys.stderr.write("Recursive error detected!\n")
traceback.print_exception(
......@@ -103,7 +115,8 @@ def safe_handle_error(exc_type, exc_value, exc_traceback):
extra={
'notebook': NOTEBOOK_NAME,
'job_id': JOB_ID,
'class': exc_type.__name__ if exc_type else 'DefaultErrorClass', # noqa
'log_class': get_class_hierarchy(exc_type),
'from_exception_handler': True
},
exc_info=(exc_type, exc_value, exc_traceback)
)
......@@ -118,12 +131,13 @@ def safe_handle_error(exc_type, exc_value, exc_traceback):
def handle_warning(message, category, filename, lineno, file=None, line=None):
try:
logger.warning(
"Warning occurred: %s, File: %s, Line: %d",
message, filename, lineno,
"%s",
message,
extra={
'notebook': NOTEBOOK_NAME,
'job_id': JOB_ID,
'class': category.__name__ if category else 'DefaultWarningClass', # noqa
'log_class': get_class_hierarchy(category),
'from_exception_handler': True
}
)
except Exception as log_error:
......@@ -134,6 +148,11 @@ def handle_warning(message, category, filename, lineno, file=None, line=None):
sys.excepthook = safe_handle_error
warnings.showwarning = handle_warning
# Set up warnings filter
warnings.filterwarnings("ignore") # Ignore all warnings
# Except CalibrationWarning and subclasses
warnings.simplefilter("default", CalibrationWarning)
# Override IPython's exception handling
def custom_showtraceback(self, *args, **kwargs):
......