parse a log file into columns - without uploading it anywhere
Production logs are the files you are least allowed to paste into a website. They carry tokens, IP addresses, email addresses, session and account ids. This one never leaves your machine: there is no server to send it to.
Drop a .log and it is read as events rather than lines. The layout is detected from the file itself and applied as a step you can see, edit, switch off, or undo.
how to use it
- Drop a
.log. The layout is detected and added as a step you can see, edit, switch off, or undo - and multi-line stack traces are folded into the event that logged them.
- Check the time column. Timestamps normalize to one sortable UTC column, and any assumption a format forced (syslog carries no year) is stated rather than made silently.
- Use the volume strip to find when it went wrong, then drag across the spike - that becomes a real filter step, so the window survives export and travels in a share link.
- For anything past the first thousand rows, open the ⚡ engine. There the strip covers the whole timeline, the grid scrolls every row, searching a text column builds a full-text index on first use, and templates group a million messages into a few shapes.
- Then treat it as data: filter to the errors, scrub anything sensitive before sharing, and export CSV, JSON, or a
.sqlite.
- Layouts it recognizes: JSON per line (pino, bunyan, winston, Docker, Kubernetes), logfmt (Go, Heroku), Apache and nginx access logs, Apache and nginx error logs, syslog in both RFC 3164 and RFC 5424 forms, Go's standard logger, and the general case of a timestamp followed by a level and a message. If nothing matches convincingly, you get your raw lines and a note saying so, rather than a confident wrong answer.
- Stack traces stay whole: a Java exception is thirty lines and one event, and it is usually the event you opened the file for. Continuation lines are folded into the entry that logged them, so the message column of the row that matters actually says something.
- Nothing is thrown away: a startup banner or a crash dump that no layout can read still becomes a row, with its text intact and the parsed columns left empty. The raw line stays beside the parsed ones so you can always see what a column came from.
- Timestamps that sort: epoch seconds, milliseconds, microseconds and nanoseconds, ISO 8601, Apache's
10/Oct/2000:13:55:36 -0700, and syslog's month-and-day are all normalized to one UTC column that sorts correctly as text. Where a format is missing information - BSD syslog carries no year and no timezone - the assumption is stated in the step and printed in the run summary, never made silently.
- See when it went wrong: once there is a timestamp column, a volume strip appears above the table, stacked by level so an error burst is a shape rather than a number. Drag across the spike and it becomes a real filter step, which means the window you picked survives export, gets saved with the recipe, and travels in a share link. Rows with no readable time are counted next to it rather than quietly left out.
- The whole timeline, not the first thousand rows: on the canvas that strip is drawn from the preview, and on a big log the preview is a keyhole - the first 1,000 lines of a 5-million-line file can be fifteen minutes of a forty-seven day history. Load the log into the engine and the histogram is computed in SQL over every row, so the spike you are looking for is actually in the picture. Dragging it still writes a real step, now onto the SQL chain.
- Numeric levels decoded: pino and bunyan write
30 for info and 50 for error. They arrive as words you can read and filter on.
- A million lines become a readable list of shapes: click a message column and choose find templates, and
user 4821 not found and user 9330 not found collapse into user <*> not found. Every event gets a template and a template id as real columns, so "which error pattern spiked at 14:32" becomes an ordinary group-and-count. The fit reads every row of the file, not a sample - on a log whose shapes arrive over time, a deploy at hour six or an incident at hour twenty, a model fitted on the first thousand lines covered 47% of a 600,000-line file and one fitted on all of it covered 100%. It is fitted once and frozen into the step, never re-derived while exporting, so the preview and the export cannot cluster differently. The same is available inside the engine, where the rows are already loaded - there it is a column scan rather than a re-read of the file, and the shapes become columns you can GROUP BY.
- Search it like a search engine, not like grep: load the log into the engine and the first search on a column builds a full-text index over it. After that, finding a request id, a build hash, or one stack trace among five million lines is instant rather than a scan - measured on a million rows, a search matching ten of them returns in under a millisecond against 68 ms for a substring scan, and the advantage grows the rarer the thing you are looking for. Whole words,
time* prefixes, "read timeout" phrases, and AND/OR/NOT all work. The search is a real chain step, so the time strip redraws over your results and you can still drag the spike.
- All of it, not the first thousand lines: in the engine the grid scrolls the entire result, however many rows that is. The row numbers are the real ones, so row 4,821,006 says so. Nothing is copied until you actually scroll past the first page, and then it is copied once per query - after that every page is a seek rather than a re-sort, which is the difference between scrolling a five-million-row log and waiting on it.
- Then it is just data: filter to the errors, extract an id with the regex painter, scrub anything sensitive before you share it, group and count with real SQL, and export CSV, JSON, or a .sqlite database.
- Reusable: save the parse as a recipe and every colleague reads your service's log format identically, from a link.
why not just grep it?
Grep is excellent until the question has a shape: how many distinct users hit the error, what the p95 latency was during the incident, which endpoint the timeouts clustered on. Those are column questions, and they need the log to be a table first. Once it is one, the rest of the workbench applies to it.
every tool in the box
- data workbench - profile, clean, transform, and export CSV, JSON, and SQLite - the full suite
- JSON flattener - nested JSON or NDJSON to flat columns, arrays and objects unrolled
- CSV PII scrubber - find emails, phones, SSNs, and card numbers - mask, hash, or drop them
- JSON to CSV - convert JSON or NDJSON to CSV with full column control
- CSV to JSON - convert CSV to JSON or NDJSON, streamed at any size
- Excel to CSV - read .xlsx workbooks and export CSV, sheets and all
- CSV to Excel - write a real .xlsx where leading zeros and dates survive
- SQL on CSV - real SQL over your files: joins, GROUP BY, a read-only console
- CSV to SQLite - drop several files, get one .sqlite database with discovered foreign keys
- CSV to SQL - CREATE TABLE and INSERT statements for Postgres, MySQL, SQL Server, SQLite
- JSON to TypeScript - TypeScript interfaces and JSON Schema derived from your real data
- large CSV viewer - open files past Excel's 1,048,576-row limit without loading them into RAM
- regex painter - highlight example matches, get a verified regular expression back
- encoding fixer - detect windows-1252/UTF-16 and repair garbled text (José → José)
- log parser - read log files as events: layouts detected, stack traces kept whole, timestamps normalized, and a volume-over-time strip drawn in SQL across every row (this page)
- visualize - chart any table you have open - bar, line, area or point - drag across it to filter, and export svg, png, or the vega-lite spec that drew it
- theme builder - design, test, and export custom color themes with live previews, palette derivation, and contrast diagnostics
Like every unfckr tool, this runs 100% in your browser: no upload, no servers, no signup, no analytics. A Content-Security-Policy header blocks every programmatic network channel, so not even malicious code could phone home - and you can watch it happen: the privacy page runs six live escape attempts and shows the browser refusing each one.
↑ back to the tool