找回密码
 会员注册
查看: 25|回复: 0

埋点自动手机方案-埋点提取

[复制链接]

3

主题

0

回帖

10

积分

新手上路

积分
10
发表于 2024-9-19 21:35:01 | 显示全部楼层 |阅读模式
点击蓝字关注我们,了解更多转转实践简介埋点统计问题一直是业务中非常重要的一环。埋点数据是后期业务分析和技术优化的重要基础。随着业务迭代次数的增多,伴随人员的变动,历史累赘也越来越多,经常PM来找开发同学询问某某功能的埋点是什么。一方面沟通成本高,一方面对开发同学频繁打扰也严重影响开发效率。针对这些问题,我们开发出了一套将项目中分散埋点自动收集、归类、上报、展示的一套系统,来协助相关业务方查看和分析业务数据。主要过程分为路由整理(依赖分析)、埋点提取和上报、展示平台三个部分。这次主要介绍埋点提取和上报部分。埋点标记首先指出的是我们业务中的埋点多是手动埋点,形如:this.$log('page_view', pageType, backup);分布在各个页面和组件中。一个首要维护问题是很多情况下,时间一长,连开发者本身也难以记得这个埋点的意义,以及附带参数的意思了。解决这个问题我们很容易想到通过增加注释的方式来增强可维护性。但是怎么加?这里我们借助于JSDoc这种通用的注释规范,来给我们的埋点做说明。同时通过一个自定义标签来标记这是一个埋点上报。像这样:/* * @log 页面展现 * @backup 参数说明 */this.$log('page_view', pageType, backup);之后,就着手准备收集工作了。埋点处理预处理因此我们的收集也是基于JSDoc来完成的。但在开始之前需要先对我们的源文件进行处理,和我们大多数工程一样,都需要Babel进行转换一下,因为一些高级语法JSDoc同样也不支持,会在在处理过程中语法报错而中断。还使用到了vue-template-compiler将vue中的js代码提取出来。以及对TypeScript的转换。JSDoc的插件写法请查阅官方文档// 一个典型的 JSDoc 插件写法exports.handlers = {  beforeParse: function(e) {    // 对文件预处理  }}标记接下来是自定义我们的标签@logexports.defineTags = function (dictionary) {  // 定义 @log 标签  dictionary.defineTag('log', {    // 声明自定义的tag可以包含文字 像:这里面的name`@param{string}name-Description`    canHaveName: true,    onTagged: function(doclet, tag) {      // 这里保存埋点文字说明      doclet.meta.log = {        name: tag.text      };    },  });  // 定义 @backup 标签  dictionary.defineTag('backup', {    onTagged: function (doclet, tag) {      // 将数 backup 描述存储起来      doclet.backup = doclet.backup || [];      if (tag.value || tag.text) {        doclet.backup.push(tag.value || tag.text);      }    }  });}细心的你也看见了上面除了定义了@log标签还定义了另外一个@backup标签,和上面对应,用于收集埋点的参数说明。这样我们通过JSDoc的自定义标签,将我们的埋点标记了出来。接下来如何把埋点收集成我们可以理解的格式。解析不知道你注意到没有,添加的blockcomment其实原本是用在方法定义上的,但我们这里使用在方法调用上,结果就是JSDoc工具直接忽略了这种类型的注释。好在JSDoc有对应的标签:@name。在注释中添加了@name声明这条注释,指出这条注释具体的含义,以便JSDoc对此进行收集。然后还需要标记出actionType,pageType,这可以通过已有的@param标签来标记。/** * @name 埋点 * @log 页面展现 * @param {string} pageType - pageType 说明 * @param {string} actionType - actionType 说明 * @backup {string} backup - 参数说明 */关键的是如何解析埋点方法中的actionType以及pageType。通常我们遇到的埋点方法调用的情形有:// 一个对象参数log_method({actionType: '', pageType: '', backup: {}});// 一个对象参数,一个字符串参数log_method({actionType: ''}, 'pageType');// 两个对象参数log_method({actionType: ''}, {});// 一个字符串参数log_method('action_type');// 两个字符串参数log_method('action_type', 'page_type');// 三个参数log_method('action_type', 'page_type', {});// 两个参数log_method('action_type', { foo: 'bar' });// 三个参数log_method('action_type', null, {});// 三个参数log_method('action_type', void 0, {});可以看到调用形式很多,而这些使用方式都是项目中已经出现的方式,所以,都要兼容。这么多情况如何准确提取参数并解析呢?还是JSDoc提供了切入点:astNodeVisitor。exports.astNodeVisitor = {  visitNode: function(node, e, parser, currentSourceName) {    // do all sorts of crazy things here  }};这里使用到了AST,前面我们大转转FE(zhuanzhuanfe)公众号文章有介绍过,这里就不再展开讲了,概括地说就是通过AST获取到我们需要的actionType,pageType以及对参数backup的解析。至此,解析问题基本解决了,紧接着就是处理数据了。收集默认情况下JSDoc收集到的注释会按照内置的模板输出为html文件,但我们这里其实并不需要文件预览,只关心数据,后续我们有自己的数据展示平台。所以,数据处理我们通过自定义JSDoc的模板来完成:JSDoc模板的写法:/** * Generate documentation output. * * @param {TAFFY} data - A TaffyDB collection representing *                       all the symbols documented in your code. * @param {object} opts - An object with options information. * @param {Tutorial} tutorials */exports.publish = function(taffyData, opts, tutorials) {  // 我们需要的数据都在 taffyData 中}我们所需要的数据都在taffyData中。在模板中我们需要根据我们的需求处理以下几件事:对PageType这种变化不大的内容提供自定义方法按照路由依赖分析的结果输出埋点(见埋点自动收集方案-路由依赖分析)提供markdown文件输出,方便本地预览重复埋点上报埋点展示平台这些任务就比较常规了,不再赘述。总结过程:配置以上就是埋点收集部分的关键步骤,考虑到不同项目的埋点上报方法的差异,我们提供了配置文件来对埋点方法名、自定义pageType方法、自定义actionType方法、公共backup定义、项目信息等进行定义。详细请参阅使用文档。总结通过借助JSDoc插件,我们完成了由注释到埋点数据的提取工作,这过程中需要了解JSDoc对应的方法,以及对我们本身需求功能点的分解。这也是一个AST和JavaScript注释的一个实际使用场景,希望对各位有所启发。references:关于JSDoc插件 -https://jsdoc.app/about-plugins.htmlastexplorer-https://astexplorer.net/
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-27 00:00 , Processed in 0.943656 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表