IndifferentKetchup Codex
Generic PHP log parsing and analysis framework. Reads a log file, detects which log type it is, parses entries (including multi-line records like Java stack traces), runs the type-specific analysers, and returns structured Information and Problem insights with attached Solutions where applicable.
Originally a fork of aternos/codex; the framework is intentionally game-agnostic. The reference implementation in this tree is Project Zomboid server logs.
Install
composer require indifferentketchup/codex
Requires PHP >=8.4. No third-party runtime dependencies.
Quick start
Given a Project Zomboid DebugLog-server.txt:
<?php
require __DIR__ . '/vendor/autoload.php';
use IndifferentKetchup\Codex\Detective\ProjectZomboid\ProjectZomboidDetective;
use IndifferentKetchup\Codex\Log\File\PathLogFile;
$detective = new ProjectZomboidDetective();
$detective->setLogFile(new PathLogFile('2026-04-30_14-00_DebugLog-server.txt'));
$log = $detective->detect();
$log->parse();
$analysis = $log->analyse();
echo $log->getTitle(), "\n\n";
foreach ($analysis->getInformation() as $info) {
echo "[INFO] ", $info->getMessage(), "\n";
}
foreach ($analysis->getProblems() as $problem) {
echo "[PROBLEM] ", $problem->getMessage(), "\n";
foreach ($problem->getSolutions() as $solution) {
echo " -> ", $solution->getMessage(), "\n";
}
}
For a session with mod issues and a server-side exception, output looks roughly like:
Project Zomboid Debug Server Log
[INFO] Engine version: 42.16.3 (build <hash>, <build date>)
[INFO] Mod loaded: <mod_id>
[INFO] Mod loaded: <other_mod_id>
[PROBLEM] Required mod "<missing>" not found.
-> Subscribe to mod "<missing>" or remove its ID from the Mods= line in serverconfig.ini.
[PROBLEM] Exception thrown: java.nio.file.NoSuchFileException
If the log content arrives without a filesystem path (clipboard paste, web upload, stream), use StringLogFile or StreamLogFile instead of PathLogFile. The detective falls back to content signatures when the filename hint is absent.
Architecture
LogFile → Log → parse() → Entry[] of Line[] → analyse() → Analysis of Insight[]
└── Information | Problem(+Solutions)
Detectiveranks candidateLogsubclasses by running each candidate's staticgetDetectors()and picking the highest-scoring result. Each game ships its own<Game>Detectivethat pre-registers its log classes.PatternParseris regex-driven; lines that don't match the entry-start regex append to the previousEntry, which is how multi-line records (Java stack traces, indented warnings) are kept intact.- Analysers come in two flavours: configured
PatternAnalyserinstances for per-entry pattern matching, and custom subclasses ofAnalyserfor cross-entry logic (pairing events, sliding-window thresholds, snapshot comparisons). - Insights are either
Information(label + value) orProblem(with attachedSolutions). Equal insights coalesce via a counter, so repeated patterns don't produce duplicate output.
Patterns live as plain string constants under src/Pattern/<Game>/ — there is no PatternInterface. Each game adds files under src/<Component>/<Game>/ (components-outer, game-suffixed). Full extension guide and conventions in CLAUDE.md.
Game support
| Game | State |
|---|---|
| Project Zomboid | Full: 11 log subclasses across all the file types a server emits; analysers covering engine version, mod loading, server exceptions, PvP combat, admin audit, connection failures, item duplication, skill progression anomalies |
| Minecraft | Stub only — MinecraftDetective skeleton, no log subclasses yet |
| Hytale | Stub only |
| Seven Days To Die | Stub only |
The framework itself is generic — adding a new game means writing the same shape of files Project Zomboid demonstrates, not modifying anything in src/{Analyser,Analysis,Detective,Log,Parser,Printer,Pattern}/ outside the new game's subdirectory.
Developing
composer test runs the suite. PHP and Composer are not required on the host — invocations wrap in the official composer:latest Docker image (PHP 8.5). See CLAUDE.md for the wrapped command, file layout, and the workflow conventions used in this repo.
Source
https://git.indifferentketchup.com/indifferentketchup/ik-codex
License
MIT — see LICENSE.