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 <runtime files> --ext .ts
- pnpm lint
This commit is contained in:
Saravana Achu Mac 2026-05-04 16:48:25 -07:00
parent 2c9dc1870d
commit 663dcdecab
5 changed files with 73 additions and 15 deletions

View File

@ -32,6 +32,22 @@ interface PushPayload {
badge?: number;
}
function logPushWarning(message: string, extra?: Record<string, unknown>): void {
process.stderr.write(JSON.stringify({ level: 'warn', module: 'push', message, ...extra }) + '\n');
}
function logPushError(message: string, error: unknown, extra?: Record<string, unknown>): 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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -39,6 +39,12 @@ function screenshotsCollection() {
return getCollection<DebugScreenshotDoc>('debug_screenshots', '/sessionId');
}
function logDiagnosticsWarning(message: string, extra?: Record<string, unknown>): 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