Logler Featured Logler benchmark overview

Rust-powered structured log investigation for local files, optimized for AI agents. Cross-service timeline reconstruction in 13ms, hierarchy building in 349ms at 50K entries, 25 JSON CLI commands.

Role: Main Developer @ Side Project
Timeline: June 2025

Logler

Rust-powered structured log investigation from local files. Point at log files, get structured answers about what happened. Optimized for AI agent consumption — every command returns JSON, every output fits a token budget.


Why Logler?

There’s a gap between grep and Datadog. grep finds strings but can’t tell you what happened across services. ELK/Loki/Datadog require infrastructure, ingestion pipelines, and ongoing costs. Most debugging sessions start with local log files and a question: what went wrong?

Logler fills that gap. Parse local files, build an in-memory index, and answer structured questions — all without leaving your terminal.

Good fit: incident debugging, log triage for AI agents, cross-service correlation without infrastructure, any situation where you have log files and need answers fast.


Quick Start

from logler.investigate import search, follow_thread, extract_ids

# Search with structured filters
result = search(["app.log"], query="timeout", level="ERROR,WARN", limit=50)
print(f"Found {result['total_matches']} matches")

# Follow a thread across files
thread = follow_thread(["app.log", "worker.log"], thread_id="req-42")
for entry in thread["entries"]:
    print(f"{entry['timestamp']} [{entry['level']}] {entry['message']}")

# Extract all IDs for exploration
ids = extract_ids(["app.log"])
print(f"{len(ids['thread_ids'])} threads, {len(ids['services'])} services")

Rust parses and indexes the files. Python provides the investigation API. Every function returns a typed dict documented in types.py.


Architecture

Three-tier design — each layer does what it’s best at:

Rust core (4.3K LOC)    — Parsing, indexing, search, hierarchy building
PyO3 bridge             — Zero-copy FFI between Rust and Python
Python layer (14.2K LOC) — Correlation, sampling, metrics, CLI

The Rust core handles format detection (JSON, syslog, logfmt, plaintext), field extraction, and search. Python implements the algorithms that need flexibility: correlation engines, sampling strategies, metric extraction, format detection, template mining.

This is not a thin wrapper. The Rust core does real parsing and indexing. The Python layer has real algorithms. DuckDB/SQL is a 220-line optional escape hatch for ad-hoc queries.


Performance

Real numbers from the benchmark suite (14 scenarios, Python 3.12, Rust backend):

OperationResultContext
Hierarchy building349ms50K entries (was 86s before optimization)
Cross-service timeline13ms5 services correlated
Error flow analysis<2msFull error propagation tree
Follow thread148ms50K entries
Token savings2,540xcount vs full output format
Smart sampling196ms10K entries, 50 representative samples

Hierarchy building: 246x faster after optimization

The single most impactful optimization: BTreeSet prefix index for hierarchy naming inference. Replaced an O(n^2) linear scan with O(log n + k) range queries. At 50K entries, this took hierarchy building from 86 seconds to 349 milliseconds.


Features

25 JSON CLI Commands

Every command returns structured JSON. No parsing stdout, no regex on human-readable output. Purpose-built for LLM agents:

# Triage — what's wrong?
logler llm triage app.log worker.log

# Search with token budget
logler llm search app.log --level ERROR --max-bytes 4096

# Cross-service correlation
logler llm correlate app.log worker.log --thread-id req-42

# Hierarchy — parent/child thread relationships
logler llm hierarchy app.log --root worker-1

Assessment: triage, summarize, schema Discovery: ids Search: search, sql Tracing: correlate, hierarchy, bottleneck Comparison: compare, diff Utilities: sample, context, export, emit, session, verify-pattern Metrics & Detection: metrics, detect, templates Formats: format list, format test, format validate Correlations: correlation list, correlation run, correlate-events

Cross-Service Timeline

Reconstruct what happened across services by correlating thread IDs, correlation IDs, and trace IDs:

from logler.investigate import cross_service_timeline

timeline = cross_service_timeline(
    ["api.log", "worker.log", "db.log"],
    correlation_id="req-42"
)
# Returns entries from all services, ordered by timestamp

Smart Sampling

Intelligent sampling strategies for large log files — get representative samples without reading everything:

from logler.investigate import smart_sample

sample = smart_sample(
    ["app.log"],
    strategy="errors_focused",  # or: representative, diverse, chronological
    sample_size=50
)
# 50 entries that represent the full dataset

Thread Hierarchy

Build parent-child relationships from naming patterns (worker-1 -> worker-1.task-a), span IDs, and correlation chains:

from logler.investigate import follow_thread_hierarchy

hierarchy = follow_thread_hierarchy(
    ["app.log"],
    root_identifier="worker-1"
)
# Tree structure with timing, error propagation, bottleneck analysis

Token Budget Control

Every search command supports --max-bytes to fit output within an LLM’s token budget:

# Fit results in 4KB for GPT-4 context
logler llm search app.log --level ERROR --max-bytes 4096

# Count-only format: 202 bytes vs 513,019 bytes (2,540x savings)
logler llm search app.log --count-only

Format Auto-Detection

Automatic detection of JSON, syslog (RFC 3164/5424, BSD), logfmt, Apache CLF, and plaintext. Custom formats via .logler.toml:

[formats.my-app]
pattern = '(?P<timestamp>\d{4}-\d{2}-\d{2}T[\d:.]+Z)\s+(?P<level>\w+)\s+\[(?P<thread_id>[\w-]+)\]\s+(?P<message>.*)'
timestamp_format = "%Y-%m-%dT%H:%M:%S%.fZ"

More

FeatureDescription
Metrics extractionNumeric value extraction, stats, z-score anomaly detection
Template miningDrain algorithm for log template discovery
Error flow analysisTrace error propagation through service hierarchies
Bottleneck detectionIdentify slowest spans in a trace
SQL escape hatchDuckDB-powered ad-hoc queries when you need them
Event correlationCross-file event correlation with time windows
Session managementStateful investigation sessions with notes
ExportJaeger/Zipkin trace format export

Interactive Tours

17 Jupyter notebook tours demonstrating every capability:

TourTopics
01. Quick StartSearch, filter, basic investigation
02. Thread TrackingFollow threads across files
03. HierarchyParent-child relationships, tree formatting
04. Cross-ServiceMulti-file correlation, timeline reconstruction
05. Error AnalysisError flow, propagation trees
06. Smart SamplingSampling strategies, coverage analysis
07. Output FormatsFull, summary, compact, count
08. SQLDuckDB ad-hoc queries
09. MetricsNumeric extraction, anomaly detection
10. Format DetectionAuto-detect, custom formats
11. Template MiningDrain algorithm, pattern discovery
12. SessionsStateful investigations
13. Event CorrelationTime-windowed cross-file events
14. BottleneckSpan timing analysis
15. FilteringAdvanced filter combinations
16. ExportJaeger/Zipkin trace export
17. CLIFull LLM CLI walkthrough

Honest Limitations

  • No persistent index — Files are re-parsed on first access per session. The LRU cache avoids re-parsing on repeated queries, but there’s no disk-based index.
  • Single machine — Designed for local files, not distributed log collection. This is the point, not a limitation — but if you need multi-machine ingestion, use Loki.
  • Rust search is the floor — The Rust engine collects all matching results before truncating to limit. A limit=10 query still scans all entries internally.
  • Smart sampling bottleneck — At 50K entries, sampling still takes 6+ seconds because the Rust search cost dominates (not the sampling algorithm).

Getting Started

pip install logler                # or: uv add logler

Python 3.12+ with Rust backend (pre-compiled wheels for Linux/macOS).

uv run pytest -q                  # 1,064 tests
uv run python -m benchmarks run   # 14 benchmark scenarios