Skip to content

Commit 53bf019

Browse files
committed
src/language: adjust panic trace capture logic
Use '[Info - ' or '[Warning - ' or '[Error - ' as the marker for the end of the panic trace. Fixes #3248 Change-Id: I3aabc0292855f63ceffeea5c09b59e4e0253e95b Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/571316 Commit-Queue: Hyang-Ah Hana Kim <[email protected]> kokoro-CI: kokoro <[email protected]> Reviewed-by: Suzy Mueller <[email protected]>
1 parent b4b68a7 commit 53bf019

File tree

2 files changed

+86
-39
lines changed

2 files changed

+86
-39
lines changed

extension/src/language/goLanguageServer.ts

Lines changed: 33 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1530,7 +1530,6 @@ async function collectGoplsLog(goCtx: GoExtensionContext): Promise<{ sanitizedLo
15301530
enum GoplsFailureModes {
15311531
NO_GOPLS_LOG = 'no gopls log',
15321532
EMPTY_PANIC_TRACE = 'empty panic trace',
1533-
INCOMPLETE_PANIC_TRACE = 'incomplete panic trace',
15341533
INCORRECT_COMMAND_USAGE = 'incorrect gopls command usage',
15351534
UNRECOGNIZED_CRASH_PATTERN = 'unrecognized crash pattern'
15361535
}
@@ -1544,34 +1543,40 @@ export function sanitizeGoplsTrace(logs?: string): { sanitizedLog?: string; fail
15441543
const panicMsgBegin = logs.lastIndexOf('panic: ');
15451544
if (panicMsgBegin > -1) {
15461545
// panic message was found.
1547-
const panicMsgEnd = logs.indexOf('Connection to server got closed.', panicMsgBegin);
1546+
let panicTrace = logs.substr(panicMsgBegin);
1547+
const panicMsgEnd = panicTrace.search(/\[(Info|Warning|Error)\s+-\s+/);
15481548
if (panicMsgEnd > -1) {
1549-
const panicTrace = logs.substr(panicMsgBegin, panicMsgEnd - panicMsgBegin);
1550-
const filePattern = /(\S+\.go):\d+/;
1551-
const sanitized = panicTrace
1552-
.split('\n')
1553-
.map((line: string) => {
1554-
// Even though this is a crash from gopls, the file path
1555-
// can contain user names and user's filesystem directory structure.
1556-
// We can still locate the corresponding file if the file base is
1557-
// available because the full package path is part of the function
1558-
// name. So, leave only the file base.
1559-
const m = line.match(filePattern);
1560-
if (!m) {
1561-
return line;
1562-
}
1563-
const filePath = m[1];
1564-
const fileBase = path.basename(filePath);
1565-
return line.replace(filePath, ' ' + fileBase);
1566-
})
1567-
.join('\n');
1568-
1569-
if (sanitized) {
1570-
return { sanitizedLog: sanitized };
1571-
}
1572-
return { failureReason: GoplsFailureModes.EMPTY_PANIC_TRACE };
1549+
panicTrace = panicTrace.substr(0, panicMsgEnd);
1550+
}
1551+
const filePattern = /(\S+\.go):\d+/;
1552+
const sanitized = panicTrace
1553+
.split('\n')
1554+
.map((line: string) => {
1555+
// Even though this is a crash from gopls, the file path
1556+
// can contain user names and user's filesystem directory structure.
1557+
// We can still locate the corresponding file if the file base is
1558+
// available because the full package path is part of the function
1559+
// name. So, leave only the file base.
1560+
const m = line.match(filePattern);
1561+
if (!m) {
1562+
return line;
1563+
}
1564+
const filePath = m[1];
1565+
const fileBase = path.basename(filePath);
1566+
return line.replace(filePath, ' ' + fileBase);
1567+
})
1568+
.join('\n');
1569+
1570+
if (sanitized) {
1571+
return { sanitizedLog: sanitized };
15731572
}
1574-
return { failureReason: GoplsFailureModes.INCOMPLETE_PANIC_TRACE };
1573+
return { failureReason: GoplsFailureModes.EMPTY_PANIC_TRACE };
1574+
}
1575+
// Capture Fatal
1576+
// foo.go:1: the last message (caveat - we capture only the first log line)
1577+
const m = logs.match(/(^\S+\.go:\d+:.*$)/gm);
1578+
if (m && m.length > 0) {
1579+
return { sanitizedLog: m[0].toString() };
15751580
}
15761581
const initFailMsgBegin = logs.lastIndexOf('gopls client:');
15771582
if (initFailMsgBegin > -1) {
@@ -1590,13 +1595,6 @@ export function sanitizeGoplsTrace(logs?: string): { sanitizedLog?: string; fail
15901595
if (logs.lastIndexOf('Usage:') > -1) {
15911596
return { failureReason: GoplsFailureModes.INCORRECT_COMMAND_USAGE };
15921597
}
1593-
// Capture Fatal
1594-
// foo.go:1: the last message (caveat - we capture only the first log line)
1595-
const m = logs.match(/(^\S+\.go:\d+:.*$)/gm);
1596-
if (m && m.length > 0) {
1597-
return { sanitizedLog: m[0].toString() };
1598-
}
1599-
16001598
return { failureReason: GoplsFailureModes.UNRECOGNIZED_CRASH_PATTERN };
16011599
}
16021600

@@ -1664,6 +1662,6 @@ async function getGoplsStats(binpath?: string) {
16641662
} catch (e) {
16651663
const duration = new Date().getTime() - start.getTime();
16661664
console.log(`gopls stats -anon failed: ${JSON.stringify(e)}`);
1667-
return `gopls stats -anon failed after running for ${duration}ms`; // e may contain user information. don't include in the report.
1665+
return `gopls stats -anon failed after ${duration} ms. Please check if gopls is killed by OS.`;
16681666
}
16691667
}

extension/test/gopls/report.test.ts

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,15 @@ suite('gopls issue report tests', () => {
2525
in: traceFromIssueVSCodeGo572LSP317,
2626
want: sanitizedTraceFromIssueVSCodeGo572LSP317
2727
},
28+
{
29+
name: 'panic trace 2024 March',
30+
in: trace2024MarchPanic,
31+
want: sanitizedTrace2024MarchPanic
32+
},
2833
{
2934
name: 'incomplete panic trace',
30-
in: 'panic: \nsecret\n',
31-
wantReason: 'incomplete panic trace'
35+
in: 'panic: \ntruncated\n',
36+
want: 'panic: \ntruncated\n'
3237
},
3338
{
3439
name: 'incomplete initialization error message',
@@ -42,7 +47,7 @@ suite('gopls issue report tests', () => {
4247
assert.strictEqual(
4348
JSON.stringify(sanitizedLog),
4449
JSON.stringify(tc.want),
45-
`sanitizeGoplsTrace(${tc.name}) returned unexpected sanitizedLog result`
50+
`sanitizeGoplsTrace(${tc.name}) returned unexpected sanitizedLog result - ${sanitizedLog}`
4651
);
4752
assert.strictEqual(
4853
failureReason,
@@ -315,7 +320,7 @@ golang.org/x/tools/internal/jsonrpc2.AsyncHandler.func1.2(0xc00021ac60, 0xc0007b
315320
handler.go:103 +0x86
316321
created by golang.org/x/tools/internal/jsonrpc2.AsyncHandler.func1
317322
handler.go:100 +0x171
318-
[Info - 12:50:26 PM] `;
323+
`;
319324

320325
const traceFromIssueVSCodeGo572LSP317 = `
321326
[Error - 12:20:35 PM] Stopping server failed
@@ -335,3 +340,47 @@ Error starting language server: Error: Socket closed before the connection was e
335340
const sanitizedTraceFromIssueVSCodeGo572LSP317 = `gopls client: couldn't create connection to server.
336341
Message: Socket closed before the connection was established
337342
Code: -32099 `;
343+
344+
const trace2024MarchPanic = `
345+
[Info - 9:58:40 AM]
346+
true
347+
[Error - 9:58:40 AM] gopls client: couldn't create connection to server.
348+
Message: Pending response rejected since connection got disposed
349+
Code: -32097
350+
panic: crash
351+
352+
goroutine 1 [running]:
353+
golang.org/x/tools/gopls/internal/cmd.(*Serve).Run(0xc000486310?, {0xc0000b8090?, 0x0?}, {0x0?, 0x0?, 0x0?})
354+
/Users/Gopher/projects/tools/gopls/internal/cmd/serve.go:81 +0x25
355+
golang.org/x/tools/internal/tool.Run({0x1012d048, 0xc00019c3f0}, 0xc000486310, {0x1012f9e0, 0xc000159b40}, {0xc0000b8090, 0x0, 0x0})
356+
/Users/Gopher/projects/tools/internal/tool/tool.go:192 +0x691
357+
golang.org/x/tools/gopls/internal/cmd.(*Application).Run(0xc000159b00, {0x1012d010, 0x107d9840}, {0xc0000b8090, 0x0, 0x0})
358+
/Users/Gopher/projects/tools/gopls/internal/cmd/cmd.go:240 +0x147
359+
golang.org/x/tools/internal/tool.Run({0x1012d010, 0x107d9840}, 0xc0004862a0, {0x1012f3a0, 0xc000159b00}, {0xc0000b8060, 0x4, 0x4})
360+
/Users/Gopher/projects/tools/internal/tool/tool.go:192 +0x691
361+
golang.org/x/tools/internal/tool.Main({0x1012d010, 0x107d9840}, {0x1012f3a0, 0xc000159b00}, {0xc0000b8060, 0x4, 0x4})
362+
/Users/Gopher/projects/tools/internal/tool/tool.go:93 +0x12a
363+
main.main()
364+
/Users/Gopher/projects/tools/gopls/main.go:34 +0x109
365+
[Error - 9:58:49 AM]
366+
[Error - 9:58:49 AM] gopls client: couldn't create connection to server.
367+
Message: Pending response rejected since connection got disposed
368+
Code: -32097
369+
Error starting language server: Error: Pending response rejected since connection got disposed`;
370+
371+
const sanitizedTrace2024MarchPanic = `panic: crash
372+
373+
goroutine 1 [running]:
374+
golang.org/x/tools/gopls/internal/cmd.(*Serve).Run(0xc000486310?, {0xc0000b8090?, 0x0?}, {0x0?, 0x0?, 0x0?})
375+
serve.go:81 +0x25
376+
golang.org/x/tools/internal/tool.Run({0x1012d048, 0xc00019c3f0}, 0xc000486310, {0x1012f9e0, 0xc000159b40}, {0xc0000b8090, 0x0, 0x0})
377+
tool.go:192 +0x691
378+
golang.org/x/tools/gopls/internal/cmd.(*Application).Run(0xc000159b00, {0x1012d010, 0x107d9840}, {0xc0000b8090, 0x0, 0x0})
379+
cmd.go:240 +0x147
380+
golang.org/x/tools/internal/tool.Run({0x1012d010, 0x107d9840}, 0xc0004862a0, {0x1012f3a0, 0xc000159b00}, {0xc0000b8060, 0x4, 0x4})
381+
tool.go:192 +0x691
382+
golang.org/x/tools/internal/tool.Main({0x1012d010, 0x107d9840}, {0x1012f3a0, 0xc000159b00}, {0xc0000b8060, 0x4, 0x4})
383+
tool.go:93 +0x12a
384+
main.main()
385+
main.go:34 +0x109
386+
`;

0 commit comments

Comments
 (0)