The tool is useful because it guesses.
A debugger samples or controls a live process. LogCallStack works after the fact. You pick a row in a log file. The extension parses the row, searches the workspace for the source call, walks backward through earlier rows on the same thread, then asks VS Code for incoming callers. If the language service cannot answer, it searches source files for call sites.
That is a reconstruction. It joins evidence from different times and systems. The log came from one execution. The source tree is what you opened now. The language service describes possible callers in that tree. A regular expression fallback finds text that looks like a call.
Use the reconstructed stack to choose the next file. Do not use it to declare what the process did.
What version 0.2.1 actually does
The source at commit 77019c6 sets a default limit of seven frames and clamps the setting at twenty. Its backward scan checks at most 10,000 earlier lines. It groups entries by thread identifier, looks for the first earlier occurrence of the selected function, and treats distinct entries before that point as possible callers.
The next pass asks VS Code for a call hierarchy. The code uses the log timeline to rank incoming callers as confirmed, likely, ambiguous, or inferred. If no call hierarchy provider answers, the extension uses VS Code's bundled ripgrep when available. It searches for the function name, finds enclosing methods, and ranks those candidates against the log timeline.
The Local Variables view also mixes two kinds of values. It can show key and value pairs found in the log. It can also show source initializers found near the matched call. The interface marks extra log values as runtime data. A source initializer is not a captured runtime value, even when both appear under one frame.
Every frame should carry its origin. Mark values as logged, source derived, or inferred. Do not flatten them into one debugger shaped list.
Three ways the chain can lie
The source moved
A production log may come from revision A while the open workspace contains revision B. A source string can survive a refactor while its callers change. Record the build or commit that produced the log before trusting navigation.
The thread label is weak
Many formats have a request, session, worker, or thread field. Some have none, so the parser uses main. Rows that share that fallback can belong to unrelated work. The code handles exact file and line formats differently because it knows a shared main timeline can produce false callers.
Possible callers are not executed callers
A language service can list functions that call the selected function. It cannot tell which branch ran in the captured event. The extension tries to resolve that gap with nearby log rows. When no row matches, its own model calls the answer inferred.
Artifact check, with the dents left visible
We fetched the Marketplace archive for version 0.2.1 without installing the extension. The VSIX measured 58,421 bytes, contained 57 entries, and had SHA-256 f17e3191040f160b29ce0a8a01189817d17f72315b2b45fe298a6185f5764735. Its manifest points to the public repository and declares VS Code 1.85 or newer.
We also checked out the linked source at commit 77019c68408fe126a12cb196ac2287a1e2af23ba. A clean TypeScript compile passed. The declared npm run test:all command did not reach its assertions. TypeScript stopped on duplicate block scoped names in fmtTest.ts and udpTest.ts. The lint command also exited with errors. Those results do not prove the extension is broken. They do mean the repository's current test command cannot support a broad reliability claim.
We did not install the VSIX, open it in VS Code, or exercise its runtime behavior. The archive check proves what was distributed. The source check proves what compiled and what failed in that checkout.
Use it as a lead generator
- Pin the revision that emitted the log.
- Check whether the selected row has a real thread, request, or session identifier.
- Open the matched source call and compare its static text with the row.
- Treat each incoming caller as a candidate until a log row, trace, test, or replay supports it.
- Keep source initializers separate from values captured in the log.
- Save the smallest replay that can reject the proposed chain.
The extension has a sharp idea: old logs can become a navigation surface. Keep that advantage. Add labels that tell you when navigation ends and evidence begins.
