mysql无侵入复制_无侵入埋点方案如何实现

埋点可以解决两大类问题: 一是了解用户使用App的行为, 二是降低分析线上问题的难度

常见的埋点方式: 代码埋点、可视化埋点、无埋点

代码埋点: 通过手写代码, 精确的在需要埋点的代码处加上埋点的代码, 存在开发工作量大, 后期难以维护的问题

可视化埋点: 增加修改的工作可视化了, 提升体验

无埋点: 埋点代码不会出现在业务代码中, 容易管理和维护, 缺点在于, 埋点成本高, 后期解析复杂, 优点是节省大量的开发和维护成本

运行时方法替换方式进行埋点

常见三种埋点: 页面进入次数、页面停留时间、点击事件

利用运行时method_exchangeImplementations接口将方法的实现进行了交换, 原方法调用时就会被hook住, 从而去执行指定的方法

#import "SMHook.h"

#import

@implementation SMHook

+ (void)hookClass:(Class)classObject fromSelector:(SEL)fromSelector toSelector:(SEL)toSe

Class class = classObject;

// 得到被替换类的实例方法

Method fromMethod = class_getInstanceMethod(class, fromSelector);

// 得到替换类的实例方法

Method toMethod = class_getInstanceMethod(class, toSelector);

// class_addMethod 返回成功表示被替换的方法没实现,然后会通过 class_addMethod 方法先实现

if(class_addMethod(class, fromSelector, method_getImplementation(toMethod), method_g

// 进行方法的替换

class_replaceMethod(class, toSelector, method_getImplementation(fromMethod), met

} else {

// 交换 IMP 指针

method_exchangeImplementations(fromMethod, toMethod);

}

}

@end

页面进入次数、页面停留时间都需要对UIViewController生命周期进行埋点, 可以创建一个UIViewController的Catagory

@implementation UIViewController (logger)

+ (void)load {

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

// 通过 @selector 获得被替换和替换方法的 SEL,作为 SMHook:hookClass:fromeSelector:toSelector 的参数传入

SEL fromSelectorAppear = @selector(viewWillAppear:);

SEL toSelectorAppear = @selector(hook_viewWillAppear:);

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

SEL fromSelectorDisappear = @selector(viewWillDisappear:);

SEL toSelectorDisappear = @selector(hook_viewWillDisappear:);

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

});

}

- (void)hook_viewWillAppear:(BOOL)animated {

// 先执行插入代码,再执行原 viewWillAppear 方法

[self insertToViewWillAppear];

[self hook_viewWillAppear:animated];

}

- (void)hook_viewWillDisappear:(BOOL)animated {

// 执行插入代码,再执行原 viewWillDisappear 方法

[self insertToViewWillDisappear];

[self hook_viewWillDisappear:animated];

}

- (void)insertToViewWillAppear {

// 在 ViewWillAppear 时进行日志的埋点

[[[[SMLogger create]

message:[NSString stringWithFormat:@"%@ Appear",NSStringFromClass([self class])]]

classify:ProjectClassifyOperation]

save];

}

- (void)insertToViewWillDisappear {

// 在 ViewWillDisappear 时进行日志的埋点

[[[[SMLogger create]

message:[NSString stringWithFormat:@"%@ Disappear",NSStringFromClass([self class])]]

classify:ProjectClassifyOperation]

save];

}

@end

对于点击事件, 可以通过运行时方法替换的方式进行无侵入埋点, 找到点击事件的方法sendAction:to:forEvent:, 然后在+load()方法使用SMHook替换

UIButton在一个视图类中可能有多个不同的继承类, 相同UIButton的子类在不同视图类的埋点也要区别开, 需要通过“action选择器名 NSStringFromSelector(action)”+“视图类名NSStringFromClass([target class])”组合成一个唯一的标识, 进行埋点

+ (void)load {

static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

// 通过 @selector 获得被替换和替换方法的 SEL,作为 SMHook:hookClass:fromeSelector:toSelector 的参数传入

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

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

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

});

}

- (void)hook_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {

[self insertToSendAction:action to:target forEvent:event];

[self hook_sendAction:action to:target forEvent:event];

}

- (void)insertToSendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event {

// 日志记录

if ([[[event allTouches] anyObject] phase] == UITouchPhaseEnded) {

NSString *actionString = NSStringFromSelector(action);

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

[[[SMLogger create] message:[NSString stringWithFormat:@"%@ %@",targetName,actionString]] save];

}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值