UNPKG

frontend-logger-advanced

Version:

Comprehensive frontend logging system with dead click detection, rage click detection, framework integrations (React/Solid), and cloud streaming support

2 lines (1 loc) 21.5 kB
import{EventHubProducerClient as e}from"@azure/event-hubs";import{jsx as t,jsxs as o}from"react/jsx-runtime";import n,{createContext as r,useRef as i,useEffect as s,useContext as c,useMemo as a}from"react";import{createSignal as l,onMount as u,onCleanup as g,createEffect as d}from"solid-js";function generateSessionId(){return`session_${Date.now()}_${Math.random().toString(36).substring(2,11)}`}function generateLogId(){return`log_${Date.now()}_${Math.random().toString(36).substring(2,11)}`}function getCurrentTimestamp(){return(new Date).toISOString()}function sanitizeData(e){if("string"==typeof e)return e.replace(/[<>]/g,"");if(Array.isArray(e))return e.map(sanitizeData);if(e&&"object"==typeof e){const t={};for(const o in e)e.hasOwnProperty(o)&&(t[sanitizeData(o)]=sanitizeData(e[o]));return t}return e}function getBrowserInfo(){var e;const t=navigator.userAgent;let o="Unknown",n="Unknown";if(t.includes("Chrome")){o="Chrome";const e=/Chrome\/(\d+\.\d+)/.exec(t);n=e?e[1]:"Unknown"}else if(t.includes("Firefox")){o="Firefox";const e=/Firefox\/(\d+\.\d+)/.exec(t);n=e?e[1]:"Unknown"}else if(t.includes("Safari")&&!t.includes("Chrome")){o="Safari";const e=/Version\/(\d+\.\d+)/.exec(t);n=e?e[1]:"Unknown"}else if(t.includes("Edge")){o="Edge";const e=/Edge\/(\d+\.\d+)/.exec(t);n=e?e[1]:"Unknown"}return{name:o,version:n,platform:(null===(e=navigator.userAgentData)||void 0===e?void 0:e.platform)||navigator.platform||"Unknown"}}function getElementSelector(e){if(e.id)return`#${e.id}`;let t=e.tagName.toLowerCase();if(e.className){const o=e.className.split(" ").filter(e=>e.trim());o.length>0&&(t+="."+o.join("."))}if(!e.id&&!e.className){const o=e.parentElement;if(o){t+=`:nth-child(${Array.from(o.children).indexOf(e)+1})`}}return t}function isInteractiveElement(e){const t=e.tagName.toLowerCase();if(-1!==["button","a","input","select","textarea","label"].indexOf(t))return!0;if(e.hasAttribute("onclick")||e.hasAttribute("role")||e.hasAttribute("tabindex"))return!0;return"pointer"===window.getComputedStyle(e).cursor}function calculateDistance(e,t){const o=e.x-t.x,n=e.y-t.y;return Math.sqrt(o*o+n*n)}function detectFramework(){return{react:void 0!==window.React||null!==document.querySelector("[data-reactroot]"),solid:void 0!==window.solidJs}}async function loadConfig(e,t){const o={logging:{level:"INFO",endpoint:"",batchInterval:5e3,batchSize:100,maxQueueSize:1e3},features:{customLogs:!0,deadClicks:!0,rageClicks:!0,localLogFile:!0,eventHub:!1,reactSupport:!1,solidSupport:!1},thresholds:{deadClickTimeout:300,rageClickCount:3,rageClickWindow:1e3,rageClickDistance:50,maxLogFileSize:5242880},metadata:{includeBrowserInfo:!0,anonymizeUserId:!0},localLogging:{autoExportOnUnload:!0,defaultFileName:"frontend_logs.json"},eventHub:{connectionString:"",eventHubName:"",useSasToken:!0,partitionKey:"sessionId"},frameworks:{enableHooks:!0,devModeOnly:!1}};try{if(e){const t=await fetch(e);if(t.ok){return mergeConfig(o,await t.json())}}if(t)return mergeConfig(o,t)}catch(e){}return o}function mergeConfig(e,t){const o={...e};for(const e in t)if(t.hasOwnProperty(e)){const n=t[e];n&&"object"==typeof n&&!Array.isArray(n)?o[e]={...o[e],...n}:o[e]=n}return o}function checkBrowserSupport(){return{fileAPI:"undefined"!=typeof Blob&&"undefined"!=typeof URL&&"createObjectURL"in URL,fetchAPI:"undefined"!=typeof fetch,eventHubs:"undefined"!=typeof WebSocket||"undefined"!=typeof EventSource}}function throttle(e,t){let o=null,n=0;return(...r)=>{const i=Date.now();i-n>t?(e(...r),n=i):(o&&clearTimeout(o),o=setTimeout(()=>{e(...r),n=Date.now()},t-(i-n)))}}function debounce(e,t){let o=null;return(...n)=>{o&&clearTimeout(o),o=setTimeout(()=>e(...n),t)}}class FileExporter{constructor(e){this.config=e}exportToFile(e,t){if(checkBrowserSupport().fileAPI)try{const o=this.prepareLogs(e),n=new Blob([o],{type:"application/json"});if(n.size>this.config.thresholds.maxLogFileSize)return void this.handleLargeFile(e,t);this.downloadFile(n,t||this.config.localLogging.defaultFileName)}catch(t){this.fallbackToConsole(e)}else this.fallbackToConsole(e)}prepareLogs(e){const t={timestamp:(new Date).toISOString(),totalLogs:e.length,logs:e};return JSON.stringify(t,null,2)}handleLargeFile(e,t){const o=this.config.thresholds.maxLogFileSize,n=this.splitLogsIntoChunks(e,o);if(1===n.length){const o=e.slice(0,Math.floor(e.length/2));return void this.exportToFile(o,t)}n.forEach((e,o)=>{const r=this.generateChunkFilename(t,o+1,n.length),i=this.prepareLogs(e),s=new Blob([i],{type:"application/json"});this.downloadFile(s,r)})}splitLogsIntoChunks(e,t){const o=[];let n=[],r=0;const i=JSON.stringify({timestamp:(new Date).toISOString(),totalLogs:0,logs:[]}).length;for(const s of e){const e=JSON.stringify(s).length;r+e+i>t&&n.length>0?(o.push([...n]),n=[s],r=e):(n.push(s),r+=e)}return n.length>0&&o.push(n),o}generateChunkFilename(e,t,o){const n=e||this.config.localLogging.defaultFileName,r=n.endsWith(".json")?".json":"";return`${n.replace(/\.json$/,"")}_part${t}_of_${o}${r}`}downloadFile(e,t){const o=URL.createObjectURL(e),n=document.createElement("a");n.href=o,n.download=t,n.style.display="none",document.body.appendChild(n),n.click(),document.body.removeChild(n),setTimeout(()=>{URL.revokeObjectURL(o)},100)}fallbackToConsole(e){}setupAutoExport(e){if(!this.config.localLogging.autoExportOnUnload)return;const handleUnload=()=>{const t=e();if(t.length>0)try{const e=this.prepareLogs(t);try{sessionStorage.setItem("frontend_logger_backup",e)}catch(e){}this.exportToFile(t,`unload_${this.config.localLogging.defaultFileName}`)}catch(e){}};window.addEventListener("beforeunload",handleUnload),document.addEventListener("visibilitychange",()=>{"hidden"===document.visibilityState&&handleUnload()})}restoreFromStorage(){try{const e=sessionStorage.getItem("frontend_logger_backup");if(e){const t=JSON.parse(e);return sessionStorage.removeItem("frontend_logger_backup"),Array.isArray(t.logs)?t.logs:[]}}catch(e){}return[]}}class Logger{constructor(e){this.logQueue=[],this.clickBuffer=[],this.deadClickTimeout=new Map,this.batchTimeoutId=null,this.isProcessing=!1,this.config=e,this.sessionId=generateSessionId(),this.fileExporter=new FileExporter(e),this.httpProcessor=new HttpProcessor(e),this.boundClickHandler=this.handleClick.bind(this),this.boundUnloadHandler=this.handleUnload.bind(this),this.initialize()}initialize(){this.setupEventListeners(),this.setupBatchProcessing(),this.setupAutoExport(),this.restoreFromStorage()}setupEventListeners(){(this.config.features.deadClicks||this.config.features.rageClicks)&&document.addEventListener("click",this.boundClickHandler,{passive:!0,capture:!0})}setupBatchProcessing(){const e=this.config.logging.batchInterval;this.batchTimeoutId=setInterval(()=>{this.processBatch()},e)}setupAutoExport(){this.config.features.localLogFile&&this.fileExporter.setupAutoExport(()=>this.logQueue)}restoreFromStorage(){if(this.config.features.localLogFile){const e=this.fileExporter.restoreFromStorage();this.logQueue.push(...e)}}debug(e,t){this.log("DEBUG","custom",e,t)}info(e,t){this.log("INFO","custom",e,t)}warn(e,t){this.log("WARN","custom",e,t)}error(e,t){this.log("ERROR","custom",e,t)}custom(e,t){this.log("INFO","custom",e,t)}log(e,t,o,n){if(!this.shouldLog(e))return;const r={id:generateLogId(),type:t,level:e,timestamp:getCurrentTimestamp(),message:o,details:sanitizeData(n||{}),metadata:this.createMetadata()};this.addToQueue(r)}shouldLog(e){const t={DEBUG:0,INFO:1,WARN:2,ERROR:3};return t[e]>=t[this.config.logging.level]}createMetadata(){const e={sessionId:this.sessionId,url:window.location.href};return this.config.metadata.includeBrowserInfo&&(e.browserInfo=getBrowserInfo(),e.userAgent=navigator.userAgent),e}addToQueue(e){if(this.logQueue.push(e),this.logQueue.length>this.config.logging.maxQueueSize){const e=this.logQueue.length-this.config.logging.maxQueueSize;this.logQueue.splice(0,e)}this.logQueue.length>=this.config.logging.batchSize&&this.processBatch()}async processBatch(){if(this.isProcessing||0===this.logQueue.length)return;this.isProcessing=!0;const e=this.logQueue.splice(0,this.config.logging.batchSize);try{if(this.config.features.eventHub)try{await this.httpProcessor.process(e)}catch(t){await this.httpProcessor.process(e)}else this.config.logging.endpoint&&await this.httpProcessor.process(e)}catch(t){this.logQueue.unshift(...e)}finally{this.isProcessing=!1}}handleClick(e){const t=e.target;if(!t)return;const o={timestamp:Date.now(),element:t,coords:{x:e.clientX,y:e.clientY},selector:getElementSelector(t)};this.config.features.deadClicks&&this.checkDeadClick(o,e),this.config.features.rageClicks&&this.checkRageClick(o)}checkDeadClick(e,t){const o=e.element;if(isInteractiveElement(o))return;const n=setTimeout(()=>{t.defaultPrevented||this.hasRecentDOMChanges()||this.logDeadClick(e),this.deadClickTimeout.delete(o)},this.config.thresholds.deadClickTimeout);this.deadClickTimeout.set(o,n)}hasRecentDOMChanges(){return!1}logDeadClick(e){const t={element:e.element.tagName.toLowerCase(),selector:e.selector,coords:e.coords,timeout:this.config.thresholds.deadClickTimeout};this.log("WARN","dead_click","Dead click detected",t)}checkRageClick(e){const t=e.timestamp,o=this.config.thresholds.rageClickWindow,n=this.config.thresholds.rageClickDistance,r=this.config.thresholds.rageClickCount;for(this.clickBuffer.push(e);this.clickBuffer.length>0&&t-this.clickBuffer[0].timestamp>o;)this.clickBuffer.shift();if(this.clickBuffer.length>=r){const e=this.clickBuffer.slice(-r),t=e[0];e.every(e=>calculateDistance(t.coords,e.coords)<=n)&&(this.logRageClick(e),this.clickBuffer.length=0)}}logRageClick(e){const t=e[0],o=e[e.length-1],n={clickCount:e.length,element:t.element.tagName.toLowerCase(),selector:t.selector,coords:t.coords,duration:o.timestamp-t.timestamp};this.log("ERROR","rage_click","Rage click detected",n)}exportToFile(e){this.config.features.localLogFile&&this.fileExporter.exportToFile([...this.logQueue],e)}getQueueSize(){return this.logQueue.length}clearQueue(){this.logQueue.length=0}handleUnload(){this.logQueue.length>0&&this.processBatch()}destroy(){document.removeEventListener("click",this.boundClickHandler),window.removeEventListener("beforeunload",this.boundUnloadHandler),this.batchTimeoutId&&clearInterval(this.batchTimeoutId),this.deadClickTimeout.forEach(e=>{clearTimeout(e)}),this.deadClickTimeout.clear(),this.clearQueue()}}class HttpProcessor{constructor(e){this.config=e}async process(e){var t;if(!this.config.logging.endpoint)throw new Error("HTTP endpoint not configured");try{const o=await fetch(this.config.logging.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({logs:e,timestamp:getCurrentTimestamp(),sessionId:null===(t=e[0])||void 0===t?void 0:t.metadata.sessionId})});if(!o.ok)throw new Error(`HTTP ${o.status}: ${o.statusText}`)}catch(e){throw new Error(`Failed to send logs to HTTP endpoint: ${e}`)}}}class EventHubProcessor{constructor(e){this.client=null,this.isConnected=!1,this.connectionPromise=null,this.config=e}async initializeConnection(){return this.connectionPromise||(this.connectionPromise=this._connect()),this.connectionPromise}async _connect(){if(!checkBrowserSupport().eventHubs)throw new Error("Event Hubs not supported in this browser environment");if(!this.config.eventHub.connectionString)throw new Error("Event Hub connection string is required");if(!this.config.eventHub.eventHubName)throw new Error("Event Hub name is required");try{this.client=new e(this.config.eventHub.connectionString,this.config.eventHub.eventHubName),await this.client.getEventHubProperties(),this.isConnected=!0}catch(e){throw this.isConnected=!1,this.client=null,new Error(`Failed to connect to Event Hub: ${e}`)}}async process(e){if(this.config.features.eventHub&&0!==e.length)try{if(await this.initializeConnection(),!this.client||!this.isConnected)throw new Error("Event Hub client not connected");await this.sendBatch(e)}catch(e){throw e}}async sendBatch(e){if(!this.client)throw new Error("Event Hub client not initialized");const t=await this.createBatches(e);for(const e of t)try{await this.client.sendBatch(e)}catch(e){throw e}}async createBatches(e){if(!this.client)throw new Error("Event Hub client not initialized");const t=[];let o=await this.client.createBatch({partitionKey:this.getPartitionKey(e[0])});for(const n of e){const e=this.createEventData(n);if(!o.tryAdd(e)){t.push(o),o=await this.client.createBatch({partitionKey:this.getPartitionKey(n)});o.tryAdd(e)}}return o.count>0&&t.push(o),t}createEventData(e){return{body:JSON.stringify(e),properties:{logType:e.type,logLevel:e.level,timestamp:e.timestamp,sessionId:e.metadata.sessionId}}}getPartitionKey(e){switch(this.config.eventHub.partitionKey){case"sessionId":default:return e.metadata.sessionId;case"userId":return e.metadata.userId||"anonymous";case"logType":return e.type;case"logLevel":return e.level}}async close(){if(this.client&&this.isConnected)try{await this.client.close(),this.isConnected=!1,this.client=null,this.connectionPromise=null}catch(e){}}isEventHubConnected(){return this.isConnected}async testConnection(){try{return await this.initializeConnection(),this.isConnected}catch(e){return!1}}getConnectionInfo(){return{connected:this.isConnected,hubName:this.config.eventHub.eventHubName}}}const h=r(null),LoggerProvider=({children:e,config:o,configPath:r,disabled:c=!1})=>{const a=i(null),[l,u]=n.useState(!1);return s(()=>((async()=>{if(c)u(!0);else try{const e=await loadConfig(r,o);if(!e.features.reactSupport)return void u(!0);if(e.frameworks.devModeOnly&&"production"===process.env.NODE_ENV)return void u(!0);a.current=new Logger(e),u(!0)}catch(e){u(!0)}})(),()=>{a.current&&(a.current.destroy(),a.current=null)}),[o,r,c]),l?t(h.Provider,{value:a.current,children:e}):null},useLogger=()=>{const e=c(h);if(void 0===e)throw new Error("useLogger must be used within a LoggerProvider");return e},useLoggerActions=()=>{const e=useLogger();return a(()=>e?{debug:(t,o)=>e.debug(t,o),info:(t,o)=>e.info(t,o),warn:(t,o)=>e.warn(t,o),error:(t,o)=>e.error(t,o),custom:(t,o)=>e.custom(t,o),exportToFile:t=>e.exportToFile(t),getQueueSize:()=>e.getQueueSize(),clearQueue:()=>e.clearQueue()}:{debug:()=>{},info:()=>{},warn:()=>{},error:()=>{},custom:()=>{},exportToFile:()=>{},getQueueSize:()=>0,clearQueue:()=>{}},[e])},useComponentLogger=e=>{const t=useLoggerActions(),o=i(Date.now());s(()=>(t.info(`Component mounted: ${e}`,{component:e,mountTime:o.current}),()=>{t.info(`Component unmounted: ${e}`,{component:e,mountTime:o.current,unmountTime:Date.now(),lifetimeDuration:Date.now()-o.current})}),[e,t]);return{...t,logRender:o=>{t.debug(`Component rendered: ${e}`,{component:e,renderTime:Date.now(),props:o?Object.keys(o):void 0})},logError:(o,n)=>{t.error(`Component error: ${e}`,{component:e,error:o.message,stack:o.stack,errorInfo:n})},logUserAction:(o,n)=>{t.custom(`User action in ${e}`,{component:e,action:o,timestamp:Date.now(),...n})}}};function withLogger(e,o){const n=o||e.displayName||e.name,WithLoggerComponent=o=>{const r=useComponentLogger(n);return s(()=>{"development"===process.env.NODE_ENV&&r.logRender(o)}),t(e,{...o})};return WithLoggerComponent.displayName=`withLogger(${n})`,WithLoggerComponent}class LoggerErrorBoundary extends n.Component{constructor(e){super(e),this.state={hasError:!1}}static getDerivedStateFromError(e){return{hasError:!0,error:e}}componentDidCatch(e,t){this.context&&this.context.error("React component error caught by boundary",{error:e.message,stack:e.stack,componentStack:t.componentStack,errorBoundary:!0}),this.props.onError&&this.props.onError(e,t)}render(){if(this.state.hasError&&this.state.error){if(this.props.fallback){const e=this.props.fallback;return t(e,{error:this.state.error})}return o("div",{role:"alert",children:[t("h2",{children:"Something went wrong."}),t("details",{style:{whiteSpace:"pre-wrap"},children:this.state.error.toString()})]})}return this.props.children}}async function initReactLogger(e={}){try{if(!detectFramework().react)return null;const t=await loadConfig(e.configPath,e.config);return t.features.reactSupport?new Logger(t):null}catch(e){return null}}function createLoggerSignal(e={}){const[t,o]=l(null),[n,r]=l(!1),[i,s]=l(null);return u(async()=>{try{if(!detectFramework().solid)return void r(!0);const t=await loadConfig(e.configPath,e.config);if(!t.features.solidSupport)return void r(!0);if(t.frameworks.devModeOnly&&"production"===process.env.NODE_ENV)return void r(!0);const n=new Logger(t);o(n),r(!0),g(()=>{n.destroy()})}catch(e){const t=e instanceof Error?e.message:"Unknown error";s(t),r(!0)}}),{logger:t,isInitialized:n,error:i}}function createLoggerActions(e={}){const{logger:t,isInitialized:o,error:n}=createLoggerSignal(e);return{actions:()=>{const e=t();return e?{debug:(t,o)=>e.debug(t,o),info:(t,o)=>e.info(t,o),warn:(t,o)=>e.warn(t,o),error:(t,o)=>e.error(t,o),custom:(t,o)=>e.custom(t,o),exportToFile:t=>e.exportToFile(t),getQueueSize:()=>e.getQueueSize(),clearQueue:()=>e.clearQueue()}:{debug:()=>{},info:()=>{},warn:()=>{},error:()=>{},custom:()=>{},exportToFile:()=>{},getQueueSize:()=>0,clearQueue:()=>{}}},logger:t,isInitialized:o,error:n}}function createComponentLogger(e,t={}){const{actions:o,logger:n,isInitialized:r,error:i}=createLoggerActions(t),[s]=l(Date.now());u(()=>{o().info(`Component mounted: ${e}`,{component:e,mountTime:s()})}),g(()=>{o().info(`Component unmounted: ${e}`,{component:e,mountTime:s(),unmountTime:Date.now(),lifetimeDuration:Date.now()-s()})});return{...o(),logger:n,isInitialized:r,error:i,logRender:t=>{o().debug(`Component rendered: ${e}`,{component:e,renderTime:Date.now(),props:t?Object.keys(t):void 0})},logError:(t,n)=>{o().error(`Component error: ${e}`,{component:e,error:t.message,stack:t.stack,errorInfo:n})},logUserAction:(t,n)=>{o().custom(`User action in ${e}`,{component:e,action:t,timestamp:Date.now(),...n})}}}function createErrorBoundary(e){const{actions:t}=createLoggerActions();return(o,n)=>{t().error("Solid JS component error caught",{error:o.message,stack:o.stack,errorInfo:n,errorBoundary:!0}),e&&e(o)}}function createLoggerResource(e={}){const[t]=function(e,t){const[o,n]=l(void 0),[r,i]=l(!0),[s,c]=l(null);return d(async()=>{try{i(!0),c(null);const o=await t(e());n(()=>o)}catch(e){c(e)}finally{i(!1)}}),[o,{loading:r(),error:s()}]}(()=>e,async e=>{try{if(!detectFramework().solid)throw new Error("Solid JS not detected in the current environment");const t=await loadConfig(e.configPath,e.config);if(!t.features.solidSupport)throw new Error("Solid JS support is disabled in configuration");return new Logger(t)}catch(e){throw e}});return t}function withSolidLogger(e,t){const o=t||e.name||"AnonymousComponent";return(...t)=>{const n=createComponentLogger(o);return d(()=>{"development"===process.env.NODE_ENV&&n.logRender(t[0])}),e(...t)}}async function initSolidLogger(e={}){try{if(!detectFramework().solid)return null;const t=await loadConfig(e.configPath,e.config);return t.features.solidSupport?new Logger(t):null}catch(e){return null}}LoggerErrorBoundary.contextType=h;let f=null;async function initLogging(e={}){try{const t=await loadConfig(e.configPath,e.config),o=detectFramework(),n={...t,features:{...t.features,reactSupport:t.features.reactSupport&&o.react,solidSupport:t.features.solidSupport&&o.solid}};return f=new Logger(n),f}catch(e){return null}}function getLogger(){return f}function destroyLogger(){f&&(f.destroy(),f=null)}async function quickStart(e){const t={features:{customLogs:!0,deadClicks:!0,rageClicks:!0,localLogFile:!0,eventHub:!1,reactSupport:!0,solidSupport:!0},logging:{level:"INFO",batchInterval:5e3,batchSize:100,maxQueueSize:1e3}};return initLogging({config:e?{...t,...e}:t})}const p={debug:(e,t)=>{null==f||f.debug(e,t)},info:(e,t)=>{null==f||f.info(e,t)},warn:(e,t)=>{null==f||f.warn(e,t)},error:(e,t)=>{null==f||f.error(e,t)},custom:(e,t)=>{null==f||f.custom(e,t)}},m={logging:{level:"INFO",endpoint:"",batchInterval:5e3,batchSize:100,maxQueueSize:1e3},features:{customLogs:!0,deadClicks:!0,rageClicks:!0,localLogFile:!0,eventHub:!1,reactSupport:!1,solidSupport:!1},thresholds:{deadClickTimeout:300,rageClickCount:3,rageClickWindow:1e3,rageClickDistance:50,maxLogFileSize:5242880},metadata:{includeBrowserInfo:!0,anonymizeUserId:!0},localLogging:{autoExportOnUnload:!0,defaultFileName:"frontend_logs.json"},eventHub:{connectionString:"",eventHubName:"",useSasToken:!0,partitionKey:"sessionId"},frameworks:{enableHooks:!0,devModeOnly:!1}};function checkCompatibility(){const e=[],t="undefined"!=typeof Blob&&"undefined"!=typeof URL&&"createObjectURL"in URL,o="undefined"!=typeof fetch,n="undefined"!=typeof WebSocket||"undefined"!=typeof EventSource;t||e.push("File API not supported - local file export will not work"),o||e.push("Fetch API not supported - HTTP logging will not work"),n||e.push("WebSocket/EventSource not supported - Event Hub integration may not work");return{compatible:t&&o,features:{fileAPI:t,fetchAPI:o,eventHubs:n},warnings:e}}export{EventHubProcessor,FileExporter,Logger,LoggerErrorBoundary,LoggerProvider,calculateDistance,checkBrowserSupport,checkCompatibility,createComponentLogger,createErrorBoundary,createLoggerActions,createLoggerResource,createLoggerSignal,debounce,m as defaultConfig,destroyLogger,detectFramework,generateLogId,generateSessionId,getBrowserInfo,getCurrentTimestamp,getElementSelector,getLogger,initLogging,initReactLogger,initSolidLogger,isInteractiveElement,loadConfig,p as log,quickStart,sanitizeData,throttle,useComponentLogger,useLogger,useLoggerActions,withLogger,withSolidLogger};