Skip to content

Commit

Permalink
Version 2.0.0 release
Browse files Browse the repository at this point in the history
  • Loading branch information
busimus committed Jul 28, 2018
1 parent 95675a8 commit d820fda
Show file tree
Hide file tree
Showing 28 changed files with 2,732 additions and 1,811 deletions.
54 changes: 19 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
# cutelog – GUI for Python's logging module
# cutelog – GUI for logging
[![PyPi](https://img.shields.io/pypi/v/cutelog.svg?style=flat-square)](https://pypi.python.org/pypi/cutelog)

This is a graphical log viewer for Python's standard logging module.
This is a graphical log viewer for Python's logging module.
It can be targeted with a SocketHandler with no additional setup (see [Usage](#usage)).

The program is in beta: it's lacking some features and may be unstable, but it works.
cutelog is cross-platform, although it's mainly written and optimized for Linux.
It can also be used from other languages or logging libraries with little effort (see the [Wiki](../../wiki/Creating-a-client-for-cutelog)).
For example, a Go library [gocutelog](https://github.com/busimus/gocutelog) shows how to enable
regular Go logging libraries to connect to cutelog.

This is my first released project, so the code is by no means stellar.
Feedback and contributions are appreciated!
This program is in beta, so please report bugs if you encounter them.

## Features
* Allows any number of simultaneous connections
* Fully customizable look of log levels and columns
* Filtering based on level and name of the logger, as well as filtering by searching
* Customizable look of log levels and columns, with presets for each
* Filtering based on level and namespace, as well as filtering by searching
* Search through all records or only through filtered ones
* Display extra fields under the message with [Extra mode](../../wiki/Creating-a-client-for-cutelog#extra-mode)
* View exception tracebacks or messages in a separate window
* Dark theme (with its own set of colors for levels)
* Pop tabs out of the window, merge records of multiple tabs into one
* Save/load records to/from a file in JSON format

## Screenshots
Light theme | Dark theme
Expand All @@ -30,15 +32,16 @@ Light theme | Dark theme
```
$ pip install cutelog
```
Or install the latest development version from the source:
Or install the latest development version from the source (requires PyQt5 to build resources):

```
$ pip install git+https://github.com/busimus/cutelog.git
```

### Requirements
* Python 3.5 (or newer)
* PyQt5 (preferably 5.6 or newer)
* PyQt5 (preferably 5.6 or newer) or PySide2
* [QtPy](https://github.com/spyder-ide/qtpy)

## Usage
1. Start `cutelog`
Expand All @@ -48,40 +51,21 @@ import logging
from logging.handlers import SocketHandler

log = logging.getLogger('Root logger')
log.setLevel(1) # to send all messages to cutelog
log.setLevel(1) # to send all records to cutelog
socket_handler = SocketHandler('127.0.0.1', 19996) # default listening address
log.addHandler(socket_handler)
log.info('Hello world!')
```
Afterwards it's recommended to designate different loggers for different parts of your program with `log_2 = log.getChild("Child logger")`.
This will create "log namespaces" which allow you to filter out messages from various subsystems of your program.

## Planned features
* [ ] Presets for colors
* [ ] Modify how rows are arranged in the detail table (like the header dialog)
* [ ] Fix double-search on the last matched result (or indicate that the last result was reached)
* [ ] Ability to save and load logs (as text or as full records)
* [ ] Alarms/notifications triggered by specified messages
* [ ] Figure out how to search up

### Code improvements:
* [ ] Proper exception handling in critical places
* [ ] Message boxes for errors to avoid relying on CLI logging
* [ ] Ability to ignore resources.py and instead use actual files for quick stylesheet reload, etc.

### Dreams, uncertainties, and low priority improvements:
* [ ] Rewrite all/most UIs in code instead of using Qt Designer
* [ ] Switch to [qtawesome](https://github.com/spyder-ide/qtawesome) instead of ion-icons?
* [ ] Support for custom themes?
* [ ] Rewrite the server with robust architecture and additional transports and serializers (e.g. ZeroMQ, WebSockets; msgpack)?
* [ ] Ditch asyncio if/when [curio](https://github.com/dabeaz/curio) takes off?
* [ ] Or rewrite the whole thing in C++ and make it be a generic logging receiver not just for Python???


## Attributions
Free software used:
* [PyQt5](https://riverbankcomputing.com/software/pyqt/intro) - GPLv3 License, Copyright (c) 2018 Riverbank Computing Limited <[email protected]>
* [ion-icons](https://github.com/ionic-team/ionicons) - MIT License, Copyright (c) 2016 Drifty (http://drifty.com/)
* Qt via either:
* [PyQt5](https://riverbankcomputing.com/software/pyqt/intro) - GPLv3 License, Copyright (c) 2018 Riverbank Computing Limited <[email protected]>
* [PySide2](https://wiki.qt.io/PySide2) - LGPLv3 License, Copyright (C) 2015 The Qt Company Ltd (http://www.qt.io/licensing/)
* [QtPy](https://github.com/spyder-ide/qtpy) - MIT License, Copyright © 2009–2018 The Spyder Development Team
* [ion-icons](https://github.com/ionic-team/ionicons) - MIT License, Copyright (c) 2015-present Ionic (http://ionic.io/)

And thanks to [logview](https://pythonhosted.org/logview/) by Vinay Sajip for UI inspiration.

Expand Down
6 changes: 2 additions & 4 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ It can be targeted with a SocketHandler with no additional setup (see Usage_).
The program is in beta: it's lacking some features and may be unstable, but it works.
cutelog is cross-platform, although it's mainly written and optimized for Linux.

This is my first released project, so the code is by no means stellar.
Feedback and contributions are appreciated!

Features
========
* Allows any number of simultaneous connections
Expand All @@ -39,7 +36,8 @@ Or install the latest development version from the source::
Requirements
------------
* Python 3.5 (or newer)
* PyQt5 (preferably 5.6 or newer)
* PyQt5 (preferably 5.6 or newer) or PySide2
* QtPy

Usage
=====
Expand Down
67 changes: 20 additions & 47 deletions cutelog/__main__.py
Original file line number Diff line number Diff line change
@@ -1,59 +1,32 @@
import asyncio
import signal
import sys

import qtpy

try:
import PyQt5.QtCore
PyQt5.QtCore
except ImportError:

if not qtpy.PYQT5 and not qtpy.PYSIDE2:
if sys.platform == 'linux':
sys.exit("Error: PyQt5 couldn't be imported.\n"
sys.exit("Error: a compatible Qt library couldn't be imported.\n"
"Please install python3-pyqt5 (or just python-pyqt5) from your package manager.")
else: # this technically shouldn't ever happen
sys.exit("Error: PyQt5 couldn't be imported.\n"
"Please install it by running `pip install pyqt5`")

from PyQt5.QtCore import pyqtRemoveInputHook
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication

# !! resources and config must be imported before main_window !!
from .resources import qCleanupResources
from .config import CONFIG, ROOT_LOG
from .main_window import MainWindow


class Application(QApplication):
def __init__(self, argv):
super().__init__(argv)
self.log = ROOT_LOG
self.setWindowIcon(QIcon(':/cutelog.png'))
self.config = CONFIG

async def process_events(self):
while not self.main_finished.is_set():
await asyncio.sleep(self.config.loop_event_delay)
self.processEvents()

def run(self):
pyqtRemoveInputHook() # to prevent Qt conflicting with pdb debug
self.loop = asyncio.get_event_loop()
self.loop.set_debug(False)

main = MainWindow(self.loop, self.log, self)
self.main_finished = main.finished
try:
self.loop.add_signal_handler(signal.SIGINT, main.shutdown, None)
except NotImplementedError: # for Windows
pass
self.loop.run_until_complete(self.process_events())
qCleanupResources()
sys.exit("Error: a compatible Qt library couldn't be imported.\n"
"Please install it by running `pip install pyqt5")


def main():
app = Application(sys.argv)
app.run()
import signal
from .config import ROOT_LOG
from .main_window import MainWindow
from .resources import qCleanupResources
from qtpy.QtGui import QIcon
from qtpy.QtWidgets import QApplication

app = QApplication(sys.argv)
app.setWindowIcon(QIcon(':/cutelog.png'))
mw = MainWindow(ROOT_LOG, app)
signal.signal(signal.SIGINT, mw.signal_handler)

sys.exit(app.exec_())
qCleanupResources()


if __name__ == '__main__':
Expand Down
13 changes: 5 additions & 8 deletions cutelog/about_dialog.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
from PyQt5 import uic
# from qtpy.uic import loadUi
from qtpy.QtWidgets import QDialog

from .config import CONFIG
from .utils import loadUi


uif = CONFIG.get_ui_qfile('about_dialog.ui')
AboutDialogBase = uic.loadUiType(uif)
uif.close()


class AboutDialog(*AboutDialogBase):
class AboutDialog(QDialog):
def __init__(self, parent):
super().__init__(parent)
self.setupUi()

def setupUi(self):
super().setupUi(self)
self.ui = loadUi(CONFIG.get_ui_qfile("about_dialog.ui"), baseinstance=self)
self.nameLabel.setText(CONFIG.full_name)
Loading

0 comments on commit d820fda

Please sign in to comment.