{"id":20246231,"url":"https://github.com/rkoschmitzky/logbook","last_synced_at":"2025-04-10T21:12:20.659Z","repository":{"id":44672371,"uuid":"155066671","full_name":"rkoschmitzky/logbook","owner":"rkoschmitzky","description":"user friendly graphical interface for reading log messages","archived":false,"fork":false,"pushed_at":"2022-12-08T09:30:13.000Z","size":388,"stargazers_count":20,"open_issues_count":1,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-10T21:12:05.106Z","etag":null,"topics":["gui","log","logger","logging","pyqt","pyside","python","qt","ui","vfx"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rkoschmitzky.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-10-28T12:04:59.000Z","updated_at":"2025-01-14T14:08:19.000Z","dependencies_parsed_at":"2023-01-25T05:45:46.316Z","dependency_job_id":null,"html_url":"https://github.com/rkoschmitzky/logbook","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rkoschmitzky%2Flogbook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rkoschmitzky%2Flogbook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rkoschmitzky%2Flogbook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rkoschmitzky%2Flogbook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rkoschmitzky","download_url":"https://codeload.github.com/rkoschmitzky/logbook/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248298316,"owners_count":21080320,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gui","log","logger","logging","pyqt","pyside","python","qt","ui","vfx"],"created_at":"2024-11-14T09:27:56.312Z","updated_at":"2025-04-10T21:12:20.633Z","avatar_url":"https://github.com/rkoschmitzky.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.com/rkoschmitzky/logbook.svg?branch=master)](https://travis-ci.com/rkoschmitzky/logbook) [![Coverage Status](https://coveralls.io/repos/github/rkoschmitzky/logbook/badge.svg?branch=master\u0026service=github)](https://coveralls.io/github/rkoschmitzky/logbook?branch=master) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n# Logbook\nA simple Qt widget to improve the pleasure of reading log messages.\n\n### Table of Contents\n- [Logging](#logging)\n- [Prerequisites](#prerequisites)\n- [The Interface](#the-logbook-graphical-user-interface)\n- [Communication](#let-your-loggers-communicate-with-the-logbook)\n- [Customization](#customization)\n  - [Attributes](#attributes)\n  - [Formatting](#recorditems-formatting)\n  - [Custom Levels](#custom-levels)\n  - [Exception ToolTips](#exception-tooltips)\n  - [Custom Signals](#custom-signals)\n\n### Logging\nThe Logging module is awesome! However, if multiple people/tools setup numerous loggers and handlers, it can make reading and filtering log messages hard.\n\n-----\n\n### Prerequisites\nYou need to ensure the [Qt.py](https://github.com/mottosso/Qt.py) wrapper is available, which supports PySide2, PyQt5, PySide and PyQt4.\n\n-----\n\n### The Logbook graphical user interface\nThe Logbook user interface is focused on making it simple for you, to search for information quickly.\n\n\u003cimg src=\"https://github.com/rkoschmitzky/logbook/blob/master/.graphics/user_interface.gif\" width=\"400\"\u003e\n\nIt exposes\n- an arbitrary number of checkable buttons for defined log levels\n- a checkbox to enable corresponding background colors per record item\n- a field for a filter regular expression\n- the actual list that holds the catched log records\n- a button to clear this list\n\n-----\n\n### Let your loggers communicate with the Logbook\nTo catch log records you only have to attach the provided Logbook handler to your loggers of choice.\n\n```python\nimport logging\n\nfrom logbook import LogbookWidget\n\n# acquire a logger\nmy_logger = logging.getLogger(\"foo\")\nmy_logbook_instance = LogbookWidget()\n\n# the `handler` property holds the required handler\nmy_logger.addHandler(my_logbook_instance.handler)\n\n# show the logbook gui\nmy_logbook_instance.show()\n```\nAs soon as your handler was attached, the log records will be catched within a background thread to keep the UI respsonsive.\n\n\u003cimg src=\"https://github.com/rkoschmitzky/logbook/blob/master/.graphics/record_addition.gif\" width=\"400\"\u003e\n\n-----\n\n### Customization\n\n#### Attributes\n\n| Attribute               | Type      | Description\n|:------------------------|:----------|:------------\n| `FLAGS`                 | `bytemask`| Set different logbook behaviors that can be combined.\n| `LEVEL_BUTTON_WIDTH`    | `int`     | Defines the width of the level buttons.\n| `LOG_LEVELS`            | `list`    | A list with levels that will correspond to the checkable level buttons that will be added. default: `[\"debug\", \"info\", \"warning\", \"error\", \"critical\"]`. When changed the `LEVEL_VALUES` and `LEVEL_COLORS` attribute needs to be adjusted too.\n| `LEVEL_VALUES`          | `dict`    | A dictionary with corresponding level numbers to the defined `LOG_LEVELS`. default: `{\"debug\": 10, \"info\": 20, \"warning\": 30, error: \"40\", \"critical\": 50}`.\n| `LEVEL_COLORS`          | `dict`    | A dictionary with corresponding colors to the defined `LOG_LEVELS`. Expects RGB values from 0-255 and an optional alpha value from 0-100. default: `        \"debug\": (255, 255, 255, 100), \"info\": (204, 236, 242, 100), \"warning\": (152, 210, 217, 100), \"error\": (223, 57, 57, 100), \"critical\": (182, 60, 66, 100)}`\n| `INITIAL_FILTER_REGEX`  | `str`     | A regular expression that will be used when launching the logbook.\n| `INITIAL_COLORING`      | `bool`    | If `True` coloring mode will be enabled by default when launching the logbook.\n| `EXCEPTION_FORMATTER`   | `logging.Formatter` |  A formatter instance that will be used to format the `exc_info` tuple that will be dispayed inside the ToolTips of recorditems.\n\n| Flag                      | Description\n|:--------------------------|:-----------\n| `COLORING_TEXT`           | When given the item's foreground color will be set instead of the background color.\n| `IGNORE_FORMATTER`        | If a formatter was set to the handler, it can be explicitly ignored by setting using this. It means, the formatter will not be considered as the recorditem's text. Instead it will only use the `LogRecord.getMessage()` directly.\n| `INITIAL_COLORING`        | When given the `Coloring` option will be checked by default when launching the logbook. \n| `READABLE_TEXT_COLOR`     | When given and `COLORING_TEXT` is NOT set it sets an automatic item foreground color based on the background color for better readability.\n| `RE_IGNORE_CASE`          | When given the `Ignore Case` option will be checked by default when launching the logbook.\n\nThis examples activates coloring of item's foreground color instead of background color.\n```python\nLogbookWidget.FLAGS = LogbookWidget.Flags.INITIAL_COLORING | LogbookWidget.Flags.COLORING_TEXT\n```\n\n\u003cimg src=\"https://github.com/rkoschmitzky/logbook/blob/master/.graphics/text_coloring.gif\" width=\"400\"\u003e\n\n#### Recorditems Formatting\nBy default, the logbook handlers doesn't use a formatter. It will use the `LogRecord.getMessage()` attribute as the recorditem's text.\nA formatter can be set easily by using the `handler` property on the logbook instance.\n\n```python\nmy_logbook.handler.setFormatter(\"%(asctime)s %(message)s\")\n```\n\n#### Custom Levels\nYou can provide custom levels for the Logbook.\n```python\nfrom logbook import LogbookWidget\n\n# the order inside the `LOG_LEVELS` list matters, the buttons will be added from left to right\n# we would like to introduce the \"paranoid\" level, that is below `logging.DEBUG`\nLogbookWidget.LOG_LEVELS.insert(0, \"paranoid\")\n# a corresponding level and color must be defined\nLogbookWidget.LEVEL_VALUES[\"paranoid\"] = 5\n# an alpha value is optional\nLogbookWidget.LEVEL_COLORS[\"paranoid\"] = (125, 80, 125)\n```\n\n\u003cimg src=\"https://github.com/rkoschmitzky/logbook/blob/master/.graphics/custom_level.gif\" width=\"400\"\u003e\n\n#### Exception ToolTips\nWhenever a catched `LogRecord` includes an `exc_info` tuple, it will display a ToolTip with the underlying exception.\nBy default `logging.Formatter().formatException(record)` will be used to format the exception. However a custom formatter can be set via `EXCEPTION_FORMATTER` attribute.\n\n```python\nfrom logging import Formatter\n\nfrom logbook import LogbookWidget\n\nclass MyExceptionFormatter(Formatter):\n    def formatException(exc_info):\n        # setup the actual formatting here\n\n# override the formatter used to format the underlying exception info tuple\nLogbookWidget.EXCEPTION_FORMATTER = MyExceptionFormatter()\n```\n\u003cimg src=\"https://github.com/rkoschmitzky/logbook/blob/master/.graphics/exception_tooltip.gif\" width=\"400\"\u003e\n\n#### Custom Signals\nThe following signals can be connected to extend functionality of the loogbook.\n\n```python\n# example shows how to call a custom QMenu\n# the event gets triggered via RMB click on a LogRecordItem\n# it will pass the global cursor position, a list of underlying/selected `LogRecordItem` instances \n# and the LogRecordsListWidget\n\nclass MyMenu(QtWidgets.QMenu):\n    def __init__(self, pos, record_items, records_list_widget):\n        super(MyMenu, self).__init__()\n        for record_item in record_items:\n            self.addAction(\"{}| {}\".format(record_item.record.levelname, record_item.record.msg))\n        self.exec_(pos)\n\nmy_logbook_instance.signals.record_context_request.connect(MyMenu)\n```\n\u003cimg src=\"https://github.com/rkoschmitzky/logbook/blob/master/.graphics/context_menu.gif\" width=\"400\"\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frkoschmitzky%2Flogbook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frkoschmitzky%2Flogbook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frkoschmitzky%2Flogbook/lists"}