From 663dcdecabafa7b0210420a23dfc53fceb6109b6 Mon Sep 17 00:00:00 2001 From: Saravana Achu Mac Date: Mon, 4 May 2026 16:48:25 -0700 Subject: [PATCH] chore(platform): replace runtime console diagnostics What changed: - Replaced platform-service runtime console diagnostics with structured stderr logging helpers. - Preserved push notification, AI diagnostics, auto-trigger, and diagnostics repository error handling semantics. Warning impact: - Platform runtime no-console warnings: 12 -> 0. - Workspace lint: 12 -> 0 warnings. Verification: - pnpm --filter @lysnrai/platform-service build - pnpm --filter @lysnrai/platform-service test - pnpm --filter @lysnrai/platform-service exec eslint --ext .ts - pnpm lint --- .../src/lib/push-notifications.ts | 31 +++++++++++++++---- .../ai-diagnostics/embedding-client.ts | 16 ++++++++-- .../modules/ai-diagnostics/llm-analyzer.ts | 13 +++++++- .../src/modules/diagnostics/auto-triggers.ts | 15 +++++++-- .../src/modules/diagnostics/repository.ts | 13 ++++++-- 5 files changed, 73 insertions(+), 15 deletions(-) diff --git a/services/platform-service/src/lib/push-notifications.ts b/services/platform-service/src/lib/push-notifications.ts index c8471a37..983c82e7 100644 --- a/services/platform-service/src/lib/push-notifications.ts +++ b/services/platform-service/src/lib/push-notifications.ts @@ -32,6 +32,22 @@ interface PushPayload { badge?: number; } +function logPushWarning(message: string, extra?: Record): void { + process.stderr.write(JSON.stringify({ level: 'warn', module: 'push', message, ...extra }) + '\n'); +} + +function logPushError(message: string, error: unknown, extra?: Record): void { + process.stderr.write( + JSON.stringify({ + level: 'error', + module: 'push', + message, + error: error instanceof Error ? error.message : String(error), + ...extra, + }) + '\n' + ); +} + /** * Store or update device token for push notifications */ @@ -130,7 +146,7 @@ export async function sendFCM( // Get FCM server key from environment const fcmKey = process.env.FCM_SERVER_KEY; if (!fcmKey) { - console.warn('[Push] FCM_SERVER_KEY not configured'); + logPushWarning('FCM_SERVER_KEY not configured'); return results; } @@ -164,11 +180,11 @@ export async function sendFCM( results.success.push(token); } else { const error = await response.text(); - console.error(`[Push] FCM failed for token ${token.substring(0, 16)}...:`, error); + logPushError('FCM send failed', error, { tokenPrefix: token.substring(0, 16) }); results.failed.push(token); } } catch (err) { - console.error(`[Push] FCM error for token ${token.substring(0, 16)}...:`, err); + logPushError('FCM send error', err, { tokenPrefix: token.substring(0, 16) }); results.failed.push(token); } } @@ -194,7 +210,7 @@ export async function sendAPNS( const apnsPrivateKey = process.env.APNS_PRIVATE_KEY; if (!apnsKeyId || !apnsTeamId || !apnsBundleId || !apnsPrivateKey) { - console.warn('[Push] APNS credentials not fully configured'); + logPushWarning('APNS credentials not fully configured'); return results; } @@ -241,7 +257,10 @@ export async function sendAPNS( results.success.push(token); } else { const error = await response.text(); - console.error(`[Push] APNS failed for token ${token.substring(0, 16)}...:`, error); + logPushError('APNS send failed', error, { + status: response.status, + tokenPrefix: token.substring(0, 16), + }); results.failed.push(token); // Handle invalid token (410 Gone) @@ -250,7 +269,7 @@ export async function sendAPNS( } } } catch (err) { - console.error(`[Push] APNS error for token ${token.substring(0, 16)}...:`, err); + logPushError('APNS send error', err, { tokenPrefix: token.substring(0, 16) }); results.failed.push(token); } } diff --git a/services/platform-service/src/modules/ai-diagnostics/embedding-client.ts b/services/platform-service/src/modules/ai-diagnostics/embedding-client.ts index 3fd3d16a..d5a35879 100644 --- a/services/platform-service/src/modules/ai-diagnostics/embedding-client.ts +++ b/services/platform-service/src/modules/ai-diagnostics/embedding-client.ts @@ -1,6 +1,5 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ import { config } from '../../lib/config.js'; -import type { FastifyBaseLogger } from 'fastify'; // ============================================================================ // Azure OpenAI Embedding Client @@ -11,6 +10,17 @@ const EMBEDDING_DIMENSIONS = 1536; const MAX_BATCH_SIZE = 100; // Azure OpenAI limit const MAX_TOKENS_PER_REQUEST = 8192; +function logEmbeddingError(message: string, error: unknown): void { + process.stderr.write( + JSON.stringify({ + level: 'error', + module: 'ai-diagnostics.embeddings', + message, + error: error instanceof Error ? error.message : String(error), + }) + '\n' + ); +} + interface EmbeddingResponse { object: 'list'; data: Array<{ @@ -93,7 +103,7 @@ export async function generateEmbedding( model: data.model, }; } catch (error) { - console.error('Failed to generate embedding:', error); + logEmbeddingError('Failed to generate embedding', error); throw error; } } @@ -174,7 +184,7 @@ export async function generateEmbeddingsBatch( await new Promise(resolve => setTimeout(resolve, 100)); } } catch (error) { - console.error('Failed to generate batch embeddings:', error); + logEmbeddingError('Failed to generate batch embeddings', error); throw error; } } diff --git a/services/platform-service/src/modules/ai-diagnostics/llm-analyzer.ts b/services/platform-service/src/modules/ai-diagnostics/llm-analyzer.ts index 2312ff0f..1dd72b65 100644 --- a/services/platform-service/src/modules/ai-diagnostics/llm-analyzer.ts +++ b/services/platform-service/src/modules/ai-diagnostics/llm-analyzer.ts @@ -21,6 +21,17 @@ interface RootCauseAnalysisPrompt { analysisType: 'root_cause' | 'pattern' | 'comparison' | 'trend'; } +function logAnalyzerError(message: string, error: unknown): void { + process.stderr.write( + JSON.stringify({ + level: 'error', + module: 'ai-diagnostics.llm-analyzer', + message, + error: error instanceof Error ? error.message : String(error), + }) + '\n' + ); +} + const ROOT_CAUSE_ANALYSIS_PROMPT_TEMPLATE = `You are an expert software engineer diagnosing production errors. Analyze this error cluster and provide root cause insights. ## Error Cluster @@ -206,7 +217,7 @@ async function callLLM( completionTokens: data.usage?.completion_tokens || 0, }; } catch (error) { - console.error('LLM call failed:', error); + logAnalyzerError('LLM call failed', error); throw error; } } diff --git a/services/platform-service/src/modules/diagnostics/auto-triggers.ts b/services/platform-service/src/modules/diagnostics/auto-triggers.ts index f15e134a..5890252a 100644 --- a/services/platform-service/src/modules/diagnostics/auto-triggers.ts +++ b/services/platform-service/src/modules/diagnostics/auto-triggers.ts @@ -9,6 +9,17 @@ import type { DebugSessionDoc } from './types.js'; import { createSession } from './repository.js'; import { getRegisteredContainer } from '@bytelyst/cosmos'; +function logTriggerError(message: string, error: unknown): void { + process.stderr.write( + JSON.stringify({ + level: 'error', + module: 'diagnostics.auto-triggers', + message, + error: error instanceof Error ? error.message : String(error), + }) + '\n' + ); +} + // ───────────────────────────────────────────────────────────────────────────── // Trigger Configuration Types // ───────────────────────────────────────────────────────────────────────────── @@ -399,7 +410,7 @@ async function sendTriggerNotifications( }); } catch (err) { // Log but don't fail - console.error('Failed to send Slack notification:', err); + logTriggerError('Failed to send Slack notification', err); } } @@ -427,7 +438,7 @@ async function sendTriggerNotifications( }), }); } catch (err) { - console.error('Failed to send Teams notification:', err); + logTriggerError('Failed to send Teams notification', err); } } diff --git a/services/platform-service/src/modules/diagnostics/repository.ts b/services/platform-service/src/modules/diagnostics/repository.ts index ffd472d7..7af2ac3b 100644 --- a/services/platform-service/src/modules/diagnostics/repository.ts +++ b/services/platform-service/src/modules/diagnostics/repository.ts @@ -39,6 +39,12 @@ function screenshotsCollection() { return getCollection('debug_screenshots', '/sessionId'); } +function logDiagnosticsWarning(message: string, extra?: Record): void { + process.stderr.write( + JSON.stringify({ level: 'warn', module: 'diagnostics.repository', message, ...extra }) + '\n' + ); +} + // ───────────────────────────────────────────────────────────────────────────── // Helper: Build composite partition key // ───────────────────────────────────────────────────────────────────────────── @@ -320,9 +326,10 @@ export async function updateSessionStats( retries++; if (retries >= MAX_RETRIES) { // Log warning but don't fail the ingest - data integrity > stats accuracy - console.warn( - `[diagnostics] Failed to update session stats after ${MAX_RETRIES} retries for session ${sessionId}` - ); + logDiagnosticsWarning('Failed to update session stats after max retries', { + retries: MAX_RETRIES, + sessionId, + }); return; } // Small delay before retry