@agentix-e/drain-ts

Production-ready TypeScript/Node.js streaming log template miner — a 1:1 port of the official Python Drain3 algorithm with zero runtime dependencies and cross-runtime support.

CI Status npm version Coverage Report MIT License Node.js >=22
npm install @agentix-e/drain-ts pnpm add @agentix-e/drain-ts Node.js ≥ 22

What is drain-ts?

drain-ts turns unstructured log messages into structured templates — in real time, with zero training. Given a stream of logs like "connection from 192.168.1.1 port 8080", it automatically identifies that the IP and port are variables, producing the template "connection from <IP> port <NUM>".

It implements the Drain algorithm (He et al., ICWS 2017) — the best-performing rule-based log parser in the LogPAI benchmark suite — using a fixed-depth prefix tree for efficient O((d+cm)n) online clustering.

This is the only TypeScript implementation with full Drain3 v0.9.11 feature parity: tree search, fast match, LRU eviction, inference mode, parameter extraction, and framework-agnostic persistence.

Key Features

⚡ Streaming Online Parsing

Process logs one at a time. No batching, no pre-training, no warm-up. Templates evolve automatically as new patterns appear.

🎯 Full Drain3 Parity

treeSearch, fastMatch, addSeqToPrefixTree, LRU eviction, match() inference, extractParameters() — all 1:1 with the Python reference.

🛡 Zero Dependencies

No runtime dependencies. No mandatory peer deps. Just TypeScript and your platform's standard library.

🌐 Cross-Runtime

Node.js ≥22, Deno ≥2, Bun ≥1, and modern browsers (ES2020+). Same API everywhere.

🔒 Type-Safe

Full TypeScript with strict mode, exactOptionalPropertyTypes, and noUncheckedIndexedAccess. Zero any types in the entire codebase.

💾 Framework-Agnostic Persistence

Save/load model state to File, Memory, Redis, Kafka, S3 — or implement the 2-method interface for any backend.

30-Second Example

import { TemplateMiner, TemplateMinerConfig, DEFAULT_MASKING_INSTRUCTIONS } from "@agentix-e/drain-ts";

const miner = new TemplateMiner({
  config: TemplateMinerConfig.from({ maskingInstructions: DEFAULT_MASKING_INSTRUCTIONS }),
});

miner.addLogMessage("connection from 192.168.1.1 port 8080");
miner.addLogMessage("connection from 10.0.0.1 port 443");
// Both mapped to: "connection from <IP> port <NUM>"

// Extract the actual values:
const params = miner.extractParameters(
  "connection from <IP> port <NUM>",
  "connection from 192.168.1.1 port 8080"
);
// [{ value: "192.168.1.1", maskName: "IP" }, { value: "8080", maskName: "NUM" }]

Persistence in 3 Lines

import { TemplateMiner, FilePersistence } from "@agentix-e/drain-ts";

const miner = new TemplateMiner({
  persistenceHandler: new FilePersistence("./state.json"),
});
// State auto-saves on every template change
// On restart, model loads from state.json automatically

vs. Python Drain3

FeatureDrain3 (Python)drain-ts (This Project)
Fixed-depth prefix tree✅ 1:1 port
Similarity-based clustering✅ Same formula
Template incremental update✅ Same algorithm
LRU eviction (maxClusters)✅ Same policy
match() inference mode✅ 3 strategies✅ 3 strategies
extractParameters()✅ Exact + inexact
LogMasker✅ Sequential replacement
Persistence (File/Redis/Kafka)✅ kafka-python, redis✅ framework-agnostic interface
Profiler✅ Same section names
simTh validation✅ 0–1 range check
Async factory✅ TemplateMiner.create()
compactTree()✅ Cleanup after LRU eviction
Zero runtime deps❌ pip install drain3✅ npm install (no deps)
Type safety❌ Dynamic✅ Strict TypeScript

Quality

MetricValue
Tests548 (unit + integration + benchmark)
CoverageView full report →
BenchmarkLoghub 2k — 16 datasets →
TypeScriptStrict mode, zero errors
Throughput~420,000 logs/sec (Node 22)
★ Star on GitHub 📦 Install from npm