Turn a Kibana JSON log export into a runnable pytest suite using the secure-log2test CLI. Use when the user has a Kibana or Elasticsearch JSON export of API traffic and wants a regression suite from production logs, when extracting test cases from staging traffic, when scrubbing auth headers or secret-looking body fields before logs leave the laptop, when bridging Kibana-captured requests into a pytest-based suite for CI, when the user mentions Kibana logs, Elasticsearch JSON export, log-to-test conversion, log replay tests, auth header redaction, PII in logs, or regression tests from production traffic.
92
100%
Does it follow best practices?
Impact
93%
1.00xAverage score across 2 eval scenarios
Passed
No known issues
Turn a Kibana API log export into an executable pytest suite. Auth headers and secret-looking body fields redacted before they reach the output.

Status: v1.1.0 on PyPI. Stable per semver. Active roadmap, see open issues.
📖 Read the design write-up on Dev.to: privacy constraint, three-layer redaction, the v1.0.0 to v1.0.1 user-feedback story.
You have Kibana logs from staging or production. Each entry is a real request: method, URL, status, duration, headers, body. That's a regression suite waiting to happen. Most teams either ignore it, screenshot interesting failures into Jira, or hand-write pytest cases from log entries one at a time.
I needed a faster path. secure-log2test reads a Kibana JSON export and writes a pytest module you can run and commit. Auth values get replaced with ***REDACTED*** before they ever touch the output, so a generated suite is safe to push to a public repo.
The tool exists because at Лента I kept doing the same five steps by hand for every production incident: open Kibana, scroll, copy the failing request, paste into a new test, repeat. Five minutes per request times ten requests means an hour gone before any actual debugging starts.
pip install secure-log2test
secure-log2test data/sample_kibana_export.json --output tests_generated.py
pytest tests_generated.py -vA sample export ships with the repo (data/sample_kibana_export.json), so you can see real output without setting up a Kibana instance first. Grab it from the GitHub repo if you installed from PyPI.
For local development:
git clone https://github.com/golikovichev/secure-log2test
cd secure-log2test
python -m venv .venv && source .venv/bin/activate # or .venv\Scripts\activate on Windows
pip install -e ".[dev]"
pytest tests/ -vTwo stages, kept separate.
Parse (core/parser.py). Reads the Kibana JSON and validates each entry through Pydantic v2. Two layers of redaction run before any further processing:
authorization, proxy-authorization, proxy-authenticate, cookie, set-cookie, x-api-key, x-auth-token, x-csrf-token, x-access-token, refresh-token, id-token, x-amz-security-token, authentication, dpop, x-hub-signature, x-hub-signature-256). The last three carry credential material (a DPoP proof JWT, webhook HMAC signatures) whose names the regex below would otherwise miss.auth|token|secret|key|session|cookie|credential|bearer|password|passwd) that catches custom header names and body field names project teams invent.The same logic walks request bodies recursively, so {"password": "..."}, {"client_secret": "..."}, OAuth {"refresh_token": "..."} all get scrubbed at parse time. It also runs over URL query strings, so ?access_token=... or ?api_key=... are redacted while the path and non-sensitive parameters stay intact. Name matching is case-insensitive. Values get replaced with ***REDACTED***. The original input dict is not mutated.
Generate (core/generator.py). Takes the cleaned entries and renders a Jinja2 template (templates/test_module.py.j2) into a pytest module. Each log entry becomes one test_* function. The slug filter turns /api/v1/users/42 into a stable function name.
| Flag | Required | Description |
|---|---|---|
--input | ✅ | Path to Kibana JSON export (positional) |
--output | ✅ | Output path for generated file |
--format | ❌ | Output format: pytest (default), json, or csv |
--base-url | ❌ | Base URL prefix for generated requests (pytest only) |
--templates | ❌ | Custom templates directory (pytest only) |
--redact-marker | ❌ | Replacement string for redacted secrets (default ***REDACTED***) |
Pick a marker your downstream pipeline expects:
secure-log2test data/sample_kibana_export.json --redact-marker "[SCRUBBED]"The split lets you reuse the parser for other formats. If you want to generate Locust scripts, k6 scenarios, or an OpenAPI spec from the same logs, the parser stays. Only the template changes.
Given this Kibana log entry:
{
"method": "POST",
"url": "/api/v1/users",
"status": 201,
"headers": {"Authorization": "Bearer abc.xyz", "Content-Type": "application/json"},
"body": {"name": "Test", "email": "test@example.com"}
}The generator emits something like:
def test_post_api_v1_users():
response = requests.post(
f"{BASE_URL}/api/v1/users",
headers={"Authorization": "***REDACTED***", "Content-Type": "application/json"},
json={"name": "Test", "email": "test@example.com"},
)
assert response.status_code == 201, (
f"Expected 201, got {response.status_code}: {response.text[:200]}"
)The Authorization value never leaves the parser intact. You set the real token in your environment at run time.
What v1.0.1 does not handle yet. Calling them out so the tool stays trustworthy.
Authorization headers, redacted to a placeholder.If something on this list blocks you, open an issue.
Open the issue tracker for the live picture; two good first issue slots are currently open if you want to jump in.
pytest tests/ -v86 tests, covering:
ast.parse.CI runs on Python 3.10, 3.11, 3.12, and 3.13 via GitHub Actions.
The redaction layer catches the well-known auth headers plus anything whose name contains auth, token, secret, key, session, cookie, credential, bearer, password, or passwd. This works for both header names and JSON body field names. If your team uses something the pattern misses (truly opaque internal name), add it to SENSITIVE_HEADERS in core/parser.py before generating output. PRs welcome.
Never commit a generated suite that includes real production tokens. The redaction layer is a safety net, not a substitute for review.
Once secure-log2test has produced your replay suite, the next layer of
work is usually fixture organisation, shared auth, and the parametrize
patterns that scale across hundreds of generated cases. The
tessl-labs/pytest-api-testing
skill on the Tessl Registry collects those follow-on conventions:
httpx AsyncClient setup, conftest.py fixture shape, database
isolation, parametrize for edge cases, and auth-flow handling. Useful
reference when the generated suite starts growing its own test
infrastructure.
Sister projects in the same workspace:
Issue templates and PR guidance live in CONTRIBUTING.md. Bug reports with a redacted sample log are the most useful kind.
MIT. See LICENSE.
.tessl-plugin
evals
scenario-1
scenario-2
secure_log2test
tests