开发直接更新埋点更新?开发和pm会不会相互扯皮?
优采云 发布时间: 2021-04-06 00:16开发直接更新埋点更新?开发和pm会不会相互扯皮?
埋点自动采集计划概述
简介
自动埋葬点采集计划将分为三章文章,因为涉及的内容很多并且考虑了问题的长度,因此分别进行了解释。
请在2020年11月5日至9日[大专注FE]官方帐户的文章中查看其他两篇文章
这篇文章文章很长,对最终效果感到好奇的学生可以先查看“后台预览”部分的屏幕截图
痛点
购买点,作为跟踪业务启动效果的核心手段
文档也是头等大事,但是许多公司或团队正在以最原创的方式对其进行维护
有些团队甚至拥有统一的掩埋平台,但总体运营成本较高
1)维护费用
每次提出需求时,PM都需要花费大量时间来维护嵌入式点文档
可以添加一个新的埋藏点,只需直接添加即可。
如果对旧的埋藏点进行了任何删除或修改,则必须先与开发班级的同学确认,然后更新文档
如果您担心遇到麻烦,则只能添加文件而不能删除它们。 。你已经知道了很久了〜
2)谁来维护埋藏点文件
如前所述,新添加的功能还可以。主要是删除或更新嵌入点。谁将促进嵌入式点文档的更新?
培养同学来推广pm吗?
pm寻找发展并更新列表吗?
直接开发和更新埋藏点文档吗?
发展中的学生在发展时需要记录和更新列表吗?
开发和pm是否互相争论?
3)没有阻止过程
在整个过程中,仅靠一个角色就很难实现目标
最后,无论是谁去维护它,如果没有阻塞过程,它都会变得有意识。
依靠自我意识,如果能够持续下去,那就死了〜
4)埋点文件不正确
由于先前的原因,埋藏点文档和实际报告代码越来越远。
自然不可能看到它是否花费很长时间,尤其是在人员变更或业务调整方面。
新同学接任后,额头上有三道黑线。
5)发展中的同学有强烈的反抗感
PM:“帮我检查xx项目的埋藏点,我急需它”
PM:“您能帮我检查一下我之前进行的xx个活动的隐患吗?”
PM:“最新需求迭代,更新列表并给我一份副本”
...
尤其是反向计划的项目。
作为一名FE,您有同样的感觉吗?
考虑
无论如何,在线数据都是通过嵌入点反馈的,而业务调整的基础就是数据
这是一个客观事实。
所以必须解决埋入一些文档的痛苦点。
一些学生可能会问,为什么不使用第三方掩埋解决方案(例如:rowingIO,Shence等)
因为,无论采用哪种方案,目前都有两种主流的报告和嵌入点方法:
所有掩埋点的报告(包括区域报告)SDK活动报告(单个掩埋点,多个掩埋点报告)
所有掩埋点的报告要求PM根据页面结构进行配置(主要维护者位于PM中)。页面结构更改后,需要重新配置。
此外,该公司的当前状况是它拥有自己的数据平台,但是如果使用所有隐蔽点进行报告,则数据分析级别以及每个业务线本身将承受非常沉重的负担。使用该代码主动进行报告。
如果sdk主动报告,您将遇到上述问题。
有些学生可能会说:“这是PM所要做的。我仅负责我的部分。”
这没什么错,但是我们仍然希望提高整个团队的效率。
在进行此项目时,我们还与许多团队的pm进行了沟通,维护一个可用的嵌入文档确实会消耗大量的精力
这也让我更加坚定!
项目构想
所有先前的问题,核心是两个:
在小组中进行了许多讨论之后,将问题细分了,相应的解决方案如下:
问题解决方案
维护角色模糊
PM仅提供需要计数的掩埋点,并且更新会自动保持在代码级别
维护成本高
通过jsdoc代码注释,在编译代码时使用代码从文件中提取隐藏点和解释
文档可用性
埋藏点的清除完成,直接向后台报告埋藏点
旧项目访问权限
提供统一的自动注释添加工具
新项目访问权限
将解决方案集成到脚手架中,并同时提供检查加载程序,以确保检查的完整性
业务效率提高
建立埋藏点背景,提供埋藏点和数据预览
看桌子可能仍然很困惑,让我们看一下总体构想图
说明过程:
pm编写掩埋点文档(仅用于开发),然后根据该文档编写和报告逻辑代码,并在联机时执行构建。此时,将触发webpack。掩埋点已从插件中删除。插件已从插件中删除。按下页面以采集其所有埋藏点。向掩埋点服务pm报告后,可以通过掩埋点平台查看掩埋点和相应的数据
这个过程非常清楚,但是必须存在一些问题,所以让我们分别进行解释:
问题1:如何采集掩埋点
我们以vue项目为例,公共报告方法链接在Vue.prototype下:
Vue.prototype。$ log =函数(actionType,备份= null){...}
如果报告的是第pv页,则附加参数为频道号channel,即:
this.$log('PAGE_SHOW', { channel: 'xxx' })
复制代码
解决方案:使用自定义jsdoc插件和自定义标签来采集评论
/**
* @log 页面展现
* @backup channel: 渠道号
*/
this.$log('PAGE_SHOW', { channel: 'xxx' })
复制代码
其中,@ log和@backup是jsdoc的自定义标记,因此jsdoc仅监视$ log方法,还需要显式指定
因此,为了保持整个插件的行为一致,需要引入一个通用的配置文件js_doc.conf.js
js_doc.conf.js
module.exports = {
// 让jsdoc识别 @log
tag: 'log',
// 告知插件this.$log是发送埋点的方法,定义成数组是因为有的项目可能存在多个
method: ['$log'],
// pageType前缀,即会给项目pageType加前缀来区分不同项目
prefix: 'H5BOOK',
// pageType具体生成规则,不同项目可能规则不同
pageTypeGen: function({ prefix, routeName, dir, path, fileName }) {
return (prefix + routeName).toUpperCase();
},
// 公共的backup说明,最终单个埋点backup由公共的和私有的拼接而成
backup: 'uid:用户id',
// 项目信息,埋点上报用
projectInfo: {
projectId: '工程id,一般用项目名称',
projectName: '中文名称',
projectDesc: '项目描述',
projectIsShowOldMark: false // 是否展示老数据
}
}
复制代码
此配置文件由js_doc插件与稍后提到的文件依赖性分析插件以及自动添加嵌入式点注释工具共享。
js_doc插件==的具体实现将在随后的“埋点自动采集方案-埋点提取” ==中具体说明,本文主要说明整个方案的原理
通过此步骤,您可以成功采集每个行为掩埋点以及相应的注释和参数描述,即actionType和相应的注释
当然,要确定一个埋藏点,需要两个核心因素
pageType通常是通过在页面运行时引用当前页面路由来获取的。那是问题。
问题2:如何在==编译时== p
获取pageType
还有一个常见的情况,公共组件,如下所示
组件A被多个页面引用
或者组件A被次要组件B引用,然后直接或间接地引入页面。
然后必须在相应的第1页和第2页中采集组分A中的掩埋点。
那呢?
这个问题等同于成为:
解决方案:
==具体实施计划的这一部分将在“埋点自动采集计划-路线依赖性分析”中详细阐述==
示例:
// 附近的人
export default {
routes: [
// 首页
{
path: '/page1',
name: 'page1',
meta: {
title: '转转活动页',
desc: 'xx首页'
},
component: () => import('../views/page1/index.vue')
},
...
]
}
复制代码
当然,实际情况会非常复杂:
如果写作很复杂,可以通过ast语法分析来兼容,但是确实需要耐心〜
至此,核心信息采集工作已经完成。
上一个jsdoc部分:获得了每个文件的所有actionTypes和相应的注释
这又是一步:项目的所有页面路由引用以及相应的组件文件依赖项
页面描述的value方法:meta.desc || meta.title ||名称||路径
由于页面描述和真实标题不一定相同,因此请单独添加desc字段
考虑一下,我可以使用页面作为单位来嵌入一些有关组织行为的数据吗?
在访问过程中,我们还遇到了一个问题,即
每个业务的pageType生成规则不统一
考虑到此问题,我们在配置文件中定义了以下内容:
module.exports = {
...
// pageType前缀,即会给项目pageType加前缀来区分不同项目
prefix: 'H5BOOK',
// pageType具体生成规则,不同项目可能规则不同
pageTypeGen: function({ prefix, routeName, dir, path, fileName }) {
return (prefix + routeName).toUpperCase();
},
...
}
复制代码
前缀:作为项目的个性化前缀(主要用于区分不同的项目,因为不同的项目可能定义相同的路径)
pageTypeGen:企业使用此方法来定义用于生成pageType的规则。我们使用这些参数将前缀(项目前缀),routeName(路由名称),dir(文件目录),path(路由)和fileName(文件名称)返回给Users,这些参数基本上可以涵盖所有路由生成方法。
确定,最终的数据结构形式:
{
// 项目所有页面
pageList: [
// 单个页面
{
// 该页面的路由信息
routeInfo: {
routeName: 'page1',
description: 'xx首页'
},
// 该页面对应所有的行为埋点
actionList: [
{
actionType: 'PAGE_SHOW',
pageType: 'H5BOOK_page1',
backup: 'channel: 渠道号',
description: '页面展现'
},
...
]
},
...
],
// 项目信息
projectInfo: {
projectId: '项目id',
projectName: '项目名称',
projectDesc: '项目描述信息',
projectMark: '项目标记',
projectLogsMark: '埋点标记',
projectType: '项目类型',
projectIsShowOldMark: false, // 是否展示老的埋点数据,默认false
projectDefBackup: '默认参数说明'
}
}
复制代码
采集掩埋点后,添加项目相关信息,然后通过界面批量报告掩埋点,以将其保存在后台。
后台购买点
我们使用eggjs +猫鼬构建后台服务
使用react + antd + bizChart(图表库)构建的后端系统
背景预览
显示所有自动安葬点采集项目的列表
单击以显示此项目下所有页面(路线)的名称
单击以显示此页面上的所有掩埋点
同时查看过去7天单个埋点的数据趋势
以上是计划的核心部分,但毕竟解决整个计划中的问题的想法是技术驱动的
所以我们还必须关心:如何使整个项目可持续地运行?
问题3:如何确保掩埋点及时更新?
这个问题相对简单。现在已经制作了webpack插件,然后
解决方案:更新构建命令,执行采集并在其联机时报告插件
掩埋点提取插件,在编译webpack后,将在采集掩埋点后自动报告。
保证嵌入文档每次联机时都更新。实时同步文档和代码
问题4:如何快速访问旧项目的掩埋点程序?
访问旧项目的掩埋点对于每个开发来说都是最麻烦的事情,尤其是对掩埋点的注释
为此,我们还提出了一套便捷的解决方案
解决方案:通过命令行工具自动完成注释
我们编写了一个名为autocomment的命令行工具,该工具已全局安装
在项目根目录中执行此命令,该工具将自动在src目录中添加所有.vue,.js和.ts文件。
命令工具和以前的插件使用公共配置文件js_doc.conf.js
module.exports = {
// 让jsdoc识别 @log
tag: 'log',
// 告知插件this.$log是发送埋点的方法,定义成数组是因为有的项目可能存在多个
method: ['$log'],
...
}
复制代码
读取内部的标记和方法属性。
自动将注释添加到形式this。$ log('xxxx',{...}),而无需注释方法
添加之前:
this.$log('PAGE_CLOSE')
复制代码
添加后
/**
* @log autocomment-PAGE_CLOSE
*/
this.$log('PAGE_CLOSE')
复制代码
添加评论的逻辑非常简单:
为什么要添加固定前缀?
因为它允许开发人员快速找出该工具自动添加了哪些注释。
全局搜索“自动注释-”
同时,为了消除学生发展的心理障碍(毕竟,该工具直接更改了源代码,我仍然感到不安)
为此,我们还创建了一个添加摘要页面,该工具将在添加评论后自动弹出。
使用模仿git-history的样式来通知开发班同学我们已经更改了这些位置
问题5:在开发过程中,如何确保遵循将注释添加到嵌入点的规则
由于是以注释的形式采集的,因此发展中的学生很容易忘记写作,所以
解决方案:提供一个监视加载程序以实时检测开发情况
在开发过程中,一旦发现this。$ log()方法被调用且之前没有注释,控制台将直接报告错误
实现方法也是使用ast语法分析,并且仅重用以前的算法。
注意:埋点规范
细心的学生可能还发现此方案确实有一些局限性:
== actionType必须为字符串==
如果它是变量或表达式,则无法正常采集ast。
因此,如果您需要报告接口返回的内容,则可以将该值放在备份中。通过参数描述报告界面
不支持的场景:
// 错误演示1:
const resp = {...}
this.$log(resp.actionType)
// 错误演示2
this.$log(type === 1 ? 'actionType1' : 'actionTyp2')
复制代码
如果遇到这种情况,则需要更改书写方式
// 错误演示1改进:
const resp = {...}
/**
* @log 内容上报
* @backup type: 数据类型
*/
this.$log('respData', { type: resp.actionType })
// 错误演示2改进:
if (type === 1) {
/**
* @log 行为埋点1
*/
this.$log('actionType1')
} else {
/**
* @log 行为埋点2
*/
this.$log('actionType2')
}
复制代码
PS:就代码的美感而言,它看起来并不好。 。 。但是,功能毕竟是最重要的
此外,此程序还==不支持动态添加路由==
当然,支持它并非并非不可能。如有必要,可以将其单独处理。
但是,对于ToC项目,一般的路线定义方法就足够了。
好的,这是自动埋葬点采集程序的核心内容。
结论
在开始时,还与许多业务方面的开发学生深入讨论了该计划
最关注的问题中
每个人面临的情况和合作模式是如此不同,真的没有办法概括
但是我们的初衷是提高协作的整体效率。
至少,它可以节省团队的工作量,以维护文档并考虑更有价值的事情,对吧〜
该解决方案目前在连接的团队中广受好评,并且确实解决了核心难题。
我们相信:技术就是效率,技术和产品应该互相促进!