Skip to content
rahul-ramadasPublic

About

A fast Windows log and text analyzer for multi-gigabyte files, with hierarchical filters. An enhanced reimagining of TextAnalysisTool.NET.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

Cascade

A log analyzer for files that don't fit in memory, with filters that nest.

A from-scratch reimplementation of TextAnalysisTool.NET.

CI

Download · Install · Filters · Reading the log · Fields · Files · Settings · Keyboard

The main window: a two-million-line log coloured by a nested filter set, with the match map beside it and the presets pane on the right


Install

Download Cascade.exe and run it. One file, no installer, and it keeps itself up to date.

curl.exe -fL --remove-on-error -o Cascade.exe https://github.com/rahul-ramadas/Cascade/releases/latest/download/Cascade.exe

You need Windows and the .NET 10 Desktop Runtime. Cascade draws with GDI rather than a GPU, so it stays quick over a remote desktop.


Filters

What a filter is

The filter editor: match type, pattern, options, colours and the three style flags

A filter matches a substring, a .NET regular expression, or marked by marker 1–8, and it either includes lines or excludes them. A line is shown when an enabled include matches it and no enabled exclude does. Colour, background, bold, italic and underline are each on, off, or inherited.

Nesting

Alt+Right nests inventory-svc under warnings, and its count falls from 330,152 to 20,666

A child narrows its parent: [ERROR] → payment-svc means errors, in payments only. Nest with Alt+→, or by dragging.

  • A child matches a line only if every one of its ancestors matches it too — whether or not those ancestors are switched on. So switching a parent off does not stop it narrowing its children: you can scope a branch without showing everything the parent matches.
  • An enabled filter nested under an exclude overrules it on the lines they both match, so exceptions read straight down the list. A → ≠ AB → ABC shows everything with A, except AB, but keeps ABC. Nest another exclude under that one and it takes over again, as deep as you like. Switch the nested filter off and the exclude has the last word again.
  • Only nesting overrules. An exclude elsewhere in the list — a sibling, or another branch — still takes the line away outright.
  • A line takes its colour from the first enabled include in the list that matched it, refined by whichever enabled includes nested under that one matched too — never by a filter in a branch further down, however deeply nested.
  • Excludes never colour anything, and an exception nested under one colours a line only if it also sits under the include that claimed it. Otherwise the line comes back in that include's colour.
  • Whatever the winning filter leaves unset it takes from its nearest ancestor that sets it, attribute by attribute, and from the view's defaults when none does.

Which filter wins

An exclude beats everything by default, wherever it sits in the list, which is how TextAnalysisTool.NET behaves. If you would rather an exclude took its precedence from its place in the list, like any other filter, Preferences ▸ Exclude filters offers the other rule: Always hide what they match, wherever they are listed is the default, Hide only what an earlier filter has not claimed the alternative.

Pick the second and the list reads as one ordered set of rules. The first enabled filter that matches a line decides everything about it, whether you see it and what colour it is, and only a filter nested under that one may take over. An exclude is then just a filter whose answer is hidden: put it above what it should beat and below what should beat it.

  • An exception then needs no special case. ≠ Heartbeat → Error hides heartbeats and keeps the ones that are errors, because a nested filter takes over from the one it sits under.
  • To say show the rest of the file, end the list with a catch-all: a filter with an empty pattern matches every line, blank ones included.
  • Switching between the two rules never re-reads the file. The view is rebuilt from the matches already in memory.

The filter list

The filter list: an exclude column, nesting, checkboxes, live counts, and an excluding filter at the foot

  • The exclude column has a crossed-out eye in its header. A crossed-out eye in a row marks an exclude filter; a blank cell means include. Click a cell or press Ctrl+Shift+X to switch. Clicking within a selected group sets the group to the clicked filter's opposite kind, without changing its checkboxes or unselected children. Undo restores the original mixed states.
  • Count is how many lines in the whole file match, not how many are on screen, or how many are in the crop when you have one.
  • Shift+Space switches a filter's whole subtree on or off.
  • The list docks to any edge of the window, or hides altogether (Ctrl+Shift+L), and comes back next time on the same edge at the same size.

From the log to a filter

Dragging over an order number inside a line, then Ctrl+N: the Add Filter dialog opens seeded with it, and the new filter arrives already coloured

Ctrl+N turns the text you have selected inside a line — or the whole line under the caret — into a filter.

Where a new filter goes

Every new filter is made in the same dialog, which asks where it should go:

Key Where it goes
Ctrl+N The top of the list, or the end of it, as set in Preferences
Ctrl+Shift+N Directly above the selected filter, as its sibling
Ctrl+Alt+N Under the selected filter, as its child

The key you press only picks a starting point. All three are offered in the dialog, each with its key beside it, and pressing one of the others moves the choice. Changing your mind after Ctrl+N costs a keystroke and never the mouse.

  • The pattern box previews the colours the filter would really take where it is going, inheritance and all, so the preview follows the choice.
  • A place that cannot be had — nothing selected to sit above, or nesting that would run past the deepest level — is shown but greyed, and asking for it settles on the default.

Colour

The paint chips palette: every unused colour pair, each cell drawn as a matching line would look

  • I'm feeling lucky picks a legible colour pair that no other filter is using; Paint chips… shows the rest of the palette.
  • A filter with no colour of its own leaves no mark on the match map.

Working on many at once

Five filters selected across two branches, the header saying so

  • Select several filters and enable, disable, delete, duplicate, reorder, nest or recolour them in one go.
  • Dragging carries the whole selection, nesting and all.
  • Ctrl+Z undoes filter edits, drags included.

Restyling three filters at once: the colour they agree on offered back, 'varies' where they don't

Finding a filter among hundreds

Searching the filter list for 'payment': matches keep their colour, everything else is dimmed but stays where it was

  • Ctrl+E searches the list without hiding or reordering it: non-matching filters dim rather than disappear.
  • F4 / Shift+F4 walk the log through the selected filter's matches, without changing which filters are on.
  • While cycling through matches, the status bar shows your position and the total, such as 4 of 10 matching lines, counting only lines in the current view. Changing the selection in the log clears the tally.

Presets

The presets pane: one preset ticked and a different one highlighted

  • A preset names a combination of filters: the payment incident, the slow queries.
  • The tick applies a preset; the highlight only says which one the commands act on.
  • Ticking two gives you both, and ticking one moves only its own filters, so anything you switched on by hand stays as you left it.

Dim or hide

Ctrl+H switching between dimming the lines that didn't match and hiding them

  • Ctrl+H switches between dimming the lines that didn't match and hiding them altogether.
  • Line numbers are always the file's own, either way.

Crop to one stretch

The log cropped to 281 lines: the menu bar says so, the line numbers still read in the millions, and every count is of the crop

  • Select a run of lines and Ctrl+[ throws the rest of the file away — a two-million-line log of forty test runs becomes the one test run you are reading.
  • Everything then behaves as though the file held only those lines: the counts, the match map, the scrollbar, Ctrl+End, Ctrl+A, the find tally, elapsed times, Save Current Lines. Only the line numbers still read the file's own, so you never lose your place in it.
  • The crop takes everything between the first and last line you selected, including lines the filters are hiding — so Ctrl+H inside a crop reveals the rest of that stretch rather than a different one.
  • Filters still read the whole file, and a filter's count says how much of it is in front of you. Hover one for both numbers.
  • Ctrl+] puts the file back, and pressing it again returns to the same crop. Looking outside for a moment costs two keystrokes and never a re-selection. Clicking the crop in the menu bar does the same.
  • Cropping clears the selection, since the lines were only the way of naming the stretch. Lifting the crop hands them back exactly, unless you have chosen something else in the meantime, which always wins.

Reading the log

Find

The find bar above the log, every occurrence marked and the tally reading 'Match 1 of 8,688'

  • Ctrl+F searches the text, literal or regex, marking every occurrence on screen as you type.
  • Selecting two or more characters marks their other occurrences on screen, using the find bar's Case sensitive setting even when the bar is closed.
  • Find works on every line, not just the shown ones: hits on hidden lines are counted separately, and it says so when a match lands on one.

Elapsed times

The log filtered down to errors: the line numbers skip, and the margin beside them shows the time between one error and the next falling from tenths of a second to thousandths as the incident starts

  • Cascade finds the timestamp in your log by itself and puts the time since the previous line in the margin — the previous line on screen, so with the noise filtered away it measures between the lines you kept, which is a latency profile of whatever the filters select.
  • Ctrl+R on a line measures everything from that line instead: how long after the trigger each thing happened, with the lines above it reading as negative. Unlike the gap to the previous line, it does not change when you filter.

The same errors measured from one of them: the lines above the reference read as negative, the reference itself sits at zero and is picked out in the margin, and the ones below climb away from it

  • Ctrl+Shift+R steps between the three: the previous line, the start of the file, and your reference. The status bar says which (Δ Prev, Δ Start, Δ Ref) and the column stays the same width whichever it is.
  • Cropped, Δ Start measures from the start of the crop, so a test case reads from its own first line rather than from the top of the log.
  • Ctrl+Shift+G goes back to the reference, wherever you have scrolled to since.
  • Select a line and the status bar says the same thing in words; select several and it says how long they cover.
  • If your timestamp is somewhere the guess cannot reach, name the field it is in under Field Settings. Ctrl+Shift+M and Ctrl+Shift+B turn the two displays off.

The match map

The match map between the log and the scrollbar: a pixel a line, markers down its left edge, find hits down its right

  • Ctrl+M puts a strip beside the scrollbar showing the log itself, a pixel a line, in the colours the filters gave it. Markers run down its left edge and find hits down its right.
  • Where one pixel stands for many lines the exception among them wins, so a lone error among ten thousand ordinary ones still gets a pixel of its own.
  • A file too big to fit even at thirty lines a pixel shows as a window around where you are, sliding as you read. The scrollbar beside it is always the whole file.

Markers

Ctrl+1, Ctrl+2 and Ctrl+3 marking three lines, then 1, 2 and 3 walking back to them

  • Eight colours for marking lines by hand: Ctrl+1…Ctrl+8 on the selection.
  • The bare number keys 1…8 then walk between the lines you marked, Shift to go backwards.
  • Marked by marker N is a filter type, so lines you picked out by hand can be treated as a category.

What matched this line

The tooltip over a line, naming three filters that matched it, one of them switched off

  • Hovering a line names every filter that matched it — including the ones that are switched off.

Getting lines out

  • File ▸ Save Current Lines… writes out exactly what the view is showing — the filters' verdict, and the crop if you have one.
  • Edit ▸ Copy with Line Numbers copies the file's own line numbers along with the text.

Fields

Long lines are either wrapped (Alt+Z) or split into fields you can hide and reorder.

Splitting a line

The log laid out as columns under a draggable header

  • Ctrl+Shift+C splits every line into fields for display, guessing a template from the line under the caret.
  • Filtering and searching always run on the whole raw line, so this can shorten a line but never hide one.
  • A line the template does not match is left whole and untouched.

The template

A template is a picture of your line: write one out, replace what changes with *, and wrap each field in { }.

your line:  [2026-08-05T09:44:02.118][payment-svc][ERROR] charge declined for order 48210
template:   {[*]}{[*]}{[*]} {*}
* the text that changes: matches as little as it can, up to whatever you wrote next
. any one character, whatever it happens to be
{ } one field: the unit that gets hidden or moved, punctuation and all
anything else has to be there, except a run of spaces, which matches any run of spaces
\ makes { } * . \ ordinary
  • Punctuation goes with the field, so hiding the middle of [a][b][c] leaves [a][c] rather than [a][][c].

Columns and Inline

Hiding a field, then Ctrl+Shift+X switching between the two layouts

Columns lays the fields out as a table: drag a header to reorder, double-click it to rename, right-click for the list of which fields are shown.

The same log laid out inline, with a chip strip above it and two fields put away

Inline keeps every row a line and leaves out what you hid — better when one field dwarfs the rest. A strip of chips stands in for the header: click one to put a field away or bring it back, drag it to move the field along the row.

Field settings

The field settings dialog: the template, a coloured band per field over a real line, and the row as it will be drawn beneath

  • Ctrl+Shift+D tries the template against real lines from the file: how many of them match, and where a line that doesn't stopped matching.
  • Detect writes the template for you when the line begins with bracketed groups: [ ], ( ) or < >.
  • Name a field as the time and Cascade proposes the format that reads it — a .NET format string like yyyy-MM-dd HH:mm:ss.fff, or epoch:ms — and shows that format reading your own log back to you.

Files

Opening

  • Drop a log on the window, hand it to Cascade.exe on the command line, or use Open from Clipboard for one you have pasted from somewhere else.
  • F5 re-reads the file, for when you have just re-run whatever produced it.
  • Dropping a .cascade or .tat file loads its filters instead of opening it as a log.
  • The file is memory-mapped and indexed as it streams, at a little over two bytes a line: a 1 GB, 10-million-line log is on screen in milliseconds and fully indexed in under half a second.

Encodings

The Encoding menu, with Auto-detect naming what it found and a tick on the encoding in effect

  • A byte-order mark is honoured; without one, UTF-8 is assumed.
  • View ▸ Encoding reads the file again as UTF-16 or UTF-32 (either endianness), Windows-1252 or the system code page.

Filter files

  • .cascade is JSON — the filter tree with its styles, the presets, and the field template — so a filter set diffs well in source control.
  • Ctrl+S saves the set you have; File ▸ Append Filters… merges another set into it.
  • TextAnalysisTool.NET .tat files are imported, flattened to top-level filters. Saving is always .cascade.

Settings

Preferences

The Preferences dialog

Font, colours, tab size and line spacing, plus the switches not worth a menu entry of their own: which filter wins, loading the last filter file at startup, where Ctrl+N puts a new filter, a memory dump to %TEMP% if the window ever stops responding, and support for screen readers and UI automation. Anything the View menu already toggles stays there rather than being repeated here.

File ▸ Settings ▸ Export / Import moves your preferences to another machine.

Where things live

Preferences in %APPDATA%\Cascade\settings.json, machine-local state in state.json, and nothing at all in the registry. CASCADE_SETTINGS_DIR moves the folder.

Command line

Cascade.exe [file] [/Filters:<path>]
  • /Filters: also stops the last-used filter file being loaded automatically.
  • CASCADE_UPDATE=off turns off the update check.

Keyboard reference

Log view

Key Action
↑ ↓ PgUp PgDn Move the caret (Shift extends the selection)
Ctrl+Home / Ctrl+End First / last line
Ctrl+↑ / Ctrl+↓ Scroll a line without moving the caret
← → / Home End Scroll sideways / to the far left and right
Drag, double-click, triple-click Select part of a line, a word, the whole line
Ctrl+A / Ctrl+C Select all / copy
1…8 / Shift+1…8 Next / previous line with that marker
Ctrl+1…Ctrl+8 Toggle that marker on the selection
Ctrl+wheel Zoom

Filter list

Key Action
Space / Shift+Space Enable or disable the selection / their subtrees
Ctrl+Shift+X Switch the current filter or selected group between include and exclude
Enter / Delete / Ctrl+D Edit / remove / duplicate the selection
Shift+↑ ↓ / Ctrl+↑ ↓ / Ctrl+Space / Ctrl+A Extend, move through, add to, or take the whole selection
Alt+↑ ↓ ← → Move, nest and un-nest
F4 / Shift+F4 Next / previous line matching the current filter
Ctrl+E, then Enter / Shift+Enter / F3 Search the list and walk the matches
Double-click a filter / the empty space below Edit it / add a new one

Global

Key Action
Ctrl+O / F5 / Ctrl+S Open / reload / save filters
Ctrl+Z / Ctrl+Y Undo / redo a filter edit
Ctrl+F / F3 / Shift+F3 Find / next / previous
Ctrl+G / Ctrl+Shift+G Go to a line you name / to the line you are measuring from
Ctrl+H Show only filtered lines
Ctrl+[ / Ctrl+] Crop to the selected lines / show the whole file again, or return to the crop
Ctrl+N / Ctrl+Shift+N / Ctrl+Alt+N New filter from the selection or the current line, going to the usual end of the list / above the selected filter / under it as a child
Ctrl+E Search the filter list
Ctrl+L / Ctrl+M / Alt+Z / Ctrl+Shift+C Line numbers / match map / word wrap / split lines into fields
Ctrl+Shift+X / Ctrl+Shift+D Switch field layout / field settings
Ctrl+Shift+M / Ctrl+Shift+B Elapsed times in the margin / in the status bar
Ctrl+R / Ctrl+Shift+R Measure from this line / step through what to measure from
Ctrl+Shift+P / Ctrl+Shift+L Show or hide the presets pane / the filter list
Ctrl+Shift+T / Ctrl+Shift+F Focus the log view / the filter list
Ctrl+Shift+↑ ↓ ← → Dock the filter list
Ctrl++ / Ctrl+- / Ctrl+0 Zoom in / out / reset
Tab Move between the log and the filter list
Esc Stop a search, then close the bar and clear its marks

Building

Needs the .NET 10 SDK.

dotnet build Cascade.slnx -c Release
dotnet test tests/Cascade.Core.Tests/Cascade.Core.Tests.csproj   # engine tests
./scripts/Run-UiTests.ps1 -Publish                               # UI automation, off-screen
./scripts/Build-DocImages.ps1                                    # every picture above, from the app

src/Cascade.Core is the UI-agnostic engine — indexing, filtering, find, markers, columns, persistence — and src/Cascade.App is the WinForms GUI.

License

MIT © 2026 Rahul Ramadas.

About

A fast Windows log and text analyzer for multi-gigabyte files, with hierarchical filters. An enhanced reimagining of TextAnalysisTool.NET.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages