工时统计工具汇总
develop
难道不想看看自己每天都干了啥嘛~
统计工时的原理本质上就是:
- 工作时工作需要使用的软件上的某个插件每隔一段时间发送数据到统计工具的服务器上
- 统计工具的服务器每隔一段时间通过邮件、微信、钉钉机器人等发送工时信息的通知
- 统计工具提供一个可视化的网站
统计工具
统计工具通过插件统计每天工作的时间。这些插件可以包括:
- 编辑器
- 浏览器
- REPL
- 办公软件(Office)
- 修图软件
- 翻译软件
- …
为了防止挂机,插件要在规定时间间隔内发心跳信号。最终显示不同系统不同编辑器不同语言不同项目的工作时间。
或者统计操作次数,一次操作称为 1 点经验:
- 编辑器中插入、删除、粘贴等
- REPL 中输入一条命令。因为大多数 REPL 不支持统计插入、删除、粘贴次数,但 zsh 因为有强大的 zle (zsh line editor) 可以。
不用发心跳信号,可以计算经验后一次性 post 到统计工具的服务器上。
一般统计操作次数的统计工具插件更难实现。最终显示不同机器不同语言不同时间段的操作次数。
-
wakatime
- 服务器不开源、插件代码开源
- 目前用户最多
- 数据保留更多时间要付费
- 引入了排行榜:可以看到别人一天写多长时间代码,互相攀比非常好玩
- 封装了 1 个命令行接口。可以直接调用此接口降低插件开发难度。
- 插件数量多。笔者也参与了一些插件开发,比如统计 python REPL / perl REPL 的使用时间
- 不光统计编程,浏览网页、修图甚至翻译都会被统计。笔者在编写一个命令行的翻译软件时就利用其功能统计翻译时间。
-
codetime
- 服务器、插件代码开源
- 国人出品
- 目前只支持 3 个插件
-
rescuetime
- 不开源
- 不支持显示具体每个项目,只能看到所有项目的时间总和
- 数据保留更多时间要付费
-
codestats:目前唯一一个统计操作次数的统计工具
- 服务器、插件代码开源
- 靠官网上广告盈利
- 引入了等级设定:按开方关系从经验计算等级。等级越高升级所需经验越多。笔者个人感觉看编程语言升级是一件非常有成就感的事情。
可以查看开源代码来了解插件需要获取哪些信息防止数据盗取。
徽章
可以通过统计工具的接口获取工时信息。用途是实现徽章以放置在你的主页上或者下载以备份。一般统计工具都提供了封装好的接口。
XP 是经验的缩写!!!
数据同步
因为不少统计工具的数据保留更多时间要付费,所以可以将每天的数据下载下来以备份。
-
wf2311/wakatime-sync
- 用 java 开发
- 把 wakatime 的信息下载后保存为 mysql 的数据库格式
- 支持 Server 酱、钉钉机器人的通知。即可以每天在微信、钉钉收到昨天的 wakatime 信息提醒
- superman66/wakatime-sync
on:
schedule:
# modify by yourself
- cron: MM HH dd mm ww
workflow_dispatch:
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: superman66/wakatime-sync@v1.0.0
env:
GH_TOKEN: $
GIST_ID: $
WAKATIME_API_KEY: $
SCU_KEY: $
数据可视化
需要对下载的数据进行可视化。
-
wf2311/wakatime-sync: 也包含可视化代码
-
效果不错,支持:
-
效果不错,支持:
- superman66/wakatime-dashboard:
插件开发
再多提一嘴关于插件的开发。因为普通用户对这个可能不感兴趣所以放在了最后。
按编程范式来分,这是典型的事件驱动编程:当某个事件触发时,执行一个回调函数,在回调函数中向 wakatime / codestats 的服务器发送信息。 wakatime 因为提供了 wakatime-cli 所以会简单一点,只需要在后台另起一个 detach 的子进程即可。
笔者负责了 wakatime 的一些编程语言的 REPL , gdb 的插件开发:
不同的软件提供了不同的回调函数(钩子 hook 或句柄 handle ):
- vim:
autocmd InsertEnter * call namespace#function_name()
每次进入插入模式调用函数。 - REPL:
- 有些 REPL 的命令提示符是一个函数,相关截图参见
REPL 主题。所以我们可以把向服务器发送信息的指令放在命令提示符的函数体内。
- python 的命令提示符是
str(sys.ps1)
, 定义sys.ps1.__str__()
即可 - perl reply 的命令提示符是
prompt()
- lua prompt 的命令提示符是
(require "prompt").prompts[0]
, 可以是字符串或函数 - tcl readline 的命令提示符是函数
::tclreadline::prompt1
- python 的命令提示符是
- 有些 REPL 的命令提示符是一个格式化字符串。例如
$PS1
可以是类似\w
,\t
构成的格式化字符串,\\
开头的子字符串会被替换为当前目录名,时间等等。这些 REPL 需要提供别的钩子函数。- bash:
$PROMPT_COMMAND
是一个由若干函数名通过;
连接的字符串。每个函数会在每次命令提示符重新生成的时候被调用 - zsh:
precmd_functions
是一个由若干函数名组成的数组。每个函数会在每次命令提示符重新生成的时候被调用 - gdb:
- 函数
hook-XXX
会在执行XXX
命令的时候被调用 - 函数
hook-stop
在每次单步调试 next ,步入 step 等都会被调用。
- 函数
- bash:
- 有些 REPL 的命令提示符是一个函数,相关截图参见
REPL 主题。所以我们可以把向服务器发送信息的指令放在命令提示符的函数体内。
笔者也希望更多开发者尝试开发相关插件,以便更好地统计大家每天使用各种软件的时间
总结
工时统计主要是用于个人编写周报时回顾工作内容。然而似乎也有一些公司部门试图用其做 KPI 考核。私以为不妥。在有开源软件代码审核员呼吁大公司不要刷 KPI 的前车之鉴下,古德哈特定律必将再次灵验:
若一个经济学的特性被用作经济指标,那这项指标最终一定会失去其功能,因为人们会开始玩弄这项指标。
– 查尔斯·古德哈特