Skip to content

Commit 1fa0770

Browse files
Will-ShaoHuadk19yfloralph
authored andcommitted
feat(amazonq): add capability to log into a local file for dev purpose (aws#1633)
Co-authored-by: Dhanasekar Karuppasamy <[email protected]> Co-authored-by: Flora <[email protected]>
1 parent 5e9e2b4 commit 1fa0770

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed

client/vscode/src/lspLogger.ts

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import * as fs from 'fs'
7+
import * as path from 'path'
8+
import * as os from 'os'
9+
import { ChildProcess } from 'child_process'
10+
import { Writable } from 'stream'
11+
12+
export class LspLogger {
13+
private logFile: fs.WriteStream | undefined
14+
private logPath: string = ''
15+
16+
constructor() {
17+
// Get settings from environment variables
18+
const enabled = process.env.LSP_LOGGING_ENABLED === 'true'
19+
const customLogPath = process.env.LSP_LOG_PATH
20+
21+
// If disabled, don't create log file
22+
if (!enabled) {
23+
return
24+
}
25+
26+
// Determine log directory
27+
const logsDir = customLogPath || path.join(os.tmpdir(), 'vscode-lsp-logs')
28+
29+
// Create directory if needed
30+
if (!fs.existsSync(logsDir)) {
31+
fs.mkdirSync(logsDir, { recursive: true })
32+
}
33+
34+
// Create log file with timestamp
35+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
36+
this.logPath = path.join(logsDir, `lsp-log-${timestamp}.jsonl`)
37+
this.logFile = fs.createWriteStream(this.logPath)
38+
39+
console.log(`LSP logging started to: ${this.logPath}`)
40+
}
41+
42+
public wrapChildProcess(childProcess: ChildProcess): ChildProcess {
43+
if (!this.logFile) {
44+
return childProcess
45+
}
46+
47+
// Intercept stdin
48+
if (childProcess.stdin) {
49+
const originalStdin = childProcess.stdin
50+
const logFile = this.logFile
51+
52+
const stdinProxy = new Writable({
53+
write(chunk, encoding, callback) {
54+
// Log outgoing messages
55+
logFile.write(
56+
JSON.stringify({
57+
direction: 'client-to-server',
58+
timestamp: new Date().toISOString(),
59+
data: chunk.toString(),
60+
}) + '\n'
61+
)
62+
63+
// Forward to original stdin
64+
originalStdin.write(chunk, encoding, callback)
65+
},
66+
})
67+
68+
;(childProcess as any).stdin = stdinProxy
69+
}
70+
71+
// Intercept stdout
72+
if (childProcess.stdout) {
73+
const logFile = this.logFile
74+
childProcess.stdout.on('data', data => {
75+
logFile.write(
76+
JSON.stringify({
77+
direction: 'server-to-client',
78+
timestamp: new Date().toISOString(),
79+
data: data.toString(),
80+
}) + '\n'
81+
)
82+
})
83+
}
84+
85+
// Intercept stderr
86+
if (childProcess.stderr) {
87+
const logFile = this.logFile
88+
childProcess.stderr.on('data', data => {
89+
logFile.write(
90+
JSON.stringify({
91+
direction: 'server-error',
92+
timestamp: new Date().toISOString(),
93+
data: data.toString(),
94+
}) + '\n'
95+
)
96+
})
97+
}
98+
99+
return childProcess
100+
}
101+
102+
public dispose(): void {
103+
if (this.logFile) {
104+
this.logFile.end()
105+
console.log(`LSP logging completed: ${this.logPath}`)
106+
}
107+
}
108+
}

0 commit comments

Comments
 (0)