@error-monitor/sdk
Version:
Monitor SDK - 多平台前端监控SDK解决方案,支持自动环境检测,Web、Taro小程序一站式监控方案
3 lines (2 loc) • 18.2 kB
JavaScript
function e(){return Date.now().toString(36)+Math.random().toString(36).substr(2)}function t(){return Date.now()}function r(){return`session_${Date.now().toString(36)}_${Math.random().toString(36).substr(2,9)}`}function i(e){if(!e)return null;if(e instanceof Error)return{name:e.name,message:e.message,stack:e.stack,...Object.getOwnPropertyNames(e).reduce((t,r)=>(["name","message","stack"].includes(r)||(t[r]=e[r]),t),{})};if("string"==typeof e)return{message:e};try{return JSON.parse(JSON.stringify(e))}catch(t){return{message:String(e)}}}function o(e){if(e&&e.stack)return e.stack.split("\n").filter(e=>e.trim()).slice(0,20).join("\n")}function s(){return"undefined"!=typeof globalThis&&void 0!==globalThis.location&&void 0!==globalThis.document?{url:globalThis.location.href,title:globalThis.document.title,referrer:globalThis.document.referrer}:{url:"",title:"",referrer:""}}function n(){return"undefined"!=typeof globalThis&&void 0!==globalThis.navigator?globalThis.navigator.userAgent:""}class a{constructor(e,t){this.dataQueue=[],this.isInitialized=!1,this.isEnabled=!0,this.listeners=new Map,this.config=this.mergeConfig(e),this.platformAdapter=t,this.sessionId=r()}mergeConfig(e){return this.deepMerge({enableInDev:!1,sampleRate:1,error:{enabled:!0,maxErrors:100,filters:[],sampleRate:1},performance:{enabled:!0,maxPerformance:100,enableResourceTiming:!0,enableUserTiming:!0},behavior:{enabled:!0,maxBehaviors:200,autoTrackClick:!0,autoTrackPageView:!0},report:{interval:1e4,maxQueueSize:500,batchSize:20,timeout:5e3,maxRetries:3,retryDelay:2e3,enableOfflineCache:!0}},e)}deepMerge(e,t){const r={...e};for(const i in t)t.hasOwnProperty(i)&&("object"!=typeof t[i]||null===t[i]||Array.isArray(t[i])?r[i]=t[i]:r[i]=this.deepMerge(e[i]||{},t[i]));return r}async init(){if(!this.isInitialized)if(this.shouldEnable())try{await this.platformAdapter.init(this.config),this.initErrorMonitor(),this.initPerformanceMonitor(),this.initBehaviorMonitor(),this.startReportTimer(),this.isInitialized=!0,this.emit("init",this.getStatus())}catch(e){throw this.emit("error",e),e}else this.isEnabled=!1}shouldEnable(){return!(this.isDevelopment()&&!this.config.enableInDev)&&!(Math.random()>(this.config.sampleRate||1))}isDevelopment(){return("undefined"==typeof process||!process.env)&&("undefined"!=typeof globalThis&&void 0!==globalThis.location&&("localhost"===globalThis.location.hostname||"127.0.0.1"===globalThis.location.hostname))}initErrorMonitor(){var e;(null===(e=this.config.error)||void 0===e?void 0:e.enabled)&&this.platformAdapter.errorCapture.initErrorListeners(e=>{this.addToQueue(e),this.emit("error",e)})}initPerformanceMonitor(){var e;(null===(e=this.config.performance)||void 0===e?void 0:e.enabled)&&this.platformAdapter.performance.initPerformanceMonitor(e=>{this.addToQueue(e),this.emit("performance",e)})}initBehaviorMonitor(){var e;(null===(e=this.config.behavior)||void 0===e?void 0:e.enabled)&&this.platformAdapter.behavior.initBehaviorMonitor(e=>{this.addToQueue(e),this.emit("behavior",e)})}addToQueue(e){var t;if(!this.isEnabled)return;e.projectId=this.config.projectId,e.userId=this.config.userId,e.sessionId=this.sessionId,e.platform=this.platformAdapter.platformInfo.platform,this.config.projectVersion&&(e.projectVersion=this.config.projectVersion),this.config.tags&&(e.tags={...e.tags,...this.config.tags});const r=(null===(t=this.config.report)||void 0===t?void 0:t.maxQueueSize)||500;this.dataQueue.length>=r&&this.dataQueue.shift(),this.dataQueue.push(e),this.emit("dataAdded",e)}startReportTimer(){var e;const t=(null===(e=this.config.report)||void 0===e?void 0:e.interval)||1e4;this.reportTimer=setInterval(()=>{this.flush()},t)}async flush(){var e;if(!this.isEnabled||0===this.dataQueue.length)return;const t=(null===(e=this.config.report)||void 0===e?void 0:e.batchSize)||20,r=this.dataQueue.splice(0,t);try{await this.sendData(r),this.emit("dataReported",r)}catch(e){throw this.dataQueue.unshift(...r),this.emit("reportError",e),e}}async sendData(e){var t,r;const i=`${this.config.serverUrl}/api/monitor/report`,o={timeout:(null===(t=this.config.report)||void 0===t?void 0:t.timeout)||5e3,retries:(null===(r=this.config.report)||void 0===r?void 0:r.maxRetries)||3,headers:this.config.apiKey?{"X-API-Key":this.config.apiKey}:void 0};await this.platformAdapter.network.sendData(i,e,o)}captureError(e,t){var r;if(!(null===(r=this.config.error)||void 0===r?void 0:r.enabled))return;const i=this.platformAdapter.errorCapture.captureError(e,t);this.addToQueue(i)}recordPerformance(e,t){var r;if(!(null===(r=this.config.performance)||void 0===r?void 0:r.enabled))return;const i=this.platformAdapter.performance.recordPerformance(e,t);this.addToQueue(i)}recordBehavior(e,t){var r;if(!(null===(r=this.config.behavior)||void 0===r?void 0:r.enabled))return;const i=this.platformAdapter.behavior.recordBehavior(e,t);this.addToQueue(i)}getStatus(){var e,t,r,i,o;const s=this.dataQueue.filter(e=>"type"in e&&e.type).length,n=this.dataQueue.filter(e=>"metrics"in e).length,a=this.dataQueue.filter(e=>"event"in e).length;return{initialized:this.isInitialized,enabled:this.isEnabled,queue:{size:this.dataQueue.length,maxSize:(null===(e=this.config.report)||void 0===e?void 0:e.maxQueueSize)||500,isFull:this.dataQueue.length>=((null===(t=this.config.report)||void 0===t?void 0:t.maxQueueSize)||500),errorCount:s,performanceCount:n,behaviorCount:a},lastReportTime:Date.now(),errorMonitor:!!(null===(r=this.config.error)||void 0===r?void 0:r.enabled),performanceMonitor:!!(null===(i=this.config.performance)||void 0===i?void 0:i.enabled),behaviorMonitor:!!(null===(o=this.config.behavior)||void 0===o?void 0:o.enabled)}}destroy(){this.isInitialized&&(this.reportTimer&&(clearInterval(this.reportTimer),this.reportTimer=void 0),this.flush().catch(e=>{}),this.platformAdapter.destroy(),this.dataQueue=[],this.listeners.clear(),this.isInitialized=!1,this.isEnabled=!1,this.emit("destroy"))}on(e,t){this.listeners.has(e)||this.listeners.set(e,[]),this.listeners.get(e).push(t)}off(e,t){if(this.listeners.has(e))if(t){const r=this.listeners.get(e),i=r.indexOf(t);i>-1&&r.splice(i,1)}else this.listeners.delete(e)}emit(e,...t){if(!this.listeners.has(e))return!1;return this.listeners.get(e).forEach(e=>{try{e(...t)}catch(e){}}),!0}once(e,t){const r=(...i)=>{this.off(e,r),t(...i)};this.on(e,r)}}var c,l,d;!function(e){e.JS_ERROR="js_error",e.PROMISE_ERROR="promise_error",e.RESOURCE_ERROR="resource_error",e.HTTP_ERROR="http_error",e.CUSTOM_ERROR="custom_error",e.FRAMEWORK_ERROR="framework_error"}(c||(c={})),function(e){e.PAGE_LOAD="page_load",e.HTTP_REQUEST="http_request",e.RESOURCE_LOAD="resource_load",e.USER_INTERACTION="user_interaction",e.CUSTOM_METRIC="custom_metric"}(l||(l={})),function(e){e.PAGE_VIEW="page_view",e.CLICK="click",e.SCROLL="scroll",e.FORM_SUBMIT="form_submit",e.ROUTE_CHANGE="route_change",e.CUSTOM="custom"}(d||(d={}));class u{constructor(){this.listeners=[]}initErrorListeners(e){this.setupGlobalErrorHandler(e),this.setupUnhandledRejectionHandler(e),this.setupResourceErrorHandler(e)}setupGlobalErrorHandler(a){const l=l=>{const d={id:e(),timestamp:t(),projectId:"",sessionId:r(),url:s().url,userAgent:n(),platform:"web",type:c.JS_ERROR,message:l.message,filename:l.filename,lineno:l.lineno,colno:l.colno,stack:l.error?o(l.error):void 0,error:i(l.error)};a(d)};window.addEventListener("error",l),this.listeners.push(()=>window.removeEventListener("error",l))}setupUnhandledRejectionHandler(a){const l=l=>{const d=l.reason,u={id:e(),timestamp:t(),projectId:"",sessionId:r(),url:s().url,userAgent:n(),platform:"web",type:c.PROMISE_ERROR,message:d instanceof Error?d.message:String(d),stack:d instanceof Error?o(d):void 0,error:i(d)};a(u)};window.addEventListener("unhandledrejection",l),this.listeners.push(()=>window.removeEventListener("unhandledrejection",l))}setupResourceErrorHandler(i){const o=o=>{var a,l;const d=o.target;if(!(d&&d!==window&&d instanceof HTMLElement))return;const u=null===(a=d.tagName)||void 0===a?void 0:a.toLowerCase(),h=d.src||d.href;if(!h)return;const m={id:e(),timestamp:t(),projectId:"",sessionId:r(),url:s().url,userAgent:n(),platform:"web",type:c.RESOURCE_ERROR,message:`Failed to load ${u}: ${h}`,filename:h,error:{tagName:u,resourceUrl:h,outerHTML:null===(l=d.outerHTML)||void 0===l?void 0:l.substring(0,200)}};i(m)};window.addEventListener("error",o,!0),this.listeners.push(()=>window.removeEventListener("error",o,!0))}destroyErrorListeners(){this.listeners.forEach(e=>e()),this.listeners=[]}captureError(a,l){return{id:e(),timestamp:t(),projectId:"",sessionId:r(),url:s().url,userAgent:n(),platform:"web",type:c.CUSTOM_ERROR,message:a instanceof Error?a.message:String(a),stack:a instanceof Error?o(a):void 0,error:i(a),...l}}captureHttpError(i){return{id:e(),timestamp:t(),projectId:"",sessionId:r(),url:s().url,userAgent:n(),platform:"web",type:c.HTTP_ERROR,message:`HTTP ${i.status} ${i.statusText}: ${i.method} ${i.url}`,error:{url:i.url,method:i.method,status:i.status,statusText:i.statusText,duration:i.duration}}}}class h{initPerformanceMonitor(e){this.onPerformance=e,this.setupNavigationTiming(),this.setupResourceTiming(),this.setupUserTiming()}setupNavigationTiming(){"undefined"!=typeof performance&&("complete"===document.readyState?this.collectNavigationTiming():window.addEventListener("load",()=>{setTimeout(()=>this.collectNavigationTiming(),0)}))}collectNavigationTiming(){var i;if(!performance.timing)return;const o=performance.timing,a={dnsTime:o.domainLookupEnd-o.domainLookupStart,tcpTime:o.connectEnd-o.connectStart,requestTime:o.responseStart-o.requestStart,responseTime:o.responseEnd-o.responseStart,domParseTime:o.domContentLoadedEventStart-o.domLoading,resourceLoadTime:o.loadEventStart-o.domContentLoadedEventStart,totalTime:o.loadEventEnd-o.navigationStart},c={id:e(),timestamp:t(),projectId:"",sessionId:r(),url:s().url,userAgent:n(),platform:"web",type:l.PAGE_LOAD,metrics:a};null===(i=this.onPerformance)||void 0===i||i.call(this,c)}setupResourceTiming(){performance.getEntriesByType&&(this.observer=new PerformanceObserver(e=>{for(const t of e.getEntries())"resource"===t.entryType&&this.handleResourceEntry(t)}),this.observer.observe({entryTypes:["resource"]}))}handleResourceEntry(i){var o;const a={id:e(),timestamp:t(),projectId:"",sessionId:r(),url:s().url,userAgent:n(),platform:"web",type:l.RESOURCE_LOAD,metrics:{duration:i.duration,size:i.transferSize||0,dnsTime:i.domainLookupEnd-i.domainLookupStart,tcpTime:i.connectEnd-i.connectStart,requestTime:i.responseStart-i.requestStart,responseTime:i.responseEnd-i.responseStart},resource:{name:i.name,size:i.transferSize||0,duration:i.duration,type:this.getResourceType(i.name)}};null===(o=this.onPerformance)||void 0===o||o.call(this,a)}getResourceType(e){var t;const r=null===(t=e.split(".").pop())||void 0===t?void 0:t.toLowerCase();return r?["js","jsx","ts","tsx"].includes(r)?"script":["css","scss","sass","less"].includes(r)?"stylesheet":["png","jpg","jpeg","gif","svg","webp"].includes(r)?"image":["woff","woff2","ttf","otf","eot"].includes(r)?"font":"other":"other"}setupUserTiming(){performance.getEntriesByType&&(this.observer=new PerformanceObserver(e=>{for(const t of e.getEntries())"measure"===t.entryType&&this.handleMeasureEntry(t)}),this.observer.observe({entryTypes:["measure"]}))}handleMeasureEntry(i){var o;const a={id:e(),timestamp:t(),projectId:"",sessionId:r(),url:s().url,userAgent:n(),platform:"web",type:l.USER_INTERACTION,metrics:{duration:i.duration,startTime:i.startTime}};null===(o=this.onPerformance)||void 0===o||o.call(this,a)}destroyPerformanceMonitor(){this.observer&&(this.observer.disconnect(),this.observer=void 0)}recordPerformance(i,o){return{id:e(),timestamp:t(),projectId:"",sessionId:r(),url:s().url,userAgent:n(),platform:"web",type:l.CUSTOM_METRIC,metrics:o}}getPagePerformance(){if(!performance.timing)return{};const e=performance.timing;return{dnsTime:e.domainLookupEnd-e.domainLookupStart,tcpTime:e.connectEnd-e.connectStart,requestTime:e.responseStart-e.requestStart,responseTime:e.responseEnd-e.responseStart,domParseTime:e.domContentLoadedEventStart-e.domLoading,totalTime:e.loadEventEnd-e.navigationStart}}}class m{constructor(){this.listeners=[]}initBehaviorMonitor(e){this.onBehavior=e,this.setupClickTracking(),this.setupPageViewTracking(),this.setupScrollTracking()}setupClickTracking(){const i=i=>{var o,a;const c=i.target,l={id:e(),timestamp:t(),projectId:"",sessionId:r(),url:s().url,userAgent:n(),platform:"web",type:d.CLICK,event:"click",target:this.getElementSelector(c),xpath:this.getElementXPath(c),data:{x:i.clientX,y:i.clientY,tagName:c.tagName,className:c.className,id:c.id,text:null===(o=c.textContent)||void 0===o?void 0:o.substring(0,100)}};null===(a=this.onBehavior)||void 0===a||a.call(this,l)};document.addEventListener("click",i,!0),this.listeners.push(()=>document.removeEventListener("click",i,!0))}setupPageViewTracking(){this.recordPageView();const e=history.pushState,t=history.replaceState;history.pushState=(...t)=>{e.apply(history,t),setTimeout(()=>this.recordPageView(),0)},history.replaceState=(...e)=>{t.apply(history,e),setTimeout(()=>this.recordPageView(),0)};const r=()=>{setTimeout(()=>this.recordPageView(),0)};window.addEventListener("popstate",r),this.listeners.push(()=>{window.removeEventListener("popstate",r),history.pushState=e,history.replaceState=t})}recordPageView(){var i;const o=s(),a={id:e(),timestamp:t(),projectId:"",sessionId:r(),url:o.url,userAgent:n(),platform:"web",type:d.PAGE_VIEW,event:"page_view",data:{title:o.title,referrer:o.referrer}};null===(i=this.onBehavior)||void 0===i||i.call(this,a)}setupScrollTracking(){let i=0;const o=()=>{var o;const a=Date.now();if(a-i<1e3)return;i=a;const c={id:e(),timestamp:t(),projectId:"",sessionId:r(),url:s().url,userAgent:n(),platform:"web",type:d.SCROLL,event:"scroll",data:{scrollTop:window.pageYOffset||document.documentElement.scrollTop,scrollLeft:window.pageXOffset||document.documentElement.scrollLeft,scrollHeight:document.documentElement.scrollHeight,clientHeight:document.documentElement.clientHeight}};null===(o=this.onBehavior)||void 0===o||o.call(this,c)};window.addEventListener("scroll",o,{passive:!0}),this.listeners.push(()=>window.removeEventListener("scroll",o))}getElementSelector(e){if(e.id)return`#${e.id}`;if(e.className){const t=e.className.split(" ").filter(e=>e).join(".");if(t)return`${e.tagName.toLowerCase()}.${t}`}return e.tagName.toLowerCase()}getElementXPath(e){if(e.id)return`//*[@id="${e.id}"]`;const t=[];let r=e;for(;r&&r.nodeType===Node.ELEMENT_NODE;){let e=1,i=r.previousSibling;for(;i;)i.nodeType===Node.ELEMENT_NODE&&i.nodeName===r.nodeName&&e++,i=i.previousSibling;t.unshift(`${r.nodeName.toLowerCase()}[${e}]`),r=r.parentElement}return"/"+t.join("/")}destroyBehaviorMonitor(){this.listeners.forEach(e=>e()),this.listeners=[]}recordBehavior(i,o){return{id:e(),timestamp:t(),projectId:"",sessionId:r(),url:s().url,userAgent:n(),platform:"web",type:d.CUSTOM,event:i,data:o}}}class p{interceptNetwork(e,t,r){this.interceptXHR(e,t,r),this.interceptFetch(e,t,r)}interceptXHR(e,t,r){const i=window.XMLHttpRequest;window.XMLHttpRequest=function(){const o=new i,s=o.open,n=o.send;let a={method:"",url:"",startTime:0,headers:{}};return o.open=function(e,t,r=!0,i,o){return a.method=e,a.url=t,a.startTime=Date.now(),s.call(this,e,t,r,i,o)},o.send=function(i){e(a);return o.addEventListener("load",()=>{var e;const i={...a,status:o.status,statusText:o.statusText,duration:Date.now()-a.startTime,responseSize:(null===(e=o.responseText)||void 0===e?void 0:e.length)||0};o.status>=400?r(i):t(i)}),o.addEventListener("error",()=>r(a)),o.addEventListener("timeout",()=>r({...a,error:"timeout"})),n.apply(this,[i])},o}}interceptFetch(e,t,r){const i=window.fetch;window.fetch=async function(o,s){const n=Date.now(),a={url:"string"==typeof o?o:o.toString(),method:(null==s?void 0:s.method)||"GET",startTime:n,headers:(null==s?void 0:s.headers)||{}};e(a);try{const e=await i(o,s),c={...a,status:e.status,statusText:e.statusText,duration:Date.now()-n};return e.status>=400?r(c):t(c),e}catch(e){throw r({...a,error:e instanceof Error?e.message:String(e)}),e}}}async sendData(e,t,r){const i={method:"POST",headers:{"Content-Type":"application/json",...null==r?void 0:r.headers},body:JSON.stringify(t)};if(null==r?void 0:r.timeout){const e=new AbortController;setTimeout(()=>e.abort(),r.timeout),i.signal=e.signal}const o=await fetch(e,i);if(!o.ok)throw new Error(`HTTP ${o.status}: ${o.statusText}`);return o.json()}}class f{setItem(e,t){try{localStorage.setItem(e,t)}catch(e){}}getItem(e){try{return localStorage.getItem(e)}catch(e){return null}}removeItem(e){try{localStorage.removeItem(e)}catch(e){}}clear(){try{localStorage.clear()}catch(e){}}}class g{constructor(){this.platformInfo={platform:"web",version:"1.0.0",userAgent:n(),deviceInfo:{language:navigator.language,cookieEnabled:navigator.cookieEnabled,onLine:navigator.onLine,screen:{width:screen.width,height:screen.height,colorDepth:screen.colorDepth}}},this.errorCapture=new u,this.performance=new h,this.behavior=new m,this.network=new p,this.storage=new f}init(e){}destroy(){this.errorCapture.destroyErrorListeners(),this.performance.destroyPerformanceMonitor(),this.behavior.destroyBehaviorMonitor()}}class v extends a{constructor(e){super(e,new g)}static init(e){return v.instance||(v.instance=new v(e),v.instance.init().catch(e=>{})),v.instance}static getInstance(){return v.instance}static destroy(){v.instance&&(v.instance.destroy(),v.instance=null)}}v.instance=null;const E={init:e=>v.init(e),setVersionInfo:e=>{v.getInstance()},getInstance:()=>v.getInstance(),captureError:(e,t)=>{const r=v.getInstance();r&&r.captureError(e,t)},recordPerformance:(e,t)=>{const r=v.getInstance();r&&r.recordPerformance(e,t)},recordBehavior:(e,t)=>{const r=v.getInstance();r&&r.recordBehavior(e,t)},flush:async()=>{const e=v.getInstance();e&&await e.flush()},getStatus:()=>{const e=v.getInstance();return e?e.getStatus():null},destroy:()=>v.destroy(),on:(e,t)=>{const r=v.getInstance();r&&r.on(e,t)},off:(e,t)=>{const r=v.getInstance();r&&r.off(e,t)}};"undefined"!=typeof window&&(window.MonitorSDK=E);export{d as BehaviorType,c as ErrorType,l as PerformanceType,v as WebMonitorSDK,E as default};
//# sourceMappingURL=index.esm.js.map