diff --git a/src/main/index.js b/src/main/index.js index 760f26c..c268edd 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -133,6 +133,33 @@ try { console.warn('[Telemetry]: Failed to set service.version from package/app version:', e?.message || e); } +// Telemetry debug configuration for main process +const getTelemetryDebug = () => { + try { + // Check consolidated VITE_ vars first (available to all processes), then fall back to old vars + return import.meta.env.VITE_TELEMETRY_DEBUG === 'true' || + import.meta.env.MAIN_VITE_TELEMETRY_DEBUG === 'true'; + } catch { + return false; + } +}; + +const getTelemetryLevel = () => { + try { + // Check consolidated VITE_ vars first (available to all processes), then fall back to old vars + const level = import.meta.env.VITE_TELEMETRY_LEVEL || + import.meta.env.MAIN_VITE_TELEMETRY_LEVEL || + 'NORMAL'; + return level.toUpperCase(); + } catch { + return 'NORMAL'; + } +}; + +const shouldLogDebug = () => { + return getTelemetryDebug() || getTelemetryLevel() === 'VERBOSE'; +}; + // Load metrics with fallback let metrics = null; try { @@ -686,8 +713,10 @@ ipcMain.handle("otel:trace-export-json", async (_e, exportJson) => { const startedAt = Date.now(); try { - console.log(`[OTEL IPC Relay][${requestId}] Received trace export from renderer`); - console.log(`[OTEL IPC Relay][${requestId}] Payload size: ${JSON.stringify(exportJson || {}).length} chars`); + if (shouldLogDebug()) { + console.log(`[OTEL IPC Relay][${requestId}] Received trace export from renderer`); + console.log(`[OTEL IPC Relay][${requestId}] Payload size: ${JSON.stringify(exportJson || {}).length} chars`); + } const base = import.meta.env.MAIN_VITE_OTEL_EXPORTER_OTLP_ENDPOINT || process.env.OTEL_EXPORTER_OTLP_ENDPOINT || ""; const endpoint = import.meta.env.MAIN_VITE_OTEL_EXPORTER_OTLP_TRACES_ENDPOINT || @@ -732,7 +761,9 @@ ipcMain.handle("otel:trace-export-json", async (_e, exportJson) => { timeout: 15000, }; - console.log(`[OTEL IPC Relay][${requestId}] → POST ${url.hostname}${options.path}`); + if (shouldLogDebug()) { + console.log(`[OTEL IPC Relay][${requestId}] → POST ${url.hostname}${options.path}`); + } const result = await new Promise((resolve, reject) => { const req = https.request(options, (res) => { @@ -742,7 +773,9 @@ ipcMain.handle("otel:trace-export-json", async (_e, exportJson) => { const ms = Date.now() - startedAt; const responseBody = Buffer.concat(chunks).toString("utf8"); - console.log(`[OTEL IPC Relay][${requestId}] ← ${res.statusCode} (${ms}ms)`); + if (shouldLogDebug()) { + console.log(`[OTEL IPC Relay][${requestId}] ← ${res.statusCode} (${ms}ms)`); + } resolve({ statusCode: res.statusCode || 0, responseBody }); }); }); @@ -762,7 +795,9 @@ ipcMain.handle("otel:trace-export-json", async (_e, exportJson) => { }); const success = result.statusCode >= 200 && result.statusCode < 300; - console.log(`[OTEL IPC Relay][${requestId}] Result: ${success ? 'success' : 'failed'}`); + if (shouldLogDebug()) { + console.log(`[OTEL IPC Relay][${requestId}] Result: ${success ? 'success' : 'failed'}`); + } return { ok: success, status: result.statusCode, requestId }; } catch (e) { diff --git a/src/renderer/src/telemetry/webTracing.js b/src/renderer/src/telemetry/webTracing.js index 770ecdf..c81276f 100644 --- a/src/renderer/src/telemetry/webTracing.js +++ b/src/renderer/src/telemetry/webTracing.js @@ -198,13 +198,30 @@ if (!telemetryEnabled && typeof window !== 'undefined') { // Telemetry Level Configuration and Sampling Utilities const getTelemetryLevel = () => { try { - const level = import.meta.env.RENDERER_VITE_TELEMETRY_LEVEL || 'NORMAL'; + // Check consolidated VITE_ vars first (available to all processes), then fall back to old vars + const level = import.meta.env.VITE_TELEMETRY_LEVEL || + import.meta.env.RENDERER_VITE_TELEMETRY_LEVEL || + 'NORMAL'; return level.toUpperCase(); } catch { return 'NORMAL'; } }; +const getTelemetryDebug = () => { + try { + // Check consolidated VITE_ vars first (available to all processes), then fall back to old vars + return import.meta.env.VITE_TELEMETRY_DEBUG === 'true' || + import.meta.env.RENDERER_VITE_TELEMETRY_DEBUG === 'true'; + } catch { + return false; + } +}; + +const shouldLogDebug = () => { + return getTelemetryDebug() || getTelemetryLevel() === 'VERBOSE'; +}; + const TELEMETRY_LEVELS = { MINIMAL: { priority: 1, @@ -291,6 +308,8 @@ const checkStartupPhase = () => { // Export utilities for use in components window.__KT_TELEMETRY_UTILS__ = { getTelemetryLevel, + getTelemetryDebug, + shouldLogDebug, shouldEmitTelemetry, shouldSampleMessageParser, shouldEmitLexicalUpdate, @@ -654,45 +673,51 @@ if (!window.__KT_RENDERER_OTEL_INITIALIZED__ && telemetryEnabled) { } catch {} } - console.log(`[Renderer OTEL][${exportId}] IPCSpanExporter.export() called:`, { - exportId, - exportCount: this.exportCount, - spanCount: spanArray.length, - serviceName: this.serviceName, - deploymentEnv: this.deploymentEnv, - traceIds: traceInfo.traceIds, - spanIds: traceInfo.spanIds.slice(0, 3), // First 3 span IDs - spanNames: traceInfo.spanNames, - parentSpanIds: traceInfo.parentSpanIds.slice(0, 3) - }); + if (shouldLogDebug()) { + console.log(`[Renderer OTEL][${exportId}] IPCSpanExporter.export() called:`, { + exportId, + exportCount: this.exportCount, + spanCount: spanArray.length, + serviceName: this.serviceName, + deploymentEnv: this.deploymentEnv, + traceIds: traceInfo.traceIds, + spanIds: traceInfo.spanIds.slice(0, 3), // First 3 span IDs + spanNames: traceInfo.spanNames, + parentSpanIds: traceInfo.parentSpanIds.slice(0, 3) + }); + } const req = this._toOtlpJson(spans); const reqSize = JSON.stringify(req).length; - console.log(`[Renderer OTEL][${exportId}] Converted to OTLP JSON:`, { - exportId, - requestSize: reqSize, - resourceSpansCount: req.resourceSpans?.length || 0, - traceIds: traceInfo.traceIds, - actualTraceIds: traceInfo.traceIds, - traceIdLengths: traceInfo.traceIds.map(id => id?.length || 0) - }); + if (shouldLogDebug()) { + console.log(`[Renderer OTEL][${exportId}] Converted to OTLP JSON:`, { + exportId, + requestSize: reqSize, + resourceSpansCount: req.resourceSpans?.length || 0, + traceIds: traceInfo.traceIds, + actualTraceIds: traceInfo.traceIds, + traceIdLengths: traceInfo.traceIds.map(id => id?.length || 0) + }); + } const res = await window.telemetry.exportTracesJson(req); const duration = performance.now() - startTime; const ok = !!res?.ok && (!res.status || (res.status >= 200 && res.status < 300)); - console.log(`[Renderer OTEL][${exportId}] IPC export result:`, { - exportId, - success: ok, - duration: `${Math.round(duration)}ms`, - responseStatus: res?.status, - responseOk: res?.ok, - requestId: res?.requestId, - traceIds: traceInfo.traceIds, - returnedTraceIds: res?.traceIds - }); + if (shouldLogDebug()) { + console.log(`[Renderer OTEL][${exportId}] IPC export result:`, { + exportId, + success: ok, + duration: `${Math.round(duration)}ms`, + responseStatus: res?.status, + responseOk: res?.ok, + requestId: res?.requestId, + traceIds: traceInfo.traceIds, + returnedTraceIds: res?.traceIds + }); + } resultCallback({ code: ok ? 0 : 1 }); } catch (e) { @@ -883,50 +908,52 @@ if (!window.__KT_RENDERER_OTEL_INITIALIZED__ && telemetryEnabled) { const directConversion = rawSec * 1000000000n + rawNs; const directDate = new Date(Number(directConversion) / 1e6); - console.log(`[Renderer OTEL] Span validation debug:`, { - traceId, - traceIdHexLength: traceId.length, - spanId, - spanIdHexLength: spanId.length, - parentSpanId, - parentSpanIdHexLength: parentSpanId.length, - // For visibility when debugging, also show base64 versions - traceIdBase64: hexToBase64(traceIdHex), - spanIdBase64: hexToBase64(spanIdHex), - parentSpanIdBase64: parentSpanIdHex ? hexToBase64(parentSpanIdHex) : '', - startTimeUnixNano: startNs.toString(), - endTimeUnixNano: endNs.toString(), - startDate: startDate.toISOString(), - endDate: endDate.toISOString(), - startYear: startDate.getFullYear(), - endYear: endDate.getFullYear(), - isStartTimeReasonable: startDate.getFullYear() >= 2020 && startDate.getFullYear() <= 2030, - isEndTimeReasonable: endDate.getFullYear() >= 2020 && endDate.getFullYear() <= 2030, - duration: (endNs - startNs).toString() + ' nanos', - durationMs: Number(endNs - startNs) / 1e6, - kind: Number(s.kind) || 0, - name: s.name || 'span', - nowMs, - nowNs: nowNs.toString(), - timeDiffFromNow: Number(nowNs - startNs), - statusCode: s.status?.code, - statusMessage: s.status?.message, - statusWillBeIncluded: !!(s.status?.code && s.status.code > 0), - statusExists: !!s.status, - statusCodeType: typeof s.status?.code, - // Raw hrtime debugging - rawStartTime: s.startTime, - rawEndTime: s.endTime, - performanceTimeOrigin: performance?.timeOrigin, - performanceNow: performance?.now?.(), - // Step-by-step conversion debugging - rawSecBigInt: rawSec.toString(), - rawNsBigInt: rawNs.toString(), - directConversion: directConversion.toString(), - directDate: directDate.toISOString(), - directYear: directDate.getFullYear(), - directVsCalculated: directConversion.toString() === startNs.toString() - }); + if (shouldLogDebug()) { + console.log(`[Renderer OTEL] Span validation debug:`, { + traceId, + traceIdHexLength: traceId.length, + spanId, + spanIdHexLength: spanId.length, + parentSpanId, + parentSpanIdHexLength: parentSpanId.length, + // For visibility when debugging, also show base64 versions + traceIdBase64: hexToBase64(traceIdHex), + spanIdBase64: hexToBase64(spanIdHex), + parentSpanIdBase64: parentSpanIdHex ? hexToBase64(parentSpanIdHex) : '', + startTimeUnixNano: startNs.toString(), + endTimeUnixNano: endNs.toString(), + startDate: startDate.toISOString(), + endDate: endDate.toISOString(), + startYear: startDate.getFullYear(), + endYear: endDate.getFullYear(), + isStartTimeReasonable: startDate.getFullYear() >= 2020 && startDate.getFullYear() <= 2030, + isEndTimeReasonable: endDate.getFullYear() >= 2020 && endDate.getFullYear() <= 2030, + duration: (endNs - startNs).toString() + ' nanos', + durationMs: Number(endNs - startNs) / 1e6, + kind: Number(s.kind) || 0, + name: s.name || 'span', + nowMs, + nowNs: nowNs.toString(), + timeDiffFromNow: Number(nowNs - startNs), + statusCode: s.status?.code, + statusMessage: s.status?.message, + statusWillBeIncluded: !!(s.status?.code && s.status.code > 0), + statusExists: !!s.status, + statusCodeType: typeof s.status?.code, + // Raw hrtime debugging + rawStartTime: s.startTime, + rawEndTime: s.endTime, + performanceTimeOrigin: performance?.timeOrigin, + performanceNow: performance?.now?.(), + // Step-by-step conversion debugging + rawSecBigInt: rawSec.toString(), + rawNsBigInt: rawNs.toString(), + directConversion: directConversion.toString(), + directDate: directDate.toISOString(), + directYear: directDate.getFullYear(), + directVsCalculated: directConversion.toString() === startNs.toString() + }); + } // Warn if timestamps are too far in the future (>5m) or in the past (>24h) try { @@ -969,12 +996,14 @@ if (!window.__KT_RENDERER_OTEL_INITIALIZED__ && telemetryEnabled) { }; } - console.log(`[Renderer OTEL] Status filtering debug:`, { - originalStatusCode: statusCode, - originalStatusMessage: s.status?.message, - isError, - willAddStatus: isError - }); + if (shouldLogDebug()) { + console.log(`[Renderer OTEL] Status filtering debug:`, { + originalStatusCode: statusCode, + originalStatusMessage: s.status?.message, + isError, + willAddStatus: isError + }); + } const spanName = (s.name || 'span'); const spanOut = { diff --git a/src/telemetry/user-analytics.js b/src/telemetry/user-analytics.js index b5c3de4..0ea24b6 100644 --- a/src/telemetry/user-analytics.js +++ b/src/telemetry/user-analytics.js @@ -2,6 +2,34 @@ const { metrics, trace, context } = require('@opentelemetry/api'); const { ErrorMonitor } = require('./error-monitoring'); +// Debug configuration for user analytics +const getTelemetryDebug = () => { + try { + // Check consolidated VITE_ vars first (available to all processes), then fall back to old vars + // Note: In main process, we access these via process.env since they're embedded at build time + return process.env.VITE_TELEMETRY_DEBUG === 'true' || + process.env.MAIN_VITE_TELEMETRY_DEBUG === 'true'; + } catch { + return false; + } +}; + +const getTelemetryLevel = () => { + try { + // Check consolidated VITE_ vars first (available to all processes), then fall back to old vars + const level = process.env.VITE_TELEMETRY_LEVEL || + process.env.MAIN_VITE_TELEMETRY_LEVEL || + 'NORMAL'; + return level.toUpperCase(); + } catch { + return 'NORMAL'; + } +}; + +const shouldLogDebug = () => { + return getTelemetryDebug() || getTelemetryLevel() === 'VERBOSE'; +}; + const pkg = require('../../package.json'); const meter = metrics.getMeter('kicktalk-user-analytics', pkg.version); const tracer = trace.getTracer('kicktalk-user-analytics', pkg.version); @@ -279,7 +307,9 @@ class UserSession { const finalScore = this.calculateFinalSatisfactionScore(); this.satisfactionScore = finalScore; - console.log(`[User Analytics] Session ${this.sessionId} ended: ${this.getSessionDuration()}s, satisfaction: ${finalScore.toFixed(1)}/10`); + if (shouldLogDebug()) { + console.log(`[User Analytics] Session ${this.sessionId} ended: ${this.getSessionDuration()}s, satisfaction: ${finalScore.toFixed(1)}/10`); + } } } @@ -293,7 +323,9 @@ const UserAnalytics = { const session = new UserSession(sessionId, userId); activeSessions.set(sessionId, session); - console.log(`[User Analytics] Started session ${sessionId} for user ${userId || 'anonymous'}`); + if (shouldLogDebug()) { + console.log(`[User Analytics] Started session ${sessionId} for user ${userId || 'anonymous'}`); + } return session; }, @@ -319,7 +351,9 @@ const UserAnalytics = { // Record final satisfaction score const finalScore = session.satisfactionScore; - console.log(`[User Analytics] Session satisfaction: ${finalScore.toFixed(2)}/10`); + if (shouldLogDebug()) { + console.log(`[User Analytics] Session satisfaction: ${finalScore.toFixed(2)}/10`); + } // Store session data for correlation analysis userBehaviorData.set(sessionId, { @@ -417,7 +451,9 @@ const UserAnalytics = { } featureAdoptionData.get(userKey).add(featureName); - console.log(`[User Analytics] Feature usage: ${featureName}.${action} by ${session.userId}`); + if (shouldLogDebug()) { + console.log(`[User Analytics] Feature usage: ${featureName}.${action} by ${session.userId}`); + } }, /** @@ -453,7 +489,9 @@ const UserAnalytics = { timestamp: Date.now() }); - console.log(`[User Analytics] Connection quality: ${quality}/10 (${eventType}) for session ${sessionId}`); + if (shouldLogDebug()) { + console.log(`[User Analytics] Connection quality: ${quality}/10 (${eventType}) for session ${sessionId}`); + } }, /** @@ -586,16 +624,18 @@ const UserAnalytics = { const cleanupDuration = Date.now() - cleanupStartTime; - console.log(`[User Analytics] Cleanup completed in ${cleanupDuration}ms:`, { - active_sessions_cleaned: cleanedSessions, - historical_data_cleaned: cleanedHistoricalData, + if (shouldLogDebug()) { + console.log(`[User Analytics] Cleanup completed in ${cleanupDuration}ms:`, { + active_sessions_cleaned: cleanedSessions, + historical_data_cleaned: cleanedHistoricalData, adoption_data_cleaned: cleanedAdoptionData, performance_data_cleaned: cleanedPerfData, active_sessions_remaining: activeSessions.size, - historical_data_remaining: userBehaviorData.size, - feature_adoption_users: featureAdoptionData.size, - error_impact_sessions: performanceCorrelationData.error_impact_sessions.size - }); + historical_data_remaining: userBehaviorData.size, + feature_adoption_users: featureAdoptionData.size, + error_impact_sessions: performanceCorrelationData.error_impact_sessions.size + }); + } return { cleaned: cleanedSessions + cleanedHistoricalData + cleanedAdoptionData + cleanedPerfData, @@ -633,15 +673,17 @@ const UserAnalytics = { error_impact_sessions: new Set() }; - console.log(`[User Analytics] Force cleanup completed:`, { - before: beforeCounts, - after: { - activeSessions: activeSessions.size, - historicalData: userBehaviorData.size, - featureAdoption: featureAdoptionData.size, - errorImpactSessions: performanceCorrelationData.error_impact_sessions.size - } - }); + if (shouldLogDebug()) { + console.log(`[User Analytics] Force cleanup completed:`, { + before: beforeCounts, + after: { + activeSessions: activeSessions.size, + historicalData: userBehaviorData.size, + featureAdoption: featureAdoptionData.size, + errorImpactSessions: performanceCorrelationData.error_impact_sessions.size + } + }); + } return beforeCounts; }, diff --git a/utils/services/connectionManager.js b/utils/services/connectionManager.js index ff70288..2441b83 100644 --- a/utils/services/connectionManager.js +++ b/utils/services/connectionManager.js @@ -120,12 +120,17 @@ class ConnectionManager { // Set up 7TV event handlers if (handlers.onStvMessage) { + console.log(`[ConnectionManager] Registering onStvMessage handler`); this.stvWebSocket.addEventListener("message", handlers.onStvMessage); + } else { + console.warn(`[ConnectionManager] No onStvMessage handler provided!`); } if (handlers.onStvOpen) { + console.log(`[ConnectionManager] Registering onStvOpen handler`); this.stvWebSocket.addEventListener("open", handlers.onStvOpen); } if (handlers.onStvConnection) { + console.log(`[ConnectionManager] Registering onStvConnection handler`); this.stvWebSocket.addEventListener("connection", handlers.onStvConnection); } }