Skip to main content

LogLynx

Log analysis and anomaly detection for application, syslog and access logs. LogLynx reads a log file and tells you what happened in it: which errors repeat, when they clustered, which time windows deviate from the file's own baseline, and what all of it adds up to as a single health score.

No dependencies. Terminal output is in Turkish.

ci PyPI python coverage tests license

LogLynx analysing a log file

Install

pip install loglynx
loglynx app.log

python -m loglynx does the same thing when the scripts directory is not on your PATH, and from a checkout python main.py app.log works with nothing installed at all.

Usage

loglynx app.log                                 analyse one file
loglynx logs/                                   a directory, .gz included
cat app.log | loglynx -                         stdin

loglynx app.log --since 18:00 --until 20:00     narrow the window
loglynx app.log --grep timeout --level ERROR    narrow the content

loglynx app.log --watch                         follow the file live
loglynx app.log --save                          record the run
loglynx --compare                               diff the last two runs
loglynx --serve                                 dashboard on :8000

loglynx app.log --html report.html              shareable report
loglynx app.log --json                          machine-readable output
loglynx app.log --notify "$SLACK_WEBHOOK"       post the result
loglynx app.log --explain                       LLM commentary

Every mode is documented in docs/GUIDE.md. --help lists the full set.

What it looks like in practice

A database outage. You are handed yesterday's log and told "something happened around six".

loglynx app.log --quiet

The score comes back 44.8/100 (D), and the findings name the incident without you reading a single line: 229 errors in the 18:00 hour against a baseline of 4, one signature accounting for 72% of them, the db module at a 59% error rate, and — the part that is easy to miss by eye — a twelve minute stretch at 22:47 with no log output at all. Without --quiet it also prints the cluster: DatabaseConnectionError, 275 occurrences, 18:15:00 to 19:19:57, with a rule-based guess at the cause.

A deploy that made things worse. Record a run before and after:

loglynx app.log --save --label "before"
loglynx app.log --save --label "after"
Sağlık skoru     87.9 → 44.8  ▼ (-43.1)   KÖTÜLEŞME
Yeni ortaya çıkan hatalar:
  + CircuitBreakerOpenError (20)

That is not a guess: error signatures are stored per run, so "new" means literally absent from the previous set. As a CI gate: loglynx app.log --fail-on health --min-health 80.

A spike of 5xx. Access logs have no level field, so the HTTP status supplies one — 5xx becomes ERROR, 4xx WARNING:

loglynx /var/log/nginx/access.log --since 18:00 --until 20:00 --level ERROR

Anomaly detection

Anomalies are scored against the file's own baseline rather than a fixed threshold, because "too many errors" only means something relative to what that system normally produces.

The default is a modified z-score, 0.6745 * (x - median) / MAD. The obvious alternative, (x - mean) / stdev, has a flaw that matters here: the outlier you are looking for inflates the standard deviation and therefore hides itself. In the sample log there are two error spikes, at 18:00 and 19:00. The classic score only reports the first; the larger spike raises stdev to 49.6 and the second one falls inside the noise. The median and MAD are unaffected by outliers, so both are reported. tests/test_anomalies.py::test_robust_beats_classic_zscore pins this down. The classic method is still available with --method zscore.

Long silences are treated as anomalies too. A stopped service or a dead log agent produces nothing at all, which error counting never catches.

Health score

A single 0-100 number, computed by subtracting penalties from 100. Each factor has a ceiling, so one bad metric cannot flatten the score and make every bad log look identical.

Factor Ceiling Full penalty at
Error rate 35 25% of entries
Critical entries 20 2% of entries
Anomalies 20 4 windows
Bursts 10 3 bursts
Log stream gaps 10 10% of the time span
Unparsed lines 5 nothing parsed

Grades: A ≥ 90, B ≥ 75, C ≥ 60, D ≥ 40, F below. The weights are a judgement call, not a derived truth; WEIGHTS in loglynx/analyzer/health.py is the one place to retune them.

Formats

Name Example
standard 2026-08-22 10:31:02 ERROR [db] Database connection failed
bracket [2026-08-22 10:31:02] [ERROR] [db] Database down
python_logging 2026-08-22 10:31:02,123 - auth - ERROR - Bad token
json {"timestamp":"...","level":"ERROR","message":"..."}
syslog_rfc5424 <11>1 2026-08-22T18:15:00Z web-01 nginx 1234 ID - refused
syslog Aug 22 18:15:00 web-01 nginx[1234]: connection refused
access_log 1.2.3.4 - - [22/Aug/2026:18:15:00 +0300] "GET / HTTP/1.1" 500 12

The format is detected per file, and lines that do not match the dominant format fall back to the other parsers, so mixed files still work. JSON field names follow OpenTelemetry, Elastic ECS or Python conventions; unrecognised keys are kept on the entry. Timestamps may be ISO strings or epoch numbers, and offset-aware values are normalised to UTC so a file mixing both does not break comparisons.

Two formats carry no level, so one is derived — syslog decodes severity from the priority number, access logs from the HTTP status. Adding a format means adding one class with an extract(line) method.

Layout

loglynx/cli.py                  argument parsing and wiring
loglynx/parser/                 formats, timestamps, reading, filtering
loglynx/analyzer/               statistics, patterns, anomalies, health,
                                insights, optional LLM commentary
loglynx/database/               run history and comparison
loglynx/watcher.py              live following and rolling window
loglynx/notify.py               webhook notifications
loglynx/server.py               dashboard HTTP server
loglynx/reports/                console, HTML, JSON, dashboard
tools/                          sample data, log replay, README assets

Everything under loglynx/analyzer is pure: it returns data and never prints, so the same code backs the terminal, the HTML report, the JSON output and the dashboard.

Development

pip install -e ".[dev]"
ruff check .
pytest

306 tests, no network access from any of them. The sample generator (python tools/make_sample_logs.py) produces a day of traffic containing a deliberate database outage between 18:15 and 19:20, which is what the pattern and anomaly tests are written against.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

loglynx-1.2.0.tar.gz (84.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

loglynx-1.2.0-py3-none-any.whl (71.0 kB view details)

Uploaded Python 3

File details

Details for the file loglynx-1.2.0.tar.gz.

File metadata

  • Download URL: loglynx-1.2.0.tar.gz
  • Upload date:
  • Size: 84.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for loglynx-1.2.0.tar.gz
Algorithm Hash digest
SHA256 aae10ca04c1da7ff58157febaab22b75be50a016ef546ae66ed297d8c37633e5
MD5 7b30b04fe7bac883fd9a761535c0ec13
BLAKE2b-256 a2a9beb988f5610d8ad4cf7d9893ba7a86906a327e89e56a0f733521960a1e3d

See more details on using hashes here.

Provenance

The following attestation bundles were made for loglynx-1.2.0.tar.gz:

Publisher: publish.yml on LocalinTheEngineer/loglynx

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file loglynx-1.2.0-py3-none-any.whl.

File metadata

  • Download URL: loglynx-1.2.0-py3-none-any.whl
  • Upload date:
  • Size: 71.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for loglynx-1.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 612a109cb2f7f2d12a51be67cd8d4e60015c77a181e440e20df308d8809d0d88
MD5 05793fc8ed4f1728256c01d0c2acfbef
BLAKE2b-256 acf62f04997ed89400469d5c60403dd3f604e1eb3764af0da16bab5e367f12a4

See more details on using hashes here.

Provenance

The following attestation bundles were made for loglynx-1.2.0-py3-none-any.whl:

Publisher: publish.yml on LocalinTheEngineer/loglynx

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

1.2.0 This release

2 files

1.1.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page