{ "info": { "author": "RobertoPrevato", "author_email": "roberto.prevato@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3" ], "description": "[![Build status](https://robertoprevato.visualstudio.com/rolog/_apis/build/status/rolog-CI)](https://robertoprevato.visualstudio.com/rolog/_build/latest?definitionId=12) [![pypi](https://robertoprevato.vsrm.visualstudio.com/_apis/public/Release/badge/82014349-4c33-499c-b834-a13d016341b9/1/2)](https://pypi.org/project/rolog/) [![Test coverage](https://img.shields.io/azure-devops/coverage/robertoprevato/rolog/12.svg)](https://robertoprevato.visualstudio.com/rolog/_build?definitionId=12)\n\n# Async friendly logging classes for Python 3\n\n**Features:**\n* logging classes using `async/await` for logs\n* handling of six logging levels, like in built-in logging module\n* built-in support for flushing of log records (e.g. making a web request, or writing to a database, every __n__ records)\n* flushing supports max retries, configurable delays, number of attempts, and fallback target in case of failure\n* support for several targets per logger\n* can be used to asynchronously log to different destinations (for example, web api integration, DBMS, etc.)\n* logged records support any kind of desired arguments and data structures\n* completely abstracted from __destination__ of log entries\n* can be used with built-in `logging` module, for sync logging and to [use built-in logging classes](https://docs.python.org/3/library/logging.handlers.html#module-logging.handlers)\n* integrated with [rodi dependency injection library](https://pypi.org/project/rodi/), to support injection of loggers by activated class name\n\n## Installation\n\n```bash\npip install rolog\n```\n\n## Classes and log levels\n\n![Classes](https://raw.githubusercontent.com/RobertoPrevato/rolog/master/documentation/classes.png \"Classes\")\n\n| Class | Description |\n| ---------------------- | -------------------------------------------------------------------------------------------------------- |\n| **LogLevel** | Int enum: _NONE, DEBUG, INFORMATION, WARNING, ERROR, CRITICAL_ |\n| **LogTarget** | base for classes that are able to send log records to a certain destination |\n| **Logger** | class responsible for creating log records and sending them to appropriate targets, by level |\n| **LoggerFactory** | configuration class, responsible for holding configuration of targets and providing instances of loggers |\n| **LogRecord** | log record created by loggers, sent to configured targets by a logger |\n| **ExceptionLogRecord** | log record created by loggers, including exception information |\n| **FlushLogTarget** | abstract class, derived of `LogTarget`, handling records in groups, storing them in memory |\n\n### Basic use\nAs with the built-in `logging` module, `Logger` class is not meant to be instantiated directly, but rather obtained using a configured `LoggerFactory`.\n\nExample:\n\n```python\nimport asyncio\nfrom rolog import LoggerFactory, Logger, LogTarget\n\n\nclass PrintTarget(LogTarget):\n\n async def log(self, record):\n await asyncio.sleep(.1)\n print(record.message, record.args, record.data)\n\n\nfactory = LoggerFactory()\n\nfactory.add_target(PrintTarget())\n\nlogger = factory.get_logger(__name__)\n\nloop = asyncio.get_event_loop()\n\nasync def example():\n\n await logger.info('Lorem ipsum')\n\n # log methods support any argument and keyword argument:\n # these are stored in the instances of LogRecord, it is responsibility of LogTarget(s)\n # to handle these extra parameters as desired\n await logger.info('Hello, World!', 1, 2, 3, cool=True)\n\nloop.run_until_complete(example())\n```\n\n## Flushing targets\n`rolog` has built-in support for log targets that flush messages in groups, this is necessary to optimize for example\nreducing the number of web requests when sending log records to a web api, or enabling bulk-insert inside a database.\nBelow is an example of flush target class that sends log records to some web api, in groups of `500`:\n\n```python\nfrom typing import List\nfrom rolog import FlushLogTarget, LogRecord\n\n\nclass SomeLogApiFlushLogTarget(FlushLogTarget):\n\n def __init__(self, http_client):\n super().__init__()\n self.http_client = http_client\n\n async def log_records(self, records: List[LogRecord]):\n # NB: implement here your own logic to make web requests to send log records\n # to a web api, such as Azure Application Insights \n # (see for example https://pypi.org/project/asynapplicationinsights/)\n pass\n```\n\nFlush targets handle retries with configurable and progressive delays, when logging a group of records fails.\nBy default, in case of failure a flush target tries to log records __3 times__, using a progressive delay of __0.6 seconds * attempt number__,\nfinally falling back to a configurable fallback target if logging always failed. Warning messages are issued, using built-in\n[`Warnings`](https://docs.python.org/3.1/library/warnings.html) module to notify of these failures.\n\nThese parameters are configurable using constructor parameters `fallback_target`, `max_size`, `retry_delay`, `progressive_delay`.\n\n```python\nclass FlushLogTarget(LogTarget, ABC):\n \"\"\"Base class for flushing log targets: targets that send the log records\n (created by loggers) to the appropriate destination in groups.\"\"\"\n\n def __init__(self,\n queue: Optional[Queue]=None,\n max_length: int=500,\n fallback_target: Optional[LogTarget]=None,\n max_retries: int=3,\n retry_delay: float=0.6,\n progressive_delay: bool=True):\n```\n\n### Flushing when application stops\nSince flushing targets hold log records in memory before flushing them, it's necessary to flush when an application stops.\nAssuming that a single `LoggerFactory` is configured in the configuration root of an application, this \ncan be done conveniently, by calling the `dispose` method of the logger factory.\n\n```python\n# on application shutdown:\nawait logger_factory.dispose()\n```\n\n## Dependency injection\n`rolog` is integrated with [rodi dependency injection library](https://pypi.org/project/rodi/), to support injection of loggers per activated class name.\nWhen a class that expects a parameter of `rolog.Logger` type is activated, it receives a logger for the category of the class name itself. \nFor more information, please refer to the [dedicated page in project wiki](https://github.com/RobertoPrevato/rolog/wiki/Dependency-injection-with-rodi).\n\n## Documentation\nPlease refer to documentation in the project wiki: [https://github.com/RobertoPrevato/rolog/wiki](https://github.com/RobertoPrevato/rolog/wiki).\n\n## Develop and run tests locally\n```bash\npip install -r dev_requirements.txt\n\n# run tests using automatic discovery:\npytest\n```\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/RobertoPrevato/rolog", "keywords": "logging async await", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "rolog", "package_url": "https://pypi.org/project/rolog/", "platform": "", "project_url": "https://pypi.org/project/rolog/", "project_urls": { "Homepage": "https://github.com/RobertoPrevato/rolog" }, "release_url": "https://pypi.org/project/rolog/1.0.2/", "requires_dist": null, "requires_python": "", "summary": "Async friendly logging classes for Python 3", "version": "1.0.2" }, "last_serial": 5304120, "releases": { "1.0.0": [ { "comment_text": "", "digests": { "md5": "eb9cdd7ad707dcf2b26729bfa9a0b224", "sha256": "a5782c89351df2e45bc065532190940aa5422078ae4dc111678b2366cc5f47b2" }, "downloads": -1, "filename": "rolog-1.0.0-py3-none-any.whl", "has_sig": false, "md5_digest": "eb9cdd7ad707dcf2b26729bfa9a0b224", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 7865, "upload_time": "2018-10-20T22:01:53", "url": "https://files.pythonhosted.org/packages/7d/66/169540886dda839f30aec68ad789a0921a3bbd83f6fd26fde232a55c6e07/rolog-1.0.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2392774635e373867a7a316b13e5935f", "sha256": "f10e0722b9eafbe507449aea6d83ac05ba1a1df422f30047c77eed5300b4e9b3" }, "downloads": -1, "filename": "rolog-1.0.0.tar.gz", "has_sig": false, "md5_digest": "2392774635e373867a7a316b13e5935f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7228, "upload_time": "2018-10-20T22:01:54", "url": "https://files.pythonhosted.org/packages/2c/ed/6c6465dee80e47b1ebd7dee9061b9ba07041984f06baf83f3873071d074a/rolog-1.0.0.tar.gz" } ], "1.0.1": [ { "comment_text": "", "digests": { "md5": "5784f19cc467cb75a0a15cbfe6e71352", "sha256": "bf5c32b1cadc5d05250c5cb989b6ac55ee122edf055dc28213c47abe411bc571" }, "downloads": -1, "filename": "rolog-1.0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "5784f19cc467cb75a0a15cbfe6e71352", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8066, "upload_time": "2019-05-18T10:39:31", "url": "https://files.pythonhosted.org/packages/6f/1d/04d5b02959f56594eda5c6c07516c0e9c3aa062a9258ab90230a4fe02a59/rolog-1.0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "cef4b5d9bf3be639fde2b025f27263e9", "sha256": "eaa87c15d069e048dfffec067a83767ec21c6893a5ec14215c8676701e20fbff" }, "downloads": -1, "filename": "rolog-1.0.1.tar.gz", "has_sig": false, "md5_digest": "cef4b5d9bf3be639fde2b025f27263e9", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8115, "upload_time": "2019-05-18T10:39:32", "url": "https://files.pythonhosted.org/packages/33/84/612a3c0aaad0220c71970ce8b1295b2b4632604e80a0f7769f44e8d06a43/rolog-1.0.1.tar.gz" } ], "1.0.2": [ { "comment_text": "", "digests": { "md5": "4f7457e3bab63edf405aa254caa36080", "sha256": "2aea11141cd89e9405b704df6a5e834a51bee4d1029fb6824173a25db3f505fc" }, "downloads": -1, "filename": "rolog-1.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "4f7457e3bab63edf405aa254caa36080", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8061, "upload_time": "2019-05-22T19:03:16", "url": "https://files.pythonhosted.org/packages/64/86/37f365c603b4adea6789b4c030e809625408a134ee5f994cb9838ef26fc8/rolog-1.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5d79651581107f3ea18acad70c573953", "sha256": "9a20de4a5f14e43a2a65dbe9fde7a3a3c4e82d03eed2b18eac4ad594aebe4cc1" }, "downloads": -1, "filename": "rolog-1.0.2.tar.gz", "has_sig": false, "md5_digest": "5d79651581107f3ea18acad70c573953", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7463, "upload_time": "2019-05-22T19:03:24", "url": "https://files.pythonhosted.org/packages/59/b8/f1552b868fb922a2ddfb039c0352f7ea5330c7784543d5e210617f815219/rolog-1.0.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "4f7457e3bab63edf405aa254caa36080", "sha256": "2aea11141cd89e9405b704df6a5e834a51bee4d1029fb6824173a25db3f505fc" }, "downloads": -1, "filename": "rolog-1.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "4f7457e3bab63edf405aa254caa36080", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 8061, "upload_time": "2019-05-22T19:03:16", "url": "https://files.pythonhosted.org/packages/64/86/37f365c603b4adea6789b4c030e809625408a134ee5f994cb9838ef26fc8/rolog-1.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5d79651581107f3ea18acad70c573953", "sha256": "9a20de4a5f14e43a2a65dbe9fde7a3a3c4e82d03eed2b18eac4ad594aebe4cc1" }, "downloads": -1, "filename": "rolog-1.0.2.tar.gz", "has_sig": false, "md5_digest": "5d79651581107f3ea18acad70c573953", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 7463, "upload_time": "2019-05-22T19:03:24", "url": "https://files.pythonhosted.org/packages/59/b8/f1552b868fb922a2ddfb039c0352f7ea5330c7784543d5e210617f815219/rolog-1.0.2.tar.gz" } ] }