Kelora
Scriptable log processor for the command line. Treats logs as structured events and lets you filter, transform, and analyze them using embedded Rhai scripts with 40+ built-in functions.
[!WARNING] Experimental tool. Vibe-coded. APIs may change without notice.
Table of Contents
- Overview
- Quick Start
- Installation
- Core Concepts
- CLI Feature Tour
- Parsers & Formats
- Format Recipes
- Rhai Building Blocks
- Multiline Strategies
- Configuration & Defaults
- Example Pipelines
- Learning Path
- Documentation Shortcuts
- When to Reach for Kelora
- License
Overview
Kelora parses log streams into structured events and runs them through a programmable pipeline powered by Rhai scripting.
- Turns lines into structured events you can access as
e.fieldore["field-name"]. - Embeds 40+ built-in Rhai helpers for parsing, enrichment, metrics, and windowed analysis.
- Speaks JSON, logfmt, syslog, CSV/TSV, column specs, and gzip-compressed inputs out of the box.
- Handles streaming or batch workloads with sequential and
--parallelexecution modes. - Emits metrics and processing stats so you can observe pipelines while they run.
Quick Start
[!TIP] Use the fixtures in
example_logs/when experimenting—no need to point at production logs.
Basics
# Filter error-level events from the logfmt sample
# Work with JSON logs and enrich the event before printing selected fields
# Parse Apache/Nginx access logs, keep key fields, and surface stats
# Show errors with surrounding context (like grep -A/-B/-C)
Advanced Moves
# Count slow responses and surface metrics alongside real-time output
# Sliding window alerting for login failures (stream from any source)
| \
# Run a scripted pipeline from disk (save your Rhai to pipelines/critical_filter.rhai first)
Installation
Kelora targets stable Rust; keep your toolchain fresh (rustup update) for best results.
# Install from crates.io
# Build from source
Pre-built binaries live in the GitHub releases. They're handy for CI or containers.
Core Concepts
- Events - Every log line becomes a structured map. Fields are accessible as
e.level,e["user-agent"], or via helper functions likee.get_path("payload.id"). - Pipeline - Logs flow through
Input -> Parse -> Filter -> Transform -> Format -> Output. Mix and match parsers, filters, exec scripts, and formatters freely. - Scripts - Rhai expressions drive filtering (
--filter), transformations (--exec/--exec-file), initialization (--begin), and teardown (--end). - Windows -
--window Nexposes recent events for sequence detection via helpers likewindow_values("field").
CLI Feature Tour
Input & Parsing
-f, --format <FORMAT>selects a parser (json,logfmt,syslog,combined,cols:<spec>, ...);-jis shorthand for JSON.--file-order {cli|name|mtime}controls multi-file processing order.--skip-lines,--keep-lines, and--ignore-linesfilter raw input before parsing.-M, --multiline <strategy>enables multi-line reconstruction (see Multiline Strategies).--extract-prefix FIELD+--prefix-sep SEPslices service prefixes before parsing.--cols-sep SEPprovides a custom delimiter when using column specs.
Filtering & Selection
--filter 'expression'runs boolean Rhai expressions; chain multiple occurrences.-l/--levelsand-L/--exclude-levelsgate standard log levels.--since,--until, and--taketrim by time range or limit output volume.-A/--after-context,-B/--before-context, and-C/--contextshow surrounding lines around matches (requires filtering).--keep-lines/--ignore-linespair well with--strictto enforce hygiene.--allow-fs-writesenables Rhai file helpers (mkdir,truncate_file,append_file) so scripts can shard or persist results; without it these functions returnfalseand perform no I/O.
Transformations & State
-e/--execand-E/--exec-filemutate events (e), emit new ones (emit_each), or track metrics.--beginseeds global read-only configuration through theconfmap;--endperforms final aggregation or reporting.--window Nexposeswindowhelpers for sliding analyses; combine withwindow_values(...),window_numbers(...), or custom loops.- Default mode is resilient—errors skip the offending event. Use
--strictfor fail-fast pipelines. - Dial verbosity with
-v/-vvvfor debugging or-q/-qqqfor quiet pipelines. -I/--includeprepends Rhai files to define reusable functions for--exec,--begin, and--endstages.
Output & Reporting
-F/--output-formatcontrols formatting (default,json,logfmt,inspect,levelmap, CSV/TSV variants, ornone).-Jis shorthand for JSON.-k/--keysand-K/--exclude-keysshape the output payload;-ckeeps only core fields;-bswitches to brief mode.--pretty-ts,-z, and-Zformat timestamps (local vs UTC).--stats,--metrics, and-S/--stats-onlyexpose processing telemetry;--metrics-filewrites JSON metrics to disk.--mark-gapsinserts visual separators when time jumps exceed a duration;--no-emojidisables emoji prefixes.- Context lines are marked with visual prefixes:
*for matches,/for before-context,\for after-context.
Performance & Reliability
--paralleland--threadscontrol concurrency; pair with--batch-size(lines per worker batch, default 1000) and--batch-timeout(max ms to flush a partial batch, default 200) to balance parallel throughput and latency.--unorderedrelaxes output ordering for faster parallel flushes.- Sequential mode (default) shines for streaming sources;
--parallelexcels at log archives. - Combine with
--config-fileor aliases for repeatable pipelines at scale.
Parsers & Formats
Kelora defaults to -f line, which trims trailing newline/CR characters and exposes the result as e.line. Reach for -f raw when you need a byte-for-byte copy (including trailing newlines or escape markers), and reserve -f 'cols:<spec>' for bespoke formats that the built-in parsers do not cover. All parsers expect UTF-8 text; binary or other encodings will raise input errors.
| Format | Fields Produced | Typical Source |
|---|---|---|
line (default) |
line |
Newline-delimited text where trimming the trailing newline is acceptable |
raw |
raw |
Exact text preservation (newline-sensitive data, continuation markers, binary artifacts) |
json |
Original JSON keys | JSONL or JSON arrays |
logfmt |
Key-value pairs | Logfmt structured logs |
syslog |
timestamp, host, facility, message, ... |
RFC3164/RFC5424 syslog |
cef |
Header fields + extension map | ArcSight/Common Event Format |
csv / tsv |
Column headers as fields | Delimited datasets |
combined |
ip, status, method, path, request, request_time, ... |
Apache/Nginx access logs |
cols:<spec> |
Named fields defined by your spec (ts, level, *rest, ...) |
Custom or proprietary log formats |
All parsers auto-detect gzip compression (files and stdin) by magic bytes—no extra flags required.
Format Recipes
Raw vs Line
Choose the right baseline for text pre-processing. -f line is the default: it trims the trailing newline/CR and gives you a tidy e.line field for downstream filters. -f raw keeps every byte (including trailing delimiters and escape markers) in e.raw, which is invaluable when you need to preserve continuation characters, feed the data into another parser verbatim, or re-emit the original payload.
# Preserve every byte (newline-sensitive analyses)
# Treat each line as plain text for simple filtering
Prefix Extraction
Strip infrastructure prefixes before parsing structured payloads.
| \
Column Specs (cols:<spec>)
Declarative column parsing with skips, joins, and tail captures. This mode shines when your data has a repeatable column layout but no dedicated parser—think bespoke appliance logs, legacy flat files, or regex capture groups you want to map into fields.
Spec tokens are space-separated:
field— consume one column intofield.field(n)— consumen ≥ 2columns, joined together (whitespace joins in default mode, literal separator joins when you set one).-/-(n)— skip one orncolumns with no output field.*field— capture the remaining text verbatim; must appear once and always at the end.
Whitespace is the default separator; add --cols-sep "|" (or another literal) when your columns are delimited. You can also feed pre-split arrays to parse_cols from Rhai (let caps = e.line.extract_all_re(...); caps.parse_cols("ip user ts *msg");). Missing data fills fields with () in resilient mode, while --strict turns shortages/extras into errors.
| \
Rhai Building Blocks
Kelora exposes the full Rhai language plus domain-specific helpers.
- Text & parsing -
extract_re,parse_logfmt,parse_cols,mask_ip,encode_*/decode_*. - Arrays & maps -
sorted,sorted_by,array.flatten,map.get_path,map.flatten,emit_each. - Hashing & anonymization -
bucket(fast sampling),hash(multi-algo),anonymize(salted SHA-256),pseudonym(short IDs). - Metrics -
track_count,track_avg,track_bucket,track_uniquepower--metricsand--endreports. - Datetime -
to_datetime,to_duration,now_utc, formatting helpers, arithmetic. - Environment & control -
get_env,read_file,read_lines,exit.
Example pipeline with shared configuration and sliding logic:
See kelora --help-rhai for syntax essentials and kelora --help-functions for the complete catalog.
Multiline Strategies
| Preset | Use When | Equivalent |
|---|---|---|
stacktrace |
ISO or syslog timestamps leading each entry | -M timestamp |
docker |
Docker JSON logs (RFC3339 timestamps) | -M timestamp:pattern=^\\d{4}-\\d{2}-\\d{2}T |
syslog |
RFC3164/5424 headers (Jan 2, <34>1 2024-01-01T...) |
`-M timestamp:pattern=^(<\d+>\d\s+\d{4}-\d{2}-\d{2}T |
combined |
Apache/Nginx access logs with remote host prefix | -M start:^\\S+\\s+\\S+\\s+\\S+\\s+\\[ |
nginx |
Nginx error logs prefixed with [dd/Mon/yyyy: |
-M timestamp:pattern=^\\[[0-9]{2}/[A-Za-z]{3}/[0-9]{4}: |
continuation |
Lines ending with \\ continue the current event |
-M backslash |
block |
BEGIN ... END sections form a single event |
-M boundary:start=^BEGIN:end=^END |
whole |
Treat the entire input as one event (fixtures, preformatted payloads) | -M whole |
When you pick a timestamp-based strategy (the presets above or -M timestamp), you can also
provide --ts-format=<chrono fmt> so Kelora matches your exact timestamp prefix instead of relying
solely on the preset regex.
Build custom strategies with timestamp:pattern=..., indent, start:REGEX, end:REGEX, boundary, backslash[:char=...], or whole (single mega-event). Remember that buffering happens until a boundary is found; when running with --parallel, lower --batch-size or --batch-timeout to keep long multi-line frames flushable, and whole will buffer the entire stream in memory.
Configuration & Defaults
Define repeatable pipelines in ~/.config/kelora/config.ini:
# Defaults applied to every run
defaults = --stats --parallel --input-tz UTC
[aliases]
errors = -l error --since 1h --stats
warnings = --filter 'e.level == "WARN" || e.level == "WARNING"'
slow-queries = --filter 'e.duration > 1000' --exec 'e.slow = true' --keys timestamp,query,duration
Usage:
Pair configs with --ignore-config for hermetic runs or CI pipelines.
Example Pipelines
# Real-time nginx monitoring with enrichment, metrics, and alerting
| \
# Authentication watch with sliding windows and unique counters
# Convert syslog to structured JSON and redact sensitive fields
# Anonymize PII while maintaining linkability and sampling
Learning Path
- Events - Practice accessing and mutating
e.fieldvalues on JSON or logfmt samples. - Parsing - Try multiple formats (
-f json,-f combined,-f 'cols:...') and experiment with--extract-prefix. - Basic Scripts - Layer
--filter,--exec, and--keysfor simple transformations. - Metrics & Stats - Introduce
track_count,track_avg,--metrics, and--stats. - Pipelines - Chain multiple
--filter/--execstages, add--beginconfiguration, and export results. - Output Control - Switch between
-Fmodes, apply-k/-K, and format timestamps. - Windows - Explore
--window,window_values, andwindow_numbersfor sequence detection. - Multi-stage Workloads - Combine
--parallel, config aliases, and--endsummarization for production-style jobs.
Each milestone builds on the previous one; you can be productive early, then layer in advanced concepts as needed.
Documentation Shortcuts
When to Reach for Kelora
- Use Kelora when you need programmable filtering, enrichment, aggregation, or custom metrics directly in the terminal.
- Pair with other tools: pipe results into
jq,ripgrep, orlnav—Kelora focuses on transformation, not visualization. - Prefer other tools when you need interactive browsing (
lnav), raw text search (ripgrep), heavy-duty JSON querying (jq), dashboards (Grafana), or centralized log shipping (Fluentd).
See also: angle-grinder, pq, Miller.
License
MIT - see the license file for full details.