Skip to content

Commit fe834d7

Browse files
authored
feat: add tolerant always on tracing (#14)
1 parent 7929cfa commit fe834d7

20 files changed

Lines changed: 778 additions & 131 deletions

README.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,18 @@ srv.Run(ctx, server.RunStdio())
469469

470470
Then open `http://localhost:7100` in a browser. The tap is transparent -- it intercepts LSP frames for display without modifying them.
471471

472+
If the HTTP listener cannot bind (port in use, locked-down environment), the server logs a warning and continues with capture-only mode. `WithDebugUI` therefore never prevents the LSP from starting; trace export still works against the in-memory recorder.
473+
474+
### Capture-only mode
475+
476+
If you want trace capture for support bundles or debugging exports but do not want to bind an HTTP port, use `WithDebugCapture`:
477+
478+
```go
479+
srv := server.NewServer(&Handler{}, server.WithDebugCapture())
480+
```
481+
482+
`WithDebugUI` implies `WithDebugCapture`, so you only need one or the other. Both feed the same recorder, which powers `SaveDebugTrace` / `ExportDebugTrace`.
483+
472484
### Messages tab
473485

474486
Real-time view of all JSON-RPC traffic between client and server:
@@ -510,7 +522,7 @@ Runtime metrics updated every 2 seconds: uptime, heap usage, goroutine count, GC
510522

511523
### Saving traces
512524

513-
When the debug UI is enabled, you can save the captured session programmatically:
525+
When `WithDebugCapture` or `WithDebugUI` is set, you can save the captured session programmatically:
514526

515527
```go
516528
err := srv.SaveDebugTrace("/tmp/session.trace.json", server.TraceExportOptions{
@@ -520,7 +532,7 @@ err := srv.SaveDebugTrace("/tmp/session.trace.json", server.TraceExportOptions{
520532
})
521533
```
522534

523-
Use `ExportDebugTrace` if you want the JSON bytes instead of writing directly to disk. `SaveDebugTrace` writes files with `0600` permissions because traces may contain source code, local paths, and project details. If the debug UI is not active, these methods return `server.ErrDebugTraceUnavailable`.
535+
Use `ExportDebugTrace` if you want the JSON bytes instead of writing directly to disk. `SaveDebugTrace` writes files with `0600` permissions because traces may contain source code, local paths, and project details. If neither capture nor UI is enabled, these methods return `server.ErrDebugTraceUnavailable`.
524536

525537
## Project structure
526538

docs-site/anchors.js

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,121 @@ function slugify(text) {
88
.replace(/^-|-$/g, "");
99
}
1010

11+
function appendGoTokens(code, source) {
12+
const keywords = new Set([
13+
"break", "case", "chan", "const", "continue", "default", "defer", "else",
14+
"fallthrough", "for", "func", "go", "goto", "if", "import", "interface",
15+
"map", "package", "range", "return", "select", "struct", "switch", "type",
16+
"var",
17+
]);
18+
const builtins = new Set([
19+
"append", "bool", "byte", "cap", "close", "complex", "comparable", "copy",
20+
"delete", "error", "false", "float32", "float64", "imag", "int", "int16",
21+
"int32", "int64", "int8", "iota", "len", "make", "new", "nil", "panic",
22+
"print", "println", "real", "recover", "rune", "string", "true", "uint",
23+
"uint16", "uint32", "uint64", "uint8", "uintptr", "any",
24+
]);
25+
const tokenPattern = /\/\/.*|"(?:\\.|[^"\\])*"|`[\s\S]*?`|'(?:\\.|[^'\\])*'|\b\d+(?:\.\d+)?\b|\b[A-Za-z_]\w*\b/g;
26+
27+
let lastIndex = 0;
28+
29+
function appendText(text) {
30+
if (text) {
31+
code.appendChild(document.createTextNode(text));
32+
}
33+
}
34+
35+
function appendToken(text, className) {
36+
const span = document.createElement("span");
37+
span.className = className;
38+
span.textContent = text;
39+
code.appendChild(span);
40+
}
41+
42+
source.replace(tokenPattern, (match, offset) => {
43+
appendText(source.slice(lastIndex, offset));
44+
45+
if (match.startsWith("//")) {
46+
appendToken(match, "token comment");
47+
} else if (match.startsWith('"') || match.startsWith("'") || match.startsWith("`")) {
48+
appendToken(match, "token string");
49+
} else if (/^\d/.test(match)) {
50+
appendToken(match, "token number");
51+
} else if (keywords.has(match)) {
52+
appendToken(match, "token keyword");
53+
} else if (builtins.has(match)) {
54+
appendToken(match, "token builtin");
55+
} else {
56+
appendText(match);
57+
}
58+
59+
lastIndex = offset + match.length;
60+
return match;
61+
});
62+
63+
appendText(source.slice(lastIndex));
64+
}
65+
66+
async function copyText(text) {
67+
if (navigator.clipboard?.writeText) {
68+
await navigator.clipboard.writeText(text);
69+
return;
70+
}
71+
72+
const input = document.createElement("textarea");
73+
input.value = text;
74+
input.setAttribute("readonly", "");
75+
input.style.position = "absolute";
76+
input.style.left = "-9999px";
77+
document.body.appendChild(input);
78+
input.select();
79+
document.execCommand("copy");
80+
input.remove();
81+
}
82+
83+
function enhanceCodeBlocks() {
84+
document.querySelectorAll("pre > code").forEach((code) => {
85+
const source = code.textContent || "";
86+
const pre = code.parentElement;
87+
88+
if (!pre) {
89+
return;
90+
}
91+
92+
pre.classList.add("code-block");
93+
94+
if (code.classList.contains("language-go")) {
95+
pre.dataset.language = "go";
96+
code.textContent = "";
97+
appendGoTokens(code, source);
98+
}
99+
100+
const button = document.createElement("button");
101+
button.className = "code-copy";
102+
button.type = "button";
103+
button.textContent = "Copy";
104+
button.setAttribute("aria-label", "Copy code to clipboard");
105+
button.addEventListener("click", async () => {
106+
try {
107+
await copyText(source);
108+
button.textContent = "Copied";
109+
button.classList.add("copied");
110+
window.setTimeout(() => {
111+
button.textContent = "Copy";
112+
button.classList.remove("copied");
113+
}, 1800);
114+
} catch {
115+
button.textContent = "Failed";
116+
window.setTimeout(() => {
117+
button.textContent = "Copy";
118+
}, 1800);
119+
}
120+
});
121+
122+
pre.appendChild(button);
123+
});
124+
}
125+
11126
document.addEventListener("DOMContentLoaded", () => {
12127
const seen = new Map();
13128

@@ -26,4 +141,15 @@ document.addEventListener("DOMContentLoaded", () => {
26141
anchor.textContent = "#";
27142
heading.appendChild(anchor);
28143
});
144+
145+
const sidebar = document.querySelector(".sidebar");
146+
const toggle = document.querySelector(".menu-toggle");
147+
if (sidebar && toggle) {
148+
toggle.addEventListener("click", () => {
149+
const open = sidebar.classList.toggle("nav-open");
150+
toggle.setAttribute("aria-expanded", open ? "true" : "false");
151+
});
152+
}
153+
154+
enhanceCodeBlocks();
29155
});

docs-site/capabilities.html

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,14 @@
1010
<body>
1111
<div class="layout">
1212
<aside class="sidebar">
13-
<a class="brand" href="index.html">go-lsp</a>
13+
<div class="sidebar-header">
14+
<a class="brand" href="index.html">go-lsp</a>
15+
<button class="menu-toggle" aria-label="Toggle navigation" aria-expanded="false" aria-controls="site-nav">
16+
<span></span><span></span><span></span>
17+
</button>
18+
</div>
1419
<p class="tagline">Build Language Server Protocol servers in Go.</p>
15-
<nav class="nav" aria-label="Documentation">
20+
<nav class="nav" id="site-nav" aria-label="Documentation">
1621
<a href="index.html">Home</a>
1722
<a href="getting-started.html">Getting Started</a>
1823
<a href="concepts.html">Core Concepts</a>
@@ -21,6 +26,10 @@
2126
<a href="testing.html">Testing</a>
2227
<a href="debugging.html">Debugging</a>
2328
<a href="examples.html">Examples</a>
29+
<a class="nav-github" href="https://github.com/owenrumney/go-lsp" target="_blank" rel="noopener">
30+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.69-.01-1.36-2.22.48-2.69-1.06-2.69-1.06-.36-.92-.89-1.17-.89-1.17-.73-.5.06-.49.06-.49.81.06 1.23.83 1.23.83.72 1.21 1.87.86 2.33.66.07-.51.28-.86.51-1.06-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg>
31+
GitHub
32+
</a>
2433
</nav>
2534
</aside>
2635
<main class="content">

docs-site/concepts.html

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,14 @@
1010
<body>
1111
<div class="layout">
1212
<aside class="sidebar">
13-
<a class="brand" href="index.html">go-lsp</a>
13+
<div class="sidebar-header">
14+
<a class="brand" href="index.html">go-lsp</a>
15+
<button class="menu-toggle" aria-label="Toggle navigation" aria-expanded="false" aria-controls="site-nav">
16+
<span></span><span></span><span></span>
17+
</button>
18+
</div>
1419
<p class="tagline">Build Language Server Protocol servers in Go.</p>
15-
<nav class="nav" aria-label="Documentation">
20+
<nav class="nav" id="site-nav" aria-label="Documentation">
1621
<a href="index.html">Home</a>
1722
<a href="getting-started.html">Getting Started</a>
1823
<a href="concepts.html" aria-current="page">Core Concepts</a>
@@ -21,6 +26,10 @@
2126
<a href="testing.html">Testing</a>
2227
<a href="debugging.html">Debugging</a>
2328
<a href="examples.html">Examples</a>
29+
<a class="nav-github" href="https://github.com/owenrumney/go-lsp" target="_blank" rel="noopener">
30+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.69-.01-1.36-2.22.48-2.69-1.06-2.69-1.06-.36-.92-.89-1.17-.89-1.17-.73-.5.06-.49.06-.49.81.06 1.23.83 1.23.83.72 1.21 1.87.86 2.33.66.07-.51.28-.86.51-1.06-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg>
31+
GitHub
32+
</a>
2433
</nav>
2534
</aside>
2635
<main class="content">

docs-site/debugging.html

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,14 @@
1010
<body>
1111
<div class="layout">
1212
<aside class="sidebar">
13-
<a class="brand" href="index.html">go-lsp</a>
13+
<div class="sidebar-header">
14+
<a class="brand" href="index.html">go-lsp</a>
15+
<button class="menu-toggle" aria-label="Toggle navigation" aria-expanded="false" aria-controls="site-nav">
16+
<span></span><span></span><span></span>
17+
</button>
18+
</div>
1419
<p class="tagline">Build Language Server Protocol servers in Go.</p>
15-
<nav class="nav" aria-label="Documentation">
20+
<nav class="nav" id="site-nav" aria-label="Documentation">
1621
<a href="index.html">Home</a>
1722
<a href="getting-started.html">Getting Started</a>
1823
<a href="concepts.html">Core Concepts</a>
@@ -21,6 +26,10 @@
2126
<a href="testing.html">Testing</a>
2227
<a href="debugging.html" aria-current="page">Debugging</a>
2328
<a href="examples.html">Examples</a>
29+
<a class="nav-github" href="https://github.com/owenrumney/go-lsp" target="_blank" rel="noopener">
30+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.69-.01-1.36-2.22.48-2.69-1.06-2.69-1.06-.36-.92-.89-1.17-.89-1.17-.73-.5.06-.49.06-.49.81.06 1.23.83 1.23.83.72 1.21 1.87.86 2.33.66.07-.51.28-.86.51-1.06-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg>
31+
GitHub
32+
</a>
2433
</nav>
2534
</aside>
2635
<main class="content">
@@ -33,6 +42,12 @@ <h2>Enable the Debug UI</h2>
3342
<pre><code class="language-go">srv := server.NewServer(h, server.WithDebugUI(":7100"))
3443
srv.Run(ctx, server.RunStdio())</code></pre>
3544
<p>Open <code>http://localhost:7100</code> while the server is running.</p>
45+
<p>If the HTTP listener cannot bind (port in use, restricted environment), the server logs a warning and continues with capture-only mode. <code>WithDebugUI</code> therefore never prevents the LSP from starting; trace export still works against the in-memory recorder.</p>
46+
47+
<h2>Capture-Only Mode</h2>
48+
<p>For support bundles or always-on trace export without binding an HTTP port, use <code>WithDebugCapture</code>:</p>
49+
<pre><code class="language-go">srv := server.NewServer(h, server.WithDebugCapture())</code></pre>
50+
<p><code>WithDebugUI</code> implies <code>WithDebugCapture</code>, so you only need one or the other. Both populate the same recorder, which powers <code>SaveDebugTrace</code> and <code>ExportDebugTrace</code>.</p>
3651

3752
<h2>What It Shows</h2>
3853
<div class="grid">
@@ -59,7 +74,7 @@ <h2>Save a Trace</h2>
5974
RedactFilePaths: true,
6075
Pretty: true,
6176
})</code></pre>
62-
<p>Use <code>ExportDebugTrace</code> to get JSON bytes instead. If debug UI is not active, both methods return <code>server.ErrDebugTraceUnavailable</code>.</p>
77+
<p>Use <code>ExportDebugTrace</code> to get JSON bytes instead. If neither <code>WithDebugCapture</code> nor <code>WithDebugUI</code> is enabled, both methods return <code>server.ErrDebugTraceUnavailable</code>.</p>
6378

6479
<h2>Debug Bundle Command</h2>
6580
<pre><code class="language-go">func (h *Handler) ExecuteCommand(ctx context.Context, params *lsp.ExecuteCommandParams) (any, error) {

docs-site/documents.html

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,14 @@
1010
<body>
1111
<div class="layout">
1212
<aside class="sidebar">
13-
<a class="brand" href="index.html">go-lsp</a>
13+
<div class="sidebar-header">
14+
<a class="brand" href="index.html">go-lsp</a>
15+
<button class="menu-toggle" aria-label="Toggle navigation" aria-expanded="false" aria-controls="site-nav">
16+
<span></span><span></span><span></span>
17+
</button>
18+
</div>
1419
<p class="tagline">Build Language Server Protocol servers in Go.</p>
15-
<nav class="nav" aria-label="Documentation">
20+
<nav class="nav" id="site-nav" aria-label="Documentation">
1621
<a href="index.html">Home</a>
1722
<a href="getting-started.html">Getting Started</a>
1823
<a href="concepts.html">Core Concepts</a>
@@ -21,6 +26,10 @@
2126
<a href="testing.html">Testing</a>
2227
<a href="debugging.html">Debugging</a>
2328
<a href="examples.html">Examples</a>
29+
<a class="nav-github" href="https://github.com/owenrumney/go-lsp" target="_blank" rel="noopener">
30+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.69-.01-1.36-2.22.48-2.69-1.06-2.69-1.06-.36-.92-.89-1.17-.89-1.17-.73-.5.06-.49.06-.49.81.06 1.23.83 1.23.83.72 1.21 1.87.86 2.33.66.07-.51.28-.86.51-1.06-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg>
31+
GitHub
32+
</a>
2433
</nav>
2534
</aside>
2635
<main class="content">

docs-site/examples.html

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,14 @@
1010
<body>
1111
<div class="layout">
1212
<aside class="sidebar">
13-
<a class="brand" href="index.html">go-lsp</a>
13+
<div class="sidebar-header">
14+
<a class="brand" href="index.html">go-lsp</a>
15+
<button class="menu-toggle" aria-label="Toggle navigation" aria-expanded="false" aria-controls="site-nav">
16+
<span></span><span></span><span></span>
17+
</button>
18+
</div>
1419
<p class="tagline">Build Language Server Protocol servers in Go.</p>
15-
<nav class="nav" aria-label="Documentation">
20+
<nav class="nav" id="site-nav" aria-label="Documentation">
1621
<a href="index.html">Home</a>
1722
<a href="getting-started.html">Getting Started</a>
1823
<a href="concepts.html">Core Concepts</a>
@@ -21,6 +26,10 @@
2126
<a href="testing.html">Testing</a>
2227
<a href="debugging.html">Debugging</a>
2328
<a href="examples.html" aria-current="page">Examples</a>
29+
<a class="nav-github" href="https://github.com/owenrumney/go-lsp" target="_blank" rel="noopener">
30+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.69-.01-1.36-2.22.48-2.69-1.06-2.69-1.06-.36-.92-.89-1.17-.89-1.17-.73-.5.06-.49.06-.49.81.06 1.23.83 1.23.83.72 1.21 1.87.86 2.33.66.07-.51.28-.86.51-1.06-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg>
31+
GitHub
32+
</a>
2433
</nav>
2534
</aside>
2635
<main class="content">

docs-site/getting-started.html

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,14 @@
1010
<body>
1111
<div class="layout">
1212
<aside class="sidebar">
13-
<a class="brand" href="index.html">go-lsp</a>
13+
<div class="sidebar-header">
14+
<a class="brand" href="index.html">go-lsp</a>
15+
<button class="menu-toggle" aria-label="Toggle navigation" aria-expanded="false" aria-controls="site-nav">
16+
<span></span><span></span><span></span>
17+
</button>
18+
</div>
1419
<p class="tagline">Build Language Server Protocol servers in Go.</p>
15-
<nav class="nav" aria-label="Documentation">
20+
<nav class="nav" id="site-nav" aria-label="Documentation">
1621
<a href="index.html">Home</a>
1722
<a href="getting-started.html" aria-current="page">Getting Started</a>
1823
<a href="concepts.html">Core Concepts</a>
@@ -21,6 +26,10 @@
2126
<a href="testing.html">Testing</a>
2227
<a href="debugging.html">Debugging</a>
2328
<a href="examples.html">Examples</a>
29+
<a class="nav-github" href="https://github.com/owenrumney/go-lsp" target="_blank" rel="noopener">
30+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.69-.01-1.36-2.22.48-2.69-1.06-2.69-1.06-.36-.92-.89-1.17-.89-1.17-.73-.5.06-.49.06-.49.81.06 1.23.83 1.23.83.72 1.21 1.87.86 2.33.66.07-.51.28-.86.51-1.06-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/></svg>
31+
GitHub
32+
</a>
2433
</nav>
2534
</aside>
2635
<main class="content">

0 commit comments

Comments
 (0)