ianxm / emacs-tracker

generate reports of personal metrics from emacs diary entries
GNU General Public License v3.0
26 stars 2 forks source link

[[https://melpa.org/#/metrics-tracker][file:https://melpa.org/packages/metrics-tracker-badge.svg]] [[https://www.gnu.org/licenses/gpl-3.0.txt][file:https://img.shields.io/badge/license-GPL_3-green.svg]]

** melpa

  1. run @@html:kbd>@@M-x@@html:</kbd@@ ~package-install~ @@html:kbd>@@RET@@html:</kbd@@ ~metrics-tracker~

** manual install

  1. download [[https://raw.github.com/ianxm/emacs-tracker/master/metrics-tracker.el][metrics-tracker.el]]
  2. run @@html:kbd>@@M-x@@html:</kbd@@ ~package-install-file~ @@html:kbd>@@RET@@html:</kbd@@
  3. choose ~metrics-tracker.el~

*** diary entry format

emacs is very loose on [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Format-of-Diary-File.html#Format-of-Diary-File][diary entry formatting]], but entries that
metrics-tracker uses must look like:

+BEGIN_SRC

[date] [time] [metric-name] [value]

+END_SRC

where,
- date :: the date of a particular day.  although the emacs diary
  allows dates like "wednesday," which apply to all wednesdays,
  metrics-tracker only uses dates for specific days.  emacs' date
  handling is [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Date-Formats.html#Date-Formats][flexible]].  some examples of valid dates are:
  - ~2019-12-31~
  - ~31 Dec 2019~
  - ~December 31, 2019~
  - ~31/Dec/2019~
- time :: the time of day is optional and ignored by
  metrics-tracker if it is provided.  if provided, it must be
  formatted as:
  - ~10:30~
  - ~10:30a~
  - ~10:30 a~
  - ~10:30:10 am~
- metric-name :: is any string.  it can be as long as you like and
  can include spaces but keeping them short helps with
  readability.  valid values may look like:
  - ~pushups~
  - ~watched tv~
- value :: is a number (integer or decimal) or a duration
  (hh:mm:ss.ss).  for number values, metrics-tracker doesn't care
  about units.  ~value~ is just a number.  if you're tracking how
  much tv you watch, a "4" could mean 4 shows or 4 hours; it's up
  to you.  do not include commas.  for duration values, hours and
  fractional seconds are optional.  metrics-tracker converts
  durations to decimal hours.  valid values may be:
  - ~40~
  - ~1.2~
  - ~10:21.21~
  - ~3:00:10~

here is an example diary file where all entries are valid metrics.
there's no advantage to mixing date formats.  the example does it
for demonstration purposes.

+BEGIN_SRC

2019-12-29 beer 1 2019-12-31 coding emacs-tracker 1 2019-12-31 wine 2 2020-01-02 bike commute 11 January 1, 2020 7:10 pm beer 1 04/Jan/2020 coding emacs-scrum 2 4 Jan 2020 coding emacs-scrum 2 Jan 4, 2020 run time 18 Jan 4, 2020 run dist 2 04/Jan/2020 10:00pm beer 1

+end_SRC

*** whitelist / blacklist

by default metrics-tracker will pick up any diary entries that match
the format it is looking for, which means it might pick up entries
you don't want in your report.  if there are a few metrics that
get picked up that you don't want to see, you can exclude them by
adding them to ~metrics-tracker-metric-names-blacklist~.  this custom
variable takes a list of metric names as a list of strings, such
as:

+BEGIN_SRC

'("run time" "run dist")

+end_SRC

if metrics-tracker picks up lots of metrics that you don't want to see,
you could instead whitelist the ones you want by adding them to
the ~metrics-tracker-metric-names-whitelist~ custom variable.  this uses
the same format as ~metrics-tracker-metric-names-blacklist~.  if you
specify a whitelist, only those are considered and the blacklist
is ignored.

** reporting

metrics-tracker provides several ways to extract information from the metrics data in your diary.

*** standard options

reports are configured with several options.

**** metric name

 metric name tells metric-tracker the name of the metric or
 metrics to include in the current report.  ~cal~ reports can only
 use one metric, but ~table~ and ~graph~ reports can combine
 multiple.

**** date grouping

 date grouping tells metrics-tracker how many days to clump
 together.  in a graph, this is the x axis.

 possible choices:
 - day
 - week
 - month
 - year
 - full

**** value transform

 the value transform tells metrics-tracker what the value at each
 date grouping should mean.  this controls how entries within
 each date grouping are combined and transformed.

 possible choices:
 - total :: sum all of the values in the date grouping
 - count :: count entries in the date grouping
 - accum :: accumulate entries
 - accum-count :: accumulate entry counts
 - min :: the minimum of all values in a date grouping
 - max :: the maximum of all values in a date grouping
 - avg :: the average of all values in a date grouping
 - percent :: percent of days within the date grouping with an entry
 - per-day :: the average value for each day in the date grouping
 - per-week :: the average value for each week in the date grouping
 - per-month :: the average value for each month in the date grouping
 - per-year :: the average value for each year in the date grouping
 - diff-total :: the difference of ~total~ from one date grouping to the next
 - diff-count :: the difference of ~count~ from one date grouping to the next
 - diff-min :: the difference of ~min~ from one date grouping to the next
 - diff-max :: the difference of ~max~ from one date grouping to the next
 - diff-avg :: the difference of ~avg~ from one date grouping to the next
 - diff-percent :: the difference of ~percent~ from one date grouping to the next
 - diff-per-day :: the difference of ~per-day~ from one date grouping to the next
 - diff-per-week :: the difference of ~per-week~ from one date grouping to the next
 - diff-per-month :: the difference of ~per-month~ from one date grouping to the next
 - diff-per-year :: the difference of ~per-year~ from one date grouping to the next

**** date range

 it is possible to restrict reports to specified date ranges.  you
 can specify either the start date, end date, neither, or both.

 as with diary entry dates, date range strings may be specified in
 any date format ~parse-time-string~ can use.

**** graph-type [graphs only]

 metrics-tracker can present metrics data using various graph types.

 possible choices:
 - line
 - bar
 - stacked
 - scatter

**** graph-output [graphs only]

 the graph output option specifies the file format for the graph.

 possible choices:
 - ascii
 - svg
 - png

*** index report

@@html:<kbd>@@M-x@@html:</kbd>@@ ~metrics-tracker-index~

this creates a table containing all of the metrics found in your
emacs diary.  the index is like a dashboard.  it gives you a broad
overview of everything you're tracking.

by default it is sorted by recency.  I find it useful to glance
down the list occasionally to see the metrics I've been away from
for a long time.

the sort column and direction can be changed by moving over
another column and hitting ~S~.  the arrow in the header indicates
the sort column and direction.

the index report has the following columns:
- metric :: the metric name
- days ago :: the number of days since "last"
- first :: the date of the first entry
- last :: the date of the last entry
- count :: the number of entries for this metric

*** table report

@@html:<kbd>@@M-x@@html:</kbd>@@ ~metrics-tracker-table~

emacs will prompt for the following input parameters:
- metric name
- date grouping
- value transform

@@html:<kbd>@@C-u@@html:</kbd>@@ @@html:<kbd>@@M-x@@html:</kbd>@@
~metrics-tracker-table~

with an argument, emacs will accept multiple metrics and prompt
for the following additional parameters:
- start-date
- end-date

table report creates a table containing the transformed data for
the requested metric(s).

the table can be sorted by either column by moving over the column
and hitting ~S~.  the arrow in the header indicates the sort
column and direction.

if the date grouping is ~full~ and the report only includes one
metric, the result is just one value.  instead of rendering a
table with one value, metrics-tracker will print it in the echo
area.

*** graph report

metrics-tracker can generate graphs from metric data.  it uses
gnuplot for graph generation, so gnuplot must be installed on your
system and available on your ~PATH~.  I tested with gnuplot 5.0.

@@html:<kbd>@@M-x@@html:</kbd>@@ ~metrics-tracker-graph~

emacs will prompt for the following input parameters:
- metric name
- date grouping
- value transform
- graph-type
- graph-output

@@html:<kbd>@@C-u@@html:</kbd>@@ @@html:<kbd>@@M-x@@html:</kbd>@@
~metrics-tracker-graph~

with an argument, emacs will accept multiple metrics and prompt
for the following additional parameters:
- start-date
- end-date

*** calendar report

@@html:<kbd>@@M-x@@html:</kbd>@@ ~metrics-tracker-cal~

metrics-tracker can render metric data onto a calendar.  the
number at each date position is one of:
- period :: no metric was recorded on this day
- underscore :: before first metric entry or after last one
- number :: the value for the day

emacs will prompt for the following input parameters:
- metric-name
- value transform

@@html:<kbd>@@C-u@@html:</kbd>@@ @@html:<kbd>@@M-x@@html:</kbd>@@
~metrics-tracker-cal~

with an argument, emacs will prompt for the following additional
parameters:
- start-date
- end-date

** derived metrics

it is possible to derive metrics by combining existing metrics using mathematical expressions by editing `metrics-tracker-derived-metrics' in [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Easy-Customization.html][customize]]. the expression uses ~$N~ to refer to the Nth metric the derived metric is based on. for example, if you have metrics for "run dist" and "run time" you could define a derived metric called "run mph" which is based on those metrics and defined as ~$1/$2~.

the expression is optional. if no expression is given, all base metrics are summed together (as if the expression was ~$1 + $2 + ... + $N~). for example, if you have one metric for "running" and another for "cycling" then you can create a derived metric called "cardio" that depends on them and omit the expression. cardio will be the total of running and cycling. when you sum metrics like this, the ~total~ may become meaningless if you recorded them in different units, but the ~percent~ and ~count~ will still be useful.

derived metrics can be based on other derived metrics, but cycles are obviously not allowed. since it is easy to combine metrics in this way, you can record metrics as granularly as you want, and put them together when you view them. the following image is a dependency graph (not generated by metrics-tracker) showing my derived metrics and their dependencies to get an idea of how metrics can be combined.

[[https://ianxm-githubfiles.s3.amazonaws.com/emacs-tracker/depgraph_60pct_v3.png]]

derived metrics can be used in all reports as if they were base metrics.

*** goodness metric

because derived metrics can accept arbitrary math expressions, it is possible to create a derived metric that combines all of your metrics, scaling to normalize them and negating metrics that are "bad." the result would be your "goodness," according to your own definition of what is it to be good. you could then compare your goodness from week to week or year to year.

** named reports

to make it easier to pull up a report that you use repeatedly, you can save it as a named report. do this by generating the report and then invoking

@@html:kbd>@@M-x@@html:</kbd@@ ~metrics-tracker-save-named-report~

or by modifying the variable ~metrics-tracker-named-reports~ in [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Easy-Customization.html][customize]]. the fields in named reports are the same as the input parameters requested during report generation.

you can display a named report by running

@@html:kbd>@@M-x@@html:</kbd@@ ~metrics-tracker-show-named-report~

and choosing which report to show from the list. the report will be rendered using current data (not the data at the time the report was saved).

** date grouping clipping

if the value transform is set to ~percent~ or one of the ~per-...~ options, the metric value is scaled by the number of days in the date grouping. for example, if date grouping is year and value transform is ~per-month~, the metric value for each year is divided by 12.

if the current year is incomplete (say it's january) this will appear to undercount it, since we'd divide by 12 but we only have one month of metrics. if the purpose of the graph is to compare performance, then this isn't helpful.

in order to overcome this we divide by the portion of the year that's complete, instead of the whole year. this means that the current year's value will represent what you're on pace to get to by the end of the year, and is comparable to the other values in the graph.

the same applies to the first date grouping. it is clipped to start on the date of the first metric entry.

one unfortunate outcome of this is that if we clip a date grouping to a very short period, our extrapolations may result in numbers that are out of our normal range. for example, if you run two times a week your percent of runs per week is 28%, but if you happen to check your graph on monday, and you happened to have run on sunday and monday, it'll say you've run 100% this week.

** min value transform

metrics-tracker ignores gap-filling zeros when computing minimum value.