logbeacon
Version:
浏览器端日志采集与上报工具,支持多种日志服务后端,包括阿里云日志服务(SLS)和Grafana Loki
3 lines (2 loc) • 14.7 kB
JavaScript
;var commonjsGlobal="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function getDefaultExportFromCjs(x){return x&&x.__esModule&&Object.prototype.hasOwnProperty.call(x,"default")?x.default:x}var loglevel$1={exports:{}};!function(module){var root,definition;root=commonjsGlobal,definition=function(){var noop=function(){},isIE="undefined"!=typeof window&&void 0!==window.navigator&&/Trident\/|MSIE /.test(window.navigator.userAgent),logMethods=["trace","debug","info","warn","error"],_loggersByName={},defaultLogger=null;function bindMethod(obj,methodName){var method=obj[methodName];if("function"==typeof method.bind)return method.bind(obj);try{return Function.prototype.bind.call(method,obj)}catch(e){return function(){return Function.prototype.apply.apply(method,[obj,arguments])}}}function traceForIE(){console.log&&(console.log.apply||Function.prototype.apply.apply(console.log,[console,arguments])),console.trace}function replaceLoggingMethods(){for(var level=this.getLevel(),i=0;i<logMethods.length;i++){var methodName=logMethods[i];this[methodName]=i<level?noop:this.methodFactory(methodName,level,this.name)}if(this.log=this.debug,"undefined"==typeof console&&level<this.levels.SILENT)return"No console available for logging"}function enableLoggingWhenConsoleArrives(methodName){return function(){"undefined"!=typeof console&&(replaceLoggingMethods.call(this),this[methodName].apply(this,arguments))}}function defaultMethodFactory(methodName,_level,_loggerName){return function(methodName){return"debug"===methodName&&(methodName="log"),"undefined"!=typeof console&&("trace"===methodName&&isIE?traceForIE:void 0!==console[methodName]?bindMethod(console,methodName):void 0!==console.log?bindMethod(console,"log"):noop)}(methodName)||enableLoggingWhenConsoleArrives.apply(this,arguments)}function Logger(name,factory){var inheritedLevel,defaultLevel,userLevel,self=this,storageKey="loglevel";function getPersistedLevel(){var storedLevel;if("undefined"!=typeof window&&storageKey){try{storedLevel=window.localStorage[storageKey]}catch(ignore){}if(void 0===storedLevel)try{var cookie=window.document.cookie,cookieName=encodeURIComponent(storageKey),location=cookie.indexOf(cookieName+"=");-1!==location&&(storedLevel=/^([^;]+)/.exec(cookie.slice(location+cookieName.length+1))[1])}catch(ignore){}return void 0===self.levels[storedLevel]&&(storedLevel=void 0),storedLevel}}function normalizeLevel(input){var level=input;if("string"==typeof level&&void 0!==self.levels[level.toUpperCase()]&&(level=self.levels[level.toUpperCase()]),"number"==typeof level&&level>=0&&level<=self.levels.SILENT)return level;throw new TypeError("log.setLevel() called with invalid level: "+input)}"string"==typeof name?storageKey+=":"+name:"symbol"==typeof name&&(storageKey=void 0),self.name=name,self.levels={TRACE:0,DEBUG:1,INFO:2,WARN:3,ERROR:4,SILENT:5},self.methodFactory=factory||defaultMethodFactory,self.getLevel=function(){return null!=userLevel?userLevel:null!=defaultLevel?defaultLevel:inheritedLevel},self.setLevel=function(level,persist){return userLevel=normalizeLevel(level),!1!==persist&&function(levelNum){var levelName=(logMethods[levelNum]||"silent").toUpperCase();if("undefined"!=typeof window&&storageKey){try{return void(window.localStorage[storageKey]=levelName)}catch(ignore){}try{window.document.cookie=encodeURIComponent(storageKey)+"="+levelName+";"}catch(ignore){}}}(userLevel),replaceLoggingMethods.call(self)},self.setDefaultLevel=function(level){defaultLevel=normalizeLevel(level),getPersistedLevel()||self.setLevel(level,!1)},self.resetLevel=function(){userLevel=null,function(){if("undefined"!=typeof window&&storageKey){try{window.localStorage.removeItem(storageKey)}catch(ignore){}try{window.document.cookie=encodeURIComponent(storageKey)+"=; expires=Thu, 01 Jan 1970 00:00:00 UTC"}catch(ignore){}}}(),replaceLoggingMethods.call(self)},self.enableAll=function(persist){self.setLevel(self.levels.TRACE,persist)},self.disableAll=function(persist){self.setLevel(self.levels.SILENT,persist)},self.rebuild=function(){if(defaultLogger!==self&&(inheritedLevel=normalizeLevel(defaultLogger.getLevel())),replaceLoggingMethods.call(self),defaultLogger===self)for(var childName in _loggersByName)_loggersByName[childName].rebuild()},inheritedLevel=normalizeLevel(defaultLogger?defaultLogger.getLevel():"WARN");var initialLevel=getPersistedLevel();null!=initialLevel&&(userLevel=normalizeLevel(initialLevel)),replaceLoggingMethods.call(self)}(defaultLogger=new Logger).getLogger=function(name){if("symbol"!=typeof name&&"string"!=typeof name||""===name)throw new TypeError("You must supply a name when creating a logger.");var logger=_loggersByName[name];return logger||(logger=_loggersByName[name]=new Logger(name,defaultLogger.methodFactory)),logger};var _log="undefined"!=typeof window?window.log:void 0;return defaultLogger.noConflict=function(){return"undefined"!=typeof window&&window.log===defaultLogger&&(window.log=_log),defaultLogger},defaultLogger.getLoggers=function(){return _loggersByName},defaultLogger.default=defaultLogger,defaultLogger},module.exports?module.exports=definition():root.log=definition()}(loglevel$1);var loglevel=getDefaultExportFromCjs(loglevel$1.exports);const ARRAY_SAMPLING_CONFIG={primitive:{threshold:20,head:10,tail:4,middle:3},complex:{threshold:10,head:5,tail:3,middle:2}},browserTypeHandlers=new Map;function serializeLogContent(content){const serializableObject=serializeSingleValue(content);try{const result=JSON.stringify(serializableObject);return result.length>1e5?result.slice(0,1e5)+"...":result}catch(e){return`[序列化失败: ${e.message}]`}}function serializeSingleValue(value,options={maxDepth:10,sensitiveKeys:["password","token","secret","auth"]},currentDepth=0,seen=new WeakSet){const{maxDepth:maxDepth,sensitiveKeys:sensitiveKeys}=options,type=typeof value;if(null===value||["string","number","boolean","undefined"].includes(type))return value;if("bigint"===type)return`${value.toString()}n`;if("symbol"===type)return value.toString();if("function"===type)return`[Function: ${value.name||"anonymous"}]`;if("object"==typeof value){if(seen.has(value))return"[循环引用]";seen.add(value)}if(currentDepth>=maxDepth)return`[达到最大深度: ${Object.prototype.toString.call(value)}]`;for(const[typeConstructor,handler]of browserTypeHandlers.entries())if(value instanceof typeConstructor)return handler(value,options,currentDepth,seen);if(value instanceof Error)return`${value.name}: ${value.message}\nStack: ${value.stack||""}`;if(value instanceof Date)return value.toISOString();if(value instanceof RegExp)return value.toString();if("undefined"!=typeof Map&&value instanceof Map){const obj={};for(const[k,v]of value.entries()){obj["object"==typeof k&&null!==k?"[object]":String(k)]=serializeSingleValue(v,options,currentDepth+1,seen)}return obj}if("undefined"!=typeof Set&&value instanceof Set){const arr=[];for(const v of value.values())arr.push(serializeSingleValue(v,options,currentDepth+1,seen));return arr}if(Array.isArray(value)){const rules=value.length>0&&"object"==typeof value[0]&&null!==value[0]?ARRAY_SAMPLING_CONFIG.complex:ARRAY_SAMPLING_CONFIG.primitive;if(value.length<=rules.threshold)return value.map((item=>serializeSingleValue(item,options,currentDepth+1,seen)));const sampledResult={_t:"arr",_l:value.length,_e:{}},indices=new Set;for(let i=0;i<rules.head&&i<value.length;i++)indices.add(i);for(let i=0;i<rules.tail&&value.length-1-i>=0;i++)indices.add(value.length-1-i);const midStart=Math.floor(value.length/2-rules.middle/2);for(let i=0;i<rules.middle&&midStart+i<value.length;i++)indices.add(midStart+i);const sortedIndices=Array.from(indices).sort(((a,b)=>a-b));for(const index of sortedIndices)sampledResult._e[index]=serializeSingleValue(value[index],options,currentDepth+1,seen);return sampledResult}if("undefined"!=typeof window&&value instanceof window.Element)return`<${value.tagName.toLowerCase()} class="${value.className}" id="${value.id}">`;if("object"==typeof value&&null!==value){if("function"==typeof value.toJSON)return serializeSingleValue(value.toJSON(),options,currentDepth+1,seen);const result={};for(const key of Object.keys(value))sensitiveKeys.includes(key.toLowerCase())?result[key]="[敏感信息已过滤]":result[key]=serializeSingleValue(value[key],options,currentDepth+1,seen);return result}return String(value)}function getOrCreateUUID(){if("undefined"==typeof window)return"";const key="_client_uuid";let uuid=window.localStorage.getItem(key);return uuid||(window.crypto&&window.crypto.randomUUID?(uuid=window.crypto.randomUUID(),window.localStorage.setItem(key,uuid)):(uuid=function(){let uuid="";for(let i=0;i<32;i++)uuid+=12===i?"4":16===i?"0123456789abcdef"[8+Math.floor(4*Math.random())]:"0123456789abcdef"[Math.floor(16*Math.random())];return[uuid.substring(0,8),uuid.substring(8,12),uuid.substring(12,16),uuid.substring(16,20),uuid.substring(20,32)].join("-")}(),window.localStorage.setItem(key,uuid))),uuid}function getOrCreateSessionId(){if("undefined"==typeof window)return"";const key="_session_id";let sessionId=window.sessionStorage.getItem(key);return sessionId||(sessionId=function(){let uuid;if("undefined"!=typeof crypto&&crypto.randomUUID)uuid=crypto.randomUUID();else{const hexChars="0123456789ABCDEF";uuid="";for(let i=0;i<32;i++)uuid+=hexChars[Math.floor(16*Math.random())]}return uuid.replace(/-/g,"").toUpperCase().substring(0,16)}(),window.sessionStorage.setItem(key,sessionId)),sessionId}async function sendEvent(msg){try{const serviceWorker=await async function(scope="/beacon/"){if(!navigator.serviceWorker)return null;try{const swRegistration=(await navigator.serviceWorker.getRegistrations()).find((reg=>reg.scope.includes(scope)));if(!swRegistration)return null;if(swRegistration.active)return swRegistration.active;if(swRegistration.installing&&swRegistration.waiting)return null;const worker=swRegistration.installing||swRegistration.waiting;if(!worker)return null;const waitForActivation=new Promise(((resolve,reject)=>{worker.addEventListener("statechange",(function(){"activated"===this.state?resolve(swRegistration.active):"redundant"===this.state&&reject(new Error("Service Worker installation failed"))}))})),timeout=new Promise(((_,reject)=>{setTimeout((()=>reject(new Error("Service Worker activation timeout"))),6e4)}));return await Promise.race([waitForActivation,timeout])}catch(e){return null}}("/beacon/");if(serviceWorker)serviceWorker.postMessage(msg);else{const event=new CustomEvent("sendLog",{detail:msg});window.dispatchEvent(event)}}catch(e){}}async function sendLog(level,logs){if("undefined"==typeof window)return;const extraInfo=function(){if("undefined"==typeof window||void 0===window.document)return{};const extendedAttributes={};if(window.LOGS_CONTEXT&&"object"==typeof window.LOGS_CONTEXT)for(const[key,value]of Object.entries(window.LOGS_CONTEXT))"string"==typeof value&&value.trim().length>0&&(extendedAttributes[key]=value);return{time:Date.now(),clientUuid:getOrCreateUUID(),userAgent:window.navigator.userAgent,screen:JSON.stringify(serializeSingleValue({width:window.screen.width,height:window.screen.height})),window:JSON.stringify(serializeSingleValue({width:window.innerWidth,height:window.innerHeight})),url:window.location.href,referrer:document.referrer,sessionId:getOrCreateSessionId(),extendedAttributes:extendedAttributes}}();sendEvent({type:"log",payload:{level:level,content:serializeLogContent(logs),...extraInfo}})}"undefined"!=typeof window&&(browserTypeHandlers.set(window.ErrorEvent,((value,options,currentDepth,seen)=>({_t:"ErrorEvent",message:value.message,filename:value.filename,lineno:value.lineno,colno:value.colno,error:serializeSingleValue(value.error,options,currentDepth+1,seen)}))),browserTypeHandlers.set(window.PromiseRejectionEvent,((value,options,currentDepth,seen)=>({_t:"PromiseRejectionEvent",reason:serializeSingleValue(value.reason,options,currentDepth+1,seen)}))),browserTypeHandlers.set(window.MessageEvent,((value,options,currentDepth,seen)=>({_t:"MessageEvent",data:serializeSingleValue(value.data,options,currentDepth+1,seen),origin:value.origin,lastEventId:value.lastEventId,source:"[WindowProxy]"}))),browserTypeHandlers.set(window.CloseEvent,((value,options,currentDepth,seen)=>({_t:"CloseEvent",code:value.code,reason:value.reason,wasClean:value.wasClean}))),browserTypeHandlers.set(window.CustomEvent,((value,options,currentDepth,seen)=>({_t:"CustomEvent",type:value.type,detail:serializeSingleValue(value.detail,options,currentDepth+1,seen),bubbles:value.bubbles,cancelable:value.cancelable,composed:value.composed}))),browserTypeHandlers.set(window.KeyboardEvent,((value,options,currentDepth,seen)=>({_t:"KeyboardEvent",type:value.type,key:value.key,code:value.code,ctrlKey:value.ctrlKey,shiftKey:value.shiftKey,altKey:value.altKey,metaKey:value.metaKey,repeat:value.repeat,bubbles:value.bubbles,cancelable:value.cancelable}))),browserTypeHandlers.set(window.InputEvent,((value,options,currentDepth,seen)=>({_t:"InputEvent",type:value.type,inputType:value.inputType,data:value.data,isComposing:value.isComposing,bubbles:value.bubbles,cancelable:value.cancelable}))),browserTypeHandlers.set(window.StorageEvent,((value,options,currentDepth,seen)=>({_t:"StorageEvent",type:value.type,key:value.key,newValue:value.newValue,oldValue:value.oldValue,url:value.url,storageArea:"[Storage]",bubbles:value.bubbles,cancelable:value.cancelable}))));const extendLoglevel={setKeyWords(keyWords){"undefined"!=typeof window&&"string"==typeof keyWords&&window.localStorage.setItem("_logFilterKeyWords",keyWords)},getKeyWords:()=>"undefined"==typeof window?"":window.localStorage.getItem("_logFilterKeyWords"),getOrCreateUUID:getOrCreateUUID},LOG_METHODS=["trace","debug","info","warn","error"],log=new Proxy(loglevel,{get(target,prop){const orig=target[prop];return"function"==typeof orig?(fnName=prop,new Proxy(orig,{apply:(target,thisArg,argumentsList)=>{if(!LOG_METHODS.includes(fnName))return target.apply(thisArg,argumentsList);if("undefined"!=typeof window&&sendLog(fnName,argumentsList),"string"!=typeof argumentsList[0])return target.apply(thisArg,argumentsList);const keyWords=extendLoglevel.getKeyWords();return keyWords?argumentsList[0].startsWith(keyWords)?target.apply(thisArg,argumentsList):void 0:target.apply(thisArg,argumentsList)}})):Object.keys(extendLoglevel).includes(prop)?extendLoglevel[prop]:orig;var fnName}});if("undefined"==typeof window){let logLevel="undefined"!=typeof process&&process.env&&process.env.LOGS_LEVEL;logLevel=logLevel||loglevel.levels.TRACE,loglevel.setLevel(logLevel)}module.exports=log;
//# sourceMappingURL=logs.cjs.map