feat(ide extension): introduce debug logging (#10416)

This commit is contained in:
Shreya Keshive
2025-10-02 13:10:13 -04:00
committed by GitHub
parent e7a13aa031
commit 12d4ec2e07
5 changed files with 57 additions and 22 deletions

View File

@@ -31,6 +31,16 @@
"onStartupFinished"
],
"contributes": {
"configuration": {
"title": "Gemini CLI",
"properties": {
"gemini-cli.debug.logging.enabled": {
"type": "boolean",
"default": false,
"description": "Enable detailed logging for debugging the Gemini CLI Companion."
}
}
},
"languages": [
{
"id": "gemini-diff-editable"

View File

@@ -168,7 +168,6 @@ export class DiffManager {
async acceptDiff(rightDocUri: vscode.Uri) {
const diffInfo = this.diffDocuments.get(rightDocUri.toString());
if (!diffInfo) {
this.log(`No diff info found for ${rightDocUri.toString()}`);
return;
}
@@ -194,8 +193,6 @@ export class DiffManager {
async cancelDiff(rightDocUri: vscode.Uri) {
const diffInfo = this.diffDocuments.get(rightDocUri.toString());
if (!diffInfo) {
this.log(`No diff info found for ${rightDocUri.toString()}`);
// Even if we don't have diff info, we should still close the editor.
await this.closeDiffEditor(rightDocUri);
return;
}

View File

@@ -47,6 +47,9 @@ vi.mock('vscode', () => ({
registerTextDocumentContentProvider: vi.fn(),
onDidChangeWorkspaceFolders: vi.fn(),
onDidGrantWorkspaceTrust: vi.fn(),
getConfiguration: vi.fn(() => ({
get: vi.fn(),
})),
},
commands: {
registerCommand: vi.fn(),

View File

@@ -107,13 +107,6 @@ function sendIdeContextUpdateNotification(
params: ideContext,
});
log(
`Sending IDE context update notification: ${JSON.stringify(
notification,
null,
2,
)}`,
);
transport.send(notification);
}
@@ -190,7 +183,7 @@ export class IDEServer {
next();
});
const mcpServer = createMcpServer(this.diffManager);
const mcpServer = createMcpServer(this.diffManager, this.log);
this.openFilesManager = new OpenFilesManager(context);
const onDidChangeSubscription = this.openFilesManager.onDidChange(() => {
@@ -222,16 +215,27 @@ export class IDEServer {
this.transports[newSessionId] = transport;
},
});
let missedPings = 0;
const keepAlive = setInterval(() => {
try {
transport.send({ jsonrpc: '2.0', method: 'ping' });
} catch (e) {
this.log(
'Failed to send keep-alive ping, cleaning up interval.' + e,
);
clearInterval(keepAlive);
}
}, 30000); // 30 sec
const sessionId = transport.sessionId ?? 'unknown';
transport
.send({ jsonrpc: '2.0', method: 'ping' })
.then(() => {
missedPings = 0;
})
.catch((error) => {
missedPings++;
this.log(
`Failed to send keep-alive ping for session ${sessionId}. Missed pings: ${missedPings}. Error: ${error.message}`,
);
if (missedPings >= 3) {
this.log(
`Session ${sessionId} missed ${missedPings} pings. Closing connection and cleaning up interval.`,
);
clearInterval(keepAlive);
}
});
}, 60000); // 60 sec
transport.onclose = () => {
clearInterval(keepAlive);
@@ -315,6 +319,8 @@ export class IDEServer {
app.get('/mcp', handleSessionRequest);
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
this.log(`Error processing request: ${err.message}`);
this.log(`Stack trace: ${err.stack}`);
if (err instanceof CORSError) {
res.status(403).json({ error: 'Request denied by CORS policy.' });
} else {
@@ -349,6 +355,14 @@ export class IDEServer {
}
resolve();
});
this.server.on('close', () => {
this.log('IDE server connection closed.');
});
this.server.on('error', (error) => {
this.log(`IDE server error: ${error.message}`);
});
});
}
@@ -421,7 +435,10 @@ export class IDEServer {
}
}
const createMcpServer = (diffManager: DiffManager) => {
const createMcpServer = (
diffManager: DiffManager,
log: (message: string) => void,
) => {
const server = new McpServer(
{
name: 'gemini-cli-companion-mcp-server',
@@ -437,6 +454,7 @@ const createMcpServer = (diffManager: DiffManager) => {
inputSchema: OpenDiffRequestSchema.shape,
},
async ({ filePath, newContent }: z.infer<typeof OpenDiffRequestSchema>) => {
log(`Received openDiff request for filePath: ${filePath}`);
await diffManager.showDiff(filePath, newContent);
return { content: [] };
},
@@ -451,6 +469,7 @@ const createMcpServer = (diffManager: DiffManager) => {
filePath,
suppressNotification,
}: z.infer<typeof CloseDiffRequestSchema>) => {
log(`Received closeDiff request for filePath: ${filePath}`);
const content = await diffManager.closeDiff(
filePath,
suppressNotification,

View File

@@ -11,7 +11,13 @@ export function createLogger(
logger: vscode.OutputChannel,
) {
return (message: string) => {
if (context.extensionMode === vscode.ExtensionMode.Development) {
const isDevMode =
context.extensionMode === vscode.ExtensionMode.Development;
const isLoggingEnabled = vscode.workspace
.getConfiguration('gemini-cli.debug')
.get('logging.enabled');
if (isDevMode || isLoggingEnabled) {
logger.appendLine(message);
}
};