diff --git a/cv_analysis/logging.py b/cv_analysis/logging.py
new file mode 100644
index 0000000..c37e3b7
--- /dev/null
+++ b/cv_analysis/logging.py
@@ -0,0 +1,60 @@
+import sys
+from functools import wraps
+from operator import attrgetter
+from typing import Callable, Any
+
+import loguru
+from funcy import log_calls
+
+dev_logger = loguru.logger
+
+dev_logger.remove()
+dev_logger.add(
+ sink=sys.stderr,
+ format="{time:YYYY-MM-DD at HH:mm:ss} | {level: <8} | {name}: {message}",
+ level="TRACE",
+)
+
+prod_logger = loguru.logger
+
+prod_logger.add(
+ sink=sys.stderr,
+ format="{time:YYYY-MM-DD at HH:mm:ss} | {level: <8} | {name}: {message}",
+ level="INFO",
+ enqueue=True,
+)
+
+logger = loguru.logger
+
+
+def __log(logger, level: str) -> Callable:
+ print_func = get_print_func(logger, level)
+
+ def inner(func: Callable) -> Callable:
+ @log_calls(print_func=print_func)
+ @wraps(func)
+ def inner(*args, **kwargs) -> Any:
+ return func(*args, **kwargs)
+
+ return inner
+
+ return inner
+
+
+def get_print_func(logger, level: str):
+ return attrgetter(level.lower())(logger)
+
+
+def dev_log(level: str = "TRACE") -> Callable:
+ return __log(dev_logger, level)
+
+
+def prod_log(level: str = "TRACE") -> Callable:
+ return __log(prod_logger, level)
+
+
+def delay(fn, *args, **kwargs):
+ def inner():
+ return fn(*args, **kwargs)
+
+ return inner