Skip to content

Commit 105074b

Browse files
theo-learnerclaude
andcommitted
feat: extend Pino logger to critical server modules
- Update k8s-config.ts (6 console calls → logger calls) - Update log-ingester.ts (3 console calls → logger calls) - Update anomaly-ai-analyzer.ts (5 console calls → logger calls) - Remove [ModuleName] prefixes from log messages (handled by logger.name field) - All 941 tests passing, build ✓ Server logs now include automatic timestamps across all critical paths: [HH:MM:ss] LEVEL (K8s Config): kubectl (358ms): get pods... [HH:MM:ss] LEVEL (LogIngester): Tailing logs from: pod-name... [HH:MM:ss] LEVEL (AnomalyAIAnalyzer): Calling AI provider with N anomalies... Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
1 parent 87d8ef1 commit 105074b

File tree

3 files changed

+22
-14
lines changed

3 files changed

+22
-14
lines changed

src/lib/anomaly-ai-analyzer.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import { AISeverity } from '@/types/scaling';
99
import { chatCompletion } from './ai-client';
1010
import { parseAIJSON } from './ai-response-parser';
1111
import { getChainPlugin } from '@/chains';
12+
import { createLogger } from '@/lib/logger';
13+
14+
const logger = createLogger('AnomalyAIAnalyzer');
1215

1316
// ============================================================================
1417
// Configuration
@@ -192,13 +195,13 @@ export async function analyzeAnomalies(
192195
if (analysisCache &&
193196
analysisCache.anomalyHash === anomalyHash &&
194197
now - analysisCache.timestamp < ANALYSIS_CACHE_TTL_MS) {
195-
console.info('[AnomalyAIAnalyzer] Returning cached analysis');
198+
logger.info('Returning cached analysis');
196199
return analysisCache.result;
197200
}
198201

199202
// 2. Rate limiting: return cached result or default response if interval not met
200203
if (now - lastAICallTime < MIN_AI_CALL_INTERVAL_MS) {
201-
console.info('[AnomalyAIAnalyzer] Rate limited, returning cached or default');
204+
logger.info('Rate limited, returning cached or default');
202205
if (analysisCache) {
203206
return analysisCache.result;
204207
}
@@ -227,7 +230,7 @@ Analyze these anomalies and provide your assessment.`;
227230

228231
// 4. Call AI Gateway
229232
try {
230-
console.info(`[AnomalyAIAnalyzer] Calling AI provider with ${anomalies.length} anomalies...`);
233+
logger.info(`Calling AI provider with ${anomalies.length} anomalies...`);
231234
lastAICallTime = now;
232235

233236
const aiResult = await chatCompletion({
@@ -248,12 +251,12 @@ Analyze these anomalies and provide your assessment.`;
248251
timestamp: now,
249252
};
250253

251-
console.info(`[AnomalyAIAnalyzer] Analysis complete: severity=${result.severity}, type=${result.anomalyType}`);
254+
logger.info(`Analysis complete: severity=${result.severity}, type=${result.anomalyType}`);
252255
return result;
253256

254257
} catch (error) {
255258
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
256-
console.error('[AnomalyAIAnalyzer] AI provider error:', errorMessage);
259+
logger.error('AI provider error: ' + errorMessage);
257260

258261
// Default response on failure
259262
return {

src/lib/k8s-config.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55

66
import { exec, execFile } from 'child_process';
77
import { promisify } from 'util';
8+
import { createLogger } from '@/lib/logger';
89

910
const execAsync = promisify(exec);
1011
const execFileAsync = promisify(execFile);
12+
const logger = createLogger('K8s Config');
1113

1214
// ============================================================
1315
// Environment Detection
@@ -26,7 +28,7 @@ function isDevelopmentEnvironment(): boolean {
2628
*/
2729
function logK8sWarning(message: string): void {
2830
if (!isDevelopmentEnvironment()) {
29-
console.warn(`[K8s Config] ${message}`);
31+
logger.warn(message);
3032
} else if (process.env.DEBUG_K8S === 'true') {
3133
console.debug(`[K8s Config] ${message}`);
3234
}
@@ -119,7 +121,7 @@ async function resolveAwsRegion(): Promise<string | undefined> {
119121
const region = stdout.trim();
120122
if (region) {
121123
regionCache = region;
122-
console.info(`[K8s Config] Auto-detected AWS region: ${region}`);
124+
logger.info(`Auto-detected AWS region: ${region}`);
123125
return regionCache;
124126
}
125127
} catch {
@@ -169,7 +171,7 @@ async function resolveK8sApiUrl(): Promise<string | undefined> {
169171

170172
if (endpoint && endpoint !== 'None') {
171173
apiUrlCache = endpoint;
172-
console.info(`[K8s Config] Auto-detected API URL: ${endpoint} (${Date.now() - startTime}ms)`);
174+
logger.info(`Auto-detected API URL: ${endpoint} (${Date.now() - startTime}ms)`);
173175
return apiUrlCache;
174176
}
175177
} catch (e) {
@@ -217,7 +219,7 @@ async function getK8sToken(): Promise<string | undefined> {
217219

218220
const startTime = Date.now();
219221
const { stdout } = await execFileAsync('aws', args, { timeout: 10000 });
220-
console.info(`[K8s Config] Token generated (${Date.now() - startTime}ms)`);
222+
logger.info(`Token generated (${Date.now() - startTime}ms)`);
221223

222224
const tokenData = JSON.parse(stdout);
223225
const token = tokenData.status.token;
@@ -302,12 +304,12 @@ export async function runK8sCommand(
302304
const result = await execAsync(fullCmd, {
303305
timeout: options?.timeout ?? 10000,
304306
});
305-
console.info(`[K8s Config] kubectl (${Date.now() - startTime}ms): ${command.substring(0, 40)}...`);
307+
logger.info(`kubectl (${Date.now() - startTime}ms): ${command.substring(0, 40)}...`);
306308
return result;
307309
} catch (e) {
308310
// Only log kubectl failures in production/configured environments
309311
if (!isDevelopmentEnvironment()) {
310-
console.info(`[K8s Config] kubectl failed (${Date.now() - startTime}ms): ${command}`);
312+
logger.info(`kubectl failed (${Date.now() - startTime}ms): ${command}`);
311313
}
312314
throw e;
313315
}

src/lib/log-ingester.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ export function generateMockLogs(mode: 'normal' | 'attack' = 'normal'): Record<s
3737
import { runK8sCommand, getNamespace, getAppPrefix } from '@/lib/k8s-config';
3838
import { isDockerMode } from '@/lib/docker-config';
3939
import { getDockerContainerLogs } from '@/lib/docker-orchestrator';
40+
import { createLogger } from '@/lib/logger';
41+
42+
const logger = createLogger('LogIngester');
4043

4144
// Fetch logs from ALL components
4245
export async function getAllLiveLogs(namespace?: string): Promise<Record<string, string>> {
@@ -68,13 +71,13 @@ export async function getLiveLogs(namespace?: string, labelSelector?: string): P
6871
);
6972

7073
if (!podName || podName.trim() === '') {
71-
console.warn(`[LogIngester] No pods found for ${label}`);
74+
logger.warn(`No pods found for ${label}`);
7275
return `WARN [System] No active pods found matching '${label}' in namespace '${ns}'.
7376
Verify your K8s context and pod labels.`;
7477
}
7578

7679
const cleanPodName = podName.trim();
77-
console.info(`[LogIngester] Tailing logs from: ${cleanPodName}`);
80+
logger.info(`Tailing logs from: ${cleanPodName}`);
7881

7982
// 2. Fetch Logs (Tail)
8083
const { stdout: logs, stderr: logsErr } = await runK8sCommand(
@@ -89,7 +92,7 @@ export async function getLiveLogs(namespace?: string, labelSelector?: string): P
8992

9093
} catch (error) {
9194
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
92-
console.error("[LogIngester] kubectl Error:", errorMessage);
95+
logger.error("kubectl Error: " + errorMessage);
9396

9497
if (errorMessage.includes('command not found')) {
9598
return `ERROR [System] 'kubectl' command not found on server.

0 commit comments

Comments
 (0)