diff --git a/src/debug/README.md b/src/debug/README.md new file mode 100644 index 00000000..97a95439 --- /dev/null +++ b/src/debug/README.md @@ -0,0 +1,54 @@ +# Debug Logging in the Console + +## Overview + +Logging is controlled via a querystring parameter: + +``` +?log= +``` + +This system works by overriding `console.*` methods at app startup. + +--- + +# Supported Log Levels + +| Level | Behavior | +| ----- | --------------------------- | +| none | No logs | +| error | Errors only | +| warn | Warnings + errors (default) | +| info | Info + warn + error | +| debug | All logs | +| all | All logs | + +--- + +# Notes + +## Default Behavior + +- Defaults to `warn` +- Ensures important issues are always visible + +--- + +## Page Reload Required + +Changing the querystring requires a manual refresh. + +--- + +## Global Impact + +This override affects **all console calls globally**, including third-party libraries. + +--- + +# `console.*` considerations + +- Use `console.error` for real failures +- Use `console.warn` for unexpected but non-breaking issues +- Use `console.log` for debugging only +- Avoid leaving excessive logs in production code diff --git a/src/debug/consoleOverride.js b/src/debug/consoleOverride.js new file mode 100644 index 00000000..326941e1 --- /dev/null +++ b/src/debug/consoleOverride.js @@ -0,0 +1,36 @@ +const LEVEL_MAP = { + none: 0, + error: 1, + warn: 2, + info: 3, + debug: 4, + all: 4, +}; + +const METHOD_LEVEL = { + error: 1, + warn: 2, + info: 3, + log: 4, + debug: 4, + trace: 4, +}; + +export function overrideConsole(config) { + const allowedLevel = LEVEL_MAP[config.logLevel]; + + const originalConsole = { + error: console.error.bind(console), + warn: console.warn.bind(console), + info: console.info.bind(console), + log: console.log.bind(console), + debug: console.debug ? console.debug.bind(console) : console.log.bind(console), + trace: console.trace ? console.trace.bind(console) : console.log.bind(console), + }; + + Object.keys(METHOD_LEVEL).forEach((method) => { + const methodLevel = METHOD_LEVEL[method]; + + console[method] = methodLevel <= allowedLevel ? originalConsole[method] : () => {}; + }); +} diff --git a/src/debug/debugConfig.js b/src/debug/debugConfig.js new file mode 100644 index 00000000..ac5c7401 --- /dev/null +++ b/src/debug/debugConfig.js @@ -0,0 +1,10 @@ +export function getDebugConfig() { + const params = new URLSearchParams(window.location.search); + + const level = params.get('log'); + const validLevels = ['none', 'error', 'warn', 'info', 'debug', 'all']; + + return { + logLevel: validLevels.includes(level) ? level : 'warn', + }; +} diff --git a/src/main.jsx b/src/main.jsx index d20721cf..209762dd 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -5,10 +5,14 @@ import ErrorBoundary from './components/ErrorBoundary'; import { QRZProvider, setupMapQRZHandler } from './components/CallsignLink'; import './styles/main.css'; import './lang/i18n'; +import { getDebugConfig } from './debug/debugConfig'; +import { overrideConsole } from './debug/consoleOverride'; // Global click handler for QRZ links in Leaflet HTML popups setupMapQRZHandler(); +overrideConsole(getDebugConfig()); + ReactDOM.createRoot(document.getElementById('root')).render(