AOP 切片无缝打点

智能体AI驱动AOP-Wiki EMOD 3.0:毒理学知识图谱的自动化评估与进化 知识图谱作为结构化知识表示的核心技术,通过实体、关系与属性的语义网络,实现了复杂领域知识的机器可读与互联。其核心原理在于将非结构化信息转化为图数据结构,利用图算法进行推理与发现。在工程实践中,知识图谱与人工智能的结合,特别是与智能体(Agent)技术的融合,正推动知识系统从静态存储向动态认知演进。智能体AI通过自主规划、工具调用与任务执行,能够持续整合新证据、评估一致性并发现知识缺口,为知识库赋予自我进化能力。在毒理学与风险评估领域,这一技术价值尤为凸显。AOP-Wiki作为全球共享的不良结局通路知识库,正 阅读详情

1、统计代码埋点真的 so easy?

统计打点是 App 开发里很重要的一个环节,App 的运行状态、改版后的效果、用户的各种行为等都需要打点,市面上也有不少可供选择的第三方库。 假设产品有这么个需求:当用户在详情页点击购买按钮时,记录一下事件。我们实现起来大概会是这样

// DetailViewController.m

- (void)onBuyButtonTapped:(UIButton *)button
{
    // do some stuff, maybe send a request to server
    [XXXAnalytics event:kSomeEventYouDefined];
}

这个需求就这样轻松搞定了,但细细想想还是有不少问题的:

  • 页面上会有其他的 Button,可能每个 Button 都要放上这么一段代码。

  • 这些统计其实跟具体的业务无关,没必要跟业务代码混杂在一起,不优雅。

  • 当改版或者重构时,有可能忘了把相应的打点代码迁移过去。

2、AOP 实现业务代码与统计代码解耦

所以需要一种更好的方式来做这件事,这就是使用 AOP(Aspect-Oriented-Programming),翻译过来就是「面向切面编程」

通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。

简单来说,就是可以动态的在函数调用的前后插一段代码。iOS 可以使用 Pete Steinberger 开发的 Aspects 这个库,大致原理是在 runtime 层,通过 swizzle method 来实现的。

来看一个小 Demo

[UIViewController aspect_hookSelector:@selector(viewWillAppear:) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo, BOOL animated) {
    NSLog(@"View Controller %@ will appear animated: %tu", aspectInfo.instance, animated);
} error:NULL];

这样在 UIViewController 的 viewWillAppear: 被调用后,还会再调一下我们定义的 Block,这段日志就会被输出。而打点正好符合这种场景:正事干完之后,额外干一些跟业务无关的事情。

上面的例子,我们通过 AOP 来做的话,大概就是这样

// DetailViewController.m
- (void)onBuyButtonTapped:(UIButton *)button
{
    // do some stuff, maybe send a request to server
    // no need to call [XXXAnalytics event:]
}

// AppDelegate.m
- (void)setupAnalytics
{
    [DetailViewController aspect_hookSelector:@selector(onBuyButtonTapped:) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo, BOOL animated) {
        [XXXAnalytics event:kSomeEventYouDefined];
    } error:NULL];
}

3、多个 Button 事件怎么办?

这样统计代码就从业务代码中剥离出来了。但是又产生了一个新问题,多个 Button Event,岂不是要写很多行这样的代码,「重复」这样的事情,作为一个程序员怎么能忍,简单,造一个方法

- (void)trackEventWithClass:(Class)klass selector:(SEL)selector event:(NSString *)event
{
    [klass aspect_hookSelector:@selector(selector) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo, BOOL animated) {
        [XXXAnalytics event:event];
    } error:NULL];
}

使用起来就像这样

- (void)setupAnalytics
{
    [self trackEventWithClass:DetailViewController selector:@seletor(onBuyButtonTapped:) event:kSomeEventYouDefined];
    [self trackEventWithClass:ListViewController selector:@seletor(followButtonTapped:) event:kAnotherEventYouDefined];
    // ...
}

4、统计事件有选择逻辑呢?

看起来又干净了些。这时,产品经理又提了个需求:当这个按钮点击时,如果已经登录了,发送 EventA,如果没有登录则发送 EventB,也就是说,不再只是 [XXXAnalytics event:] 这么简单了,还需要加上额外的逻辑,这也难不倒我们,加上一个 block 即可。

- (void)trackEventWithClass:(Class)klass
                   selector:(SEL)selector
               eventHandler:(void (^)(id<AspectInfo> aspectInfo))eventHandler
{
    [klass aspect_hookSelector:@selector(selector) withOptions:AspectPositionAfter usingBlock:^(id<AspectInfo> aspectInfo, BOOL animated) {
        if (eventHandler) {
            eventHandler(aspectInfo);
        }
    } error:NULL];
}

// 使用
[self trackEventWithClass:DetailViewController selector:@seletor(onBuyButtonTapped:) eventHandler:^(id<AspectInfo> aspectInfo){
    user.loggedIn ? [XXXAnalytics event:EventA] : [XXXAnalytics event:EventB];
}];

好了,现在只要不是太复杂的打点逻辑(那些需要方法上下文变量的)我们都能应付了,接下来就该等产品来验收了。产品搬了个凳子坐在身边,然后点一下 Button,看一下 Console,被几轮蹂躏后,产品也慢慢地接受了这种验收方式。后来某一天,忽然发现某一项或某几项数据有异常,然后找到开发,瞄了一眼:哦,这个方法被重构了。或者新加的方法忘了加统计了。只能等到下个版本再加上了,如果只是一般的统计数据倒还好,跟钱相关的就麻烦了。

5、如何避免统计代码被遗忘?

那么有没有一种直观的验证方式呢?当然,程序员是万能的呀。一个理想的状况是,产品打开 App 后,开启某个开关就能看到所有会发送 Event 的按钮,就像这样

其中数字代表了 EventID。如何实现呢?还记得注册事件时,我们有传入 class 和 selector 么,一般我们都会有一个 BaseViewController,那么就可以在 BaseViewController 的 viewDidAppear: 里做点文章了。

// BaseViewController.m

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    // 获取已经注册过的 classes
    NSDictionary *registeredClasses = [OurAnalytics sharedInstance].registeredClasses;

    [registeredClasses enumerateKeysAndObjectsUsingBlock:^(NSString *className, NSArray *selectors, BOOL *stop) {
        if ([self isKindOfClass:NSClassFromString(className)]) {
            // 如何根据 selector 找到它的宿主?
        }
    }];
}

所以现在问题就剩下,如何根据 selector 找到对应的 Button,这里要注意,有些 Button 可能要等网络请求完成才会出现,比如 TableViewCell 里的 Button。

没有想到太方便的方法,简单粗暴点就是设置个 Timer 每隔一段时间扫一下 subviews,如果是 button 或 包含 tapGesture 的,就拿它们的 action 对比一下,如果 match 就可以高亮那个 button / view 了。

EventID 也一样,之前在注册时也会传一个 EventID 过来,这里直接显示出来即可。对于那些传 eventHandler 的就不行了。

所以理论上是可行的,性能上会稍微有点损耗,尤其是当 subViews 的结构比较复杂时,不过只是内部用来做验证,所以这也不是什么问题。

6、如何解决 APP 埋码要发版的问题?

看起来效果已经不错了,有没有可能让这套体系再灵活一些?比如可以从后端制定打点规则?客户端只是读取一个配置文件,就像这样

- (void)setupAnalytics
{
    // analyticsRules 是从配置文件中读取出来的
    [analyticsRules enumerateObjectsUsingBlock:^(NSDictionary *rules, NSUInteger idx, BOOL *stop) {
        Class klass = NSClassFromString(rules[@"class"]);
        SEL selector = NSSelectorFromString(rules[@"selector"]);
        NSString *eventID = rules[@"eventID"];
        [self trackEventWithClass:klass seletor:seletor event: eventID];
    }];
}

那如果在后台的时候填错了 Class 或 Selector 怎么办?还好有 objc_getClassList 和 class_copyMethodList 这两个运行时方法,有了它们就可以在 App 启动时扫一遍已注册的类(过滤掉 UI / NS 开头的),然后将它们的 seletor 也一并保存下来发送给服务端,当然这种操作只需在适当的时机做一下就可以了,比如集成打包时。

现在,这套体系就比较完整了。当然这只是我的一些构想,并没有在实践中尝试过,所以肯定会踩到各种各样的坑,不过至少看起来是个可行的方案。

7、Refer:

[1] iOS 统计打点那些事

http://limboy.me/ios/2015/09/09/ios-analytics.html

[2] 基于Aspects和JSPatch的热埋点方案

http://t.cn/RyGQ9wm

[3] 移动APP日志上报优化实践

http://dwz.cn/24BfTW

[4] 天猫App A/B测试实践

http://bit.ly/1pTkxrp

[5] 统计埋点的那些事
http://www.jianshu.com/p/973d626fa19a?from=timeline

[6] 用户行为的深度追踪——事件与埋点

http://www.cnblogs.com/ventlam/p/6414584.html

[7] Android无埋点数据收集SDK关键技术

http://www.jianshu.com/p/b5ffe845fe2d#


原文地址:http://limboy.me/ios/2015/09/09/ios-analytics.html

MTGS与3D高斯泼溅:如何用多轨迹数据重建自动驾驶场景(附代码解析) 本文深入解析了MTGS(多轨迹高斯泼溅)技术在自动驾驶场景重建中的工程实践。该方法通过分层场景表示,巧妙融合多轨迹数据,利用3D高斯泼溅技术统一处理静态几何与动态物体,有效解决了复杂环境下的重建难题。文章结合代码,详细阐述了其实现框架、损失函数设计及优化策略,为构建高保真数字孪生场景提供了实用指南。 阅读详情

相关推荐

XGBoost算法案例 - 红酒品质分类

数据集共包含 11 个特征,共计 3269 条数据. 我们通过训练模型来预测红酒的品质, 品质共有 6 个各类别,分别使用数字: 0、1、2、3、4、5 来表示。

YIAN爱学习的博客 449

iOS 统计打点那些事

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34128237的博客 212

Docker篇——Docker常用命令大全!史上最全面的Docker命令,涵盖常规命令、镜像基本命令、容器基本命令以及常用其他命令,一篇文章速通!

本篇文章介绍的关于DOcker的命令非常全面,Docker常见的命令介绍完毕,涉及到的命令比较繁杂,希望大家可以收藏并坚持学习。后续还会持续更新相关技术点,敬请期待

我热爱学习,也乐于分享。无论是科技前沿的洞见,还是生活中的小技巧,我都会在这里与你分享。我相信,知识就是力量,而分享则能让这份力量得到更好的传递。 5746

AOP埋点从入门到放弃(一)(2024年08月13日修改),真的醉了

代码真的是重质不重量,质量高的代码,是当前代码界提倡的,当然写出高质量的代码肯定需要一个相当高的专业素养,这需要在日常的代码书写中逐渐去吸收掌握,谁不是每天都在学习呀,目的还不是为了一个,为实现某个功能写出高质量的代码。所以,长征路还长,大家还是好好地做个务实的程序员吧。最后,小编这里有一系列Android提升学习资料,有兴趣的小伙伴们可以来看下哦~我的 Android 学习,面试文档,视频收集大整理。

870

用Blender给ArduPilot无人船编队设计灯光秀:从建模到飞行的保姆级教程

本文详细介绍了如何利用Blender和ArduPilot为无人船编队设计灯光秀的全流程技术方案。从3D动画设计、坐标转换、数据导出到ArduPilot飞控配置和灯光控制,提供了一套完整的保姆级教程,帮助开发者实现水面灯光编队表演。

weixin_29213525的博客 386

【阅读文献笔记】FoundationStereo: Zero-Shot Stereo Matching

提出首个零样本泛化立体匹配基础模型设计 STA 模块融合单目先验提出 AHCF 模块增强代价滤波构建 100 万合成数据集 FSD + 自净化流程。

qq_46460379的博客 1257

面向切片编程AOP相关概念

AOP的概念、作用、切入点表达式、通知类型、如何在通知中获取参数

bb_111的博客 447

NVIDIA DGX Spark实战指南:从开箱到部署200B参数大模型

本文详细介绍了NVIDIA DGX Spark桌面AI超级计算机的开箱体验与实战部署指南。文章深入解析了其Grace Blackwell架构与128GB统一内存的核心优势,并逐步演示了从系统初始化、运行200B参数大模型到进行QLoRA微调的全过程。该设备将高达1 PetaFLOP的AI算力浓缩于桌面,为开发者和研究团队提供了本地化、高性能的AI开发与部署一体化解决方案。

weixin_29274969的博客 2230

redis数据结构HyperLogLog

如果我们要实现记录网站每天访问的独立IP数量这样的一个功能 集合实现: 使用集合来储存每个访客的 IP ,通过集合性质(集合中的每个元素都各不相同)来得到多个独立 IP ,然后通过调用 SCARD 命令来得出独立 IP 的数量。举个例子,程序可以使用以下代码来记录 2014 年 8 月 15 日,每个网站访客的 IP :ip = get_vistor_ip()SADD '2014.8.15::...

weixin_30628077的博客 273

WRF所需气象数据的下载方法

#数据下载是个大问题,巧妇难为无米之炊,没有数据就无法模拟啦,疫情期间国外服务器响应慢,打开网页慢都很正常啦~ WRF数据所需要的外部数据分为两种:静态地理数据,grib格式的气象数据(NAM、GFS、RUC、AGRMET等)。静态地理数据可以从WRF官网获得,比较简单,这里不做介绍。所以这篇日志重点介绍的是气象数据的获取。 提前说明,WRF官网不提供气象数据,但WRF官网提供各类气象数据的下载网址链接,所以我们下载一般还是从WRF官网开始。首先进入WRF官网,然后点击WRF ARW Uusres’ .

六出的博客 1万+

CY7C68013 C0模式启动

C0或是C2启动的目的,是更改USB芯片的ID信息,并把固件载入到芯片内部RAM中运行。C0模式是指只从EEPROM中载入USB ID信息,因为只有ID信息(8个字节),所以只需要一个小容量的EEPROM即可。当然大容量的EEPROM也可以使用C0模式,但是小容量的EEPROM只能使用C0模式启动。如下图所示: 使用小容量的EEPROM要将A0,A1,A2接地。 这里我用了个24LC01,容量1

Fezl的博客 1740

Firebase SDK之打点事件(event)

环境 Unity 2020.3.20f1 Firebase Unity SDK 8.3.0 接入 接入代码教程不赘述,可以直接看文档。这里提一下需要注意的几个地方: 1,事件名不需要配置到后台,后台要配置的是事件参数 后台只需要配置事件参数这一点和很多打点SDK都是不同的。Firebase中后台统计会自动获得用户上传的事件名并形成相关图文报告。 另外UnitySDK中事件参数类型只支持string、long、double类型(即字符、整数、浮点) 2,后台事件参数配置 事件参数通过"自定义定义(Custom

iningwei的博客 5487

(11-3-01 )

以太坊(Ethereum)是一种基于区块链技术的开源平台和加密货币。它于2015年由Vitalik Buterin和Gavin Wood等开发者创建,并成为比特币之后最受欢迎的加密货币之一。以太坊不仅支持加密货币交易,还为开发者和企业提供了构建去中心化应用程序的强大工具。在本节的内容中,将实型一个完整的机器学习模型项目,智能检测出以太坊区块链中的非法账户。从问题定义到模型建立和评估,再到最终的总结和建议。本实例突出了处理类别不平衡问题的重要性,并展示了如何使用多种机器学习算法来解决实际问题。此外,通过数据可

码农三叔 2170

Spring-AOP面向切片编程介绍 2021-09-15

Spring的基础和应用系列文章目录 第一部分 Spring 基础 1.1 XML使用-IoC配置与依赖(DI)配置 1.2 基于注解和XML混合方式的使用 1.3 基于纯注解方式的使用 1.4 AOP 介绍 1.5 Spring 整合AspectJ的AOP使用 第二部分 组件支持 2.1 整合Junit 2.2 事务支持 Spring AOP面向切片编程介绍Spring的基础和应用系列文章目录第一部分 Spring 基础第二部分 组件支持一、 AOP介绍1.1 为什么使用AOP二、 AOP相关术语介绍三

qq_21438267的博客 260

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Aop技术框架在移动端的实施应用

内容目录什么是AOP(What)AOP的定义AOP中的几个概念AspectJ 介绍为什么要有AOP?(Why)怎么在客户端中应用(How)几个重要场景的分析(Where)写在最后AOP原理其他两个小问题 面向过程编程(Procedure Oriented Programming),即OPP 注重算法,功能不同的函数调用。常用的C语言 优点:任务分解,按部就班 面向对象编程(Object Orien...

ezview_uniview的博客 501

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

android中的aop

自从在徐医生的公众号上面看到了AOP的介绍,心中一阵窃喜,还有这么牛逼的技术。赶紧github了一把,看了几个大神的项目之后,就要自己去尝试下。还是先把感谢的链接帖下吧。 徐医生:http://mp.weixin.qq.com/s/Io9q9OT4fhkkaPGuqFs0-A  大家可关注他的微信公众号,很多的技术干活在等着你哦。 https://github.com/android10/An

翟锐的博客 565

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Spring 简介

Spring是一个主流的Java Web开发框架。实际上,Spring不仅能用于Java EE,也能用于Java SE。 Spring是一个分层的Java SE/EE full-stack(一站式)轻量级开源框架。它以Ioc(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切片编程)为内核,使用基本的Java...

weixin_30563917的博客 186

Spring Testing与JUnit 5测试切片技术:构建高效Java应用测试体系

在Java企业级应用开发中,软件测试是保障代码质量和系统稳定性的核心环节。其基本原理是通过模拟各种运行场景来验证代码逻辑的正确性,从而预防缺陷并支持持续重构。从技术价值看,高效的测试体系能显著提升开发效率、降低维护成本,是现代敏捷开发流程的基石。在Spring Boot生态中,测试实践尤为关键,它直接关系到微服务架构下模块的可靠性与交付速度。应用场景广泛覆盖单元测试、集成测试及端到端测试等多个层次。其中,JUnit 5作为新一代测试框架,通过模块化架构和扩展模型提供了更强大的灵活性;而Spring的测试切片

weixin_34411563的博客 392

SpringAOP基础入门与日志实践详解

【1】AOP(Aspect-Oriented Programming, 面向切面编程),是一种新的方法论, 是对传统 OOP(Object-Oriented Programming, 面向对象编程) 的补充.AOP 的主要编程对象是切面(aspect), 而切面模块化横切关注点. 在应用 AOP 编程时, 仍然需要定义公共功能, 但可以明确的定义这个功能在哪里, 以什么方式应用, 并且不必修改受.........

小小默:进无止境 1682

Spring

Spring面试题(持续更新中~)

weixin_56924632的博客 835

Spring基础入门详解与实践

Spring AOP 其余IOC一样是spring的核心模块,围绕着AOP的增强功能,Spring集成了AspectJ作为AOP的一个特定实现,同时还在JVM动态代理/CGLIB的基础上,实现了一个AOP框架作为spring集成其他模块的工具,比如TransactionProxyFactoryBean声明式事务处理,就是通过AOP集成到Spring中的。Web层使用Web层框架,可选的,可以是Spring自己的MVC框架,或者提供的Web框架,如Struts、Webwork、tapestry和jsf。

m0_74824845的博客 1074

spring的简介

1.spring的简介 Spring是一个分层的 full-stack(一站式)轻量级框架,以Ioc(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切片编程)为内核,使用简单的JavaBean来完成以前只能由EJB(Enterprise Java Beans)完成的工作,取代了臃肿、低效的EJB。 Spring致力于JavaEE应用各层的解决方案,是企业应用一站式开发很好的选择,在表现层它提供了Spring MVC以及整合Strut

m0_56027341的博客 173

spring简介

1、spring简介 Spring是一个分层的 full-stack(一站式)轻量级框架,以Ioc(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切片编程)为内核,使用简单的JavaBean来完成以前只能由EJB(Enterprise Java Beans)完成的工作,取代了臃肿、低效的EJB。Spring致力于JavaEE应用各层的解决方案,是企业应用一站式开发很好的选择,在表现层它提供了Spring MVC以及整合Struts的

清风微凉亦暖心 747
上一篇: Python 爬虫问题记录
下一篇: Kali Linux系统更改镜像源使用阿里云镜像更新
光速之年
博客等级 码龄12年 31粉丝 97原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值