===================
risclog.logging
===================
.. image:: https://github.com/risclog-solution/risclog.logging/actions/workflows/test.yml/badge.svg
:target: https://github.com/risclog-solution/risclog.logging/actions/workflows/test.yml
:alt: CI Status
.. image:: https://img.shields.io/pypi/v/risclog.logging.svg
:target: https://pypi.python.org/pypi/risclog.logging
The **risclog.logging** package provides a comprehensive solution for structured logging in Python
applications. It combines Python’s built-in logging module with [structlog](https://www.structlog.org/)
to generate detailed and formatted log entries. In this new release, the API has been updated to use:
- **`getLogger`** – the new factory function for creating logger instances (the legacy ``get_logger`` is deprecated).
- **`log_decorator`** – a decorator for automatic logging of function calls, including arguments, return values,
durations, and exceptions.
- **Rich Traceback Integration** – by default, the package installs a beautiful exception renderer via:
.. code-block:: python
from rich import traceback
traceback.install()
Features
========
- **Structured logging:** Combines standard logging with structlog for rich, contextual logs.
- **Synchronous and asynchronous logging:** Use the same API in both sync and async environments.
- **Automatic function logging:** Use the ``log_decorator`` to automatically log function calls and errors.
- **Email notifications:** Optionally send email notifications on exceptions (requires setting specific environment variables).
- **Rich traceback:** Enhanced exception display is provided by default via Rich.
- **Flexible configuration:** Programmatically set log levels and add handlers (e.g. file handlers).
Installation
============
Install via pip:
.. code-block:: bash
pip install risclog.logging
Configuration and Usage
=======================
Creating a Logger
-----------------
Use the new ``getLogger`` function to obtain a logger. (Note that the old ``get_logger`` is now deprecated.)
.. code-block:: python
from risclog.logging import getLogger
logger = getLogger(__name__)
logger.set_level("DEBUG") # You can pass a string (e.g. "DEBUG") or a logging constant (logging.DEBUG)
You can also add a file handler to write warnings and above to a file:
.. code-block:: python
file_logger = logger.add_file_handler('test.log', level=logging.WARNING)
Logging Messages
----------------
Log messages synchronously:
.. code-block:: python
logger.debug("This is a debug message")
logger.info("This is an info message")
logger.warning("This is a warning message")
logger.error("This is an error message")
logger.critical("This is a critical message")
Or asynchronously (e.g. within async functions):
.. code-block:: python
await logger.debug("Async debug message")
await logger.info("Async info message")
# etc.
Automatic Function Logging with Decorators
--------------------------------------------
The ``log_decorator`` automatically logs function calls (including arguments, execution time, results,
and any exceptions). It works with both synchronous and asynchronous functions.
.. code-block:: python
from risclog.logging import getLogger, log_decorator
import asyncio
logger = getLogger(__name__)
logger.set_level("DEBUG")
@log_decorator
def sync_function(a, b):
result = a + b
return result
@log_decorator
async def async_function(a, b):
await asyncio.sleep(1)
result = a + b
return result
Using the Decorator in Classes
------------------------------
You can use the decorator on class methods as well. For example:
.. code-block:: python
from risclog.logging import getLogger, log_decorator
import asyncio
class AwesomeClass:
def __init__(self):
self.logger = getLogger("AwesomeLogger")
@log_decorator
def class_sync_add(self, a: int, b: int):
self.logger.warn("Debugging class_sync_add", a=a, b=b)
self.logger.info("Information in class_sync_add", a=a, b=b)
self.logger.info("class_sync_add called", a=a, b=b)
return a + b
@log_decorator
async def class_async_add(self, a: int, b: int, c: dict):
await self.logger.info("class_async_add called", a=a, b=b)
await self.logger.info("Dependency class name:", c=c['dependency'].__class__.__name__)
await asyncio.sleep(1)
result = a + b
await self.logger.info("class_async_add result", result=result)
return result
class DependencyClass:
pass
Email Notification on Exceptions
---------------------------------
To enable email notifications when an exception occurs, pass ``send_email=True`` to the decorator.
**Remember:** The following environment variables must be set:
- ``logging_email_smtp_user``
- ``logging_email_smtp_password``
- ``logging_email_to``
- ``logging_email_smtp_server``
.. code-block:: python
@log_decorator(send_email=True)
def function_with_exception():
# Your code that might raise an exception
...
Rich Traceback Integration
---------------------------
The package now automatically installs a beautiful traceback handler via Rich:
.. code-block:: python
from rich import traceback
traceback.install()
This provides enhanced, colored, and more informative tracebacks when errors occur.
Full Example
============
Below is a complete example demonstrating the usage of the new logger, decorators, and asynchronous logging.
.. code-block:: python
import asyncio
import logging
from risclog.logging import getLogger, log_decorator
# Configure logger
logger = getLogger(__name__)
logger.set_level(logging.DEBUG)
logger.add_file_handler('test.log', level=logging.WARNING)
@log_decorator
def sync_function(a, b):
result = a + b
return result
@log_decorator
async def async_function(a, b):
await asyncio.sleep(1)
result = a + b
return result
class AwesomeClass:
def __init__(self):
self.logger = getLogger("AwesomeLogger")
@log_decorator
def class_sync_add(self, a: int, b: int):
self.logger.warn("Debugging class_sync_add", a=a, b=b)
self.logger.info("Information in class_sync_add", a=a, b=b)
self.logger.info("class_sync_add called", a=a, b=b)
return a + b
@log_decorator
async def class_async_add(self, a: int, b: int, c: dict):
await self.logger.info("class_async_add called", a=a, b=b)
await self.logger.info("Dependency class name:", c=c['dependency'].__class__.__name__)
await asyncio.sleep(1)
result = a + b
await self.logger.info("class_async_add result", result=result)
return result
class DependencyClass:
pass
@log_decorator
def sample_function(*args, **kwargs):
logger.debug("Debugging sample_function", args=args, kwargs=kwargs)
logger.info("Called with args", args=args)
logger.info("Called with kwargs", kwargs=kwargs)
result = {'sum_args': sum(args) if args else 0, **kwargs}
logger.info("Result", result=result)
if result['sum_args'] > 5:
logger.warning("Sum of arguments is greater than 5", sum=result['sum_args'])
try:
1 / 0
except ZeroDivisionError:
logger.error("Division by zero error occurred during calculation. Check the input values",
exc_info=True)
return result
@log_decorator
def sample_critical_function(*args, **kwargs):
logger.critical("Critical issue in sample_critical_function", args=args, kwargs=kwargs)
raise RuntimeError("Simulated critical problem")
async def main():
dc = DependencyClass()
ac = AwesomeClass()
sync_result = sync_function(3, 5)
await async_function(4, 6)
ac.class_sync_add(6, 7)
await ac.class_async_add(8, 9, {'dependency': dc})
sample_function(1, 2, 3, name='Alice', age=30)
try:
sample_critical_function(10, 20)
except RuntimeError:
pass
if __name__ == '__main__':
logger.info("Starting main function")
sync_result = sync_function(3, 5)
asyncio.run(main())
# Trigger an exception to test rich traceback formatting:
raise ValueError("Test exception")
Example Output
==============
Below is an example output generated by running the new logger code:
.. code-block:: bash
2025-02-07 13:23:18 [info ] [4311754480 Decorator start: sync_function] [__main__] _function=sync_function _script=all_in_one.py args=('a:int=3', 'b:int=5') kwargs={}
2025-02-07 13:23:18 [info ] [4311754480 Decorator success: sync_function] [__main__] _function=sync_function _script=all_in_one.py duration=0.00044sec result=8
2025-02-07 13:23:19 [info ] [4311754480 Decorator start: sync_function] [__main__] _function=sync_function _script=all_in_one.py args=('a:int=3', 'b:int=5') kwargs={}
2025-02-07 13:23:19 [info ] [4311754480 Decorator success: sync_function] [__main__] _function=sync_function _script=all_in_one.py duration=0.01749sec result=8
2025-02-07 13:23:19 [info ] [4311755376 Decorator start: async_function] [__main__] _function=async_function _script=all_in_one.py args=('a:int=4', 'b:int=6') kwargs={}
2025-02-07 13:23:20 [info ] [4311755376 Decorator success: async_function] [__main__] _function=async_function _script=all_in_one.py duration=1.00177sec result=10
2025-02-07 13:23:20 [info ] [4312228144 Decorator start: class_sync_add] [__main__] _function=class_sync_add _script=all_in_one.py args=('self:AwesomeClass=<__main__.AwesomeClass object at 0x10310b110>', 'a:int=6', 'b:int=7') kwargs={}
2025-02-07 13:23:20 [warning ] [4312228144 Debugging class_sync_add] [AwesomeLogger] a=6 b=7
2025-02-07 13:23:20 [info ] [4312228144 Information in class_sync_add] [AwesomeLogger] a=6 b=7
2025-02-07 13:23:20 [info ] [4312228144 class_sync_add called] [AwesomeLogger] a=6 b=7
2025-02-07 13:23:20 [info ] [4312228144 Decorator success: class_sync_add] [__main__] _function=class_sync_add _script=all_in_one.py duration=0.00189sec result=13
2025-02-07 13:23:20 [info ] [4312228528 Decorator start: class_async_add] [__main__] _function=class_async_add _script=all_in_one.py args=('self:AwesomeClass=<__main__.AwesomeClass object at 0x10310b110>', 'a:int=8', 'b:int=9', "c:dict={'dependency': <__main__.DependencyClass object at 0x10310af90>}") kwargs={}
2025-02-07 13:23:20 [info ] [4312228528 class_async_add called] [AwesomeLogger] a=8 b=9
2025-02-07 13:23:20 [info ] [4312228528 dependency class name:] [AwesomeLogger] c=DependencyClass
2025-02-07 13:23:21 [info ] [4312228528 class_async_add result] [AwesomeLogger] result=17
2025-02-07 13:23:21 [info ] [4312228528 Decorator success: class_async_add] [__main__] _function=class_async_add _script=all_in_one.py duration=1.00326sec result=17
2025-02-07 13:23:21 [info ] [4312229040 Decorator start: sample_function] [__main__] _function=sample_function _script=all_in_one.py args=('args:int=1', 'kwargs:int=2', 'name:str=Alice', 'age:int=30') kwargs={'name': 'Alice', 'age': 30}
2025-02-07 13:23:21 [debug ] [4312229040 Debugging sample_function] [__main__] args=(1, 2, 3) kwargs={'name': 'Alice', 'age': 30}
2025-02-07 13:23:21 [info ] [4312229040 Called with args] [__main__] args=(1, 2, 3)
2025-02-07 13:23:21 [info ] [4312229040 Called with kwargs] [__main__] kwargs={'name': 'Alice', 'age': 30}
2025-02-07 13:23:21 [info ] [4312229040 Result] [__main__] result={'sum_args': 6, 'name': 'Alice', 'age': 30}
2025-02-07 13:23:21 [warning ] [4312229040 Sum of arguments is greater than 5] [__main__] sum=6
2025-02-07 13:23:21 [error ] [4312229040 Division by zero error occurred during calculation. Check the input values] [__main__]
2025-02-07 13:23:21 [info ] [4312229040 Decorator success: sample_function] [__main__] _function=sample_function _script=all_in_one.py duration=0.00297sec result={'sum_args': 6, 'name': 'Alice', 'age': 30}
2025-02-07 13:23:21 [info ] [4312158640 Decorator start: sample_critical_function] [__main__] _function=sample_critical_function _script=all_in_one.py args=('args:int=10', 'kwargs:int=20') kwargs={}
2025-02-07 13:23:21 [critical ] [4312158640 Critical issue in sample_critical_function] [__main__] args=(10, 20) kwargs={}
2025-02-07 13:23:21 [error ] ('[4312158640 Decorator error in sample_critical_function]',) [__main__] _function=sample_critical_function _script=all_in_one.py error='Simuliertes kritisches Problem'
Running Tests
=============
To run the tests for this package, simply execute:
.. code-block:: bash
./pytest
Credits
=======
This package was created using Cookiecutter_ and the
`risclog-solution/risclog-cookiecutter-pypackage`_ project template.
.. _Cookiecutter: https://github.com/audreyr/cookiecutter
.. _`risclog-solution/risclog-cookiecutter-pypackage`: https://github.com/risclog-solution/risclog-cookiecutter-pypackage
Additional Notes
================
- The legacy functions ``get_logger`` and the method ``decorator`` are deprecated and will be removed in version 1.3.0.
- For advanced configuration (custom processors, multiple handlers, etc.), please refer to the documentation.
- The package automatically configures loggers to filter out excessive log messages from libraries like Uvicorn and asyncio.
==============================
Change log for risclog.logging
==============================
1.3.1 (2025-09-08)
==================
- Unify default log level and set it from DEBUG to WARNING.
1.3.0 (2025-02-06)
==================
- added `add_file_handler` method to add a file handler to a logger
- added `set_level` method to set the level of a logger
- Fix log decorator mixed async sync Problem
- old `decorator` function is now deprecated
- old `get_logger` function is now deprecated
1.2.1 (2024-09-20)
==================
- forward exceptions
1.2.0 (2024-09-19)
==================
- rename email environments
1.1.0 (2024-08-27)
==================
- Allow logging with multiple loggers in a single module.
1.0.2 (2024-08-06)
==================
- Fix CI status badge.
1.0.1 (2024-08-06)
==================
- Fix `classifiers` and README structure.
1.0 (2024-08-06)
================
* initial release
Raw data
{
"_id": null,
"home_page": "https://github.com/risclog-solution/risclog.logging",
"name": "risclog.logging",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "risclog.logging",
"author": "riscLOG Solution GmbH",
"author_email": "info@risclog.de",
"download_url": "https://files.pythonhosted.org/packages/5e/9b/a63f8282121aaf3bea8cd5ac7e306ebd21feafaffb7d21b178779c797a6b/risclog.logging-1.3.1.tar.gz",
"platform": null,
"description": "===================\nrisclog.logging\n===================\n\n.. image:: https://github.com/risclog-solution/risclog.logging/actions/workflows/test.yml/badge.svg\n :target: https://github.com/risclog-solution/risclog.logging/actions/workflows/test.yml\n :alt: CI Status\n\n.. image:: https://img.shields.io/pypi/v/risclog.logging.svg\n :target: https://pypi.python.org/pypi/risclog.logging\n\nThe **risclog.logging** package provides a comprehensive solution for structured logging in Python\napplications. It combines Python\u2019s built-in logging module with [structlog](https://www.structlog.org/)\nto generate detailed and formatted log entries. In this new release, the API has been updated to use:\n\n- **`getLogger`** \u2013 the new factory function for creating logger instances (the legacy ``get_logger`` is deprecated).\n- **`log_decorator`** \u2013 a decorator for automatic logging of function calls, including arguments, return values,\n durations, and exceptions.\n- **Rich Traceback Integration** \u2013 by default, the package installs a beautiful exception renderer via:\n\n .. code-block:: python\n\n from rich import traceback\n traceback.install()\n\nFeatures\n========\n\n- **Structured logging:** Combines standard logging with structlog for rich, contextual logs.\n- **Synchronous and asynchronous logging:** Use the same API in both sync and async environments.\n- **Automatic function logging:** Use the ``log_decorator`` to automatically log function calls and errors.\n- **Email notifications:** Optionally send email notifications on exceptions (requires setting specific environment variables).\n- **Rich traceback:** Enhanced exception display is provided by default via Rich.\n- **Flexible configuration:** Programmatically set log levels and add handlers (e.g. file handlers).\n\nInstallation\n============\n\nInstall via pip:\n\n.. code-block:: bash\n\n pip install risclog.logging\n\nConfiguration and Usage\n=======================\n\nCreating a Logger\n-----------------\n\nUse the new ``getLogger`` function to obtain a logger. (Note that the old ``get_logger`` is now deprecated.)\n\n.. code-block:: python\n\n from risclog.logging import getLogger\n\n logger = getLogger(__name__)\n logger.set_level(\"DEBUG\") # You can pass a string (e.g. \"DEBUG\") or a logging constant (logging.DEBUG)\n\nYou can also add a file handler to write warnings and above to a file:\n\n.. code-block:: python\n\n file_logger = logger.add_file_handler('test.log', level=logging.WARNING)\n\nLogging Messages\n----------------\n\nLog messages synchronously:\n\n.. code-block:: python\n\n logger.debug(\"This is a debug message\")\n logger.info(\"This is an info message\")\n logger.warning(\"This is a warning message\")\n logger.error(\"This is an error message\")\n logger.critical(\"This is a critical message\")\n\nOr asynchronously (e.g. within async functions):\n\n.. code-block:: python\n\n await logger.debug(\"Async debug message\")\n await logger.info(\"Async info message\")\n # etc.\n\nAutomatic Function Logging with Decorators\n--------------------------------------------\n\nThe ``log_decorator`` automatically logs function calls (including arguments, execution time, results,\nand any exceptions). It works with both synchronous and asynchronous functions.\n\n.. code-block:: python\n\n from risclog.logging import getLogger, log_decorator\n import asyncio\n\n logger = getLogger(__name__)\n logger.set_level(\"DEBUG\")\n\n @log_decorator\n def sync_function(a, b):\n result = a + b\n return result\n\n @log_decorator\n async def async_function(a, b):\n await asyncio.sleep(1)\n result = a + b\n return result\n\nUsing the Decorator in Classes\n------------------------------\n\nYou can use the decorator on class methods as well. For example:\n\n.. code-block:: python\n\n from risclog.logging import getLogger, log_decorator\n import asyncio\n\n class AwesomeClass:\n def __init__(self):\n self.logger = getLogger(\"AwesomeLogger\")\n\n @log_decorator\n def class_sync_add(self, a: int, b: int):\n self.logger.warn(\"Debugging class_sync_add\", a=a, b=b)\n self.logger.info(\"Information in class_sync_add\", a=a, b=b)\n self.logger.info(\"class_sync_add called\", a=a, b=b)\n return a + b\n\n @log_decorator\n async def class_async_add(self, a: int, b: int, c: dict):\n await self.logger.info(\"class_async_add called\", a=a, b=b)\n await self.logger.info(\"Dependency class name:\", c=c['dependency'].__class__.__name__)\n await asyncio.sleep(1)\n result = a + b\n await self.logger.info(\"class_async_add result\", result=result)\n return result\n\n class DependencyClass:\n pass\n\nEmail Notification on Exceptions\n---------------------------------\n\nTo enable email notifications when an exception occurs, pass ``send_email=True`` to the decorator.\n**Remember:** The following environment variables must be set:\n\n- ``logging_email_smtp_user``\n- ``logging_email_smtp_password``\n- ``logging_email_to``\n- ``logging_email_smtp_server``\n\n.. code-block:: python\n\n @log_decorator(send_email=True)\n def function_with_exception():\n # Your code that might raise an exception\n ...\n\nRich Traceback Integration\n---------------------------\n\nThe package now automatically installs a beautiful traceback handler via Rich:\n\n.. code-block:: python\n\n from rich import traceback\n traceback.install()\n\nThis provides enhanced, colored, and more informative tracebacks when errors occur.\n\nFull Example\n============\n\nBelow is a complete example demonstrating the usage of the new logger, decorators, and asynchronous logging.\n\n.. code-block:: python\n\n import asyncio\n import logging\n from risclog.logging import getLogger, log_decorator\n\n # Configure logger\n logger = getLogger(__name__)\n logger.set_level(logging.DEBUG)\n logger.add_file_handler('test.log', level=logging.WARNING)\n\n @log_decorator\n def sync_function(a, b):\n result = a + b\n return result\n\n @log_decorator\n async def async_function(a, b):\n await asyncio.sleep(1)\n result = a + b\n return result\n\n class AwesomeClass:\n def __init__(self):\n self.logger = getLogger(\"AwesomeLogger\")\n\n @log_decorator\n def class_sync_add(self, a: int, b: int):\n self.logger.warn(\"Debugging class_sync_add\", a=a, b=b)\n self.logger.info(\"Information in class_sync_add\", a=a, b=b)\n self.logger.info(\"class_sync_add called\", a=a, b=b)\n return a + b\n\n @log_decorator\n async def class_async_add(self, a: int, b: int, c: dict):\n await self.logger.info(\"class_async_add called\", a=a, b=b)\n await self.logger.info(\"Dependency class name:\", c=c['dependency'].__class__.__name__)\n await asyncio.sleep(1)\n result = a + b\n await self.logger.info(\"class_async_add result\", result=result)\n return result\n\n class DependencyClass:\n pass\n\n @log_decorator\n def sample_function(*args, **kwargs):\n logger.debug(\"Debugging sample_function\", args=args, kwargs=kwargs)\n logger.info(\"Called with args\", args=args)\n logger.info(\"Called with kwargs\", kwargs=kwargs)\n\n result = {'sum_args': sum(args) if args else 0, **kwargs}\n logger.info(\"Result\", result=result)\n if result['sum_args'] > 5:\n logger.warning(\"Sum of arguments is greater than 5\", sum=result['sum_args'])\n\n try:\n 1 / 0\n except ZeroDivisionError:\n logger.error(\"Division by zero error occurred during calculation. Check the input values\",\n exc_info=True)\n return result\n\n @log_decorator\n def sample_critical_function(*args, **kwargs):\n logger.critical(\"Critical issue in sample_critical_function\", args=args, kwargs=kwargs)\n raise RuntimeError(\"Simulated critical problem\")\n\n async def main():\n dc = DependencyClass()\n ac = AwesomeClass()\n sync_result = sync_function(3, 5)\n await async_function(4, 6)\n ac.class_sync_add(6, 7)\n await ac.class_async_add(8, 9, {'dependency': dc})\n sample_function(1, 2, 3, name='Alice', age=30)\n\n try:\n sample_critical_function(10, 20)\n except RuntimeError:\n pass\n\n if __name__ == '__main__':\n logger.info(\"Starting main function\")\n sync_result = sync_function(3, 5)\n asyncio.run(main())\n\n # Trigger an exception to test rich traceback formatting:\n raise ValueError(\"Test exception\")\n\nExample Output\n==============\n\nBelow is an example output generated by running the new logger code:\n\n.. code-block:: bash\n\n 2025-02-07 13:23:18 [info ] [4311754480 Decorator start: sync_function] [__main__] _function=sync_function _script=all_in_one.py args=('a:int=3', 'b:int=5') kwargs={}\n 2025-02-07 13:23:18 [info ] [4311754480 Decorator success: sync_function] [__main__] _function=sync_function _script=all_in_one.py duration=0.00044sec result=8\n 2025-02-07 13:23:19 [info ] [4311754480 Decorator start: sync_function] [__main__] _function=sync_function _script=all_in_one.py args=('a:int=3', 'b:int=5') kwargs={}\n 2025-02-07 13:23:19 [info ] [4311754480 Decorator success: sync_function] [__main__] _function=sync_function _script=all_in_one.py duration=0.01749sec result=8\n 2025-02-07 13:23:19 [info ] [4311755376 Decorator start: async_function] [__main__] _function=async_function _script=all_in_one.py args=('a:int=4', 'b:int=6') kwargs={}\n 2025-02-07 13:23:20 [info ] [4311755376 Decorator success: async_function] [__main__] _function=async_function _script=all_in_one.py duration=1.00177sec result=10\n 2025-02-07 13:23:20 [info ] [4312228144 Decorator start: class_sync_add] [__main__] _function=class_sync_add _script=all_in_one.py args=('self:AwesomeClass=<__main__.AwesomeClass object at 0x10310b110>', 'a:int=6', 'b:int=7') kwargs={}\n 2025-02-07 13:23:20 [warning ] [4312228144 Debugging class_sync_add] [AwesomeLogger] a=6 b=7\n 2025-02-07 13:23:20 [info ] [4312228144 Information in class_sync_add] [AwesomeLogger] a=6 b=7\n 2025-02-07 13:23:20 [info ] [4312228144 class_sync_add called] [AwesomeLogger] a=6 b=7\n 2025-02-07 13:23:20 [info ] [4312228144 Decorator success: class_sync_add] [__main__] _function=class_sync_add _script=all_in_one.py duration=0.00189sec result=13\n 2025-02-07 13:23:20 [info ] [4312228528 Decorator start: class_async_add] [__main__] _function=class_async_add _script=all_in_one.py args=('self:AwesomeClass=<__main__.AwesomeClass object at 0x10310b110>', 'a:int=8', 'b:int=9', \"c:dict={'dependency': <__main__.DependencyClass object at 0x10310af90>}\") kwargs={}\n 2025-02-07 13:23:20 [info ] [4312228528 class_async_add called] [AwesomeLogger] a=8 b=9\n 2025-02-07 13:23:20 [info ] [4312228528 dependency class name:] [AwesomeLogger] c=DependencyClass\n 2025-02-07 13:23:21 [info ] [4312228528 class_async_add result] [AwesomeLogger] result=17\n 2025-02-07 13:23:21 [info ] [4312228528 Decorator success: class_async_add] [__main__] _function=class_async_add _script=all_in_one.py duration=1.00326sec result=17\n 2025-02-07 13:23:21 [info ] [4312229040 Decorator start: sample_function] [__main__] _function=sample_function _script=all_in_one.py args=('args:int=1', 'kwargs:int=2', 'name:str=Alice', 'age:int=30') kwargs={'name': 'Alice', 'age': 30}\n 2025-02-07 13:23:21 [debug ] [4312229040 Debugging sample_function] [__main__] args=(1, 2, 3) kwargs={'name': 'Alice', 'age': 30}\n 2025-02-07 13:23:21 [info ] [4312229040 Called with args] [__main__] args=(1, 2, 3)\n 2025-02-07 13:23:21 [info ] [4312229040 Called with kwargs] [__main__] kwargs={'name': 'Alice', 'age': 30}\n 2025-02-07 13:23:21 [info ] [4312229040 Result] [__main__] result={'sum_args': 6, 'name': 'Alice', 'age': 30}\n 2025-02-07 13:23:21 [warning ] [4312229040 Sum of arguments is greater than 5] [__main__] sum=6\n 2025-02-07 13:23:21 [error ] [4312229040 Division by zero error occurred during calculation. Check the input values] [__main__]\n 2025-02-07 13:23:21 [info ] [4312229040 Decorator success: sample_function] [__main__] _function=sample_function _script=all_in_one.py duration=0.00297sec result={'sum_args': 6, 'name': 'Alice', 'age': 30}\n 2025-02-07 13:23:21 [info ] [4312158640 Decorator start: sample_critical_function] [__main__] _function=sample_critical_function _script=all_in_one.py args=('args:int=10', 'kwargs:int=20') kwargs={}\n 2025-02-07 13:23:21 [critical ] [4312158640 Critical issue in sample_critical_function] [__main__] args=(10, 20) kwargs={}\n 2025-02-07 13:23:21 [error ] ('[4312158640 Decorator error in sample_critical_function]',) [__main__] _function=sample_critical_function _script=all_in_one.py error='Simuliertes kritisches Problem'\n\nRunning Tests\n=============\n\nTo run the tests for this package, simply execute:\n\n.. code-block:: bash\n\n ./pytest\n\nCredits\n=======\n\nThis package was created using Cookiecutter_ and the\n`risclog-solution/risclog-cookiecutter-pypackage`_ project template.\n\n.. _Cookiecutter: https://github.com/audreyr/cookiecutter\n.. _`risclog-solution/risclog-cookiecutter-pypackage`: https://github.com/risclog-solution/risclog-cookiecutter-pypackage\n\nAdditional Notes\n================\n\n- The legacy functions ``get_logger`` and the method ``decorator`` are deprecated and will be removed in version 1.3.0.\n- For advanced configuration (custom processors, multiple handlers, etc.), please refer to the documentation.\n- The package automatically configures loggers to filter out excessive log messages from libraries like Uvicorn and asyncio.\n\n\n==============================\nChange log for risclog.logging\n==============================\n\n\n1.3.1 (2025-09-08)\n==================\n\n- Unify default log level and set it from DEBUG to WARNING.\n\n\n1.3.0 (2025-02-06)\n==================\n\n- added `add_file_handler` method to add a file handler to a logger\n\n- added `set_level` method to set the level of a logger\n\n- Fix log decorator mixed async sync Problem\n\n- old `decorator` function is now deprecated\n\n- old `get_logger` function is now deprecated\n\n\n1.2.1 (2024-09-20)\n==================\n\n- forward exceptions\n\n\n1.2.0 (2024-09-19)\n==================\n\n- rename email environments\n\n\n1.1.0 (2024-08-27)\n==================\n\n- Allow logging with multiple loggers in a single module.\n\n\n1.0.2 (2024-08-06)\n==================\n\n- Fix CI status badge.\n\n\n1.0.1 (2024-08-06)\n==================\n\n- Fix `classifiers` and README structure.\n\n\n1.0 (2024-08-06)\n================\n\n* initial release\n",
"bugtrack_url": null,
"license": "MIT license",
"summary": "A logger based on structlog",
"version": "1.3.1",
"project_urls": {
"Homepage": "https://github.com/risclog-solution/risclog.logging"
},
"split_keywords": [
"risclog.logging"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "07f220e874bc3e525286d804ccf9274ec456b1a526e86234eab940e567a37180",
"md5": "a5f3a9bd2eb2089efed708f98aea91b4",
"sha256": "00cbca6bd76d145ecc3a7356da030d95125c5e71fd8453b9cb5e5ca9bd2e21e6"
},
"downloads": -1,
"filename": "risclog.logging-1.3.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "a5f3a9bd2eb2089efed708f98aea91b4",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 16214,
"upload_time": "2025-09-08T07:17:27",
"upload_time_iso_8601": "2025-09-08T07:17:27.696099Z",
"url": "https://files.pythonhosted.org/packages/07/f2/20e874bc3e525286d804ccf9274ec456b1a526e86234eab940e567a37180/risclog.logging-1.3.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "5e9ba63f8282121aaf3bea8cd5ac7e306ebd21feafaffb7d21b178779c797a6b",
"md5": "8feb0812a8117d58d010bff71123fdf8",
"sha256": "e09c0f831d4ef30251a5d38c47eb38fce17b4962e93bba7f073e4806d2e75be0"
},
"downloads": -1,
"filename": "risclog.logging-1.3.1.tar.gz",
"has_sig": false,
"md5_digest": "8feb0812a8117d58d010bff71123fdf8",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 24783,
"upload_time": "2025-09-08T07:17:29",
"upload_time_iso_8601": "2025-09-08T07:17:29.285462Z",
"url": "https://files.pythonhosted.org/packages/5e/9b/a63f8282121aaf3bea8cd5ac7e306ebd21feafaffb7d21b178779c797a6b/risclog.logging-1.3.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-08 07:17:29",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "risclog-solution",
"github_project": "risclog.logging",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [],
"lcname": "risclog.logging"
}