Tracking tool for coding statistics, compatible with WakaTime.
Deploy this app to Linode with a free $100 credit!
Installation instructions can be found below and in the Wiki.
Plans for the near future mainly include, besides usual improvements and bug fixes, a UI redesign as well as additional types of charts and statistics (see #101, #76, #12). If you have feature requests or any kind of improvement proposals feel free to open an issue or share them in our user survey.
There are different options for how to use Wakapi, ranging from our hosted cloud service to self-hosting it. Regardless of which option choose, you will always have to do the client setup in addition.
If you want to try out a free, hosted cloud service, all you need to do is create an account and then set up your client-side tooling (see below).
$ curl -L https://wakapi.dev/get | bash
Alternatively using eget:
$ eget muety/wakapi
# Create a persistent volume
$ docker volume create wakapi-data
$ SALT="$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w ${1:-32} | head -n 1)"
# Run the container
$ docker run -d \
-p 3000:3000 \
-e "WAKAPI_PASSWORD_SALT=$SALT" \
-v wakapi-data:/data \
--name wakapi \
ghcr.io/muety/wakapi:latest
Note: By default, SQLite is used as a database. To run Wakapi in Docker with MySQL or Postgres, see Dockerfile and config.default.yml for further options.
If you want to run Wakapi on Kubernetes, there is wakapi-helm-chart for quick and easy deployment.
# Build and install
# Alternatively: go build -o wakapi
$ go install github.com/muety/wakapi@latest
# Get default config and customize
$ curl -o wakapi.yml https://raw.githubusercontent.com/muety/wakapi/master/config.default.yml
$ vi wakapi.yml
# Run it
$ ./wakapi -config wakapi.yml
Note: Check the comments in config.yml
for best practices regarding security configuration and more.
π‘ When running Wakapi standalone (without Docker), it is recommended to run it as a SystemD service.
Wakapi relies on the open-source WakaTime client tools. In order to collect statistics for Wakapi, you need to set them up.
~/.wakatime.cfg
file as follows.[settings]
# Your Wakapi server URL or 'https://wakapi.dev/api' when using the cloud server
api_url = http://localhost:3000/api
# Your Wakapi API key (get it from the web interface after having created an account)
api_key = 406fe41f-6d69-4183-a4cc-121e0c524c2b
Optionally, you can set up a client-side proxy in addition.
You can specify configuration options either via a config file (default: config.yml
, customizable through the -c
argument) or via environment variables. Here is an overview of all options.
YAML key / Env. variable | Default | Description |
---|---|---|
env /ENVIRONMENT |
dev |
Whether to use development- or production settings |
app.aggregation_time /WAKAPI_AGGREGATION_TIME |
0 15 2 * * * |
Time of day at which to periodically run summary generation for all users |
app.report_time_weekly /WAKAPI_REPORT_TIME_WEEKLY |
0 0 18 * * 5 |
Week day and time at which to send e-mail reports |
app.leaderboard_generation_time /WAKAPI_LEADERBOARD_GENERATION_TIME |
0 0 6 * * *,0 0 18 * * * |
One or multiple times of day at which to re-calculate the leaderboard |
app.data_cleanup_time /WAKAPI_DATA_CLEANUP_TIME |
0 0 6 * * 0 |
When to perform data cleanup operations (see app.data_retention_months ) |
app.import_batch_size /WAKAPI_IMPORT_BATCH_SIZE |
50 |
Size of batches of heartbeats to insert to the database during importing from external services |
app.inactive_days /WAKAPI_INACTIVE_DAYS |
7 |
Number of days after which to consider a user inactive (only for metrics) |
app.heartbeat_max_age / WAKAPI_HEARTBEAT_MAX_AGE |
4320h |
Maximum acceptable age of a heartbeat (see ParseDuration ) |
app.custom_languages |
- | Map from file endings to language names |
app.avatar_url_template /WAKAPI_AVATAR_URL_TEMPLATE |
(see config.default.yml ) |
URL template for external user avatar images (e.g. from Dicebear or Gravatar) |
app.support_contact /WAKAPI_SUPPORT_CONTACT |
hostmaster@wakapi.dev |
E-Mail address to display as a support contact on the page |
app.data_retention_months /WAKAPI_DATA_RETENTION_MONTHS |
-1 |
Maximum retention period in months for user data (heartbeats) (-1 for unlimited) |
server.port /WAKAPI_PORT |
3000 |
Port to listen on |
server.listen_ipv4 /WAKAPI_LISTEN_IPV4 |
127.0.0.1 |
IPv4 network address to listen on (leave blank to disable IPv4) |
server.listen_ipv6 /WAKAPI_LISTEN_IPV6 |
::1 |
IPv6 network address to listen on (leave blank to disable IPv6) |
server.listen_socket /WAKAPI_LISTEN_SOCKET |
- | UNIX socket to listen on (leave blank to disable UNIX socket) |
server.listen_socket_mode /WAKAPI_LISTEN_SOCKET_MODE |
0666 |
Permission mode to create UNIX socket with |
server.timeout_sec /WAKAPI_TIMEOUT_SEC |
30 |
Request timeout in seconds |
server.tls_cert_path /WAKAPI_TLS_CERT_PATH |
- | Path of SSL server certificate (leave blank to not use HTTPS) |
server.tls_key_path /WAKAPI_TLS_KEY_PATH |
- | Path of SSL server private key (leave blank to not use HTTPS) |
server.base_path /WAKAPI_BASE_PATH |
/ |
Web base path (change when running behind a proxy under a sub-path) |
server.public_url /WAKAPI_PUBLIC_URL |
http://localhost:3000 |
URL at which your Wakapi instance can be found publicly |
security.password_salt /WAKAPI_PASSWORD_SALT |
- | Pepper to use for password hashing |
security.insecure_cookies /WAKAPI_INSECURE_COOKIES |
false |
Whether or not to allow cookies over HTTP |
security.cookie_max_age /WAKAPI_COOKIE_MAX_AGE |
172800 |
Lifetime of authentication cookies in seconds or 0 to use Session cookies |
security.allow_signup /WAKAPI_ALLOW_SIGNUP |
true |
Whether to enable user registration |
security.expose_metrics /WAKAPI_EXPOSE_METRICS |
false |
Whether to expose Prometheus metrics under /api/metrics |
db.host /WAKAPI_DB_HOST |
- | Database host |
db.port /WAKAPI_DB_PORT |
- | Database port |
db.socket /WAKAPI_DB_SOCKET |
- | Database UNIX socket (alternative to host ) (for MySQL only) |
db.user /WAKAPI_DB_USER |
- | Database user |
db.password /WAKAPI_DB_PASSWORD |
- | Database password |
db.name /WAKAPI_DB_NAME |
wakapi_db.db |
Database name |
db.dialect /WAKAPI_DB_TYPE |
sqlite3 |
Database type (one of sqlite3 , mysql , postgres , cockroach ) |
db.charset /WAKAPI_DB_CHARSET |
utf8mb4 |
Database connection charset (for MySQL only) |
db.max_conn /WAKAPI_DB_MAX_CONNECTIONS |
2 |
Maximum number of database connections |
db.ssl /WAKAPI_DB_SSL |
false |
Whether to use TLS encryption for database connection (Postgres and CockroachDB only) |
db.automgirate_fail_silently /WAKAPI_DB_AUTOMIGRATE_FAIL_SILENTLY |
false |
Whether to ignore schema auto-migration failures when starting up |
mail.enabled /WAKAPI_MAIL_ENABLED |
true |
Whether to allow Wakapi to send e-mail (e.g. for password resets) |
mail.sender /WAKAPI_MAIL_SENDER |
Wakapi <noreply@wakapi.dev> |
Default sender address for outgoing mails (ignored for MailWhale) |
mail.provider /WAKAPI_MAIL_PROVIDER |
smtp |
Implementation to use for sending mails (one of [smtp , mailwhale ]) |
mail.smtp.host /WAKAPI_MAIL_SMTP_HOST |
- | SMTP server address for sending mail (if using smtp mail provider) |
mail.smtp.port /WAKAPI_MAIL_SMTP_PORT |
- | SMTP server port (usually 465) |
mail.smtp.username /WAKAPI_MAIL_SMTP_USER |
- | SMTP server authentication username |
mail.smtp.password /WAKAPI_MAIL_SMTP_PASS |
- | SMTP server authentication password |
mail.smtp.tls /WAKAPI_MAIL_SMTP_TLS |
false |
Whether the SMTP server requires TLS encryption (false for STARTTLS or no encryption) |
mail.mailwhale.url /WAKAPI_MAIL_MAILWHALE_URL |
- | URL of MailWhale instance (e.g. https://mailwhale.dev ) (if using mailwhale mail provider) |
mail.mailwhale.client_id /WAKAPI_MAIL_MAILWHALE_CLIENT_ID |
- | MailWhale API client ID |
mail.mailwhale.client_secret /WAKAPI_MAIL_MAILWHALE_CLIENT_SECRET |
- | MailWhale API client secret |
sentry.dsn /WAKAPI_SENTRY_DSN |
β | DSN for to integrate Sentry for error logging and tracing (leave empty to disable) |
sentry.enable_tracing /WAKAPI_SENTRY_TRACING |
false |
Whether to enable Sentry request tracing |
sentry.sample_rate /WAKAPI_SENTRY_SAMPLE_RATE |
0.75 |
Probability of tracing a request in Sentry |
sentry.sample_rate_heartbeats /WAKAPI_SENTRY_SAMPLE_RATE_HEARTBEATS |
0.1 |
Probability of tracing a heartbeat request in Sentry |
quick_start /WAKAPI_QUICK_START |
false |
Whether to skip initial boot tasks. Use only for development purposes! |
Wakapi uses GORM as an ORM. As a consequence, a set of different relational databases is supported.
See our Swagger API Documentation.
$ go install github.com/swaggo/swag/cmd/swag@latest
$ swag init -o static/docs
You can export your Wakapi statistics to Prometheus to view them in a Grafana dashboard or so. Here is how.
# 1. Start Wakapi with the feature enabled
$ export WAKAPI_EXPOSE_METRICS=true
$ ./wakapi
# 2. Get your API key and hash it
$ echo "<YOUR_API_KEY>" | base64
# 3. Add a Prometheus scrape config to your prometheus.yml (see below)
# prometheus.yml
# (assuming your Wakapi instance listens at localhost, port 3000)
scrape_configs:
- job_name: 'wakapi'
scrape_interval: 1m
metrics_path: '/api/metrics'
bearer_token: '<YOUR_BASE64_HASHED_TOKEN>'
static_configs:
- targets: ['localhost:3000']
There is also a nice Grafana dashboard, provided by the author of wakatime_exporter.
Wakapi plays well together with WakaTime. For one thing, you can forward heartbeats from Wakapi to WakaTime to effectively use both services simultaneously. In addition, there is the option to import historic data from WakaTime for consistency between both services. Both features can be enabled in the Integrations section of your Wakapi instance's settings page.
Wakapi also integrates with GitHub Readme Stats to generate fancy cards for you. Here is an example.
![](https://github-readme-stats.vercel.app/api/wakatime?username={yourusername}&api_domain=wakapi.dev&bg_color=2D3748&title_color=2F855A&icon_color=2F855A&text_color=ffffff&custom_title=Wakapi%20Week%20Stats&layout=compact)
There is a WakaTime plugin for GitHub Metrics that is also compatible with Wakapi.
Preview:
- uses: lowlighter/metrics@latest
with:
# ... other options
plugin_wakatime: yes
plugin_wakatime_token: ${{ secrets.WAKATIME_TOKEN }} # Required
plugin_wakatime_days: 7 # Display last week stats
plugin_wakatime_sections: time, projects, projects-graphs # Display time and projects sections, along with projects graphs
plugin_wakatime_limit: 4 # Show 4 entries per graph
plugin_wakatime_url: http://wakapi.dev # Wakatime url endpoint
plugin_wakatime_user: .user.login # User
It is recommended to use wakapi behind a reverse proxy, like Caddy or nginx, to enable TLS encryption (HTTPS).
However, if you want to expose your wakapi instance to the public anyway, you need to set server.listen_ipv4
to 0.0.0.0
in config.yml
.
Unit tests are supposed to test business logic on a fine-grained level. They are implemented as part of the application, using Go's testing package alongside stretchr/testify.
$ CGO_ENABLED=0 go test `go list ./... | grep -v 'github.com/muety/wakapi/scripts'` -json -coverprofile=coverage/coverage.out ./... -run ./...
API tests are implemented as black box tests, which interact with a fully-fledged, standalone Wakapi through HTTP requests. They are supposed to check Wakapi's web stack and endpoints, including response codes, headers and data on a syntactical level, rather than checking the actual content that is returned.
Our API (or end-to-end, in some way) tests are implemented as a Postman collection and can be run either from inside Postman, or using newman as a command-line runner.
To get a predictable environment, tests are run against a fresh and clean Wakapi instance with a SQLite database that is populated with nothing but some seed data (see data.sql). It is usually recommended for software tests to be safe, stateless and without side effects. In contrary to that paradigm, our API tests strictly require a fixed execution order (which Postman assures) and their assertions may rely on specific previous tests having succeeded.
# 1. sqlite (cli)
$ sudo apt install sqlite # Fedora: sudo dnf install sqlite
# 2. newman
$ npm install -g newman
$ ./testing/run_api_tests.sh
To keep things minimal, all JS and CSS assets are included as static files and checked in to Git. TailwindCSS and Iconify require an additional build step. To only require this at the time of development, the compiled assets are checked in to Git as well.
$ yarn
$ yarn build # or: yarn watch
New icons can be added by editing the icons
array in scripts/bundle_icons.js.
As explained in #284, precompressed (using Brotli) versions of some of the assets are delivered to save additional bandwidth. This was inspired by Caddy's precompressed
directive. gzipped.FileServer
checks for every static file's .br
or .gz
equivalents and, if present, delivers those instead of the actual file, alongside Content-Encoding: br
. Currently, compressed assets are simply checked in to Git. Later we might want to have this be part of a new build step.
To pre-compress files, run this:
# Install brotli first
$ sudo apt install brotli # or: sudo dnf install brotli
# Watch, build and compress
$ yarn watch:compress
# Alternatively: build and compress only
$ yarn build:all:compress
# Alternatively: compress only
$ yarn compress
Since Wakapi heavily relies on the concepts provided by WakaTime, their FAQs largely apply to Wakapi as well. You might find answers there.
|---o---o--------------o---o---|
| |10s| 3m |10s| |
It is unclear how to handle the three minutes in between. Did the developer do a 3-minute break, or were just no heartbeats being sent, e.g. because the developer was staring at the screen trying to find a solution, but not actually typing code?
Coding in open source is my passion and I would love to do it on a full-time basis and make a living from it one day. So if you like this project, please consider supporting it π. You can donate either through buying me a coffee or becoming a GitHub sponsor. Every little donation is highly appreciated and boosts my motivation to keep improving Wakapi!
I highly appreciate the efforts of @alanhamlett and the WakaTime team and am thankful for their software being open source.
Moreover, thanks to Frachtwerk for sponsoring server infrastructure for Wakapi.dev.
GPL-v3 @ Ferdinand MΓΌtsch
Please login to review this project.
No reviews for this project yet.
Open source API to compile and run source code.
Self-hosted server for source code parsing. It can parse anβ¦
Open source workspace server and cloud IDE.
Comments (0)
Please login to join the discussion on this project.