mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-24 20:14:44 -07:00
refactor(logging): Centralize console logging with debugLogger (#11590)
This commit is contained in:
@@ -8,11 +8,13 @@ import * as fs from 'node:fs/promises';
|
||||
import * as path from 'node:path';
|
||||
import type { FileDiscoveryService } from '../services/fileDiscoveryService.js';
|
||||
import type { FileFilteringOptions } from '../config/constants.js';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
// Simple console logger for now.
|
||||
// TODO: Integrate with a more robust server-side logger.
|
||||
const logger = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
debug: (...args: any[]) => console.debug('[DEBUG] [BfsFileSearch]', ...args),
|
||||
debug: (...args: any[]) =>
|
||||
debugLogger.debug('[DEBUG] [BfsFileSearch]', ...args),
|
||||
};
|
||||
|
||||
interface BfsFileSearchOptions {
|
||||
@@ -84,7 +86,7 @@ export async function bfsFileSearch(
|
||||
} catch (error) {
|
||||
// Warn user that a directory could not be read, as this affects search results.
|
||||
const message = (error as Error)?.message ?? 'Unknown error';
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`[WARN] Skipping unreadable directory: ${currentDir} (${message})`,
|
||||
);
|
||||
if (debug) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import type { FileSystemService } from '../services/fileSystemService.js';
|
||||
import { ToolErrorType } from '../tools/tool-error.js';
|
||||
import { BINARY_EXTENSIONS } from './ignorePatterns.js';
|
||||
import { createRequire as createModuleRequire } from 'node:module';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
const requireModule = createModuleRequire(import.meta.url);
|
||||
|
||||
@@ -260,7 +261,7 @@ export async function isBinaryFile(filePath: string): Promise<boolean> {
|
||||
// If >30% non-printable characters, consider it binary
|
||||
return nonPrintableCount / bytesRead > 0.3;
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Failed to check if file is binary: ${filePath}`,
|
||||
error instanceof Error ? error.message : String(error),
|
||||
);
|
||||
@@ -270,7 +271,7 @@ export async function isBinaryFile(filePath: string): Promise<boolean> {
|
||||
try {
|
||||
await fh.close();
|
||||
} catch (closeError) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Failed to close file handle for: ${filePath}`,
|
||||
closeError instanceof Error ? closeError.message : String(closeError),
|
||||
);
|
||||
|
||||
@@ -11,6 +11,7 @@ import { getErrorMessage, isNodeError } from './errors.js';
|
||||
import type { FileDiscoveryService } from '../services/fileDiscoveryService.js';
|
||||
import type { FileFilteringOptions } from '../config/constants.js';
|
||||
import { DEFAULT_FILE_FILTERING_OPTIONS } from '../config/constants.js';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
const MAX_ITEMS = 200;
|
||||
const TRUNCATION_INDICATOR = '...';
|
||||
@@ -104,7 +105,7 @@ async function readFullStructure(
|
||||
isNodeError(error) &&
|
||||
(error.code === 'EACCES' || error.code === 'ENOENT')
|
||||
) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Warning: Could not read directory ${currentPath}: ${error.message}`,
|
||||
);
|
||||
if (currentPath === rootPath && error.code === 'ENOENT') {
|
||||
|
||||
@@ -10,6 +10,7 @@ import { type BaseLlmClient } from '../core/baseLlmClient.js';
|
||||
import { LruCache } from './LruCache.js';
|
||||
import { DEFAULT_GEMINI_FLASH_MODEL } from '../config/models.js';
|
||||
import { promptIdContext } from './promptIdContext.js';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
const MAX_CACHE_SIZE = 50;
|
||||
|
||||
@@ -112,7 +113,7 @@ export async function FixLLMEditWithInstruction(
|
||||
let promptId = promptIdContext.getStore();
|
||||
if (!promptId) {
|
||||
promptId = `llm-fixer-fallback-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Could not find promptId in context. This is unexpected. Using a fallback ID: ${promptId}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,15 +16,17 @@ import type { FileFilteringOptions } from '../config/constants.js';
|
||||
import { DEFAULT_MEMORY_FILE_FILTERING_OPTIONS } from '../config/constants.js';
|
||||
import { GEMINI_DIR } from './paths.js';
|
||||
import type { GeminiCLIExtension } from '../config/config.js';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
// Simple console logger, similar to the one previously in CLI's config.ts
|
||||
// TODO: Integrate with a more robust server-side logger if available/appropriate.
|
||||
const logger = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
debug: (...args: any[]) =>
|
||||
console.debug('[DEBUG] [MemoryDiscovery]', ...args),
|
||||
debugLogger.debug('[DEBUG] [MemoryDiscovery]', ...args),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
warn: (...args: any[]) => console.warn('[WARN] [MemoryDiscovery]', ...args),
|
||||
warn: (...args: any[]) =>
|
||||
debugLogger.warn('[WARN] [MemoryDiscovery]', ...args),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
error: (...args: any[]) =>
|
||||
console.error('[ERROR] [MemoryDiscovery]', ...args),
|
||||
|
||||
@@ -8,14 +8,16 @@ import * as fs from 'node:fs/promises';
|
||||
import * as path from 'node:path';
|
||||
import { isSubpath } from './paths.js';
|
||||
import { marked, type Token } from 'marked';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
// Simple console logger for import processing
|
||||
const logger = {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
debug: (...args: any[]) =>
|
||||
console.debug('[DEBUG] [ImportProcessor]', ...args),
|
||||
debugLogger.debug('[DEBUG] [ImportProcessor]', ...args),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
warn: (...args: any[]) => console.warn('[WARN] [ImportProcessor]', ...args),
|
||||
warn: (...args: any[]) =>
|
||||
debugLogger.warn('[WARN] [ImportProcessor]', ...args),
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
error: (...args: any[]) =>
|
||||
console.error('[ERROR] [ImportProcessor]', ...args),
|
||||
|
||||
@@ -9,6 +9,7 @@ import { DEFAULT_GEMINI_FLASH_MODEL } from '../config/models.js';
|
||||
import type { BaseLlmClient } from '../core/baseLlmClient.js';
|
||||
import type { GeminiChat } from '../core/geminiChat.js';
|
||||
import { isFunctionResponse } from './messageInspectors.js';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
const CHECK_PROMPT = `Analyze *only* the content and structure of your immediately preceding response (your last turn in the conversation history). Based *strictly* on that response, determine who should logically speak next: the 'user' or the 'model' (you).
|
||||
**Decision Rules (apply in order):**
|
||||
@@ -126,7 +127,7 @@ export async function checkNextSpeaker(
|
||||
}
|
||||
return null;
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
'Failed to talk to Gemini endpoint when seeing if conversation should continue.',
|
||||
error,
|
||||
);
|
||||
|
||||
@@ -10,6 +10,7 @@ import { ApiError } from '@google/genai';
|
||||
import type { HttpError } from './retry.js';
|
||||
import { retryWithBackoff } from './retry.js';
|
||||
import { setSimulate429 } from './testUtils.js';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
// Helper to create a mock function that fails a certain number of times
|
||||
const createFailingFunction = (
|
||||
@@ -43,7 +44,7 @@ describe('retryWithBackoff', () => {
|
||||
// Disable 429 simulation for tests
|
||||
setSimulate429(false);
|
||||
// Suppress unhandled promise rejection warnings for tests that expect errors
|
||||
console.warn = vi.fn();
|
||||
debugLogger.warn = vi.fn();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
isGenericQuotaExceededError,
|
||||
} from './quotaErrorDetection.js';
|
||||
import { delay, createAbortError } from './delay.js';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
const FETCH_FAILED_MESSAGE =
|
||||
'exception TypeError: fetch failed sending request';
|
||||
@@ -168,7 +169,7 @@ export async function retryWithBackoff<T>(
|
||||
}
|
||||
} catch (fallbackError) {
|
||||
// If fallback fails, continue with original error
|
||||
console.warn('Fallback to Flash model failed:', fallbackError);
|
||||
debugLogger.warn('Fallback to Flash model failed:', fallbackError);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,7 +196,7 @@ export async function retryWithBackoff<T>(
|
||||
}
|
||||
} catch (fallbackError) {
|
||||
// If fallback fails, continue with original error
|
||||
console.warn('Fallback to Flash model failed:', fallbackError);
|
||||
debugLogger.warn('Fallback to Flash model failed:', fallbackError);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,7 +228,7 @@ export async function retryWithBackoff<T>(
|
||||
}
|
||||
} catch (fallbackError) {
|
||||
// If fallback fails, continue with original error
|
||||
console.warn('Fallback to Flash model failed:', fallbackError);
|
||||
debugLogger.warn('Fallback to Flash model failed:', fallbackError);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,7 +245,7 @@ export async function retryWithBackoff<T>(
|
||||
|
||||
if (delayDurationMs > 0) {
|
||||
// Respect Retry-After header if present and parsed
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Attempt ${attempt} failed with status ${delayErrorStatus ?? 'unknown'}. Retrying after explicit delay of ${delayDurationMs}ms...`,
|
||||
error,
|
||||
);
|
||||
@@ -367,13 +368,13 @@ function logRetryAttempt(
|
||||
}
|
||||
|
||||
if (errorStatus === 429) {
|
||||
console.warn(message, error);
|
||||
debugLogger.warn(message, error);
|
||||
} else if (errorStatus && errorStatus >= 500 && errorStatus < 600) {
|
||||
console.error(message, error);
|
||||
} else if (error instanceof Error) {
|
||||
// Fallback for errors that might not have a status but have a message
|
||||
if (error.message.includes('429')) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Attempt ${attempt} failed with 429 error (no Retry-After header). Retrying with backoff...`,
|
||||
error,
|
||||
);
|
||||
@@ -383,9 +384,9 @@ function logRetryAttempt(
|
||||
error,
|
||||
);
|
||||
} else {
|
||||
console.warn(message, error); // Default to warn for other errors
|
||||
debugLogger.warn(message, error); // Default to warn for other errors
|
||||
}
|
||||
} else {
|
||||
console.warn(message, error); // Default to warn if error type is unknown
|
||||
debugLogger.warn(message, error); // Default to warn if error type is unknown
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import { execSync } from 'node:child_process';
|
||||
import os from 'node:os';
|
||||
import { detect as chardetDetect } from 'chardet';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
// Cache for system encoding to avoid repeated detection
|
||||
// Use undefined to indicate "not yet checked" vs null meaning "checked but failed"
|
||||
@@ -66,7 +67,7 @@ export function getSystemEncoding(): string | null {
|
||||
`Unable to parse Windows code page from 'chcp' output "${output.trim()}". `,
|
||||
);
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`Failed to get Windows code page using 'chcp' command: ${error instanceof Error ? error.message : String(error)}. ` +
|
||||
`Will attempt to detect encoding from command output instead.`,
|
||||
);
|
||||
@@ -88,7 +89,7 @@ export function getSystemEncoding(): string | null {
|
||||
.toString()
|
||||
.trim();
|
||||
} catch (_e) {
|
||||
console.warn('Failed to get locale charmap.');
|
||||
debugLogger.warn('Failed to get locale charmap.');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -141,7 +142,7 @@ export function windowsCodePageToEncoding(cp: number): string | null {
|
||||
return map[cp];
|
||||
}
|
||||
|
||||
console.warn(`Unable to determine encoding for windows code page ${cp}.`);
|
||||
debugLogger.warn(`Unable to determine encoding for windows code page ${cp}.`);
|
||||
return null; // Return null if no mapping found
|
||||
}
|
||||
|
||||
@@ -159,7 +160,7 @@ export function detectEncodingFromBuffer(buffer: Buffer): string | null {
|
||||
return detected.toLowerCase();
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('Failed to detect encoding with chardet:', error);
|
||||
debugLogger.warn('Failed to detect encoding with chardet:', error);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
import path from 'node:path';
|
||||
import { promises as fsp, readFileSync } from 'node:fs';
|
||||
import { Storage } from '../config/storage.js';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
interface UserAccounts {
|
||||
active: string | null;
|
||||
@@ -33,7 +34,7 @@ export class UserAccountManager {
|
||||
|
||||
// Inlined validation logic
|
||||
if (typeof parsed !== 'object' || parsed === null) {
|
||||
console.log('Invalid accounts file schema, starting fresh.');
|
||||
debugLogger.log('Invalid accounts file schema, starting fresh.');
|
||||
return defaultState;
|
||||
}
|
||||
const { active, old } = parsed as Partial<UserAccounts>;
|
||||
@@ -43,7 +44,7 @@ export class UserAccountManager {
|
||||
(Array.isArray(old) && old.every((i) => typeof i === 'string')));
|
||||
|
||||
if (!isValid) {
|
||||
console.log('Invalid accounts file schema, starting fresh.');
|
||||
debugLogger.log('Invalid accounts file schema, starting fresh.');
|
||||
return defaultState;
|
||||
}
|
||||
|
||||
@@ -66,7 +67,10 @@ export class UserAccountManager {
|
||||
) {
|
||||
return defaultState;
|
||||
}
|
||||
console.log('Error during sync read of accounts, starting fresh.', error);
|
||||
debugLogger.log(
|
||||
'Error during sync read of accounts, starting fresh.',
|
||||
error,
|
||||
);
|
||||
return defaultState;
|
||||
}
|
||||
}
|
||||
@@ -84,7 +88,7 @@ export class UserAccountManager {
|
||||
) {
|
||||
return defaultState;
|
||||
}
|
||||
console.log('Could not parse accounts file, starting fresh.', error);
|
||||
debugLogger.log('Could not parse accounts file, starting fresh.', error);
|
||||
return defaultState;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { isNodeError } from '../utils/errors.js';
|
||||
import * as fs from 'node:fs';
|
||||
import * as path from 'node:path';
|
||||
import * as process from 'node:process';
|
||||
import { debugLogger } from './debugLogger.js';
|
||||
|
||||
export type Unsubscribe = () => void;
|
||||
|
||||
@@ -72,7 +73,7 @@ export class WorkspaceContext {
|
||||
this.directories.add(resolved);
|
||||
this.notifyDirectoriesChanged();
|
||||
} catch (err) {
|
||||
console.warn(
|
||||
debugLogger.warn(
|
||||
`[WARN] Skipping unreadable directory: ${directory} (${err instanceof Error ? err.message : String(err)})`,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user