Native Shell
Native Shell: AI-generated UI, native in your app, on every platform. Apps on iOS, Android, macOS, Windows and Linux, GPUI apps and web pages load signed, sandboxed TSX modules at run time and draw th
Find out what your app did, from its logs to its threads: multi-GB logs, live tail, filters, requests, exceptions, thread dumps and JVM profiles. Free and open source for Windows, macOS and Linux.
Developer toolsJava · PythonGitHub @bdarwinOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Find out what your app did, from its logs to its threads: multi-GB logs, live tail, filters, request tracing, exceptions, thread dumps, JVM profiling, SSH. Windows, macOS, Linux.
Taken from the repository README
Loading the full README.
Read the full README ↗Find out what your app did, from its logs to its threads. Logsift opens gigabytes of logs instantly, tails them live and points out errors, bursts and restarts. Follow one request through every log, even inside zips; see exceptions grouped by cause; chart how long things take. Then go deeper: it explains Java and Python thread dumps, and attaches to running JVMs to profile them and look at their heap, on your computer or on a server. Windows, macOS and Linux.
User guide: what each view shows, what its colours and numbers mean, and what to do about them (also Help → Documentation in the app).
logback.xml or log4j2.xml: each layout in it becomes a format). A live preview shows how lines split into columns.placed in 345 ms, queue size=42) and columns of numbers (duration_ms in a CSV) as charts over time, with the slowest lines a click away..zip and it opens as a tab with its folders and files (zips inside it too); open any of them as a log, with everything a log has, merge them by time, or search them all. A .gz opens directly. Open logs from web addresses, or download several and search them together..gz and .zip files, and zips inside zips.kill -3 output inside a log; py-spy dump and faulthandler for Python), or attach to a running JVM on your computer, on a server over SSH, or through its JMX port. Logsift points out deadlocks, threads queueing for a lock, stuck and busy threads and full thread pools, and shows each thread over time..hprof file and Logsift says what fills the memory in plain sentences ("one HashMap in static SessionCache.CACHE holds 1.2 GB: mostly 20,000 sessions"), and for any object, the chain of references that keeps it alive. Dumps of tens of GB open with the app's usual 2 GB of memory: a 12 GB dump with 223 million objects in about 2½ minutes..dmp, .mdmp, full or mini, of any program) or a Java hs_err_pid file, and Logsift says what happened in plain words ("Access violation: reading address 0x18, a null pointer, in OrdersService!Order::total"), the code to blame, what to try, and every thread's stack, with threads that share a stack together. Stacks are rebuilt from the dump itself, with names from your PDB files and, if you let it, Windows' own from Microsoft. For a JVM crash it explains how it happened (native library, JNI, Unsafe, the garbage collector, the JIT compiler, out of memory) and which other threads and libraries may have caused it.Get the latest version from the Releases page:
| System | File |
|---|---|
| Windows (x64, ARM64) | Logsift-<version>-windows-x64.msi / -windows-arm64.msi: installer, no admin rights needed. Or the .zip: unzip, run Logsift\Logsift.exe |
| macOS (Apple Silicon, Intel) | Logsift-<version>-macos-arm64.dmg / -macos-x64.dmg |
| Debian / Ubuntu | Logsift-<version>-linux-x64.deb |
| Other Linux (x64, ARM64) | Logsift-<version>-linux-x64.tar.gz / -linux-arm64.tar.gz: unpack, run Logsift/bin/Logsift |
| Any OS with Java 21+ | Logsift-<version>-any-java21.zip: run bin/logsift |
The native downloads include their own Java runtime, so nothing else needs to be installed. They are not code-signed yet:
xattr -dr com.apple.quarantine /Applications/Logsift.app.Builds of the latest code are on the snapshot release. What changed in each version is in the CHANGELOG.
Files: File → Open, or drag files onto the window. On Windows, right-click a file or folder → Open with Logsift (a folder opens as a tab of its files); Logsift is also in the Open with list of .log, .txt and .out files, without taking over what double-click does. On macOS, use Open With or drop files on the Dock icon. If Logsift is already running, files open in the same window.
Folders: File → Open Folder… (or drop a folder on the window) shows a folder's files in a tab, as a tree with sizes, like a zip's: filter them by name, open files as logs, Merge by Time, and Find in all files (Ctrl+F in that tab) searches the folder. Refresh lists the files again; a very big folder shows its first 20,000 files.
Zip and .gz files: a .zip (File → Open, drag and drop, Recent files) opens as a tab showing its folders and files as a tree, also the files of zips inside it, with their sizes and a filter. Double-click a file (or select several and press Open) to open it as a log; Merge by Time merges the selected logs; Find in all files (Ctrl+F in the zip's tab) searches every file in it, whatever it is called. A zip with one file opens that file right away, and a .gz file opens directly. A file from a zip is named by its place in it (bundle.zip/logs/app.log) and behaves like any log: its bookmarks, filters and format are remembered, and it is in Recent files and the last session. It is unpacked to a temporary copy once, when first opened.
Web addresses: File → Open URL… (Ctrl+Shift+U) takes one or more http/https addresses, one per line, with an optional user and password or token (sent as a Bearer token). One address opens in a tab; several are downloaded into one temporary folder and searched together. A .zip or .gz download is unpacked as above. The file is a copy: it doesn't follow the server's file as it grows. Certificates count as trusted when Java or this computer trusts them (Windows' and macOS's own stores, where a company proxy's certificate usually is); when neither does, Logsift asks whether to open it anyway without checking, once or always for that server.
WSL (Windows): File → Open from WSL… opens your Linux home folder. Windows reaches WSL files directly (\\wsl.localhost\Ubuntu\…), so they open and follow like any other file, without SSH.
Command line: . prints the version.
~/.logsift/errors.log (Help → Open Error Log).| Start page: the ways to begin, and recent files | Find (Ctrl+F): matches light up as you type |
| Filters as chips above the log: click one to turn it off | Several searches at once, with a search inside another's results |
| Timeline: select a time range, keep stack traces | Columns and top messages |
| Folder search, including inside .gz and .zip | JSON logs with a details panel |
| Compare a bad run with a good one | CSV files as columns, here from a zip inside a zip |
| Zips open as a tab: open files as logs, merge or search them | Follow a request through a folder of logs |
| Exceptions by root cause | Metrics from the messages |
| Insights with known problems | Thread dumps, explained |
| Profiling with a flame graph | Heap dumps explained, and why an object is alive |
| Wasted memory: copies of strings, empty collections | A log knows its JVM |
| GC logs explained | GC charts: heap, pauses, allocation, time in GC |
| Two heap dumps compared: what grew, and where | The heap as a map: boxes as big as what they hold |
| Dark mode |
./gradlew run --args="/path/to/app.log" # or open files via File → Open / drag and drop
./gradlew installDist # launcher in build/install/logsift/bin/logsift
Make a test log:
./gradlew genLog -Pout=/tmp/sample.log -PsizeMb=500 # 500 MB realistic log
./gradlew genLog -Pout=/tmp/live.log -PsizeMb=5 -Pfollow=2000 # keeps appending 2000 lines/s
| Action | Shortcut (macOS uses ⌘ in place of Ctrl) |
|---|---|
| Open files (or drag files onto the window) | Ctrl+O |
| Find in this log (matches light up as you type) | Ctrl+F, or Find in the log's bar; the selected text becomes the search |
| Next / previous match | Enter / Shift+Enter in the find bar, F3 / Shift+F3 anywhere (also ⌘G / ⇧⌘G on macOS) |
| Match case / whole word / regex | Aa W .* buttons inside the find box |
| Find All (every match listed below the log) | Ctrl+Enter in the find bar, or Find All |
| Turn the search into a filter | Filter ▾ in the find bar: show only, hide or color its lines |
| Close the find bar | Esc |
| Close results | Shift+Esc |
| Jump from a result to the line | click it, or move with the arrow keys in the results |
| Wrap long lines | Alt+Z (⌥Z on macOS), or the Wrap button (works in the Columns view too) |
| Next / previous error | F8 / Shift+F8 |
| Follow the current line's request (or the selected text) | Ctrl+Shift+R |
| Bookmark the current line | Ctrl+F2 (⌘F2 on macOS) |
| Next / previous bookmark | F2 / Shift+F2 |
| Search in a folder | Ctrl+Shift+F (⇧⌘F on macOS) |
| Merge logs by time | Ctrl+Shift+M |
| Open a remote log (SFTP) | Ctrl+Shift+O |
| Compare logs by message | Ctrl+Shift+D |
| Next / previous difference in a comparison | F7 / Shift+F7 |
| Columns view | Ctrl+Shift+K |
| Export lines shown by filters | Ctrl+Shift+E |
| Go to line | Ctrl+L |
| Go to time | Ctrl+Shift+L |
| Matching lines only / all lines | Ctrl+Shift+H (⇧⌘H on macOS) |
| Fold / open the bottom panel | Ctrl+J, the ▾ button, or double-click a tab |
| Follow the end of the file (tail -f) |
File → Search in Folder… (Ctrl+Shift+F, ⇧⌘F on macOS), or Find in all files in a folder's tab, opens a search tab:
*.log;*.txt), and whether to include subfolders and archives.*.log also finds app.log.1, app.log.2026-10-21, app.log.2.gz, and .log files inside any .zip, also inside zips and .gz files within a zip (up to 5 levels deep)..gz or .zip are unpacked to a temporary file first. Double-click a file name to fold it. Above the results, Filter results by file name shows only the files whose name or path has some text, and Expand All / Collapse All open or fold every file.When a log has timestamps, a timeline above it shows how much was logged over time, with errors in red and warnings in amber, so incidents stand out at a glance. The box shows which part of the file you are looking at.
10:05, 10:05:30.250 or 2026-10-21 10:05.2026-10-21 10:02:13, ISO with T, 2026/10/21, 21-10-2026, 21.10.2026, 21-Oct-2026, syslog Oct 21 10:02:13, Apache [21/Oct/2026:10:02:13 +0000], timestamps inside JSON lines, time only, and epoch seconds or milliseconds. Times are shown as written in the log (time zones are not converted).Ctrl+F2 (⌘F2 on macOS) bookmarks the current line (or right-click → Bookmark This Line); F2 / Shift+F2 jump to the next / previous bookmark. Bookmarks show as blue dots by the line number and on the highlight bar. The Bookmarks tab lists them with their time and text; type a note in the Note column, double-click to go there, Delete to remove. Bookmarks are remembered per file, and dropped if the file was truncated (the lines would have moved).
Logsift detects how a log's text is encoded: UTF-8 (with or without a byte order mark), UTF-16 (as written by some Windows tools; with or without a byte order mark), and Windows-1252 (Western European, used by older Windows programs). The status bar shows the encoding; View → Encoding reopens the log in another one (Latin-1, Cyrillic, Shift_JIS, GB18030 and more). UTF-16 logs are read through a UTF-8 copy that is kept up to date, so following a growing UTF-16 log works too. Folder search detects the encoding of each file.
File → Open Recent lists the last 15 files. When Logsift starts without a file to open, it reopens the logs that were open last time (File → Reopen Last Session does it any time). Every file remembers its filters, formula, level chips, Matching only and position, so reopening a log puts you back where you were; if the file got smaller in the meantime (truncated or rotated), it starts fresh.
File → Export saves lines to a new file: the lines shown by filters (Ctrl+Shift+E), the Find results, the selected lines, or everything in the view. The original bytes are copied (line endings and encoding unchanged), in runs of consecutive lines, so even large exports take seconds.
The Columns button (or View → Columns, Ctrl+Shift+K) shows lines as columns: Time, Level, Thread, Logger, Message, with the level colored and stack traces under the message. Logsift recognizes common layouts by itself: logback and log4j patterns, Spring Boot's default layout (with its process id), Python logging, syslog (host, process, pid), web server access logs (client, user, request, status, size), "time level message", and merged logs (a Source column). Drag a header edge to resize a column.
When Logsift doesn't know a log's layout, the Columns view says so and offers Define Its Format…. Formats are also under View → Log Format → New Format from This Log and in Settings → Log Formats. There are three ways to make one:
[thread], logger, separators like - : |) and how its times are written, for example dd.MM.yy HH:mm:ss.SSS.%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n, a whole logback.xml, log4j2.xml or log4j.properties, a log4j2.properties, .yaml or .json, Spring Boot's layout, a Log4j 1.x XML config, a java.util.logging logging.properties (SimpleFormatter.format), or Python logging: a format such as %(asctime)s %(levelname)s %(name)s: %(message)s, a logging.conf or dictConfig (with datefmt), or basicConfig(…) in code. Dropping the config file works too. Properties the pattern uses (${LOG_PATTERN}, ${sys:PID}, ${env:X:-default}) are filled in from the same file. When the config has several appenders or formatters with different layouts, each becomes a format, named after its appender, and each log uses the one its lines fit.{time} {level} [{thread}] {logger} - {message}. Columns go in braces and everything else is matched as written. {time} takes a timestamp and {level} a level word (also E, ERR, warning…). {*} skips a part, and other columns take everything up to the next character. A regex with named groups like (?<level>…) works too.A preview shows sample lines split into columns, with the times as they are read. Lines that don't fit continue the entry above (stack traces). A format is used when most of a log's lines fit it, or always for the file names you give (app*.log; *.trace). The log's bar shows the format each log is read with (Format: …▾, on the right). If Logsift picked the wrong one, click it (or use View → Log Format) to choose another for that file, which is remembered, or to show it as plain text. Levels in your format's level column drive the colors, the error marks and the E W I D T chips. Formats are saved in ~/.logsift/formats.properties, so you can copy them to another computer.
The Insights tab (next to Filters) tells you at a glance what is going on in the log. It fills in by itself once a file is read (for files up to 2 GB; bigger ones when you open the tab), and its title shows how many problems it found, so you can see them without clicking.
Each finding has buttons to Go to its line, Find all of that message, Show only it or Hide it. Refresh looks again after the log grew.
The Exceptions tab groups the log's exceptions by their root cause (the innermost Caused by: in Java, the first exception of a chained Python traceback) and where it was thrown in your own code. Frames of the JDK, Python and well-known frameworks and libraries (Spring, Hibernate, Netty, connection pools, site-packages…) are skipped when deciding where. So 60 NullPointerExceptions thrown in PriceCalculator.discount are one row, however they were wrapped and whatever their messages said, and the same exception thrown somewhere else is another.
com/acme/shop/PriceCalculator.java, inner classes too), Python files by the most folders in common with the path on the server (/app/orders/payment.py → orders/payment.py). Build output, dependencies and virtual environments are skipped. It opens in IntelliJ IDEA or PyCharm when installed, else Visual Studio Code, or the editor you choose there, or your own command ({file} and {line} are filled in).at …, Caused by:, ... 5 more, Suppressed:) and Python (Traceback (most recent call last):, chained with "During handling of the above exception…") stacks are read.The Metrics tab shows what the log measures, without any setup:
ms, s, MB, %, rows) or a word like took, size, latency or queue before it is a measurement: order … placed in # ms, queue size=#. Order numbers and IDs are not. Durations are in milliseconds and sizes in bytes, whatever unit each line used (1.5s, 300ms).duration_ms, bytes, the access log's size; units from the value or the name), and a column with a few values (status, host) gives how many rows have each value per minute (or per second, per hour, as fits the log).Right-click a line → Follow traceId 4bf92f… (or press Ctrl+Shift+R), and the Request tab shows every line of that request in order: when it happened, the time since the line before (After), its thread, level and message. The top line sums it up: 6 lines · 2 threads · 10:02:19.097 → 10:02:27.337 (8.24 s) · 1 error · longest wait 8.20 s, and the longest wait is marked, which is usually where the time went. Click a line to go there.
traceId=…, request_id: …, X-Request-Id, "correlationId":"…" and any other …Id / …_id key, the [app,traceId,spanId] and [traceId-spanId] that tracing libraries add, a W3C traceparent, and UUIDs. Process and thread ids (pid, tid) and span ids are left out. With several IDs on a line, traces come first, then requests. To follow anything else (an order number, a user), select it first..zip you choose), every file in it is searched, also inside zips, zips in zips and .gz files unless Inside zips and .gz is off. Lines from all files are put in one order by time, with a File column; double-click a line of another file to open it there. Merged logs work too.Logs with a logger column (or class, component, thread, host…) get a tree on the left: com.acme.db.Pool sits under com.acme › db, with line counts. Uncheck a branch to hide its lines and their stack traces. Double-click a name, or right-click → Show Only, to see just that one; Show all brings everything back. The list at the top picks the column. Counts keep up while the log grows, and what you hid is remembered for the file. Close the tree with ✕, and bring it back with the Tree button or View → Tree of Loggers (Ctrl+Shift+B).
Reading logs changes nothing. Reaching a running JVM can: some actions stop it for a moment, some cost CPU, memory, disk or network on its server. This is what each one does, from lightest to heaviest. Logsift says the same where you start each action.
| Action | What the JVM or its server feels | How much |
|---|---|---|
| Opening a log (on this computer or over SSH) | Logsift looks for the JVM that writes it: ps, and which processes have the file open (for a remote log, over its own SSH login). | A few small commands, once. |
| Following a remote log (Open Remote) | A check for new lines every second, and reading what was added. Whole file reads all of it first. | Light; a whole multi-GB file is a big read. |
| Attach / Connect | Attaching to a JVM on this computer starts its management agent (it stays until the JVM ends). Every connection takes a first thread dump. | One short stop. |
| Thread dump (Take Dump, Record…) | The JVM stops while the stacks are written, and while it walks the heap to see who holds which lock. Record repeats it. | Usually milliseconds; longer with thousands of threads or a big heap. |
| Heap histogram (Take Histogram) | Only live objects (the default) runs a full garbage collection first. Off, the JVM still stands still while it counts the heap. | Seconds for a big heap with a full GC; less without. |
| Profile, Flight Recorder | Recording with the "profile" settings; the first recording starts Flight Recorder in that JVM. The recording ends by itself after the run, even if Logsift is gone. | About 2–3% CPU while it runs. |
| Profile, async-profiler | async-profiler is loaded into the JVM for the first run and stays loaded until the JVM ends (Java 21 and later print a warning about it in the JVM's output). CPU, allocations, wall clock, hardware events: light. Locks: light to moderate. Native memory and Everything at once record every malloc: noticeable on busy native code. Calls of a method instruments the method: every call costs a little, and the JVM recompiles some code; only one class can be named (a * only in the method name). | From about 1% to noticeable, by mode. |
| Save Heap Dump | A full garbage collection, then the JVM stops while every object is written. The file, about as big as the heap in use, is written (in over SSH, in the JVM's temporary folder over a JMX port) and copied here. Logsift checks the room first (the heap in use against the free space there) and refuses a folder that is too small, or a in memory, asking for another folder on that machine. |
For JVMs of other users Logsift uses sudo on the server (you can turn that off). On a production JVM, prefer thread dumps, Flight Recorder and live-objects-off histograms; save a heap dump or profile native memory at a quiet time.
Logsift never removes files on a server. What it writes there stays, and Logsift says where:
/tmp/logsift-*.hprof over SSH, logsift-heap-*.hprof in the JVM's temporary folder over a JMX port), readable only by your login user;/tmp/logsift-*.jfr), also only for your login user;/tmp/logsift-<user>-async-profiler-*), and the heap reader (~/.logsift/heap);NAME.part); Logsift refuses a name that is already taken rather than overwrite it.The only files that go are the heap reader's index, made of temporary files that vanish when the reader ends.
JVM → Open Thread Dump… reads jstack and jcmd Thread.print output, the plain and JSON files of jcmd Thread.dump_to_file (with virtual threads), and dumps saved by Logsift. A log with kill -3 dumps in it (a console log, catalina.out, even docker logs --timestamps output) shows a bar offering Analyze Threads; JVM → Analyze Thread Dumps in This Log does the same for any open log. Several dumps in one file, taken some seconds apart, are read as a series.
Python thread dumps open the same way: py-spy dump output (thread names, idle or active, holding the GIL; the arguments and locals under a frame are skipped) and faulthandler dumps (faulthandler.dump_traceback(), faulthandler.register(signal.SIGUSR1), or what Python writes when it crashes), also in the middle of a log. Idle threads show as waiting and active ones as runnable, so grouping by pool, the stack view, several dumps over time and stuck threads work for them too.
The Threads tab starts with what stands out, worst first. Each finding has a Show threads button:
ReentrantLocks), as a chain.http-nio-8080-exec-∗) busy, so new work waits.Below that:
JVM → Attach to a Running JVM… (Ctrl+Shift+J) lists the Java programs running as you on this computer, or on a server over SSH (with the same login as remote logs). Pick one and its Threads tab can Take Dump or Record… several dumps some seconds apart. A dump pauses the JVM for a moment (usually milliseconds), and Logsift only reads: it changes nothing in the JVM.
jcmd from a JDK folder you give.jcmd: from the JDK folder you give, the PATH, or the JDK the program itself runs on. Servers with only a Java runtime and no JDK tools work too: Logsift copies async-profiler to the server's /tmp and uses that. JVMs running as another user (tomcat, app) are reached with sudo. Logsift asks for the sudo password if it needs one and keeps it only while it runs. JVMs in containers are listed too.-Dcom.sun.management.jmxremote.port=9010), from anywhere, with no SSH: give the host and port, and the user and password if the port has them. Over JMX, Logsift takes thread dumps and heap histograms, and profiles with Flight Recorder, the recording sent back over the same port. Save Heap Dump… works too: the JVM writes the dump on its own machine (it can't come back over JMX), in its temporary folder; Logsift then offers to copy it here over SSH (asking how to sign in to that machine) and opens it. The dump stays on that machine (Logsift doesn't remove files there): remove it when you are done. Without SSH, Logsift says where it is. A Windows server needs its OpenSSH Server turned on for the copy. For a JVM on this computer, the dump goes straight to the file you chose. async-profiler needs SSH or this computer.A log tab shows which JVM writes the log, in a bar above it, with Threads, Profile and Heap buttons. Logsift finds it by itself:
The link is remembered for the log and for the other logs in its folder, by program (orders.jar, com.acme.App), not by process id, so it finds the JVM again after a restart or a new version of the jar. The bar's menu links another JVM, or forgets the link.
Thread names connect the two:
nio-8080-exec-1) still finds http-nio-8080-exec-1.Save… writes the dumps as a text file that opens again here, or in any other tool.
Profile… in the Threads tab of a running JVM shows where it spends its time, memory or lock waits. Choose what to measure, for how long, and Start Profiling. The JVM keeps running as usual.
| Measure | Shows |
|---|---|
| CPU | where the threads use the CPU |
| Wall clock | where they spend their time, running or waiting |
| Allocations | where memory is allocated, and for which classes |
| Live objects (memory leaks) | objects allocated during the run and still alive at its end: what makes the heap grow |
| Locks | where threads wait to get locks |
| Native memory / Native memory leaks | native allocations (malloc, direct buffers), or only those never freed |
| Native locks | waits for native (pthread) locks |
| Calls of a method | every call of a method you name (com.acme.Api.handle, java.io.FileInputStream.read*), and where it comes from |
| Slow calls of a method | calls slower than a time you give, with their total time |
| Hardware event (Linux) | cache misses, page faults, context switches, CPU cycles… |
| Everything at once | CPU, wall clock, allocations, live objects, locks and native memory from one run |
Per thread gives each thread its own flame graph.
The result is a flame graph: the outermost calls on top, what they call below, each as wide as its share. Green is Java code (paler for the JDK's own), yellow native code, orange the kernel, and teal the class an allocation was for. To look closer:
Every run stays in the tab. Compare with an earlier run colors each frame by how its share changed: red grew, blue shrank. The method list then gets a Change column.
Two engines:
Save… writes collapsed stacks. They open again with JVM → Open Profile…, along with .jfr recordings (each kind of event in them becomes a view).
Heap… in the Threads tab of a running JVM shows what fills its heap, by class: how many objects, their size, and their share.
.hprof file and opens it (see below). It pauses the JVM while it is written, and the file is about as big as the heap. From a server, it is copied over SSH.Open a .hprof file (File → Open, JVM → Open Heap Dump…, Open Heap Dump… on the start page, or drop it on the window). Logsift reads every object, works out which object holds which, and starts with what matters:
class LeakApp → static CACHE → HashMap → table → [1440] → value → Session). A GC root is a loaded class's static fields, a local variable in a running thread (named, with its method), a running thread, native code, or a lock in use. To free the object, one link in that chain has to go.Compare with Another Dump… (or JVM → Compare Two Heap Dumps…) takes an earlier dump of the same program and says what grew, and where: "HashMap in static LeakApp.CACHE grew by 11.8 MB (3.92 MB → 15.7 MB). 5,000 entries → 20,000 entries. Mostly 20,000 × LeakApp.Session." Objects move between dumps, so places are matched by the chain of fields from a GC root that keeps them, not by address; when a place grows mostly because of a place inside it, the inner one is shown. Classes lists every class with its objects before and after. The dumps are put in order by when they were taken.
On a server: JVM → Open Heap Dump on a Server… reads a dump where it is, over SSH, on a Linux or macOS server (not Windows yet), so a 40 GB dump doesn't have to come to your computer. Logsift first looks at the server (the dump's size, a Java 8 or later there, free disk and memory) and says what reading it takes before anything starts: up to the dump's size in disk for the index, 2 GB of memory, a CPU core for some minutes, and one read of the dump. Its reader is copied to ~/.logsift/heap there and runs at low priority (nice, ionice); the app asks it questions through an SSH tunnel to a port only reachable on that machine, with a secret token. It keeps going if the connection drops (opening the dump again reconnects), and ends when you close the tab or after 30 minutes with no one connected. Its index is made of temporary files that go when the reader ends; nothing else is removed there. On a production machine, Copy to Another Machine… copies the dump to a folder on another server and reads it there: that server fetches it itself when it can sign in to the first with its own key and already knows its host key (Logsift adds nothing to its known_hosts), else (if you agree) it goes through your computer; either way the first machine reads it once at low priority.
Threads (N) at the top opens the dump's threads in the Threads view: names, states and stacks at the moment of the dump (a heap dump doesn't record which locks they hold).
From a log: when a JVM started with -XX:+HeapDumpOnOutOfMemoryError runs out of memory, it prints Dumping heap to java_pid4242.hprof .... Right-click the OutOfMemoryError line (or that one) and choose Open the Heap Dump, or click Open Heap Dump on the known problem in Insights: Logsift finds where the log says the dump went (as written, or next to the log) and opens it; for a log read over SSH, it is copied from the server first.
Weak, soft and phantom references don't keep anything alive here (as in the JVM when memory runs low): what only they reach is shown apart, since it isn't a leak. Sizes are the JVM's own (12-byte headers, 4-byte references with compressed pointers, objects aligned to 8 bytes); the tests check them against the JVM's class histogram.
Big dumps: when a dump is too big to index in memory, the index goes to files on disk (in Logsift's folder, removed when the tab closes). A 1.6 GB dump with 41 million objects opens in about 20 seconds with 2 GB of memory; the index on disk is a few times the size of the dump.
Open a Java GC log like any log: Logsift sees it is one and offers Analyze GC in a bar above it (also JVM → Analyze GC in This Log, or JVM → Open GC Log… to open and explain one in one go). GC lines inside other output (a console log with -Xlog:gc) count too.
Logsift reads the logs of Java 9 and later (-Xlog:gc*, with any decorations: uptime, time, both) and the older ones of Java 8 (-XX:+PrintGCDetails, with or without -XX:+PrintGCDateStamps), for every collector: G1, Parallel, Serial, CMS, ZGC (also generational) and Shenandoah. For the most to go on, log with -Xlog:gc*,safepoint:file=gc.log:time,uptime,level,tags (Java 9 and later) or -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationStoppedTime -Xloggc:gc.log (Java 8).
The tab starts with the numbers that matter (the share of the time stopped for GC, the longest pause, 99% of pauses under, full collections, allocation per second, the most left after GC), then says what it found, worst first, each with what to try and Show in Log:
Then: Heap (in use before and after each collection, with the heap size and full collections marked), Pauses (each pause by kind over time, on a log scale, and how many took how long), Allocation & GC Time (allocated per second and the share of time stopped, per stretch of time), By Kind (pauses by kind and cause: how many, in all, average, longest) and All Collections (every collection, pause and stall, sortable). Drag across a chart to zoom in on that time (all charts follow), double-click to see it all; click a point or double-click a row to see its line in the log.
Ask your coding agent about your logs and it asks Logsift: "why is orders.log full of timeouts?", "what is stuck in this thread dump?", "is this service's GC healthy?". Logsift reads the files on your computer, fast on gigabytes, and answers the agent with short summaries and line numbers, never whole files; the agent can then search and read the lines around what it found. It works with GitHub Copilot in VS Code, Visual Studio and JetBrains IDEs, Copilot CLI, and any other agent that supports MCP (the Model Context Protocol).
Set it up: Settings → Agents shows the exact setup for your agent, with the path of logsift-mcp on this computer filled in: copy it into the agent's MCP settings. For VS Code, add to .vscode/mcp.json (or your own mcp.json: Command Palette → MCP: Open User Configuration):
{
"servers": {
"logsift": {
"type": "stdio",
"command": "/Applications/Logsift.app/Contents/MacOS/logsift-mcp"
}
}
}
Then choose Agent mode in Copilot Chat. logsift-mcp comes with Logsift: next to Logsift.exe on Windows, in Logsift.app/Contents/MacOS on macOS, in bin/ on Linux and in the zip. Other agents: add a local (stdio) MCP server that runs logsift-mcp.
What the agent can ask: open a log (also .gz, or a file in a zip) and get its format and time range; insights (what happened, most important first); exceptions by root cause; search (text or regex, by line range) and read lines; the most frequent messages; durations and numbers; search a folder (zips too); explain a GC log; explain thread dumps. Slow work (a first look at a multi-GB log) goes on in the background, and the agent is told to ask again.
What it can't do: change or delete anything, run commands, or connect to servers by itself. A thread dump or heap histogram of a running JVM happens only after you say yes, and never a heap dump. It reads only under your home folder (or the folders you list in Settings → Agents), and never files that hold keys or passwords (~/.ssh, ~/.aws, *.pem, key stores…), even through a link.
Privacy: whatever Logsift answers goes to the agent's AI provider, under your agreement with them. Logsift masks secrets in its answers (passwords, tokens, API keys, private keys, card numbers) as ‹masked:token›, and says how many it masked; in Settings → Agents you can also mask email addresses, IP addresses and your own patterns (customer numbers, host names). Each call is recorded in ~/.logsift/agent.log: when, which agent, which tool, how long the answer was and whether it worked, never the answer itself (What Agents Asked… opens it). Text from logs is passed on as data: Logsift tells the agent never to follow instructions found in a log.
From a terminal: logsift-mcp --help. --root FOLDER (repeatable) limits reading to those folders; --mask-emails, --mask-ips and --mask REGEX mask more; --no-mask masks nothing.
GitHub Copilot is a trademark of GitHub, Inc. Logsift is not affiliated with or endorsed by GitHub.
Settings (Ctrl+, or Logsift → Settings on macOS) has the font and its size, tab width, line stripes, the timeline, dark mode, the encoding for text that isn't UTF-8 (for example Shift_JIS or GB18030), how often files are checked for changes, whether the last session reopens at start, update checks, your log formats, and what coding agents get (Agents).
A .csv or .tsv file is read as a table: its header row names the columns and each row is split into them, by comma, semicolon, tab or | (whichever the file uses), with quoted fields ("a, b", "" for a quote) handled. Columns named like a time, level, thread, logger or message (timestamp, severity, msg, …) are used as such: the timeline uses the time column, and levels color the rows. Other columns keep their names and appear in the tree beside the log, where unchecking a value hides its rows. Files with other names are read as CSV when they clearly are one (a header of names, then rows with the same number of fields), or choose CSV in Format: …▾ in the log's bar. A quoted field over several lines is shown as continuing its row. In the Columns view the header row isn't repeated as a row: its names are the column titles (line numbers stay those of the file). The Profile tab shows what each column holds (numbers, times, categories, IDs, text) with a chart per column; click a bar to filter. Right-click a value for Show Only Rows Where Host = web-1 (a filter on that column), and the Metrics tab charts the columns of numbers and how many rows each host or status has over time.
Logs with one JSON object per line are recognized. With Columns on, the usual fields become columns (@timestamp/ts/time → Time, level/severity → Level, thread, logger, message/msg) and the rest are shown together in a Fields column. The timeline uses ISO times or epoch milliseconds in the JSON. The Details tab (next to Filters) shows the current entry in full (a line with its stack trace), or just the text you selected (several lines, or part of one). Its Text | JSON switch pretty-prints the JSON in it with colors, also JSON in the middle of a message, and opens up JSON written inside strings. A JSON line or selection is shown pretty-printed by itself; click Text to see it as written.
File → Open Remote (SFTP)… (Ctrl+Shift+O): enter the host, user, and a password or private key (~/.ssh/id_ed25519 or id_rsa is suggested), then Connect. Pick the log in the file browser: type a folder in the address bar (/var/log, ~/logs, or a name relative to the folder shown) and press Enter, or double-click folders (.. goes up, Backspace too); double-click a file or press Open. Load the whole file or just the last N MB. LogSift keeps a local copy up to date while the remote log grows (new bytes are fetched every second), starts over when it is truncated or rotated, and reconnects by itself if the connection drops (the status bar says so). Host keys are checked against ~/.ssh/known_hosts; for a new server you are asked first. It remembers the server, user, key and last folder per server, never passwords. Every feature works on remote logs.
File → Merge Files by Time… (Ctrl+Shift+M) merges several logs (say, the same app on two nodes, or an app log and its server log) into one view in timestamp order. Each line starts with a label like <node2-app> and a colored stripe, so you can see where it came from; right-click → Show Only Lines from filters to one source. Stack traces stay with their log line. The merged view is an ordinary log, so filters, the timeline, messages and search all work on it, and it keeps updating while the source logs grow. CSV files merge into one CSV instead: one header with all their columns (matched by name), a Source column, rows in time order (or one file after the other when a file has no times).
The Messages tab (next to Filters) groups the log's lines into kinds of messages and counts them, most frequent first. Variable parts (numbers, IDs, hosts, durations, user names) are shown as ∗, so ERROR [worker-7] Database connection lost after 26579 ms and ERROR [worker-2] Database connection lost after 812 ms count as one message. Stack traces count with their log line.
File → Compare Files… (or Compare Files… on the start page, Compare on a folder's tab with two files selected, or the compare button in a CSV tab's bar) opens a Compare tab with a file browser on each side, where zips and zips inside zips open like folders. CSV and TSV files are compared as tables. Rows are matched by a key, so row order doesn't matter: Logsift suggests one (a column, or two or three together, that is unique and filled in in both files, preferring names like id and …_id), one click uses it, and you can pick others. Columns are matched by name; a column only one file has is mentioned once. Tiles count what was added, removed, changed and the same, and key repeats (a key value on several rows of a file), which are listed, never paired at random. Changes per column says which columns changed most; a changed value shows as old → new. Options: trim spaces, ignore case, numbers as numbers within a tolerance (absolute or %), empty = missing. F7 goes to the next difference, a double-click opens the row in its file, and Export writes the differences as CSV. Drop a file on a side to compare another one. See Compare files.
File → Compare Logs by Message… (Ctrl+Shift+D) compares the current log with a baseline, for example the log of a run that went well. Comparing line by line is useless for logs (every timestamp differs), so Logsift compares kinds of messages (as in the Messages tab): what is new in this log, what is gone, and what happens much more or less often, with counts scaled to the logs' lengths. New errors come first. Double-click a row to find all its lines in the log that has them.
A narrow bar beside the scrollbar shows the whole file at a glance. It has red marks for errors (ERROR, FATAL, SEVERE, CRITICAL), amber for warnings, a second lane for Find All hits and colored filters, and a box showing where you are. Click a mark to jump to that line; hover to see it. F8 / Shift+F8 jump to the next or previous error. The marks stay up to date while the file grows.
Ctrl+F (⌘F on macOS) opens a find bar at the top of the log, with the selected text filled in. Matches light up as you type and the log goes to the first one; the bar counts them ("3 of 1,240"). Enter and Shift+Enter go to the next and previous match, and Esc closes the bar. From there:
Each log has its own bar: Find, Filters and the filters that are on on the left; Wrap, Columns, Tree, Timeline, Follow and Reload on the right. Each log keeps its own view settings, and your last choice is the default for the next log you open. There is no toolbar on top: opening files, remote logs, Search in Folder and Settings are in the menus (with their shortcuts), so a profile, a heap dump or a folder search gets the whole window. With nothing open, the start page has big buttons for the ways to begin (a log, a folder, a remote log, a web address, a JVM, a heap dump, a thread dump, a profile) and your recent files; with logs open, + after the tabs shows it again.
Filters that are on show as chips in the log's bar: click a chip to turn its filter off or on, ✕ to remove it, right-click to change what it does. Chosen levels, a time range and branches hidden in the tree show as chips too.
The Filters panel below the log holds any number of filters (up to 26). Each one has:
1.5 s is more than 800 ms)Aa / W / .* options as FindCombine says how filters work together. In Auto mode it is "any Show filter, and no Hide filter", for example (A OR B) AND NOT C. Type your own to get anything else: A AND B, (A OR B) AND NOT (C OR D), NOT C. AND OR NOT ( ) work, and so do & | ! -.
All lines / Matching only (Ctrl+Shift+H, ⇧⌘H on macOS) switches between every line, with filtered-out lines grayed, and only the lines that pass. Your place in the file is kept when you switch, so you can filter down, click a line, switch back and see everything around it.
Keep stack traces (on by default) treats a log line and the lines under it (stack traces, wrapped messages) as one entry: if any line of the entry matches, the whole entry is shown, and Hide filters hide whole entries. Logsift detects how entries start from the first lines of the file (a date, a time, a syslog date, a level word, or { for JSON lines); the checkbox tooltip shows what it found. Context ±N adds N grayed lines before and after each match, with a dashed line where lines were skipped, like grep -C.
Alerts: click the bell on a filter to be told when new lines matching it are written (while the file grows). Logsift shows a desktop notification and a popup you can click to jump to the line, beeps, and puts a count on the tab. Bursts are combined (at most one alert per filter every 3 seconds). Lines that were already in the file don't alert.
Clear All in the log's bar (lit while anything is set) goes back to the whole log: it removes every filter, turns all levels back on, clears the time range and what the tree hides, and closes the find bar and the Find results. Clear all in Filters (next to + Add filter) clears only the filters. In Find results, Close removes the selected search, Close all removes every one, and Shift+Esc closes the selected search.
Quick ways to add filters: select text in the log, right-click, then choose Show / Hide / Mark lines with "…"; in the Columns view, right-click a value for Show Only Rows Where Host = web-1 or Hide Rows Where …, or a column title for Filter by …. Filter sets can be saved and loaded (the ⋯ menu), and filters keep working while the file grows.
Several searches at once: each Find All is added to the top of the Find results window and opens there, while earlier searches fold to a header line (“ERROR” — 1,234 lines) and stay available. Click a header (or its chevron) to fold or open it; with the keyboard, Enter, Left and Right do the same. Fold all / Unfold all do every search. Every search has its own color in the log and on the highlight bar. Running a search you already have moves it back to the top. F3 / Shift+F3 step through the selected search's hits.
Search within results: select a search (or any of its lines), type in Search in these results and press Enter. A nested search like “ERROR › timeout” appears under it, showing only the lines that match both. You can keep narrowing it further, and closing a search also closes the searches nested in it.
Find All keeps running on a growing file. New matching lines show up in the results as they are written, including nested searches.
These numbers come from ./gradlew visualTest on an Apple Silicon Mac (10 cores, 32 GB RAM). The file had just been generated, so it was already in the OS file cache. With a cold cache, the disk speed sets the limit.
| 1 GB, 9.4M lines | 3 GB, 28.1M lines | |
|---|---|---|
| First lines on screen | 0.12 s | 0.22 s |
| Full line index built | 0.26 s | 1.1 s |
| Jump to any line + repaint | ~10 ms | ~6 ms |
Find All ERROR (literal, 335k / 1M hits) | 0.17 s | 0.58 s |
Find All WARN (whole word) | 0.15 s | 0.38 s |
Find All müller (ignore case, non-ASCII) | 0.19 s | 0.45 s |
Find All regex Payment failed .* user=u12\d4 | 0.12 s | 0.37 s |
Filters on a 200 MB log (1.8M lines): four filters with formula (A OR B) AND NOT C take 0.2 s. Changing only the formula takes about 2 ms, because the filters' results are kept and only merged again.
Heap use stays at a few hundred MB for these sizes. The index costs about 12 MB per 100M lines.
Stress test (./gradlew stress -PstressGb=10, same Mac, 2 GB heap as in the installed app):
| Time | |
|---|---|
| 10 GB log (93.6M lines): first lines / full index | 0.01 s / 2.6 s |
| Jump to the end, or 20 random jumps | under 10 ms |
| Find All: 0.9M / 3.4M / 5.1M (regex) hits | 1.7 s / 1.9 s / 3.0 s |
Filter ERROR AND NOT timeout | 3.5 s |
| Timeline / tree of loggers | 1.9 s / 10 s (in the background) |
| One 200 MB line: open / search it | 0.02 s / 0.17 s |
| 300 million short lines (3 GB): full index | 0.4 s |
The heap stayed under 500 MB through all of it.
./gradlew test # fast unit tests (index, tail, search vs simple reference code)
./gradlew visualTest # opens a generated 1 GB log in the real UI
./gradlew visualTest -PsizeMb=3072 # same with 3 GB
visualTest generates build/visual/big-<N>mb.log (and reuses it on later runs). It then drives the real window and checks the following against independent, plain-Java reference code:
It saves screenshots and a timing summary to build/screenshots/. Delete build/visual when you need the disk space back.
For the full, educational explanation (sparse index, SWAR byte search, the regex pre-filter, filter merging, tail and rotation, and lessons learned), see docs/how-it-works.md. Short version:
logsift.core (no UI code; could later back a VS Code extension or a CLI)
FileSource positional reads (pread), safe from many threads
LineIndex sparse index: chunks of 4 MB; offset of every 64th line
LogDocument open file + index + tail polling (growth, truncation, rotation)
ByteScan newline/byte search 8 bytes at a time (SWAR)
LineMatcher literal byte search, regex, or literal pre-filter + regex
RequiredLiteral finds text every regex match must contain (ripgrep's trick)
SearchSession parallel Find All, hits published in line order, follows growth
Formula AND / OR / NOT of filter letters (parser and auto formula)
FilterEngine one live search per filter; merges their sorted hits by the formula
FilterResult the passing lines: a sorted list, or "all lines except a list"
FolderSearch parallel search of a folder's files, streaming; .gz and .zip inside
Archives a zip's files (zips inside too), unpacking one; UrlFetch downloads over HTTP(S)
EntryFormat how entries start (date, time, level...), to keep stack traces together
TimeFormat timestamp formats parsed from bytes; TimeIndex: a time every ~64 lines
MessageStats groups lines into message templates; LogCompare compares two logs
LogFormat columns (regex with named groups, JSON fields, or CSV); ColumnStats counts values
LogMerger merges logs by time; Encoding / Utf16Mirror; RemoteMirror (SFTP)
LineExporter copies chosen lines' original bytes to a file
logsift.core.diff (comparing files)
SequenceDiff lines up two sequences of hashes (patience anchors, then Myers) into Edits
TableDiff CSV files by key (a hash join on two 64-bit key hashes) or in file order
CsvFile a CSV file's rows streamed; only where each row is, kept; rows read again when shown
KeySuggester columns unique and filled in in both files, id-like names first
DiffStatus, ChangeNavigator, DiffOptions: shared by every kind of comparison
logsift.jvm (thread dumps and running JVMs)
DumpParser jstack / jcmd / kill -3 text (also inside logs), dump_to_file plain and JSON
ThreadAnalysis deadlocks (cycles of lock waits), lock queues, stuck and busy threads, pools
LocalJvms attach + JMX (the JVM's own diagnostic commands), or jcmd
SshJvms ps, jcmd or async-profiler over SSH, sudo for other users' JVMs
JmxJvms a JMX port: diagnostic commands, Flight Recorder streamed back, heap dumps on the JVM's machine
LogOrigin which JVM writes a log: who has it open, what it says, its file server
JvmLink a log's JVM, remembered by program
Profiler async-profiler (every mode) or Flight Recorder → Profiles (trees of stacks)
HeapHistogram GC.class_histogram, and what grew between two
GcLog GC logs (Java 8 and -Xlog:gc*, every collector) → collections, pauses, stalls, safepoints
GcReport a GC log worked out: time stopped, pauses, allocation, growth of the memory kept, findings
logsift.heap
HeapDump reads a .hprof: object graph, dominators (Semi-NCA), retained sizes, paths to GC roots
HeapFindings what fills the heap, in sentences
HeapWaste copies of the same strings, empty and mostly empty collections
HeapDiff two dumps compared: what grew, matched by where it is kept
HeapMap what an object holds, as boxes for the map
HeapServer reads a dump on a server, answers the app over one connection (Java 8+)
RemoteHeap the app's side of that connection
(logsift.heap is built for Java 8 into logsift-heap.jar, which is also copied to servers)
Store big arrays in memory, or in memory-mapped files on disk for big dumps
logsift.ui
LogView virtual view: paints only visible rows; scrollbar counts rows
LogTab log view + Filters and Find results panels for one file
FilterPanel the filter rows, formula field and All lines / Matching only switch
OverviewBar highlight bar beside the scrollbar (errors, warnings, filters, hits)
FolderSearchTab folder search form and results grouped by file
TimelineBar, MessagesPanel, BookmarksPanel, DetailsPanel, CompareTab, CsvCompareTab, ColumnLayout ...
ThreadsTab, ThreadTimeline, ProfileTab, FlameGraph, HeapTab, HeapDumpTab, GcTab, GcChart, JvmDialog, JvmBar
MainFrame window, menus, status bar, drag & drop
logsift.tools
LogGenerator realistic reproducible logs (levels, threads, stack traces, Unicode)
Design choices:
.hprof format are read (not compressed .hprof.gz, and not OpenJ9 .phd). A dump doesn't say how the JVM laid its objects out (compressed pointers or not, compact headers), so Logsift works it out from the addresses of objects next to each other. A big dump's index needs free disk space up to the dump's size, in ~/.logsift/heap-index (Logsift says so before it starts when there isn't enough). Comparing two dumps works with dumps on this computer, not with ones read on a server. A server needs sh, nohup and nice (any Linux or macOS has them) and a Java 8 or later. Wasted memory counts the JDK's collections (ArrayList, Vector, HashMap, LinkedHashMap, HashSet, Hashtable, WeakHashMap, IdentityHashMap, ConcurrentHashMap, ArrayDeque, CopyOnWriteArrayList, LinkedList, TreeMap, TreeSet), not those of other libraries.javacore files are not.gc.log.0, gc.log.1…) is read one file at a time; merge them first (Merge by Time) to see them together.Ideas for next versions: continuous profiling of a running JVM, editable highlight rules and signed installers. Suggestions and bug reports are welcome in Issues.
Bug reports, ideas and pull requests are welcome: see CONTRIBUTING.md.
MIT © 2026 bdarwin
Logsift includes async-profiler (Apache License 2.0) for profiling and for thread dumps on servers without JDK tools.
logsift app.log other.loglogsift --versionAnother program's output, live: pipe it in with -:
kubectl logs -f my-pod | logsift -
docker logs -f my-app 2>&1 | logsift -
journalctl -f | logsift -
The output is saved to ~/.logsift/stdin/ as it arrives and followed like a growing log. Captures older than a week are removed. On macOS the command is /Applications/Logsift.app/Contents/MacOS/Logsift, and on Linux /opt/logsift/bin/Logsift (.deb) or Logsift/bin/Logsift (.tar.gz); add an alias for convenience.
| Ctrl+T, Follow in the log's bar, or End |
| Load changes to the file | F5 or the log's Reload (it lights up when the file changed); Reload ▾ → Reload Automatically loads them as they happen |
| Select text | drag; double-click = word, triple-click or click the line number = whole line; Shift+click extends |
| Copy | Ctrl+C (with nothing selected, copies the current line) · Select all: Ctrl+A |
| Font size | Ctrl+= / Ctrl+- |
| Dark mode | View → Toggle Dark Mode |
| Tree of loggers | Ctrl+Shift+B |
| Settings | Ctrl+, (⌘, on macOS) |
/tmp/tmp| Seconds to minutes of stop; disk the size of the heap; that much network. |
| A heap dump from a log (the OutOfMemoryError line, for a remote log) | The dump is read from the server's disk and sent over the network at full speed. Logsift asks first. | The dump's size, once. |
| Open Heap Dump on a Server | Logsift's heap reader runs there at low priority (nice, ionice): 2 GB of memory plus the disk cache for its index, disk up to the dump's size for the index, some minutes of a CPU core, one read of the dump. It keeps running until you close the tab, or 30 minutes after the last connection. Logsift says what it takes before it starts. | Heavy for a production machine: copy the dump elsewhere first. |
| Copy to Another Machine | The dump is read once on the first server at low CPU and disk priority; the network between the servers isn't limited. | The dump's size over the network. |