Posted on Fri 16 March 2012

Life-logging for your computer usage

Have you ever wondered where most of your time goes when using your computer? I always did, so I wrote a small script which logs the currently visible and focused apps:

#!/usr/bin/python
import json
import os
import time
import subprocess

visible_workspaces = []
filtered = [								# filter everything which is not a window
	"root", "LVDS", "DFP1",															# monitors
	"i3bar for output LVDS", "i3bar for output DFP1",		# i3bar
	"topdock", "content", "bottomdock",									# docks
	"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", 	# workspace numbers
	"#00FF00", "#aa00aa", "#00aa00"											# window title bar colors
	]
clean_mapping = {						# strings to recognize apps by and the correct app name
	"XChat": "XChat",
	"Sublime": "Sublime Text 2",
	"Chrome": "Google Chrome",
	"Skype": "Skype",
	"VLC": "VLC",
	"calibre": "calibre",
	"GNU Image Manipulation": "GIMP",
	"Buddy List": "Pidgin",
	"jabber": "Pidgin",
	"pts": "Terminal",
	"Defender's Quest": "Defender's Quest",
	"Desura": "Desura"
	}

visible_apps = []
focused_apps = []

# i3's windows are contained in a tree structure, so we need to parse that
def parse_node(node):
	if "num" in node and node["num"] not in visible_workspaces:
		return

	name = node["name"]
	if name not in filtered:
		visible_apps.append(name)
		if node["focused"] == True:
			focused_apps.append(name)

	for n in node["nodes"]:
		parse_node(n)

# clean up window titles
def clean_name(name):
	for key in clean_mapping:
		if key in name:
			return clean_mapping[key]
	return name


screensaver_enabled = False
try:
	screensaver_enabled = "non" not in subprocess.check_output(
		"xscreensaver-command -time 2> /dev/null", shell=True)
except:
	pass

workspaces = json.loads(
	subprocess.check_output(
		"i3-ipc -j -t 1", shell=True))

for w in workspaces:
	if w["visible"] == True:
		visible_workspaces.append(int(w["name"]))

apps = json.loads(subprocess.check_output(
	"i3-ipc -j -t 4", shell=True))

parse_node(apps)

visible_apps = [clean_name(n) for n in visible_apps]
focused_apps = [clean_name(n) for n in focused_apps]

output_template = """{ "time": %d, "visible": %s, "focused": %s }"""
if screensaver_enabled:
	focused_apps = ["screensaver"]

print (output_template % 
	(time.time(), visible_apps, focused_apps)
	).replace("'", "\"")

It uses the IPC interface to communicate with i3, the tiling window manager I use. (if you don't already use a tiling wm: I highly recommend it!) Communication also relies on the i3-ipc ruby library, which you'd have to install to use my script.

Output looks like this:

{ "time": 1331935529, "visible": ['Terminal', 'Sublime Text 2'], "focused": ['Terminal'] }

The current time in seconds, a list of all visible windows and finally a list of the currently focused windows. Each line is one json object, so you can easily pare it. I use cron to run this script every minute and log it's ouput to a file:

# m h  dom mon dow   command
  * *  *   *   *     export DISPLAY=:0 && /home/mononofu/.app_usage.py >> /home/mononofu/.app_usage.log

It's important to set the DISPLAY variable or the script won't work! I'll publish a script for easy analysis of the data in the next few days, so stay tuned.

Tags: life

© Julian Schrittwieser. Built using 開板. Theme by Giulio Fidente on github. .