A minimal, lightweight self-hosted web service which tracks and visualizes code performance metrics over time.
Benchmark runs are triggered manually or by webhooks, such as pushes to a GitHub repository. Benchmarks execute using an extensible set of benchmarking tools, allowing for analysis of projects written in any language. Results are pushed via an internal-only API into a database, from which an (optionally) public-facing web service will make those metrics accessible. This frontend displays the data in a manner which makes it easy to understand trends over time, as well as catch and track down regressions quickly.
⚠ NOTE: Unlike most of my projects, this code is AGPL licensed.
Architecture Overview
Toujou is split into 3 main components:
- Runner (executes benchmarks)
- DataAPI (receives benchmark data from runners)
- Viewer (serves the frontend)
Viewer: box "Viewer" arrow right "HTML" above from east of Viewer Web: ellipse "Frontend" "(external)" small move left 1.2 from Viewer Hook: ellipse "Webhook" arrow "trigger runs" above from Hook.e to Viewer.w Runner1: circle "Runner" "1" at 1.3 heading 200 from Viewer Runner2: circle "Runner" "n" italic at 1.3 heading 160 from Viewer DotBox: box invisible ". . ." with .w at Runner1.e width (Runner2.w.x-Runner1.e.x) arrow <- "trigger" above aligned from Runner1 chop to 1/3<Viewer.sw,Viewer.se> arrow -> "trigger" above aligned from 2/3<Viewer.sw,Viewer.se> to Runner2 chop move down 2 from Viewer API: box "DataAPI" "(internal-only)" small arrow -> "data" below aligned from Runner1 to 1/3<API.nw,API.ne> chop arrow <- "data" below aligned from 2/3<API.nw,API.ne> to Runner2 chop DB: cylinder "Database" with .e at 2cm left of Runner1 arrow "read-only" above aligned from 2/3<DB.se,DB.ne> to 2/3<Viewer.nw,Viewer.sw> arrow <-> "read/write" above aligned from 1/3<DB.se,DB.ne> to 1/3<API.nw,API.sw>→ /pikchrshow
Components
As long as .NET 8+, PowerShell Core 7+, and PostgreSQL are supported on your platform, Toujou should work. However, I only run on Windows and Windows Server, and cannot offer support for other platforms.
ToujouRunner
Implemented as PowerShell scripts, which operate based on a JSON config file. The scripts will download the repository for a specific commit, and run a benchmark script in the repositry. Once benchmarks are completed, the results are parsed and uploaded to ToujouDataAPI.
Requirements:
- PowerShell Core 7+ - (PowerShell that is pre-installed on Windows is too old)
- .NET SDK 8+ - if benchmarking .NET code
- Compilers for any other languages used in your projects
- A local administrator account if hardware counter data should be collected
Config File Template
{
"APIBaseURL": "http://ToujouDataAPIServer/api/v1",
"Projects":
{
"MyProject":
{
"RepositoryType": "Git",
"RepositoryURL": "https://github.com/Me/My_Project.git",
"DirectoryName": "My Project",
"Benchmarks":
[
{
"Type": "BenchmarkDotNet",
"Command": "./Tests/ToujouRunBDNBenchmarks.ps1"
}
]
}
}
}
ToujouDataAPI
⚠ WARNING: ToujouDataAPI is entirely unauthenticated, exposes database write access, and as such must not be made internet-accessible or used on any untrusted networks.
Implemented as a .NET application that can run in IIS or standalone (via Kestrel). Connects to the database over a TCP connection.
Requirements:
- .NET Runtime 8+
- Firewall exception to allow connections from the local network
Specify the database connection string in appsettings.json:
{
// (other settings)
"DatabaseConnection": "Host=dbserver;Username=toujou_rw;Password=AlsoSecure;Database=ToujouDB"
}
Database
At this time, only PostgreSQL is supported.
Requirements:
- PostgreSQL 17+ (will likely work on somewhat older versions, untested)
- A database user with read-only access for ToujouViewer
- A database user with write access for ToujouDataAPI
Installation:
- Install PostgeSQL if you do not have an installation prepared already.
- On Windows Server, I download the latest installer (replace the version below):
$PostgresVersion = '18.3.2'; Invoke-WebRequest "https://get.enterprisedb.com/postgresql/postgresql-$PostgresVersion-windows-x64.exe" -OutFile "postgresql-$PostgresVersion-windows-x64.exe" - Run the installer (for GUI installer):
& "postgresql-$PostgresVersion-windows-x64.exe" - Alternatively, run the installer in silent mode (replace the password):
& "postgresql-$PostgresVersion-windows-x64.exe" --unattendedmodeui none --mode unattended --datadir "C:\PostgresData" --serverport 5432 --superpassword PASSWORDHERE
- On Windows Server, I download the latest installer (replace the version below):
- Create a database named
ToujouDB(or what you prefer) for Toujou using superuser accountpostgres:& "C:\Program Files\PostgreSQL\17\bin\createdb.exe" -U postgres -p 5432 ToujouDB - Start the PostgreSQL shell as superuser account
postgres(or what you prefer):& "C:\Program Files\PostgreSQL\17\bin\psql.exe" -U postgres -p 5432- Create user accounts (use different, secure passwords obviously):
CREATE USER toujou_ro WITH PASSWORD 'SomethingSecure'; CREATE USER toujou_rw WITH PASSWORD 'AlsoSecure'; - Assign permissions for read-only user:
\c ToujouDB GRANT CONNECT ON DATABASE "ToujouDB" TO toujou_ro; GRANT USAGE ON SCHEMA public TO toujou_ro; GRANT SELECT ON ALL TABLES IN SCHEMA public TO toujou_ro; GRANT SELECT ON ALL SEQUENCES IN SCHEMA public TO toujou_ro; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO toujou_ro; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON SEQUENCES TO toujou_ro; - Assign permissions for write user:
GRANT CONNECT ON DATABASE "ToujouDB" TO toujou_rw; GRANT USAGE ON SCHEMA public TO toujou_rw; GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO toujou_rw; GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO toujou_rw; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO toujou_rw; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON SEQUENCES TO toujou_rw; - Exit the shell
exit
- Create user accounts (use different, secure passwords obviously):
- Add the new user accounts to the
pg_hba.conffile located in the data directory used during installation:- This config assumes the database and public-facing webserver (ToujouViewer) are running on the same machine, but ToujouDataAPI is on a different host. Adapt the config to your environment as necessary.
host ToujouDB toujou_ro 127.0.0.1/32 scram-sha-256 host ToujouDB toujou_rw 192.168.xxx.xxx/32 scram-sha-256
- This config assumes the database and public-facing webserver (ToujouViewer) are running on the same machine, but ToujouDataAPI is on a different host. Adapt the config to your environment as necessary.
- Adjust config
- By default, only connections from localhost may be allowed. Adjust
listen_addressesinpostgresql.confif you need to connect from other machines.
- By default, only connections from localhost may be allowed. Adjust
- Configure backup and maintenance tasks appropriate for your environment.
ToujouViewer
Implemented as a .NET application that can run in IIS or standalone (via Kestrel). Connects to the database over a TCP connection. Intended to be publicly-accessible if desired.
Requirements:
I run ToujouViewer as an in-process IIS hosted application, as this was the best fit for my existing infrastructure. PRs with documentation for setting up in any other environments welcomed.
Specify the database connection string for a user with read-only privileges in appsettings.json:
{
// (other settings)
"DatabaseConnectionReadOnly": "Host=dbserver;Username=toujou_ro;Password=SomethingSecure;Database=ToujouDB"
}
Utilities
TODO
Help Wanted
This project is the first time I've done any web backend development in ~10 years, my first time using ASP.NET and PostgreSQL, my first time using C# async, and is generally well outside of my expertise. Please open issues for any problems you encounter or issues you find in the code.
Here is a partial list of things I'd welcome pull requests for:
- Documentation corrections or additional documentation for different hosting configurations
- ToujouRunner template PowerShell scripts to compile/run benchmarks for projects that are written in non-.NET languages
- Performance improvements (of course!)
- UI appearance fixes
- Authentication for ToujouDataAPI
- Please only take this on if you are sufficiently experienced in ASP.NET to properly implement this. I prefer no authentication over a false sense of security offered by poorly implemented authentication.
But... For things not mentioned here that you'd like to contribute, please open an issue to discuss first, as I intend to keep this project lean in order to minimize support overhead and code complexity. As maintenance of your submitted code ultimately falls on me, I will not accept code written in languages I don't wish to maintain, such as Python, Perl, Bash, etc. You are of course welcome to implement any functionality you wish, in any way you wish, in your own fork.