5

There is an application usage time tracker script, that Jacob Vlijm wrote in another question. https://askubuntu.com/a/780542/654800

Due to small reputation I cannot comment there. So I will ask here, is it possible to sort entries by percentage of use, instead of current relative order?

Here is a script in case you don't want to check the original question.

#!/usr/bin/env python3
import subprocess
import time
import os

# -- set update/round time (seconds)
period = 5
# -- 
# 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])
        report.write("")
        for app in applist:
            wins = [r for r in winlist if r[0] == app]
            apptime = sum([it[2] for it in winlist if it[0] == app])
            appperc = round(100*apptime/totaltime)
            report.write(("-"*60)+"\n"+app+"\n"+time_format(apptime)+\
                         " ("+str(appperc)+"%)\n"+("-"*60)+"\n")
            for w in wins:
                wperc = str(round(100*w[2]/totaltime))
                report.write("   "+time_format(w[2])+" ("+\
                             wperc+"%)"+(6-len(wperc))*" "+w[1]+"\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
oiceod0
  • 53

1 Answers1

2

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!


Jacob Vlijm
  • 83,767