2.2、newrelic.agent
newrelic.agent的整体框架主要分成android api注入,数据采集器,数据任务队列,measurement生产者消费者模型,数据预处理和发送模块;
newrelic.agent模块的整体框架如下图所示;

图2.2 newrelic.agent的模块框架

2.2.1、android api注入
android api的注入工作在rewriter.agent中完成,根据type_map.properties文件中配置的目标api注入方式进行相应的替换(REPLACE_CALL_SITE)和包裹(WRAP_METHOD)注入;

2.2.2、数据采集器
采集器采集的数据种类主要有StatsEngine数据,sampler数据,TransactionState数据,activityTrace数据,threadLoadTrace数据,HttpTransaction数据,HttpError数据,Activity生命周期数据;
TraceMachine作为sampler,TransactionState,activityTrace,threadLoadTrace数据,HttpTransaction数据,HttpError数据,Activity生命周期数据的采集器;
2.2.2.1、性能数据采集方式
主要有以下几种;
1)method的性能数据采集
将enterMethod和exitMethod方法注入(注入工作在rewriter.agent中完成)到替换android api的api开始和结束处,hook的目的用来采集该api执行的性能数据;其中sampler,SummaryMetricMeasurementConsumer都实现了TraceLifecycleAware接口并在TraceMachine中注册,当已被hook api触发TraceMachine.enterMethod和exitMethod方法时,会启动和结束TraceMachine中已注册类实例的性能数据采样工作;
比如,当应用执行sqlite的query方法时会触发TraceMachine.enterMethod(“SQLiteDatabase#query”),在enterMethod方法中启动Trace跟踪和调用sampler的onEnterMethod方法启动内存数据的采样。当sqlite结束时会触发TraceMachine.exitMethod(),在exitMethod方法中结束trace跟中和调用sampler的onExitMethod方法停止内存采样;最后将trace放到TaskQueue中,TaskQueue会负责将trace分发到对应的Measurement中;
2)事务的性能数据采集
将TransactionState实例注入(注入工作在rewriter.agent中完成)到替换android api的api中,TransactionState实例会记录本次事务过程中产生的性能数据;
比如,当应用执行HttpRequest的execute方法时会被替换成使用HttpInstrumentation中的execute方法,其中会使用TransactionState实例记录整个request到response过程中的数据,数据包括request uri,运营商信息,header,response code,response data等;
3)activity的性能数据采集
主要hook了activity生命周期内的onStart,activityStarted和onStop方法;在这些方法中注入enterMethod和exitMethod方法,在执行时会通过registerNewTrace方法创建childTrace并加入到TraceMachine的rootActivityTrace中;
4)StatsEngine异常数据采集
StatsEngine用来记录newrlic.agent本身的异常数据,采集在与后端服务器数据交互的周期内agent本身发生的一些异常信息,它继承了HarvestAdapter类,因此会在Harvester发生CONNECTIONED状态时被触发onHarvest方法->populateMetrics方法将异常数据包装成Metric通过TaskQueue发送给对应的HarvestData中machineMeasurements;

2.2.3、任务队列
TaskQueue类为newrelic.agent中的任务队列,它在Measurements中实例化,用来接收不同数据采集器采集到的性能数据,并根据类型将他们分别转发到下游的Measurements工厂和Harvest中;其中Measurements为生产者和消费者模型,进行性能数据预处理、统计和组装工作;

2.2.4、Measurements”工厂”
Measurements作为所有MeasurementProducer和MeasurementConsumer的管理者,通过MeasurementEngine的MeasurementPool增删producer和consumer,它主要负责生产和消费不同种类性能数据;
比如,当收到TaskQueue的Trace数据时,会使用methodMeasurementProducer的produceMeasurement方法包装trace数据并通过MeasurementPool的broadcastMeasurements方法通知对应的trace数据消费者methodMeasurementConsumer,消费者使用consumeMeasurement将处理后的数据加入到自己的MetricStore中;

2.2.5、Harvest
Harvest负责对所有数据最终收集、验证、打包和回传服务器;HarvestTimer作为定时器会周期性的触发数据收集和回传服务器的动作,具体的过程为,HarvestTimer定时器触发Harvester的execute方法,若CONNECTED状态则会触发fireOnHarvestBefore,fireOnHarvest,fireOnHarvestFinalize方法,fireOnXXX方法中会遍历所有已实现HarvestLifecycleAware接口并且注册在Harvester的XXXMeasurementConsumer,XXXMeasurementConsumer中的onHarvestXXX方法会将采集、处理过的数据统一添加到HarvestData中并打包;最后通过Harvester的connected方法发送本周期的性能数据到服务器上;

2.3、plugin部分
这部分比较简单,按照正常的plugin开发流程写就是了;
主要步骤;
1)在plugin.xml中把导出的class.rewriter.jar和newrelic.android.jar加入到Classpath中;
2)开发实现IStartup接口的Bootstrap类,并实现earlyStartup方法;在这里需要通过tools.jar的com.sun.tools.attach.VirtualMachine动态加载Instrumentation代理(class.rewriter.jar中的rewriter.agent),另外,runtime中装载tools.jar前面已经说过;
主要的代码如下;

3)开发IObjectActionDelegate实现newrelic.android.jar的自动安装
右键install会将newrelic.android.jar安装到工程libs中;主要代码如下;

2.4、山寨
源代码位置:https://github.com/fifa2002nb/xxxrelic
山寨sdk eclipse插件在线安装地址:http://www.apmbe.com:8070/android