java无侵入埋点 point_基于Hook的无侵入埋点

埋点

埋点是一个开发中常需要用到的东西,这篇文章主要介绍一下三种常用的埋点场景如何做到无侵入埋点,Controller 页面进入和退出、Button 点击和 Cell 点击。

具体的思路就是 hook 相关的方法,在 hook 的方法里面做埋点。这里面需要注意的就两点:hook 方法和标识唯一性;

Controller 页面进入和退出

Controller 的进入和退出,我们很容易就能想到 viewWillAppear和viewWillDisappear,所以接下来操作就很简单了:

+ (void)load {

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

SEL fromSelectorAppear =(viewWillAppear:);

SEL toSelectorAppear =(hook_viewWillAppear:);

[Hook hookClass:self fromSelector:fromSelectorAppear toSelector:toSelectorAppear];

SEL fromSelectorDisappear =(viewWillDisappear:);

SEL toSelectorDisappear =(hook_viewWillDisappear:);

[Hook hookClass:self fromSelector:fromSelectorDisappear toSelector:toSelectorDisappear];

});

}

记录标识的唯一性,这里直接用 class name 来标识就好:

NSLog(@"埋点:%@",[NSString stringWithFormat:@"%@ Appear",NSStringFromClass([self class])]);

Button 点击

对于 Button 的点击,思路是一样的,hook 点击相关的方法,不过我们 hook 的是UIControl的sendAction:to:forEvent::

+ (void)load {

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

SEL fromSelector =(sendAction:to:forEvent:);

SEL toSelector =(hook_sendAction:to:forEvent:);

[Hook hookClass:self fromSelector:fromSelector toSelector:toSelector];

});

}

对于 Button 点击的唯一标识,我们只需要使用记录调用的 target 和 action 就行了:

NSString *actionString = NSStringFromSelector(action);

NSString *targetName = NSStringFromClass([target class]);

NSLog(@"埋点:%@",[NSString stringWithFormat:@"%@ %@",targetName,actionString]);

Cell 点击

Cell 点击的 hook 思路就稍微不太一样了,Cell 点击调用的是 UITableView 的 delegate 类的方法,而不是 UITableView 或 UITableViewCell 的方法。这时候,我们可以倒过来推导这件事情:

为了达到无痕埋点需要 hook tableView:didSelectRowAtIndexPath:方法

tableView:didSelectRowAtIndexPath: 在 delegate 的类中

所以我们需要 hook 的是 delegate 的类中的 tableView:didSelectRowAtIndexPath: 方法

要 hook delegate 的类,我们就需要获取设置 delegate 的时候

所以我们需要 hook UITableView 的setDelegate:方法

到此我们就清楚需要做什么了,我们需要做两次 hook,一次是 hook UITableView 的setDelegate:,一次是 hook delegate 的类中的 tableView:didSelectRowAtIndexPath:。

这时还有一个问题就是如何 hook delegate 类的方法?具体思路是这样,新建一个中间类,让它来跟 delegate 类做方法交换,代码如下:

- (void)hook_setDelegate:(id)delegate {

// 获得delegate的实际调用类

Class aClass = [delegate class];

// 传递给TableDelegateTool来交互方法

[TableDelegateTool exchangeTableViewDelegateMethod:aClass];

[self hook_setDelegate:delegate];

}

TableDelegateTool.m

TableDelegateTool

+ (void)exchangeTableViewDelegateMethod:(Class)aClass

{

[Hook hookClass:aClass to:self fromSelector(tableView:didSelectRowAtIndexPath:) toSelector(hook_tableView:didSelectRowAtIndexPath:)];

}

-(void)hook_tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

NSLog(@"埋点:%@",[NSString stringWithFormat:@"%@ tableViewDidSelect section:%ld row:%ld",NSStringFromClass([self class]),(long)indexPath.section,(long)indexPath.row]);

[self hook_tableView:tableView didSelectRowAtIndexPath:indexPath];

}

这里 Cell 点击的唯一标识,我们可以用 class name 和 NSIndexPath 来处理。

总结

最后我们回到实用性的角度来看一下,无侵入埋点固然爽,它能直接把场景下的所有数据都采集起来,减少客户端的手动埋点的工作量。但是有时收集的数据不全是我们需要的,结果就是还要在服务端进行数据的标注和分析,才能得到我们想要的埋点数据。所以无侵入埋点的方案维护成本是比较高的,更适合用在一些功能稳定性高的地方。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值