Overkill
Overkill is a publish-subscribe framework for collecting and distributing information on a local machine.
So why should anyone care? It's a great tool for generating status bar text (hence the name, overkill). Basically, I have a bunch of system monitors that watch various data sources (number of files in a directory, commands that print system statistics, etc.).
This is an approximate diagram (with quite a few data sources/sinks omitted for clarity) of my current setup:
(bspc control --subscribe) (conky) [clock] [inotify]
| | | |
v v v v
BSPWMSource ConkySource TimeSource MailCountSource
| | | |
+---------+----------+----------+-------------+
|
v
Manager
|
+-----------+------------+----------------+------------+
| | | | |
v v v v v
DesktopWidget CpuWidget MailCountWidget ClockWidget MailCountNotifier
| | | | |
| +------------+----------------+ v
| | (notification daemon)
| v
| LayoutWidget
| |
+------------+-----------+
|
v
LayoutWidget
|
v
BarSink
|
v
(bar-aint-recursive)
Installing
You can find the various python packages on my
GitHub. I recommend that you install them in
your home directory using python setup.py install --user
.
Packages
- overkill: The main framework
- overkill-misc: Miscellaneous sources (really just a timer source)
- overkill-mail: Maildir/mailqueue (msmtp) sources + notification sink
- overkill-writers: File writing mixins (needed by overkill-bar)
- overkill-pulseaudio: Pulseaudio data source
- overkill-conky: Conky data source
- overkill-bspwm: BSPWM data source
- overkill-bar: bar-aint-recursive overkill sink/widgets
- overkill-notify: Notification daemon sink
- overkill-config: My configuration files
Dependency Graph
I haven't uploaded the packages to PyPI so here is a dependency graph:
Using
To use overkill, add some python scripts to $XDG_CONFIG_HOME/overkill/
to up your various sources and sinks and then run overkill
. Overkill
will start any registered sinks which will in turn start up any relevant
sources.
You can find my configs here.
I have also reproduced them below:
Common sources
To use overkill, you'll first need to initialize and register your data sources. Note: A source won't actually start collecting data unless something subscribes to it.
from overkill.extra.sources import *
from overkill import manager
import os
MAIL_BASE = os.path.expanduser("~/.mail")
MAIL_DIRS = [
os.path.join(MAIL_BASE, f)
for f in os.listdir(MAIL_BASE)
if f[0] != "."
]
MAIL_QUEUE = os.path.expanduser("~/.mail.queue")
manager.add_source(BSPWMSource())
manager.add_source(PulseaudioSource())
manager.add_source(ConkySource())
manager.add_source(TimeSource())
manager.add_source(MaildirSource(MAIL_DIRS))
manager.add_source(MailqueueSource(MAIL_QUEUE))
Notifications
The following will setup mail and battery notification sinks. The battery notification sink will also suspend your computer when your battery gets low.
from overkill import manager
from overkill.extra.mail import MailNotifySink
from overkill.extra.notify import Notify
from overkill.sinks import SimpleSink
from subprocess import Popen
manager.add_sink(MailNotifySink())
class BatteryNotifySink(SimpleSink, Notify):
summary = "Battery Warning"
subscription = "battery_percent"
urgent_percent = 5
critical_percent = 10
low_percent = 15
_current = 100
def handle_update(self, update):
# FIXME: It starts at zero
if update == "0":
return
previous = self._current
self._current = int(update)
if previous > self.urgent_percent >= self._current:
Popen(["/usr/bin/systemctl", "suspend"])
if previous > self.critical_percent >= self._current:
self.message = "Critical Battery: %d%%" % self._current
self.urgency = self.notify.URGENCY_CRITICAL
self.show()
elif previous > self.low_percent >= self._current:
self.message = "Low Battery: %d%%" % self._current
self.urgency = self.notify.URGENCY_NORMAL
self.show()
manager.add_sink(BatteryNotifySink())
lemonbar
This script will start lemonbar.
from overkill import manager
from overkill.extra.bar import *
from overkill.extra.bar.widgets import *
bar = Bar()
arrows = r'\f7 << \fr'
bar.set_widget(Layout([
MultiMonitorWidget(),
Layout([
CPUWidget(),
MemWidget(),
TempWidget(),
AudioWidget(),
BatteryWidget(),
ExtendedMailCountWidget(),
NetWidget(("eth0", "wlan0")),
ClockWidget(" ".join(("%Y{faded}.{normal}%m{faded}.{normal}%d{focus}/{faded}%a{normal}",
"{highlight}%H{faded}:{highlight}%M{normal}")).format(
faded = r"\f3",
normal = r"\fr",
focus = r"\f7",
highlight = r"\f5"
))
], prefix=r"\r"+arrows, postfix=arrows, separator=arrows, debounce_params=(.1, 1))
], postfix=" "*5, ))
manager.add_sink(bar)
As I understand that these instructions are underspecified, please feel free to either email me questions or, preferably, post an issue on the relevant GitHub project.
Overkill Initial Release
I have been working on a project I call overkill for the past few months or so. It's is a publish-subscribe framework (or a functional-reactive programming framework if you want to use the latest buzz word) for collecting and distributing information on a local machine. Personally, I use it to generate my status bar (hence the name, overkill). See the project page for more information.