Building an activity tracker with Go, Grafana, and InfluxDB


Recently, my routine changed a lot. Since I stopped running teams I’m not jumping from one meeting to another; I now spend most working time on my laptop. I have the tendency to procrastinate when I’m alone so I need measurable data to understand what to improve in my habits. I ran into rescue time and tried it out for a few days despite having privacy concerns. The service is helpful and I decided to write a simplified version of it as an excuse to play around with Grafana and InfluxDB, two open source projects I like very much. This was my plan:

  • Figure out a way to say which application is running in the foreground
  • Write a Go daemon that sends this information to InfluxDB once per second
  • Create a dashboard in Grafana to visualise my activities
  • Open source the small program
  • Write the article you’re reading :)

Check what’s in the foreground #

I had no idea how to check which application is running in the foreground, so I had to do some research. I discovered AppleScript is a thing and scoped my search. Some copy and pasting got me to this script. Only after I was done with a first version, I learned that it’s possible to use JavaScript for automation. I will probably rewrite the script in JavaScript before adding more features, but at the time I already had a working script and decided to move forward with it.

The Go program #

I wrapped the script with a Go program here and, as usual, I liked the experience with Go. The language is boring, fast, and has a solid standard library.

It was time for the program to send data to InfluxDB which I installed it via brew. I couldn’t make InfluxDB work as a service at first try and decided to ignore the problem, I could go back to it later. Then I created a db called me and moved on to the writing data guide. The protocol looked simple, so I decided to copy a piece of the official Go client instead of adding a dependency to such a small program. The InfluxDB API is friendly and the code from the client library is easy to adapt; I made it work in this commit.

The only noticeable thing the introduction of categories. The program figures out the activity name via the AppleScript. Each activity has an associated category and each category has a score. That’s a way of clustering activities together, e.g. “iTerm2” and “github.com” are associated with “Development” that has a score of 1. “Twitter” is associated with “Social” that has a score of -1. That way I can build a dashboard that quantifies how productive my day is and which kind of activity I spend my time on. I had to try a couple of times to make it work as I had some trouble understanding how to send a string as a value: it needed quotes around the value itself and I had tried things out without reading the documentation. The docs do a great job at explaining the details here . It was a good reminder to read the documentation before writing the code. Before moving on to the visualisation of the data, I split the programs in multiple files so that it was easier to reason about it. I also added some tests.

Run it in the background #

It was time to run tracker in the background. I had to get back to the issue with InfluxDB, so I started reading the logs to understand why it wouldn’t start. The fix consisted of one command:

influxd config > /usr/local/etc/influxdb.conf

Probably something was wrong with the brew formula. Normally, I would have investigated and tried to open a pull request, but I was too excited to get to the first version of the Grafana dashboard. As soon as I tried to visualise the data, I realised I had understood the InfluxDB data model wrong. The score of each activity had to be a field and not a tag, otherwise InfluxDB could not perform any math. It makes sense, and once again I should have read the docs first! I changed the data model here so I could get the average score of an activity in a given time-frame.

I left the program running on my machine for a few days so I could test the Grafana dashboard with meaningful data. As soon as I looked at the data, I realised I needed to add more default categories. I improved how the program loaded default categories here with the nice little go-bindata tool. tracker read the content of the file from the binary itself and put the default categories database in memory. This way the database became easier to extend.

Grafana dashboard #

Finally, I built a dashboard and it looked like this:

tracker screenshot

Grafana has all the characteristics of a good product: you don’t need to read the documentation to use its interface and if you try things out they often just work. The documentation is very good anyway, I needed help with the table panel and the official documentation was my only source of information.

What’s next? #

tracker has been an exciting exercise so far. It’s amazing how much you can accomplish and how little effort it takes if you use open source projects like Grafana and InfluxDB. In my attempt to give back to the open source community, I will slowly make tracker more usable for other people and I will keep taking notes along the way so I can write other articles about the experience. I created a roadmap, so it’s easier to understand the direction of the project.

Thank you for reading and stay tuned for the next article!