From d8e0e64c00f6ec275c2484b40c6676b9a397e350 Mon Sep 17 00:00:00 2001 From: mjfwebb Date: Fri, 19 Sep 2025 22:27:08 +0200 Subject: [PATCH] fix: update logging to help identify issues in specific versions --- src/TwitchAuthHandler.tsx | 2 +- src/TwitchBroadcasterIdLoader.tsx | 6 ++-- src/TwitchWebSocketClient.tsx | 36 +++++++++---------- .../bttv/fetchBetterTTVGlobalEmotes.ts | 2 +- src/handlers/bttv/fetchBetterTTVUser.ts | 2 +- .../fetchFrankerFaceZGlobalEmotes.ts | 2 +- .../fetchFrankerFaceZRoomEmotes.ts | 2 +- src/handlers/sevenTV/fetchSevenTVEmote.ts | 2 +- src/handlers/sevenTV/fetchSevenTVEmoteSets.ts | 2 +- .../sevenTV/fetchSevenTVTwitchUser.ts | 2 +- src/handlers/sevenTV/sevenTVWebsocket.ts | 2 +- .../event-sub/subscribers/eventSubscribe.ts | 2 +- .../event-sub/subscribers/subscribeToChat.ts | 2 +- src/handlers/twitch/helix/fetchBadges.ts | 4 +-- src/handlers/twitch/helix/fetchCheers.ts | 4 +-- .../twitch/helix/fetchUserInformation.ts | 2 +- src/handlers/twitch/id/validateAccessToken.ts | 2 +- src/main.tsx | 4 --- src/utils/logger.ts | 17 +++++---- 19 files changed, 48 insertions(+), 49 deletions(-) diff --git a/src/TwitchAuthHandler.tsx b/src/TwitchAuthHandler.tsx index 17a1562..a6daad6 100644 --- a/src/TwitchAuthHandler.tsx +++ b/src/TwitchAuthHandler.tsx @@ -19,7 +19,7 @@ export const TwitchAuthHandler = () => { const { accessToken, state } = getTwitchAuthResponseData(); if (state !== authStateValue) { - logger.error('Invalid state value. Possible CSRF attack. Expected:', authStateValue, 'Received:', state); + logger.error('Invalid state value. Possible CSRF attack.'); return Error: Invalid state value.; } diff --git a/src/TwitchBroadcasterIdLoader.tsx b/src/TwitchBroadcasterIdLoader.tsx index af27a45..32615a0 100644 --- a/src/TwitchBroadcasterIdLoader.tsx +++ b/src/TwitchBroadcasterIdLoader.tsx @@ -45,7 +45,7 @@ export const TwitchBroadcasterIdLoader = () => { // If a channel is specified, try to get the broadcaster ID from the channel name if (channel) { loadedBroadcasterId = await getBroadcasterIdFromChannel(channel); - logger.info('Loaded broadcaster ID:', loadedBroadcasterId, 'from channel:', channel); + logger.info(`Loaded broadcaster ID: ${loadedBroadcasterId} from channel: ${channel}`); } // If we still don't have a broadcaster ID, try to get it from the access token, @@ -57,9 +57,9 @@ export const TwitchBroadcasterIdLoader = () => { return; } if (res.id && res.login) { - logger.info('Loaded broadcaster ID:', res.id, 'from access token'); + logger.info(`Loaded broadcaster ID: ${res.id} from access token`); loadedBroadcasterId ??= res.id; - logger.info('Loaded user ID:', res.id, 'from access token'); + logger.info(`Loaded user ID: ${res.id} from access token`); store.getState().setUserId(res.id); store.getState().setUserLogin(res.login); } diff --git a/src/TwitchWebSocketClient.tsx b/src/TwitchWebSocketClient.tsx index 96d8f17..37477e8 100644 --- a/src/TwitchWebSocketClient.tsx +++ b/src/TwitchWebSocketClient.tsx @@ -85,7 +85,7 @@ export const TwitchWebSocketClient = () => { // Don't share so we can close the socket explicitly if needed share: false, onError: (event) => { - logger.warn('WebSocket error', event); + logger.warn(`WebSocket error: ${JSON.stringify(event)}`); }, onOpen: () => { logger.info(`WebSocket opened to ${socketUrl}`); @@ -147,7 +147,7 @@ export const TwitchWebSocketClient = () => { } } } catch (e) { - logger.warn('Error closing temporary reconnect socket', e); + logger.warn(`Error closing temporary reconnect socket: ${JSON.stringify(e)}`); } finally { temporarySocketRef.current = null; } @@ -187,7 +187,7 @@ export const TwitchWebSocketClient = () => { try { getWebSocket()?.close(); } catch (e) { - logger.warn('Failed to close primary socket during handover', e); + logger.warn(`Failed to close primary socket during handover: ${JSON.stringify(e)}`); } // We can now close the temporary socket; the hook-managed connection will take over closeTemporarySocket(); @@ -205,14 +205,14 @@ export const TwitchWebSocketClient = () => { break; } case 'revocation': { - logger.warn('EventSub subscription revoked (temporary socket)', jsonData.payload?.subscription); + logger.warn(`EventSub subscription revoked (temporary socket): ${JSON.stringify(jsonData.payload?.subscription)}`); break; } default: break; } } catch (e) { - logger.warn('Failed to handle temporary reconnect message', e); + logger.warn(`Failed to handle temporary reconnect message: ${JSON.stringify(e)}`); } }, [closeTemporarySocket, getWebSocket, hasSeenMessageId, rememberMessageId, resetInactivityWatchdog], @@ -289,33 +289,33 @@ export const TwitchWebSocketClient = () => { temporarySocket.onopen = () => { logger.info('Temporary reconnect WebSocket opened'); }; - temporarySocket.onmessage = (evt) => { - const dataStr = typeof evt.data === 'string' ? evt.data : ''; + temporarySocket.onmessage = (event) => { + const dataStr = typeof event.data === 'string' ? event.data : ''; if (dataStr) { handleTempSocketMessage(dataStr); } }; - temporarySocket.onerror = (evt) => { - logger.warn('Temporary reconnect WebSocket error', evt); + temporarySocket.onerror = (event) => { + logger.warn(`Temporary reconnect WebSocket error: ${JSON.stringify(event)}`); }; - temporarySocket.onclose = (evt) => { - logger.info(`Temporary reconnect WebSocket closed (code ${evt.code} reason: ${evt.reason || ''})`); + temporarySocket.onclose = (event) => { + logger.info(`Temporary reconnect WebSocket closed (code ${event.code} reason: ${event.reason || ''})`); }; - } catch (e) { - logger.warn('Failed to create temporary reconnect WebSocket', e); + } catch (error) { + logger.warn(`Failed to create temporary reconnect WebSocket: ${JSON.stringify(error)}`); // Fall back: close primary to trigger hook reconnect on base try { getWebSocket()?.close(); - } catch (err) { - logger.warn('Fallback close after temporary socket failure also failed', err); + } catch (error) { + logger.warn(`Fallback close after temporary socket failure also failed: ${JSON.stringify(error)}`); } } } else { logger.warn('session_reconnect without reconnect_url; closing socket to trigger base reconnect'); try { getWebSocket()?.close(); - } catch (err) { - logger.warn('Fallback close without reconnect_url failed', err); + } catch (error) { + logger.warn(`Fallback close without reconnect_url failed: ${JSON.stringify(error)}`); } } } @@ -323,7 +323,7 @@ export const TwitchWebSocketClient = () => { } case 'revocation': - logger.warn('EventSub subscription revoked', jsonData.payload?.subscription); + logger.warn(`EventSub subscription revoked: ${JSON.stringify(jsonData.payload?.subscription)}`); break; default: break; diff --git a/src/handlers/bttv/fetchBetterTTVGlobalEmotes.ts b/src/handlers/bttv/fetchBetterTTVGlobalEmotes.ts index 7cf8d60..3f0d32c 100644 --- a/src/handlers/bttv/fetchBetterTTVGlobalEmotes.ts +++ b/src/handlers/bttv/fetchBetterTTVGlobalEmotes.ts @@ -18,7 +18,7 @@ export const fetchBetterTTVGlobalEmotes = async (): Promise return json as BttvEmote[]; } } catch (error) { - logger.error(error); + logger.error(`Failed to fetch BetterTTV global emotes: ${JSON.stringify(error)}`); } return null; diff --git a/src/handlers/bttv/fetchBetterTTVUser.ts b/src/handlers/bttv/fetchBetterTTVUser.ts index 14fbd39..0d294bd 100644 --- a/src/handlers/bttv/fetchBetterTTVUser.ts +++ b/src/handlers/bttv/fetchBetterTTVUser.ts @@ -17,7 +17,7 @@ export const fetchBetterTTVUser = async (broadcasterId: string): Promise => logger.warn('No badges found or data is not an array.'); } } else { - logger.error('Failed to parse badges response:', parsed.error); + logger.error(`Failed to parse badges response: ${parsed.error.message}`); } } catch (error) { - logger.error(error); + logger.error(`Failed to fetch Twitch badges: ${JSON.stringify(error)}`); } }; diff --git a/src/handlers/twitch/helix/fetchCheers.ts b/src/handlers/twitch/helix/fetchCheers.ts index 896722d..f48316f 100644 --- a/src/handlers/twitch/helix/fetchCheers.ts +++ b/src/handlers/twitch/helix/fetchCheers.ts @@ -33,10 +33,10 @@ export const fetchCheers = async (type: 'global' | 'channel'): Promise => logger.warn('No cheers found or data is not an array.'); } } else { - logger.error('Failed to parse cheers response:', parsed.error); + logger.error(`Failed to parse cheers response: ${parsed.error.message}`); } } catch (error) { - logger.error(error); + logger.error(`Failed to fetch Twitch cheers: ${JSON.stringify(error)}`); } }; diff --git a/src/handlers/twitch/helix/fetchUserInformation.ts b/src/handlers/twitch/helix/fetchUserInformation.ts index c6558a0..b12a156 100644 --- a/src/handlers/twitch/helix/fetchUserInformation.ts +++ b/src/handlers/twitch/helix/fetchUserInformation.ts @@ -31,7 +31,7 @@ export const fetchUserInformation = async (loginName: string): Promise => return data; } } catch (error) { - logger.error(error); + logger.error(`Failed to validate access token: ${error}`); } return null; diff --git a/src/main.tsx b/src/main.tsx index 99e9dd9..d947efb 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -7,10 +7,6 @@ Sentry.init({ dsn: 'https://a688e1582950d78e4cb076f4fad4d95f@o939511.ingest.us.sentry.io/4510030479556608', sendDefaultPii: false, enableLogs: true, - integrations: [ - // send console calls as logs to Sentry - Sentry.consoleLoggingIntegration({ levels: ['log', 'info', 'warn', 'error'] }), - ], }); createRoot(document.getElementById('root')!).render( diff --git a/src/utils/logger.ts b/src/utils/logger.ts index 852f2d8..f5fc428 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -1,3 +1,4 @@ +import * as Sentry from '@sentry/react'; import pc from 'picocolors'; export const logLevels = ['error', 'warn', 'info', 'debug']; @@ -26,23 +27,25 @@ export function setLogLevel(logLevelString: string) { logLevel = logLevelsMap[logLevelString]; } +const APP_VERSION = import.meta.env.APP_VERSION || 'unknown'; + export const logger = { - error: (...args: unknown[]) => { - console.error(`${formattedDate()} ${pc.red('Error:')}`, ...args); + error: (message: string, extra?: Record) => { + Sentry.logger.error(`${formattedDate()} (v${APP_VERSION}) ${pc.red('Error:')} ${message}`, extra); }, - warn: (...args: unknown[]) => { + warn: (message: string, extra?: Record) => { if (logLevel >= logLevelsMap['warn']) { - console.warn(`${formattedDate()} ${pc.yellow('Warn:')}`, ...args); + Sentry.logger.warn(`${formattedDate()} (v${APP_VERSION}) ${pc.yellow('Warn:')} ${message}`, extra); } }, - info: (...args: unknown[]) => { + info: (message: string, extra?: Record) => { if (logLevel >= logLevelsMap['info']) { - console.info(`${formattedDate()} ${pc.cyan('Info:')}`, ...args); + Sentry.logger.info(`${formattedDate()} (v${APP_VERSION}) ${pc.cyan('Info:')} ${message}`, extra); } }, debug: (...args: unknown[]) => { if (logLevel >= logLevelsMap['debug']) { - console.debug(`${formattedDate()} ${pc.magenta('Debug:')}`, ...args); + console.debug(`${formattedDate()} (v${APP_VERSION}) ${pc.magenta('Debug:')}`, ...args); } }, };