{ "info": { "author": "Florimond Manca", "author_email": "florimond.manca@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3 :: Only" ], "description": "# watchl\n\n[![build status](https://travis-ci.com/florimondmanca/watchl.svg?token=2WTbCxyyjrjzR5LpHFc3&branch=master)](https://travis-ci.com/florimondmanca/watchl)\n[![codecov](https://codecov.io/gh/florimondmanca/watchl/branch/master/graph/badge.svg?token=O5ZSL569hc)](https://codecov.io/gh/florimondmanca/watchl)\n[![code style](https://img.shields.io/badge/code_style-black-black)](https://github.com/psf/black)\n![license](https://img.shields.io/badge/license-MIT-green)\n\nLightweight HTTP log monitoring and alerting console tool written in Python.\n\n**Note**: only [W3C-formatted logs](https://www.w3.org/Daemon/User/Config/Logging.html) are supported for now. See [here](https://raw.githubusercontent.com/elastic/examples/master/Common%20Data%20Formats/apache_logs/apache_logs) for an example W3C-formatted log file.\n\n## Features\n\n- Live tail of log files.\n- Stats reporting in the console: top hit sections, traffic, throughput, etc.\n- Live alerting and recovery detection with customizable thresholds and delays.\n- Friendly command line interface.\n- Detailed and machine-readable JSON-formatted output.\n- Asynchronous architecture with low resources footprint.\n- Optional Docker-based execution.\n\nExample command:\n\n```\n$ watchl -f access.log --report-every=2 --alert-tick=2 --traffic-up=1 --traffic-down=1\n```\n\nOutput (JSON prettification by piping into [jq](https://stedolan.github.io/jq/)):\n\n```json\n{\n \"levelname\": \"INFO\",\n \"message\": \"process started\",\n \"timestamp\": \"2019-07-30T21:02:30.652107\",\n \"pid\": 2417\n}\n{\n \"levelname\": \"INFO\",\n \"message\": \"watching logs\",\n \"timestamp\": \"2019-07-30T21:02:30.653034\",\n \"path\": \"access.log\"\n}\n{\n \"levelname\": \"INFO\",\n \"message\": \"activity in the past 2.0 seconds\",\n \"timestamp\": \"2019-07-30T21:02:32.708673\",\n \"sections.count\": {\n \"unit\": \"hits\",\n \"value\": [\n {\n \"key\": \"/presentations\",\n \"count\": 68\n },\n {\n \"key\": \"/images\",\n \"count\": 13\n },\n {\n \"key\": \"/blog\",\n \"count\": 9\n }\n ]\n },\n \"requests.total\": {\n \"unit\": \"req\",\n \"value\": 135\n },\n \"requests.average\": {\n \"unit\": \"req/s\",\n \"value\": 67.5\n },\n \"transfer.average\": {\n \"unit\": \"bytes/s\",\n \"value\": 3064559\n },\n \"transfer.mean\": {\n \"unit\": \"bytes/req\",\n \"value\": 45400.874074074076\n }\n}\n{\n \"levelname\": \"WARNING\",\n \"message\": \"alert status changed\",\n \"timestamp\": \"2019-07-30T21:02:34.773988\",\n \"status\": \"active\",\n \"previous_status\": \"activating\",\n \"value\": 89.5,\n \"reason\": \"stayed above threshold for longer than up delay\",\n \"metric\": \"requests.average\",\n \"threshold\": 10,\n \"up\": \"0:00:01\",\n \"down\": \"0:00:01\"\n}\n...\n```\n\n## Installation\n\n- If you have Python 3.6+ installed, you can install `watchl` from PyPI:\n\n```bash\npip install watchl\n```\n\nor locally by cloning the repository and running:\n\n```bash\npip install .\n```\n\n- If you have Docker installed, you can build the image by cloning the repository and running:\n\n```bash\ndocker build -t watchl .\n```\n\n## Usage\n\n### General notes\n\n`watchl` exposes a command line executable named `watchl`.\n\nWhen run without any other options, `watchl` will read logs from `/tmp/access.log` (this is configurable \u2014 see [CLI reference](#cli-reference) for options) and consume them as they are written to the file.\n\n> **Known limitation**: `watchl` does not handle log rotation yet. If the log file is renamed, truncated or moved, `watchl` won't be able to read new logs anymore, and will need to be restarted. See [#9](https://github.com/florimondmanca/watchl/issues/9).\n\nIf using Docker, and assuming you have a log file somewhere on your machine, you can run a `watchl` container using:\n\n```\ndocker run -it --rm -v /host/path/to/access.log:/tmp/access.log watchl \n```\n\nBy default, `watchl` works on relatively long time scales (minutes). For quicker feedback (e.g. when trying `watchl` for the first time), you can try the following options:\n\n```bash\nwatchl --report-every=5 --alert-tick=1 --traffic-up=1 --traffic-down=1\n```\n\n### CLI reference\n\n```\nUsage: watchl [OPTIONS]\n\nOptions:\n -f PATH Path to an actively written-to log file.\n [default: /tmp/access.log]\n --report-every FLOAT Number of seconds between stats reports.\n [default: 10]\n --sections-top INTEGER Number of most hit website sections to\n display in the report. [default: 3]\n --traffic-threshold FLOAT [default: 10]\n --traffic-up FLOAT Number of seconds to trigger an alert after\n traffic exceeded the threshold. [default:\n 120]\n --traffic-down FLOAT Number of seconds to stop an alert after\n traffic dropped below the threshold.\n [default: 120]\n --alert-tick FLOAT Number of seconds between evaluation of\n stats for alerting purposes. [default: 10]\n --tick FLOAT Number of seconds between system event\n checks. Note: lower values increase CPU\n usage. [default: 0.5]\n --log-level [debug|info|warning|critical|error]\n Level for internal log messages [default:\n info]\n --limit-max-log-lines INTEGER Limit the number of log lines to ingest\n before terminating the process.\n --help Show this message and exit.\n```\n\n## Contributing\n\nSee [Contributing guidelines](https://github.com/florimondmanca/watchl/blob/master/CONTRIBUTING.md).\n\n## License\n\nMIT\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/florimondmanca/watchl.git", "keywords": "", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "watchl", "package_url": "https://pypi.org/project/watchl/", "platform": "", "project_url": "https://pypi.org/project/watchl/", "project_urls": { "Homepage": "https://github.com/florimondmanca/watchl.git" }, "release_url": "https://pypi.org/project/watchl/0.2/", "requires_dist": [ "trio (<0.13,>=0.12)", "click (<8,>=7)", "python-json-logger", "pytest ; extra == 'dev'", "pytest-cov ; extra == 'dev'", "codecov ; extra == 'dev'", "black ; extra == 'dev'", "pylint ; extra == 'dev'", "rope ; extra == 'dev'", "mypy ; extra == 'dev'" ], "requires_python": ">=3.6", "summary": "Lightweight HTTP log monitoring and alerting tool", "version": "0.2" }, "last_serial": 5628077, "releases": { "0.1": [ { "comment_text": "", "digests": { "md5": "8e3fba0aeb52b372be6166a59cf2b449", "sha256": "cbd11ce7779f2407c83010bcb6667195f1070ae74de7fbe36111db38dff0b475" }, "downloads": -1, "filename": "watchl-0.1-py3-none-any.whl", "has_sig": false, "md5_digest": "8e3fba0aeb52b372be6166a59cf2b449", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 13759, "upload_time": "2019-07-30T23:18:35", "url": "https://files.pythonhosted.org/packages/64/a3/d8b7d322ecce3b81401d438bbf713f439c9e0ef7b50a8801bfe8cd9ae62b/watchl-0.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "1833e14966a165d480a5bbd1e554335f", "sha256": "78eb0d859906176adc372344f984eb2c344cff80077f66a2c2a9d81907bf1d27" }, "downloads": -1, "filename": "watchl-0.1.tar.gz", "has_sig": false, "md5_digest": "1833e14966a165d480a5bbd1e554335f", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 12387, "upload_time": "2019-07-30T23:18:38", "url": "https://files.pythonhosted.org/packages/68/44/02a117d3b383484a7c7a79a09702be272655a8b77911126b778f807d80c7/watchl-0.1.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "850ffaf2d89a3ea2c7b73008cf610217", "sha256": "cf6e08f612b2409b54c35c01ddcb53d2aaab897e479b317140eec048a59484ab" }, "downloads": -1, "filename": "watchl-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "850ffaf2d89a3ea2c7b73008cf610217", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 14149, "upload_time": "2019-07-31T07:52:25", "url": "https://files.pythonhosted.org/packages/ee/bc/0ae5ed52d7ef3ddfa5c72709bbbe0679974c57b3b6b41e51c07c8443279b/watchl-0.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c7708f508325cdf7c6f9cf3241371e94", "sha256": "68da1246f01088e546e91538c0f468c96e58d8f54594832e942abc983f80649d" }, "downloads": -1, "filename": "watchl-0.1.1.tar.gz", "has_sig": false, "md5_digest": "c7708f508325cdf7c6f9cf3241371e94", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 12657, "upload_time": "2019-07-31T07:52:27", "url": "https://files.pythonhosted.org/packages/15/9a/568772fcbcb2373d8cd384e69aa6a49440e1b7fd37bc16d04012931b95f3/watchl-0.1.1.tar.gz" } ], "0.2": [ { "comment_text": "", "digests": { "md5": "45abff42e206494ebb45353ad6eaa7bd", "sha256": "6d77dce0d56858af1330b4daccde5781de1cb9874538d28ff37999a7eb2617dc" }, "downloads": -1, "filename": "watchl-0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "45abff42e206494ebb45353ad6eaa7bd", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 13573, "upload_time": "2019-08-03T12:23:25", "url": "https://files.pythonhosted.org/packages/4c/e6/fc7671dfefb4e664c79e7c5ab8b5db5d0440f49b4fb4a019f465187d7b9f/watchl-0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0bc31203fbefa900a51d2b82259dc3c9", "sha256": "ddd268a31d092e2f08de15dbb02fe16c352c45e125f9afab07777fe519cbf01a" }, "downloads": -1, "filename": "watchl-0.2.tar.gz", "has_sig": false, "md5_digest": "0bc31203fbefa900a51d2b82259dc3c9", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 12229, "upload_time": "2019-08-03T12:23:27", "url": "https://files.pythonhosted.org/packages/18/53/89f0072776171c87574401e2726351e1360dc9ee0d4a655c9e2550ed2973/watchl-0.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "45abff42e206494ebb45353ad6eaa7bd", "sha256": "6d77dce0d56858af1330b4daccde5781de1cb9874538d28ff37999a7eb2617dc" }, "downloads": -1, "filename": "watchl-0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "45abff42e206494ebb45353ad6eaa7bd", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 13573, "upload_time": "2019-08-03T12:23:25", "url": "https://files.pythonhosted.org/packages/4c/e6/fc7671dfefb4e664c79e7c5ab8b5db5d0440f49b4fb4a019f465187d7b9f/watchl-0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "0bc31203fbefa900a51d2b82259dc3c9", "sha256": "ddd268a31d092e2f08de15dbb02fe16c352c45e125f9afab07777fe519cbf01a" }, "downloads": -1, "filename": "watchl-0.2.tar.gz", "has_sig": false, "md5_digest": "0bc31203fbefa900a51d2b82259dc3c9", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 12229, "upload_time": "2019-08-03T12:23:27", "url": "https://files.pythonhosted.org/packages/18/53/89f0072776171c87574401e2726351e1360dc9ee0d4a655c9e2550ed2973/watchl-0.2.tar.gz" } ] }