当前位置: 首页 > news >正文

asp网站 打开在线制图

asp网站 打开,在线制图,包头市建设局网站,百度一下网页最近在负责团队前端监控系统搭建的任务。因为我们公司有统一的日志存储平台、日志清洗平台和基于 Grafana 搭建的可视化看板#xff0c;就剩日志的采集和上报需要自己实现了#xff0c;所以决定封装一个前端监控 SDK 来完成日志的采集和上报。 架构设计 因为想着以后有机会…最近在负责团队前端监控系统搭建的任务。因为我们公司有统一的日志存储平台、日志清洗平台和基于 Grafana 搭建的可视化看板就剩日志的采集和上报需要自己实现了所以决定封装一个前端监控 SDK 来完成日志的采集和上报。 架构设计 因为想着以后有机会可以把自己封装的 SDK 推广给其他团队使用所以 SDK 在架构设计上就需要有更多的可拓展性。我的想法是把 SDK 根据职责拆解成几个模块然后有一个核心模块来管理所有的模块各团队往不同的模块里添加插件由此实现自身定制化的需求。 我们知道一个前端监控 SDK 它需要完成的任务有日志采集 日志整理 日志上报。所以根据这个工作流我把整个 SDK 分成四个模块 Plugin负责原始数据的采集。Plugin 内部采用插件化的方式去实现不同的插件采集不同的数据。比如如果我们想采集网络请求相关的数据那个可以封装一个专门采集网络请求的插件。Builder负责把原始数据封装成我们想要的数据结构。Reporter负责把数据上报到日志平台。因为考虑到一份数据可能会上报到不同的日志平台所以 Reporter 我也是采用插件化的方式去实现不同的插件上报到不同的日志平台。Manager负责和各模块之间进行通信以及封装一些公共的方法。 综上整个 SDK 的工作流程如下 Manager 建立和各个模块之间的联系。 Plugin 中的某个插件采集到相应的数据并把数据发送给 Manager。 Manager 接收到来自 Plugin 的数据并把数据转发给 Builder。 Builder 接收到数据以后按照预设的数据处理方法对数据进行处理处理完后再把数据发送给 Manager 。 Manager 接收到来自 Builder 的数据并把数据转发给 Reporter 。 Reporter 中的每个插件接收到数据以后会把数据上报到对应的日志平台。 在整个SDK运作的过程中每个模块专注于自己的职责全程只和 Manager 通信不受其他模块的影响。 另外在模块接收或者发送数据的时候都会对外暴露相应的生命周期这样开发者就可以拿到不同阶段的数据并对数据进行自定义处理以及决定是否要中断流程。 模块通信 模块通信我采用的是发布-订阅模式并定义了3个事件assign 注册、receive 接收数据、next 发送数据。 Manager 会订阅 next 事件而其他模块会订阅 assign 事件和 receive 事件。最开始的时候其他模块通过 assign 事件接收到 Manager 的实例由此其他模块就可以使用 Manager 上定义的发布-订阅相关的方法。当数据在某个模块处理完毕后这个模块会发布 next 事件把数据传给 Manager Manager 接收到数据后再发布 receive 事件把数据传给下一个模块。 export class ManagerO extends ManagerConfigType extends EventBus {constructor(config?: O) {super()this.assignPlugins(config.plugins || [])this.assignBuilder(config.builder || {})this.assignReporter(config.reporters || [])this.on(manager:next, this.next.bind(this))this.on(manager:next, this.next.bind(this))}private assignPlugins(plugins: any[]) {plugins.forEach(plugin {this.on(plugin:assign, plugin.init.bind(plugin))})this.emit(plugin:assign, this)}private assignBuilder(builder: any) {this.on(builder:assign, builder.init.bind(builder))this.emit(builder:assign, this)}private assignReporter(reporters: any[]) {reporters.forEach(reporter {this.on(reporter:assign, reporter.init.bind(reporter))})this.emit(reporter:assign, this)}// 从上一级模块接收数据然后发给下一级模块public next(args: { from: plugin | builder | reporter, data: any}) {const { from, data } argsif (from plugin) {this.emit(builder:receive, data)} else if (from builder) {this.emit(reporter:receive, data)}} }export class PluginAO extends PluginAConfigType {public init(manager: any) {this._manager manager}private handleError(msg) {this._manager.emit(manager:next, { from: plugin, data: msg })} }export class BuilderO extends BuilderConfigType {public init(manager: any) {this._manager managerthis._manager.on(builder:receive, this.receive.bind(this))}private receive(data: any) {// 处理数据const newData this.process(data)this._manager.emit(manager:next, { from: builder, data: newData })} }export class ReporterAO extends ReporterAConfigType {public init(manager: any) {this._manager managerthis._manager.on(reporter:receive, this.receive.bind(this))}public receive(args: any) {this.report(args)} }接口请求捕获 在大多数情况下前端通过HTTP的方式和服务端进行交互。不管是自己封装请求方法还是直接使用类似于 axios 的 HTTP 请求库都是需要基于 XHR 和 Fetch 去实现的。所以我们需要重写 XHR 和 Fetch 暴露出来的 Hook 并进行代理由此获得请求相关的信息。 XMLHttpRequest XMLHttpRequest.open() 方法用来初始化一个新创建的请求在这个方法里我们可以拿到请求的 URL 和请求方法。 XMLHttpRequest.send() 方法用来发送HTTP请求在这个方法里我们可以拿到请求参数。 另外在 XMLHttpRequest.onreadystatechange 事件里我们可以监听到请求状态的变化。当 xhr.readyState XMLHttpRequest.DONE 时表示请求操作已经完成这时候我们就可以记录请求的状态码和请求结束的时间。 public overideXHRMethod() {const xhrproto XMLHttpRequest.prototype;const originalOpen xhrproto.openconst originalSend xhrproto.sendxhrproto.send function (this, ...args: any): void {const xhr this;msg {...msg,request: args[0],}return originalSend.apply(xhr, args);}xhrproto.open function (this, ...args: any): void {const xhr this;msg {...msg,url: args[1],method: (args[0] || ).toUpperCase(),statusCode: 0,startTimestamp: Date.now() // 请求开始时间}const onreadystatechangeHandler function (): void {if (xhr.readyState XMLHttpRequest.DONE) {try {msg.statusCode xhr.statusmsg.endTimestamp Date.now() // 请求结束时间msg.responseHeaders xhr.getAllResponseHeaders()if ([, json, text].indexOf(xhr.responseType) ! -1) {msg.response typeof xhr.response object ? JSON.stringify(xhr.response) : xhr.response}} catch (e) {/* do nothing */}}}if (onreadystatechange in xhr typeof xhr.onreadystatechange function) {const original xhr.onreadystatechangexhr.onreadystatechange function (...readyStateArgs: any): void {onreadystatechangeHandler();return original.apply(xhr, readyStateArgs);}} else {xhr.addEventListener(readystatechange, onreadystatechangeHandler);}return originalOpen.apply(xhr, args);}}如果想获取响应头可以使用方法 XMLHttpRequest.getAllResponseHeaders() 和 XMLHttpRequest.getResponseHeader() 。不过这两个方法并不能拿到所有的响应头信息对于跨域的请求只能拿到以下几个字段 Cache-ControlContent-LanguageContent-LengthContent-TypeExpiresLast-ModifiedPragma 如果想拿到其他字段需要在响应头 Access-Control-Expose-Headers 里指定哪些字段是可以公开的。 Fetch window.fetch() 方法用来发起获取资源的请求它的第一个参数为请求的 URL第二个参数为 Request 对象。它返回一个 promise这个 promise 会在请求响应后被 resolve并传回 Response 对象。 public overideFetchMethod() {const originalFetch window.fetchif (!originalFetch) {return}window.fetch function(...args) {const method String(args[1]?.method || get).toUpperCase()const url String(args[0])return originalFetch.apply(window, args).catch((err: Error) {let msg: ReportMsgType {url,method: method}throw err})}}因为公司的项目里很少用到由 Fetch 发起的请求所以这里写的比较简单。 JS错误捕获 对于那些可预见的 JS 错误通常我们通过 try/catch 去捕获。其他的 JS 错误我们可以通过全局监听 error 事件来捕获。另外值得一提的是对于 Promise 中的错误如果我们有用 reject 去处理错误那么会触发 rejectionhandled 事件否则会触发 unhandledrejection 事件。 private handleError(event: ErrorEvent | PromiseRejectionEvent) {const error error in event ? event.error : event.reasonconst msg: ReportMsgType {name: browserError,catchBy: PluginBrowser,error}}private initMonitor() {window.addEventListener(error, this.handleError.bind(this))window.addEventListener(unhandledrejection, this.handleError.bind(this))}资源加载错误捕获 常见的前端资源加载包括图片的渲染和外部文件的引用我们可以通过监听 img、link 和 script 标签的 error 事件来捕获这些资源的加载错误。 const resourceTagName: string[] [img, script, link]export class PluginResourceO extends ResourceConfigType {private handleError(event: Event) {const target event.target as HTMLScriptElement | HTMLLinkElementif (!target) {return}const tagName (target.tagName || ).toLowerCase()const isResource resourceTagName.includes(tagName)if (!isResource) {return}const msg: ReportMsgType {name: ResourceLoadError,catchBy: PluginResource,url: src in target ? target.src : target.href,tagName: tagName}}private initMonitor() {window.addEventListener(error, this.handleError.bind(this), true)} }最后 目前整个 SDK 还处于很初级的阶段能完成常见错误类型的捕获和上报后续随着需求的增加 SDK 需要实现更多的功能希望后续再更新一波~
http://www.zqtcl.cn/news/672097/

相关文章:

  • 采购需求网站建设呼伦贝尔网站开发
  • 东莞网站建设方案服务极速网站建设定制价格
  • 网站建设费记账福州百度网络推广
  • 中国农村建设网站邵阳房产网
  • 做非法网站网站上海备案查询
  • 网站制作要学哪些北京信管局 网站备案
  • 百度新闻源网站有哪些wordpress怎么配置七牛cdn加速
  • 山东城乡住房建设厅网站wordpress 购物网站主题
  • 石家庄制作网站查网站流量查询工具
  • 信誉好的永州网站建设静态网站的短处
  • wordpress主题汉化软件河南网站优化哪家好
  • 关于水果的网站建设前端页面设计
  • 随州网站推广哪家好河南网站seo营销多少费用
  • 重庆网站优化排名软件方案谁能做网站开发
  • 河南官网网站建设报价app网站制作多少钱
  • 做网站页面一般用什么软件网站建设项目说明书
  • 做国外lead应该做什么网站网站运营报告
  • 建立一个自己的网站需要多少钱我的世界查找建筑网站
  • 广州网站建设互广做响应式网站设计图是多大的
  • 网站建设 运维 管理包括建大网站首页
  • 快手做任务网站python基础教程作者
  • 网站添加 百度商桥企信网查询
  • 用易语言可以做网站吗西安外贸网站开发
  • 常用网站推广方法电商便捷的网站建设平台
  • 做网站免费的app是什么免费公司注册
  • 做平面素材比较好的网站网络系统设计的步骤
  • 西安网站建设 乐云seo全国旅游景点网站开源
  • 中山快速做网站价格网站投稿源码
  • 免费网站建设教程青岛网站建设收费哪个平台好
  • 关于网站建设外文文献金蝶软件多少钱一套