diff --git a/src/xfel_calibrate/setup_logging.py b/src/xfel_calibrate/setup_logging.py
index 5526ef72dcd3396d40e6448d4bcdaea7652a8c1b..1ecc6658f3e48f20870ed8fb975efb2af46ee7fe 100644
--- a/src/xfel_calibrate/setup_logging.py
+++ b/src/xfel_calibrate/setup_logging.py
@@ -1,8 +1,10 @@
 import logging
+import os
 import sys
 import traceback
 import warnings
-import os
+
+import IPython
 
 
 class ContextFilter(logging.Filter):
@@ -18,7 +20,8 @@ formatter = logging.Formatter(
     '[Notebook: %(notebook)s] - [Directory: %(directory)s] - %(message)s'
 )
 
-# Retrieve notebook name and current working directory from environment variables
+# Retrieve notebook name and current working directory from
+# environment variables
 NOTEBOOK_NAME = os.getenv('CAL_NOTEBOOK_NAME', 'Unknown notebook')
 CURRENT_WORKING_DIR = os.getenv('CAL_WORKING_DIR', 'Unknown directory')
 
@@ -37,22 +40,23 @@ warning_handler.setLevel(logging.WARNING)
 warning_handler.addFilter(lambda record: record.levelno < logging.ERROR)
 warning_handler.setFormatter(formatter)
 
-# Create console handler for info and debug
-# No formatter used for console handler on purpose.
-# console is slurm.out & the notebook output cells.
-console_handler = logging.StreamHandler()
-console_handler.setLevel(logging.DEBUG)
+# In case any info is logged and for logged data
+# by other packages like calibration_client.
+info_handler = logging.FileHandler('info.log')
+info_handler.setLevel(logging.DEBUG)
+info_handler.setFormatter(formatter)
+
 
 # Add the custom filter to handlers
 context_filter = ContextFilter()
 error_handler.addFilter(context_filter)
 warning_handler.addFilter(context_filter)
-console_handler.addFilter(context_filter)
+info_handler.addFilter(context_filter)
 
 # Add handlers to logger
 logger.addHandler(error_handler)
 logger.addHandler(warning_handler)
-logger.addHandler(console_handler)
+logger.addHandler(info_handler)
 
 handling_error = False
 
@@ -61,7 +65,8 @@ def safe_handle_error(exc_type, exc_value, exc_traceback):
     global handling_error
     if handling_error:  # Avoid infinite loop of errors.
         sys.stderr.write("Recursive error detected!\n")
-        traceback.print_exception(exc_type, exc_value, exc_traceback, file=sys.stderr)
+        traceback.print_exception(
+            exc_type, exc_value, exc_traceback, file=sys.stderr)
         return
 
     handling_error = True
@@ -70,13 +75,17 @@ def safe_handle_error(exc_type, exc_value, exc_traceback):
         logger.error(
             "An error occurred. Exception type: %s, Message: %s",
             exc_type.__name__, str(exc_value),
-            extra={'notebook': NOTEBOOK_NAME, 'directory': CURRENT_WORKING_DIR},
+            extra={
+                'notebook': NOTEBOOK_NAME,
+                'directory': CURRENT_WORKING_DIR
+            },
             exc_info=(exc_type, exc_value, exc_traceback)
         )
 
     except Exception as log_error:
         sys.stderr.write(f"Logging failed: {log_error}\n")
-        traceback.print_exception(exc_type, exc_value, exc_traceback, file=sys.stderr)
+        traceback.print_exception(
+            exc_type, exc_value, exc_traceback, file=sys.stderr)
     finally:
         handling_error = False
 
@@ -97,6 +106,9 @@ def handle_warning(message, category, filename, lineno, file=None, line=None):
 sys.excepthook = safe_handle_error
 warnings.showwarning = handle_warning
 
+
 # Override IPython's exception handling
-import IPython
-IPython.core.interactiveshell.InteractiveShell.showtraceback = lambda self, *args, **kwargs: safe_handle_error(*sys.exc_info())
\ No newline at end of file
+def custom_showtraceback(self, *args, **kwargs):
+    return safe_handle_error(*sys.exc_info())
+
+IPython.core.interactiveshell.InteractiveShell.showtraceback = custom_showtraceback  # noqa