Toujou

Toujou: Performance Tracking Platform
Login

Toujou: Performance Tracking Platform

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:

Viewer HTML Frontend (external) Webhook trigger runs Runner 1 Runner n . . . trigger trigger DataAPI (internal-only) data data Database read-only read/write
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>

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:

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:

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:

Installation:

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:

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.