14

Is there a software which keeps time of my activities and gives a report? Based on focused window and window title. Report would just show time spent for specific window and its title like:

Application   Title                             Time
Firefox       Ask Ubuntu - Mozilla Firefox      5:58
Jacob Vlijm
  • 83,767
ambi
  • 183
  • 1
    There is a time tracker in the software center that does just this – Mateo May 31 '16 at 13:11
  • 1
    This can be done extremely easily with avaible programs - lets not assign motive to this, I have used such a program to record my own time on a project before. This certainly isn't in the "too broad" category – Mateo May 31 '16 at 15:17
  • Any which way, I don't get why this question is heavily downvoted. It's a normal and clear question. I didn't see a "only ask question nobody knows the answer to" warning anywhere on the site. – Jacob Vlijm May 31 '16 at 20:09
  • Hi Ambi. Posted my answer. Please let me know if you manage! – Jacob Vlijm Jun 01 '16 at 19:49
  • Yes may be my description was not correct - i don't want to spy on anyone except me. I want just have a statistics on what i have wasted my time. I have checked 'Time tracking overview' and 'GTimeLog Time Tracker' but there you need to enter everything manually - that i don't want to do.

    Jacob Vlijm, thank you, that is exactly what i was looking for except i thought that there is a software like that with GUI

    – ambi Jun 01 '16 at 20:04
  • @ambi great, thanks. I might add a GUI later, since it is a nice question and nice data to be aware of! Thanks for the nice question, and sorry for the downvotes it got. – Jacob Vlijm Jun 01 '16 at 20:30

3 Answers3

8

EDIT: a version of the script with sorted reports can be found here


Always fun to write a script for it!

The script below will produce an output (report) like:

------------------------------------------------------------
nautilus
0:00:05 (3%)
------------------------------------------------------------
   0:00:05 (3%)     .usagelogs
------------------------------------------------------------
firefox
0:01:10 (36%)
------------------------------------------------------------
   0:00:05 (3%)     The Asker or the Answerer? - Ask Ubuntu Meta - Mozilla Firefox
   0:00:15 (8%)     scripts - Is there software which time- tracks window & application usage? - Ask Ubuntu - Mozilla Firefox
   0:00:10 (5%)     Ask Ubuntu - Mozilla Firefox
   0:00:15 (8%)     Why is a one line non-understandable answer used as review audit? - Ask Ubuntu Meta - Mozilla Firefox
   0:00:20 (10%)    bash - How to detect the number of opened terminals by the user - Ask Ubuntu - Mozilla Firefox
   0:00:05 (3%)     BlueGriffon - Mozilla Firefox
------------------------------------------------------------
gedit
0:02:00 (62%)
------------------------------------------------------------
   0:02:00 (62%)    2016_06_04_10_33_29.txt (~/.usagelogs) - gedit

============================================================
started: 2016-06-04 10:33:29    updated: 2016-06-04 10:36:46
============================================================


..which is updated once per minute.

Notes

  • The report will possibly report windows under the category: "Unknown". This is the case when windows have pid 0 (tkinter windows, such as Idle windows, aPython IDE). Their window title and usage will be reported correctly however.

  • The lock screen with password input is reported a "nux input window".

  • The percentages are rounded percentages, which might occasionally lead to minor differences between the application's percentage and the sum of its window's percentage.

    An example: If an application has two windows used, each used 0,7% of the total time, both windows will report 1% each (0.7 --> rounded to 1), while the application's usage reports 1% (1.4 --> rounded to 1)

    No need to say that these differences are totally irrelevant in the whole picture.

The script

#!/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

How to set up

  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"
    

More notes

  • ~/.uselogs is a hidden directory by default. Press (in nautilus) Ctrl+H to make it visible.
  • As it is, the script rounds the window's activeness on 5 seconds, assuming less then 5 seconds is not really using the window. If you'd like to change the value, set it in the head of the script in the line:

    # -- set update/round time (seconds)
    period = 5
    # -- 
    
  • The script is extremely "low on juice". Furthermore, since the time- updates per window are done inside the script, the number of lines in the log file is limited to the actual number of used windows.

    Nevertheless, I wouldn't run the script for weeks in a row for example, to prevent accumulating too many lines (=window records) to maintain.

Jacob Vlijm
  • 83,767
  • 1
    Exactly what i was looking for except it is good to have a GUI as well but i can do it myself. Thank you. – ambi Jun 01 '16 at 20:09
  • 1
    Love this script. Unfortunately after an Ubuntu upgrade it crashes. Cause in my case: xdotool getactivewindow getwindowname fails with XGetWindowProperty[_NET_ACTIVE_WINDOW] failed (code=1). I added an extra ternary so the script doesn't break, however it doesn't make the log files useful, as xdotool is broken. – aross Aug 24 '20 at 13:08
  • @aross Ah, better use the "fix" for personal use, leave it here as it is for now to not hide issues. Methods I use are quite different these days, will look into it and probably modernize soon. I will then refuse the edit, but thanks a lot for mentioning. – Jacob Vlijm Aug 24 '20 at 13:22
  • Funny thing is, I've got about an hour of useful .usagelog, then xdotool starts returning this error. I've read that it doesn't work on Wayland (why it does work shortly after booting is beyond me)... https://github.com/ActivityWatch/activitywatch/issues/92 – aross Aug 24 '20 at 13:44
  • xdotool partially works for me. If I focus firefox/thunderbird it works, some others don't... strange – aross Aug 24 '20 at 14:20
3

there is arbtt that does exactly what you describe: https://www.joachim-breitner.de/blog/336-The_Automatic_Rule-Based_Time_Tracker

update: this project is still alive (Oct 2020) and the arbtt home page here: http://arbtt.nomeata.de/

the github project is here: https://github.com/nomeata/arbtt

mnagel
  • 995
  • 1
  • 8
  • 21
0

Here's an even simpler script written in bash based on the xdotool mentioned in Jacob Vlijm's answer.

while :
do
    sleep 1
    echo $(date +"%H:%M:%S") $(xdotool getactivewindow getwindowname) >> $datapath/log-$(date +"%Y-%m-%d").txt; 
done

Make sure to specify what $datapath is. Save the file as scrip.sh and run it in the background:

./script.sh &

Kill it in your jobs list to stop it. Or bring it to the foreground with fg and use ctrl-c.

If you prefer to sample at a rate slower than 1 second, change the sleep line. It saves data for each day in a separate file. Assuming 300 bytes per line, sampling at this rate will generate approximately 3600*24*300 = 25MB of data a day. That can be easily compressed (in post processing) as many window titles are repeated.

If you want usage percentages, awk the second column and pipe it to uniq -c and then pipe to sort -nr. That will give you the total number of minutes.

abnry
  • 101