How can I make this window & application time- track script produce sorted output?

Solution 1:

Same script, but producing sorted reports, either ascending or descending

I edited the script to produce sorted reports, either ascending or descending, to be set in the head of the script.

The sorting is done on both the order of the applications, as well as their windows (in the sublists per application).

The script

#!/usr/bin/env python3
import subprocess
import time
import os
from operator import itemgetter

# -- set update/round time (seconds)
period = 5 
# -- set sorting order. up = most used first, use either "up" or "down"
order = "up"

# don change anything below
home = os.environ["HOME"]
logdir = home+"/.usagelogs"

def currtime(tformat=None):
    return time.strftime("%Y_%m_%d_%H_%M_%S") if tformat == "file"\
           else time.strftime("%Y-%m-%d %H:%M:%S")

try:
    os.mkdir(logdir)
except FileExistsError:
    pass

# path to your logfile
log = logdir+"/"+currtime("file")+".txt"; startt = currtime()

def get(command):
    try:
        return subprocess.check_output(command).decode("utf-8").strip()
    except subprocess.CalledProcessError:
        pass

def time_format(s):
    # convert time format from seconds to h:m:s
    m, s = divmod(s, 60); h, m = divmod(m, 60)
    return "%d:%02d:%02d" % (h, m, s)

def summarize():
    with open(log, "wt" ) as report:
        totaltime = sum([it[2] for it in winlist]) # total time
        report.write("")
        alldata = []      
        for app in applist:
            appdata = []; windata = []
            apptime = sum([it[2] for it in winlist if it[0] == app])
            appperc = round(100*apptime/totaltime)            
            for d in [app, apptime, appperc]:
                appdata.append(d)
            wins = [r for r in winlist if r[0] == app]            
            for w in wins:
                wperc = str(round(100*w[2]/totaltime))
                windata.append([w[1], w[2], wperc])                
            windata = sorted(windata, key=itemgetter(1))
            windata = windata[::-1] if order == "up" else windata
            appdata.append(windata); alldata.append(appdata)            
        alldata = sorted(alldata, key = itemgetter(1))
        alldata = alldata[::-1] if order == "up" else alldata        
        for item in alldata:
            app = item[0]; apptime = item[1]; appperc = item[2]
            report.write(
                ("-"*60)+"\n"+app+"\n"+time_format(apptime)\
                +" ("+str(appperc)+"%)\n"+("-"*60)+"\n"
                )            
            for w in item[3]:
                wname = w[0]; time = w[1]; perc = w[2]
                report.write(
                    "   "+time_format(time)+" ("+perc+"%)"\
                    +(6-len(perc))*" "+wname+"\n"
                    )
        report.write(
            "\n"+"="*60+"\nstarted: "+startt+"\t"+"updated: "\
            +currtime()+"\n"+"="*60
            )

t = 0; applist = []; winlist = []

while True:
    time.sleep(period)
    frpid = get(["xdotool", "getactivewindow", "getwindowpid"])
    frname = get(["xdotool", "getactivewindow", "getwindowname"])
    app = get([
        "ps", "-p", frpid, "-o", "comm="
        ]) if frpid != None else "Unknown"
    # fix a few names
    if "gnome-terminal" in app:
        app = "gnome-terminal"
    elif app == "soffice.bin":
        app = "libreoffice"
    # add app to list
    if not app in applist:
        applist.append(app)
    checklist = [item[1] for item in winlist]
    if not frname in checklist:
        winlist.append([app, frname, 1*period])
    else:
        winlist[checklist.index(frname)][
            2] = winlist[checklist.index(frname)][2]+1*period
    if t == 60/period:
        summarize()
        t = 0
    else:
        t += 1

It produces output like:

------------------------------------------------------------
firefox
0:08:25 (97%)
------------------------------------------------------------
   0:06:50 (79%)    Sort by percentage of use in a python script - Ask Ubuntu - Mozilla Firefox
   0:01:30 (17%)    scripts - Is there software which time- tracks window & application usage? - Ask Ubuntu - Mozilla Firefox
   0:00:05 (1%)     Ask Ubuntu General Room | chat.stackexchange.com - Mozilla Firefox
------------------------------------------------------------
gedit
0:00:10 (2%)
------------------------------------------------------------
   0:00:10 (2%)     2017_02_15_20_47_10.txt (~/.usagelogs) - gedit
------------------------------------------------------------
zenity
0:00:05 (1%)
------------------------------------------------------------
   0:00:05 (1%)     Paste snippets

============================================================
started: 2017-02-15 20:58:19    updated: 2017-02-15 21:07:03
============================================================

To use

  1. The script needs xdotool to get the window's information

    sudo apt-get install xdotool
    
  2. Copy the script into an empty file, save it as window_logs.py

  3. Test- run the script: tart the script by the command (from a terminal):

    python3 /path/to/window_logs.py
    

    After one minute, the script creates a log file with the first results in ~/.usagelogs. The file is time- stamped with the creation date & time. The file is updated once per minute.

    At the bottom of the file, you can see both the start- time and the time-stamp of the latest edit. This way you can always see what is the file's time span.

    If the script restarts, a new file with a new (start-) time stamp is created.

  4. If all works fine, add to Startup Applications: Dash > Startup Applications > Add. Add the command:

    /bin/bash -c "sleep 15 && python3 /path/to/window_logs.py"
    

Reverse sorting order

To reverse the sorting order, simply change the argument in the head of the script:

# -- set sorting order. up = most used first, use either "up" or "down"
order = "up"

NB Please read the Notes and More notes sections in the linked answer!