Skip to content

Commit eab90fb

Browse files
Prepare for release 1.0.0
1 parent ef560ec commit eab90fb

51 files changed

Lines changed: 865 additions & 218 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Tracker is a lightweight tracking framework based on [the tracking idea of Buzzv
88

99
## Tracking idea
1010

11-
- [Why use chain of responsibility tracking?](https://dylancaicoding.github.io/Tracker/#/idea)
11+
[Why use chain of responsibility tracking?](https://dylancaicoding.github.io/Tracker/#/idea)
1212

1313
## Sample
1414

@@ -39,7 +39,7 @@ dependencies {
3939

4040
### Usage
4141

42-
See the documentation for [Java usage](https://dylancaicoding.github.io/Tracker/#/java).
42+
> See the documentation for [Java usage](https://dylancaicoding.github.io/Tracker/#/java).
4343
4444
#### Initialization
4545

@@ -64,15 +64,15 @@ trackNode = TrackNode("channel_name" to "recommend")
6464
```
6565

6666
```kotlin
67-
holder.itemView.trackNode = TrackNode("video_id" to item.id)
67+
holder.itemView.trackNode = TrackNode("video_id" to item.id, "video_type" to item.type)
6868
```
6969

7070
#### Establish a page source responsibility chain
7171

72-
When starting an activity, you need to call `intent.setReferrerTrackNode(activity/fragment/view)` to set the source node.
72+
When starting an activity, you need to call `intent.putReferrerTrackNode(activity/fragment/view)` to set the source node.
7373

7474
```kotlin
75-
val intent = Intent(activity, DetailsActivity::class.java).setReferrerTrackNode(view)
75+
val intent = Intent(activity, DetailsActivity::class.java).putReferrerTrackNode(view)
7676
activity.startActivity(intent)
7777
```
7878

@@ -102,27 +102,27 @@ view.postTrack("click_favorite")
102102
In the activity, you can set up a thread node, which can share the tracking parameter between views or pages.
103103

104104
```kotlin
105-
class ResultThreadNode : TrackNode {
106-
var result: String? = null
105+
class RecordTrackNode : TrackNode {
106+
var isRecord = false
107107

108108
override fun fillTackParams(params: TrackParams) {
109-
result?.let { params.put("result", it) }
109+
params.put("is_record", it)
110110
}
111111
}
112112

113-
activity.putTrackThreadNode(ResultThreadNode())
113+
activity.putThreadTrackNode(RecordTrackNode())
114114
```
115115

116116
You can then update the parameters of the thread node in Activity, Fragment, View.
117117

118118
```kotlin
119-
view.updateTrackThreadNode<ResultThreadNode> { result = "success" }
119+
view.updateThreadTrackNode<RecordTrackNode> { isRecord = true }
120120
```
121121

122122
Declare the thread node class when reporting.
123123

124124
```kotlin
125-
view.postTrack("click_favorite", ResultThreadNode::class.java)
125+
view.postTrack("click_publish", RecordTrackNode::class.java)
126126
```
127127

128128
## Author's other libraries

README_ZH.md

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
[![](https://www.jitpack.io/v/DylanCaiCoding/Tracker.svg)](https://www.jitpack.io/#DylanCaiCoding/Tracker) [![](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](https://github.com/DylanCaiCoding/Tracker/blob/master/LICENSE)
66

7-
Tracker 是基于[西瓜视频责任链的埋点思路](https://mp.weixin.qq.com/s/iMn--4FNugtH26G90N1MaQ)实现的轻量级埋点框架。个人理解其核心思想后进行改进和优化,最后使用了不到 200 行代码(不含注释)实现,整体更加简洁易用,同时兼顾了 Kotlin 和 Java 的用法
7+
Tracker 是基于[西瓜视频责任链的埋点思路](https://mp.weixin.qq.com/s/iMn--4FNugtH26G90N1MaQ)实现的轻量级埋点框架。个人理解其核心思想后进行了改进和优化,最后使用了不到 200 行代码(不含注释)实现,学习成本更低,并且兼顾了 Kotlin 和 Java 用法
88

99
## 埋点思路
1010

11-
- [为什么使用责任链的埋点方案?](https://dylancaicoding.github.io/Tracker/#/idea)
11+
[为什么使用责任链的埋点方案?](https://dylancaicoding.github.io/Tracker/#/idea)
1212

1313
## 示例
1414

@@ -39,7 +39,7 @@ dependencies {
3939

4040
### 用法
4141

42-
[Java 用法](https://dylancaicoding.github.io/Tracker/#/java) 请查看文档。
42+
> [Java 用法](https://dylancaicoding.github.io/Tracker/#/java) 请查看文档。
4343
4444
#### 初始化
4545

@@ -57,26 +57,26 @@ class UMTrackHandler : TrackHandler {
5757
}
5858
```
5959

60-
#### 建立页面上下级责任链
60+
#### 建立页面内上下级责任链
6161

62-
Activity、FragmentView 设置埋点节点 `trackNode` 添加埋点参数。
62+
可以给 Activity、FragmentView 设置埋点节点 `trackNode` 添加埋点参数。
6363

6464
```kotlin
6565
trackNode = TrackNode("channel_name" to "recommend")
6666
```
6767

6868
```kotlin
69-
holder.itemView.trackNode = TrackNode("video_id" to item.id)
69+
holder.itemView.trackNode = TrackNode("video_id" to item.id, "video_type" to item.type)
7070
```
7171

7272
通过视图树的层级关系(比如:`Activity -> Fragment -> ViewHolder -> Button`)就能建立节点的上下级责任链关系。
7373

7474
#### 建立页面来源责任链
7575

76-
页面跳转时需要调用 `intent.setReferrerTrackNode(activity/fragment/view)` 设置来源节点。
76+
页面跳转时需要调用 `intent.putReferrerTrackNode(activity/fragment/view)` 设置来源节点。
7777

7878
```kotlin
79-
val intent = Intent(activity, DetailsActivity::class.java).setReferrerTrackNode(view)
79+
val intent = Intent(activity, DetailsActivity::class.java).putReferrerTrackNode(view)
8080
activity.startActivity(intent)
8181
```
8282

@@ -86,7 +86,7 @@ activity.startActivity(intent)
8686
trackNode = PageTrackNode("page_name" to "details")
8787
```
8888

89-
`PageTrackNode` 会将前面所有节点的参数添加进节点中,添加的时候可以设置一些转换规则。比如上个页面的 `page_name`,跳转后上报 `from_page`
89+
`PageTrackNode` 会添加前面所有节点的参数,添加的时候可以设置一些转换规则。比如上个页面的 `page_name`,跳转后上报 `from_page`
9090

9191
```kotlin
9292
val referrerKeyMap = mapOf("page_name" to "from_page", "channel_name" to "from_channel_name")
@@ -103,34 +103,38 @@ view.postTrack("click_favorite")
103103

104104
#### 线索节点
105105

106-
线索节点适合用于具有会话特性的流程中,方便在流程中共享参数,常见的有登录、注册的流程订单创建流程等。
106+
线索节点适合用于具有会话特性的流程中,方便在流程中共享参数,常见的有登录、注册的流程订单创建流程等。
107107

108108
在 Activity 可以设置线索节点,线索节点能在 View 或页面之间共享埋点参数。
109109

110110
```kotlin
111-
class ResultThreadNode : TrackNode {
112-
var result: String? = null
111+
class RecordTrackNode : TrackNode {
112+
var isRecord = false
113113

114114
override fun fillTackParams(params: TrackParams) {
115-
result?.let { params.put("result", it) }
115+
params.put("is_record", it)
116116
}
117117
}
118118

119-
activity.putTrackThreadNode(ResultThreadNode())
119+
activity.putThreadTrackNode(RecordTrackNode())
120120
```
121121

122122
之后就能在 Activity、Fragment、View 更新线索节点中的参数。
123123

124124
```kotlin
125-
view.updateTrackThreadNode<ResultThreadNode> { result = "success" }
125+
view.updateThreadTrackNode<RecordTrackNode> { isRecord = true }
126126
```
127127

128128
上报的时候需要对线索节点进行声明才会收集参数。
129129

130130
```kotlin
131-
view.postTrack("click_favorite", ResultThreadNode::class.java)
131+
view.postTrack("click_publish", RecordTrackNode::class.java)
132132
```
133133

134+
## 反馈
135+
136+
有问题可以提 [issues](https://github.com/DylanCaiCoding/Tracker/issues) 或加个人微信 `DylanCaiCoding`直接反馈。
137+
134138
## 作者其它的库
135139

136140
|| 简介 |

docs/README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
[![](https://www.jitpack.io/v/DylanCaiCoding/Tracker.svg)](https://www.jitpack.io/#DylanCaiCoding/Tracker) [![](https://img.shields.io/badge/License-Apache--2.0-blue.svg)](https://github.com/DylanCaiCoding/Tracker/blob/master/LICENSE)
44

5-
Tracker 是基于[西瓜视频责任链的埋点思路](https://mp.weixin.qq.com/s/iMn--4FNugtH26G90N1MaQ)实现的轻量级埋点框架。个人理解其核心思想后进行改进和优化,最后使用了不到 200 行代码(不含注释)实现,整体更加简洁易用,同时兼顾了 Kotlin 和 Java 的用法
5+
Tracker 是基于[西瓜视频责任链的埋点思路](https://mp.weixin.qq.com/s/iMn--4FNugtH26G90N1MaQ)实现的轻量级埋点框架。个人理解其核心思想后进行了改进和优化,最后使用了不到 200 行代码(不含注释)实现,学习成本更低,并且兼顾了 Kotlin 和 Java 用法
66

77
### 埋点思路
88

9-
- [为什么使用责任链的埋点方案?](/idea)
9+
[为什么使用责任链的埋点方案?](/idea)
1010

1111
### 示例
1212

@@ -38,6 +38,10 @@ dependencies {
3838
- [Kotlin 用法](/kotlin)
3939
- [Java 用法](/java)
4040

41+
### 反馈
42+
43+
有问题可以提 [issues](https://github.com/DylanCaiCoding/Tracker/issues) 或加个人微信 `DylanCaiCoding`直接反馈。
44+
4145
### 作者其它的库
4246

4347
|| 简介 |

docs/idea.md

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1+
## 责任链埋点思路
2+
13
### 埋点需求
24

35
行为分析埋点通常需要包括某一事件发生时的前因、后果,以及事件发生对象的特征。在复杂的数据分析、模型训练等需求中,不仅仅需要获知某个事件的发生次数,对埋点上下文尤为关注。此处上下文指的通常有 2 类,分别是:
46

5-
- 事件发生的页面信息和页面位置信息
6-
- 用户经过怎样的路径来到当前页面,也就是“来源”信息
7+
- 事件发生的页面信息和页面位置信息
8+
- 用户经过怎样的路径来到当前页面,也就是“来源”信息
79

8-
下面结合具体西瓜视频的场景,看一个简单的埋点需求,“点击收藏”事件
10+
下面结合具体的西瓜视频场景,看一个简单的埋点需求,“点击收藏”事件
911

1012
![图片](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/85f841476fd74b33ad4caa095bc2ceea~tplv-k3u1fbpfcp-zoom-1.image)
1113

1214
作为最常见的消费场景,列表和详情都有收藏按钮,产品希望知道每一个收藏事件发生的场景,方便后续优化收藏功能,以及结合用户收藏的情况,优化推荐模型。西瓜视频埋点需求是上报收藏按钮的点击事件 click_favorite,要求包含收藏影片的信息,所在的场景信息等。
1315

14-
1. 如果收藏事件发生在列表页,会上报如下的内容
16+
1. 如果收藏事件发生在列表页,会上报如下的内容
1517

1618
```
1719
{
@@ -26,7 +28,7 @@
2628
}
2729
```
2830

29-
2. 如果收藏事件发生在详情页,会上报如下的内容
31+
2. 如果收藏事件发生在详情页,会上报如下的内容
3032

3133
```
3234
{
@@ -50,19 +52,19 @@
5052

5153
通过平台支持的参数传递方式,逐个定义并且读写参数;或者基于面向对象程序设计,对每个类添加相应的埋点参数,在类对象的关系中进行埋点参数传递。直接传参有非常显著的缺陷:
5254

53-
- 每增加一个参数,都需要写大量的重复代码,工程代码膨胀
54-
- 模块间约定了很多埋点参数的协议,耦合程度高,难以维护
55-
- 一些场景的嵌套层次深,经过很多层的参数传递,非常容易漏报埋点参数
55+
- 每增加一个参数,都需要写大量的重复代码,工程代码膨胀
56+
- 模块间约定了很多埋点参数的协议,耦合程度高,难以维护
57+
- 一些场景的嵌套层次深,经过很多层的参数传递,非常容易漏报埋点参数
5658

5759
#### 单例传参
5860

5961
上述问题有一种轻微缓解的办法,使用单例来进行埋点参数的访问。通过一个单例进行埋点参数的维护,由于单例提供了全局唯一访问入口,程序中的任何位置都能方便地读和写埋点参数。这种方式带来的好处是不需要在每个类都定义大量的埋点参数,只需要访问单例进行修改和读取。
6062

6163
会比前面的直接传参更简单,但这种方案治标不治本,同样有明显的弊端:
6264

63-
- 首先,无法解决列表页这种多实例场景的问题,比如一个推荐列表中有多个卡片,每个卡片的埋点参数都不一样,卡片的埋点参数还是需要自己传
64-
- 单例的数据可能被多个位置写入,且一旦被覆盖就没法恢复,比如这样的路径:列表 -> 详情页 1 -> 相关推荐 -> 详情页 2,进到详情页 2 以后,单例的数据被覆盖了,这时候再回到详情页 1,获取到的埋点参数实际是详情页 2 的,导致埋点参数上报错误。
65-
- 存放和清理的时机难以控制,清理早了会导致埋点参数缺失,忘记清理可能导致后面的埋点获取不到参数
65+
- 首先,无法解决列表页这种多实例场景的问题,比如一个推荐列表中有多个卡片,每个卡片的埋点参数都不一样,卡片的埋点参数还是需要自己传
66+
- 单例的数据可能被多个位置写入,且一旦被覆盖就没法恢复,比如这样的路径:列表 -> 详情页 1 -> 相关推荐 -> 详情页 2,进到详情页 2 以后,单例的数据被覆盖了,这时候再回到详情页 1,获取到的埋点参数实际是详情页 2 的,导致埋点参数上报错误。
67+
- 存放和清理的时机难以控制,清理早了会导致埋点参数缺失,忘记清理可能导致后面的埋点获取不到参数
6668

6769
#### 无埋点
6870

@@ -72,11 +74,11 @@
7274

7375
有这么好的事?为什么字节没有广泛使用?此方案的缺陷在于:
7476

75-
1. 仅能上报有限的简单事件类型,如页面视图曝光、点击等,无法完成复杂事件的上报,如一次支付行为的操作路径、结果、错误信息等
76-
2. 无法自定义参数,主要指跳转的来源、所处的场景等上下文信息,无法满足复杂的数据分析和推荐模型所需的数据要求
77-
3. 由产品经理、数据分析师等在埋点管理后台进行的事件录入,把复杂度从开发转嫁给了产品,消费成本较高
78-
4. 对页面视图的稳定性有很高的要求,需要约定 id、文本、视图的层级,保持页面结构不变,如果客户端工程师因为一些新需求开发、性能优化等调整了视图结构,将会导致已录入的埋点失效,增加了额外的维护成本
79-
5. 全场景的数据上报,可能产生大量的无用数据,消耗大量传输、存储、计算资源
77+
1. 仅能上报有限的简单事件类型,如页面视图曝光、点击等,无法完成复杂事件的上报,如一次支付行为的操作路径、结果、错误信息等
78+
2. 无法自定义参数,主要指跳转的来源、所处的场景等上下文信息,无法满足复杂的数据分析和推荐模型所需的数据要求
79+
3. 由产品经理、数据分析师等在埋点管理后台进行的事件录入,把复杂度从开发转嫁给了产品,消费成本较高
80+
4. 对页面视图的稳定性有很高的要求,需要约定 id、文本、视图的层级,保持页面结构不变,如果客户端工程师因为一些新需求开发、性能优化等调整了视图结构,将会导致已录入的埋点失效,增加了额外的维护成本
81+
5. 全场景的数据上报,可能产生大量的无用数据,消耗大量传输、存储、计算资源
8082

8183
### 西瓜视频的责任链方案
8284

@@ -86,12 +88,16 @@
8688

8789
![图片](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/c777c72524ee4fd3b75b7cbb05ab967f~tplv-k3u1fbpfcp-zoom-1.image)
8890

89-
比如在收藏按钮被点击时,只需要从收藏按钮的节点按照`卡片 -> 推荐频道 -> 放映厅Tab`的顺序向上找,就能够拿到所有需要的参数了,并且这个上下级关系(责任链)是已经客观存在的。
91+
比如在收藏按钮被点击时,只需要从收藏按钮的节点按照`卡片 -> 推荐频道 -> 放映厅Tab` 的顺序向上找,就能够拿到所有需要的参数了,并且这个上下级关系(视图树责任链)是已经客观存在的。
9092

9193
再来看看页面的跳转链路,跳转到详情页,有很多种路径。比如`推荐列表 -> 详情页``推荐列表 -> 选集 -> 详情页`,但逻辑上也是一个树状结构。
9294

9395
![图片](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4906defb017f474391880c5399951459~tplv-k3u1fbpfcp-zoom-1.image)
9496

9597
![图片](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e4056fcff5a84c75988f4fa60e7e6ab5~tplv-k3u1fbpfcp-zoom-1.image)
9698

97-
所以我们需要的埋点上下文参数,理论上都可以通过节点的关系找到。
99+
所以我们需要的埋点上下文参数,理论上都可以通过节点的关系找到。
100+
101+
### 参考文章
102+
103+
- [《西瓜客户端埋点实践:基于责任链的埋点框架》](https://mp.weixin.qq.com/s/iMn--4FNugtH26G90N1MaQ)

docs/java.md

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,27 @@ public class UMTrackHandler implements TrackHandler {
1818
}
1919
```
2020

21-
### 建立页面上下级责任链
21+
### 建立页面内上下级责任链
2222

23-
Activity、FragmentView 设置埋点节点 `trackNode` 添加埋点参数。
23+
可以给 Activity、FragmentView 设置埋点节点 `trackNode` 添加埋点参数。
2424

2525
```java
2626
Tracker.setTrackNode(this, params -> params.put("channel_name", "recommend"));
2727
```
2828

2929
```java
30-
Tracker.setTrackNode(holder.itemView, params -> params.put("video_id", item.id));
30+
Tracker.setTrackNode(holder.itemView, params -> params.put("video_id", item.getId()).put("video_type", item.getType()));
3131
```
3232

3333
通过视图树的层级关系(比如:`Activity -> Fragment -> ViewHolder -> Button`)就能建立节点的上下级责任链关系。
3434

3535
### 建立页面来源责任链
3636

37-
页面跳转时需要调用 `Tracker.setReferrerTrackNode(intent, activity/fragment/view)` 设置来源节点。
37+
页面跳转时需要调用 `Tracker.putReferrerTrackNode(intent, activity/fragment/view)` 设置来源节点。
3838

3939
```java
4040
Intent intent = new Intent(activity, DetailsActivity.class);
41-
Tracker.setReferrerTrackNode(intent, view);
41+
Tracker.putReferrerTrackNode(intent, view);
4242
activity.startActivity(intent);
4343
```
4444

@@ -48,7 +48,7 @@ activity.startActivity(intent);
4848
Tracker.setPageTrackNode(this, params -> params.put("page_name", "details"));
4949
```
5050

51-
`PageTrackNode` 会将前面所有节点的参数添加进埋点中,添加的时候可以设置一些转换规则。比如上个页面的 `page_name`,跳转后上报 `from_page`
51+
`PageTrackNode` 会添加前面所有节点的参数,添加的时候可以设置一些转换规则。比如上个页面的 `page_name`,跳转后上报 `from_page`
5252

5353
```java
5454
HashMap<String, String> referrerKeyMap = new HashMap<>();
@@ -67,36 +67,34 @@ Tracker.postTrack(view, "click_favorite")
6767

6868
### 线索节点
6969

70-
线索节点适合用于具有会话特性的流程中,方便在流程中共享参数,常见的有登录、注册的流程订单创建流程等。
70+
线索节点适合用于具有会话特性的流程中,方便在流程中共享参数,常见的有登录、注册的流程订单创建流程等。
7171

7272
在 Activity 可以设置线索节点,线索节点能在 View 或页面之间共享埋点参数。
7373

7474
```java
75-
public class ResultTrackNode implements TrackNode {
75+
public class RecordTrackNode implements TrackNode {
7676

77-
public String result = null;
77+
public boolean isRecord = false;
7878

7979
@Override
8080
public void fillTackParams(@NonNull TrackParams params) {
81-
if (result != null) {
82-
params.put("result", result);
83-
}
81+
params.put("is_record", isRecord);
8482
}
8583
}
8684
```
8785

8886
```java
89-
Tracker.putThreadTrackNode(new ResultTrackNode());
87+
Tracker.putThreadTrackNode(new RecordTrackNode());
9088
```
9189

9290
之后可以在 Activity、Fragment、View 更新线索节点中的参数。
9391

9492
```java
95-
Tracker.updateThreadTrackNode(v, ResultTrackNode.class, node -> node.result = "success");
93+
Tracker.updateThreadTrackNode(v, RecordTrackNode.class, node -> node.isRecord = true);
9694
```
9795

9896
上报的时候需要对线索节点进行声明才会收集参数。
9997

10098
```java
101-
Tracker.postTrack(view, "click_sign_in", ResultTrackNode.class);
99+
Tracker.postTrack(view, "click_publish", RecordTrackNode.class);
102100
```

0 commit comments

Comments
 (0)