diff --git a/src/agora/abc.py b/src/agora/abc.py
index 6c1fd343e04bf42fb798642484b0b55c2de0a97a..c396b4b1503c7558dc51eaf9032b7cb14485bc38 100644
--- a/src/agora/abc.py
+++ b/src/agora/abc.py
@@ -10,6 +10,8 @@ from typing import Union
 from flatten_dict import flatten
 from yaml import dump, safe_load
 
+from agora.logging import timer
+
 atomic = t.Union[int, float, str, bool]
 
 
@@ -239,21 +241,12 @@ class StepABC(ProcessABC):
     def _run_tp(self):
         pass
 
-    def run_tp(self, tp: int, log: bool = True, **kwargs):
+    @timer
+    def run_tp(self, tp: int, **kwargs):
         """
         Time and log the timing of a step.
         """
-        if log:
-            t = perf_counter()
-            result = self._run_tp(tp, **kwargs)
-            self._log(
-                f"Timing:{self.__class__.__name__}:{perf_counter()-t}s",
-                "debug",
-            )
-        else:
-            result = self._run_tp(tp, **kwargs)
-
-        return result
+        return self._run_tp(tp, **kwargs)
 
     def run(self):
         # Replace run withn run_tp
diff --git a/src/agora/io/signal.py b/src/agora/io/signal.py
index 1b174089ba5f176cdfb1a90be5fc7a16666ce243..0210ef3427552c8d7fa62a9f366976459d112e51 100644
--- a/src/agora/io/signal.py
+++ b/src/agora/io/signal.py
@@ -84,7 +84,7 @@ class Signal(BridgeH5):
         try:
             df.columns = (df.columns * self.tinterval // 60).astype(int)
         except Exception as e:
-            self._log(f"Unable to convert columns to minutes: {e}")
+            self._log(f"Unable to convert columns to minutes: {e}", "debug")
         return df
 
     @cached_property
diff --git a/src/agora/io/writer.py b/src/agora/io/writer.py
index 0ff20f7d6dd7bd03bae028dc9a696c89ea225465..264478482875c6992241ed9ad00613f0ef96fbf0 100644
--- a/src/agora/io/writer.py
+++ b/src/agora/io/writer.py
@@ -1,4 +1,3 @@
-import itertools
 import logging
 from collections.abc import Iterable
 from pathlib import Path
@@ -55,6 +54,11 @@ class DynamicWriter:
         if Path(file).exists():
             self.metadata = load_attributes(file)
 
+    def _log(self, message: str, level: str = "warn"):
+        # Log messages in the corresponding level
+        logger = logging.getLogger("aliby")
+        getattr(logger, level)(f"{self.__class__.__name__}: {message}")
+
     def _append(self, data, key, hgroup):
         """
         Append data to existing dataset in the h5 file otherwise create a new one.
@@ -170,7 +174,9 @@ class DynamicWriter:
                             self._append(value, key, hgroup)
                     except Exception as e:
                         print(key, value)
-                        raise (e)
+                        self._log(
+                            f"{key}:{value} could not be written: {e}", "error"
+                        )
             # write metadata
             for key, value in meta.items():
                 hgroup.attrs[key] = value
diff --git a/src/agora/logging.py b/src/agora/logging.py
new file mode 100644
index 0000000000000000000000000000000000000000..a004b0182363d495c32ffcb2edf9d51cd8875303
--- /dev/null
+++ b/src/agora/logging.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env jupyter
+"""
+Add general logging functions and decorators
+"""
+
+import logging
+from time import perf_counter
+
+
+def timer(func):
+    # Log duration of a function into aliby logfile
+    def wrap_func(*args, **kwargs):
+        t1 = perf_counter()
+        result = func(*args, **kwargs)
+        logging.getLogger("aliby").debug(
+            f"{func.__qualname__} took {(perf_counter()-t1):.4f}s"
+        )
+        return result
+
+    return wrap_func
diff --git a/src/aliby/pipeline.py b/src/aliby/pipeline.py
index 0d26f6789e541882758367d3af4ef3283ed01ed7..26e9b9dc92e24b9cdf731363ca5432ca702e52b2 100644
--- a/src/aliby/pipeline.py
+++ b/src/aliby/pipeline.py
@@ -475,7 +475,7 @@ class Pipeline(ProcessABC):
                                         step == "tiler"
                                         and i == min_process_from
                                     ):
-                                        print(
+                                        logging.getLogger("aliby").info(
                                             f"Found {steps['tiler'].n_traps} traps in {image.name}"
                                         )
                                     elif (