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) 22 kB
"use strict";var e=require("@azure/event-hubs"),t=require("react/jsx-runtime"),o=require("react"),n=require("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}}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}`)}}}const r=o.createContext(null),useLogger=()=>{const e=o.useContext(r);if(void 0===e)throw new Error("useLogger must be used within a LoggerProvider");return e},useLoggerActions=()=>{const e=useLogger();return o.useMemo(()=>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(),n=o.useRef(Date.now());o.useEffect(()=>(t.info(`Component mounted: ${e}`,{component:e,mountTime:n.current}),()=>{t.info(`Component unmounted: ${e}`,{component:e,mountTime:n.current,unmountTime:Date.now(),lifetimeDuration:Date.now()-n.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})}}};class LoggerErrorBoundary extends o.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.jsx(e,{error:this.state.error})}return t.jsxs("div",{role:"alert",children:[t.jsx("h2",{children:"Something went wrong."}),t.jsx("details",{style:{whiteSpace:"pre-wrap"},children:this.state.error.toString()})]})}return this.props.children}}function createLoggerSignal(e={}){const[t,o]=n.createSignal(null),[r,i]=n.createSignal(!1),[s,c]=n.createSignal(null);return n.onMount(async()=>{try{if(!detectFramework().solid)return void i(!0);const t=await loadConfig(e.configPath,e.config);if(!t.features.solidSupport)return void i(!0);if(t.frameworks.devModeOnly&&"production"===process.env.NODE_ENV)return void i(!0);const r=new Logger(t);o(r),i(!0),n.onCleanup(()=>{r.destroy()})}catch(e){const t=e instanceof Error?e.message:"Unknown error";c(t),i(!0)}}),{logger:t,isInitialized:r,error:s}}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:r,isInitialized:i,error:s}=createLoggerActions(t),[c]=n.createSignal(Date.now());n.onMount(()=>{o().info(`Component mounted: ${e}`,{component:e,mountTime:c()})}),n.onCleanup(()=>{o().info(`Component unmounted: ${e}`,{component:e,mountTime:c(),unmountTime:Date.now(),lifetimeDuration:Date.now()-c()})});return{...o(),logger:r,isInitialized:i,error:s,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})}}}LoggerErrorBoundary.contextType=r;let i=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 i=new Logger(n),i}catch(e){return null}}const s={debug:(e,t)=>{null==i||i.debug(e,t)},info:(e,t)=>{null==i||i.info(e,t)},warn:(e,t)=>{null==i||i.warn(e,t)},error:(e,t)=>{null==i||i.error(e,t)},custom:(e,t)=>{null==i||i.custom(e,t)}};exports.EventHubProcessor=class{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.EventHubProducerClient(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}}},exports.FileExporter=FileExporter,exports.Logger=Logger,exports.LoggerErrorBoundary=LoggerErrorBoundary,exports.LoggerProvider=({children:e,config:n,configPath:i,disabled:s=!1})=>{const c=o.useRef(null),[a,l]=o.useState(!1);return o.useEffect(()=>((async()=>{if(s)l(!0);else try{const e=await loadConfig(i,n);if(!e.features.reactSupport)return void l(!0);if(e.frameworks.devModeOnly&&"production"===process.env.NODE_ENV)return void l(!0);c.current=new Logger(e),l(!0)}catch(e){l(!0)}})(),()=>{c.current&&(c.current.destroy(),c.current=null)}),[n,i,s]),a?t.jsx(r.Provider,{value:c.current,children:e}):null},exports.calculateDistance=calculateDistance,exports.checkBrowserSupport=checkBrowserSupport,exports.checkCompatibility=function(){const e=[],t="undefined"!=typeof Blob&&"undefined"!=typeof URL&&"createObjectURL"in URL,o="undefined"!=typeof fetch,n="undefined"!=typeof WebSocket||"undefined"!=typeof EventSource;return 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"),{compatible:t&&o,features:{fileAPI:t,fetchAPI:o,eventHubs:n},warnings:e}},exports.createComponentLogger=createComponentLogger,exports.createErrorBoundary=function(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)}},exports.createLoggerActions=createLoggerActions,exports.createLoggerResource=function(e={}){const[t]=function(e,t){const[o,r]=n.createSignal(void 0),[i,s]=n.createSignal(!0),[c,a]=n.createSignal(null);return n.createEffect(async()=>{try{s(!0),a(null);const o=await t(e());r(()=>o)}catch(e){a(e)}finally{s(!1)}}),[o,{loading:i(),error:c()}]}(()=>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},exports.createLoggerSignal=createLoggerSignal,exports.debounce=function(e,t){let o=null;return(...n)=>{o&&clearTimeout(o),o=setTimeout(()=>e(...n),t)}},exports.defaultConfig={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}},exports.destroyLogger=function(){i&&(i.destroy(),i=null)},exports.detectFramework=detectFramework,exports.generateLogId=generateLogId,exports.generateSessionId=generateSessionId,exports.getBrowserInfo=getBrowserInfo,exports.getCurrentTimestamp=getCurrentTimestamp,exports.getElementSelector=getElementSelector,exports.getLogger=function(){return i},exports.initLogging=initLogging,exports.initReactLogger=async function(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}},exports.initSolidLogger=async function(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}},exports.isInteractiveElement=isInteractiveElement,exports.loadConfig=loadConfig,exports.log=s,exports.quickStart=async function(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})},exports.sanitizeData=sanitizeData,exports.throttle=function(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)))}},exports.useComponentLogger=useComponentLogger,exports.useLogger=useLogger,exports.useLoggerActions=useLoggerActions,exports.withLogger=function(e,n){const r=n||e.displayName||e.name,WithLoggerComponent=n=>{const i=useComponentLogger(r);return o.useEffect(()=>{"development"===process.env.NODE_ENV&&i.logRender(n)}),t.jsx(e,{...n})};return WithLoggerComponent.displayName=`withLogger(${r})`,WithLoggerComponent},exports.withSolidLogger=function(e,t){const o=t||e.name||"AnonymousComponent";return(...t)=>{const r=createComponentLogger(o);return n.createEffect(()=>{"development"===process.env.NODE_ENV&&r.logRender(t[0])}),e(...t)}};