SDK API
由于C/C++应用程序框架/架构的多样性,基调听云3.0 CSDK 提供两套SDK方法,分别用于异步方式调用的框架和同步方式调用的框架。
头文件引入:
#include <tingyun.h>
初始化SDK:
void TingYunAgentInit();
探针初始化函数。
这个函数不是必须要显式调用。
当应用代码中没有调用这个函数时,在首次事务埋点触发时,这个函数会被隐式调用 。
由于探针的初始化过程是异步方式在后台进行的,因此在探针初始化完成前的事务数据不会被采集 。
异步API方法
创建事务
说明:应用性能分解过程中,我们使用Action定义一个完整事务,通常它对应的是一个完整的http请求过程。
代码:
//参数:
// uri : 是Action对应的事务名,为空串则使用所在函数的类名::函数名 。
// 返回值 : 事务Id 。
TActionId CreateAction(const char *uri);
//功能: 定义一个事务过程 。
//调用时机: 客户端请求处理过程开始时 。
创建后台任务
说明:服务端应用中,可能会产生某些服务响应之外的事务处理过程,比如某些定时过程等。我们将其定义为后台任务。
代码:
//参数:
// cmd : 是后台事务对应的事务名,为空串则使用所在函数的类名::函数名 。
// 返回值 : 事务Id 。
TActionId CreateBackGroundAction(const char *cmd);
//功能: 定义一个后台事务过程 。
//调用时机: 后台事务开始时 。
结束事务
说明:事务结束时调用的方法,以次测量分析事务的执行过程 。
代码:
//参数:
// action : 事务id 。
void ActionDestroy(TActionId action);
//功能: 结束事务过程 。
//调用时机: 事务处理过程结束时 。
//说明: ActionDestroy调用之后,即表示事务的数据采集过程完成,此后action和由action创建的所有component将失效 。
创建Component
Component说明
一个事务通常会包含多个组件过程,组件过程还可能继续分解成几个其他组件过程。我们将这样的子过程定义为Component,通过对Component树的耗时分析来定位事务执行过程中的性能瓶颈 。
从Action创建Component
一般组件
//方法1:
//不指定函数名过程名,获取当前方法名作为组件名称 。
//参数
// action: 事务Id 。
// 返回值: 组件Id 。
TComponentId ACreateComponent(TActionId action);
//功能: 开始一个组件的数据采集,这个API获取当前所处的函数名字作为组件名 。
//调用时机: 一个可能耗时的计算类型的子过程开始的时候 。
//方法2:
//自定义组件名称 。
//参数:
// action: 事务Id 。
// ComponentName: 自定义组件名 。
// 返回值: 组件Id 。
TComponentId ActionCreateComponent(TActionId action, const char *ComponentName);
//功能: 同上,这个API使用自定义的名字作为组件名 。
//调用时机: 同上 。
数据库组件
//方法1: 有SQL语句的情况下,使用SQL语句自动解析 。
//参数:
// action: 事务Id 。
// type: 数据库类型: "Mysql"/"Postgresql" 。
// host: 数据库主机地址 。
// dbname: 数据库名 。
// sql: 执行的SQL语句 。
// 返回值: 组件Id 。
TComponentId CreateSQLComponent(TActionId action, const char *type, const char *host, const char *dbname, const char *sql);
//功能: 开始一个数据库调用过程的数据采集,需要传递sql语句.内部将解析出数据库操作类型和表名,作为组件名的一部分 。
//调用时机: 数据库过程开始时 。
//方法2: 无SQL语句的情况下,传递表名和操作名(select/update/insert/delete) 。
//参数:
// action: 事务Id 。
// type: 数据库类型: "Mysql"/"Postgresql" 。
// host: 数据库主机地址 。
// dbname: 数据库名 。
// table: 表名 。
// op: 表上的操作名 。
// 返回值: 组件Id 。
TComponentId CreateDBComponent(TActionId action, const char *type, const char *host, const char *dbname, const char *table, const char *op);
//功能: 同上,差别是明确指定表明和操作方法(select/update/insert/delete) 。
//调用时机: 同上 。
NoSQL组件
//参数:
// action: 事务Id 。
// type: 数据库类型: "Mysql"/"Postgresql" 。
// host: 数据库主机地址 。
// dbname: 数据库名 。
// object_name: 对象名 。
// op: 对象上的操作名 。
// 返回值: 组件Id 。
TComponentId CreateNoSQLComponent(TActionId action, const char *type, const char *host, const char *dbname, const char *object_name, const char *op);
//功能: 开始一个NoSQL数据库调用过程的数据采集 。
//调用时机: 数据库过程开始时 。
外部调用组件(RPC、HTTP等)
//自定义组件名称 。
//参数:
// action: 事务Id 。
// url: 外部调用的url 。
// 返回值: 组件Id 。
TComponentId CreateExternalComponent(TActionId action, const char *url);
//功能: 开始一个外部调用的数据采集,外部调用可以是向其他服务器发起的http请求,或者rpc调用 。
//调用时机: 外部调用开始时
MQ调用组件(生产者,消费者)
//自定义组件名称 。
//参数:
// action: 事务Id 。
// type: MQ类型: RabbitMQ, ActiveMQ, Kafka... 。
// host: MQ地址 。
// queue: 队列名 。
// 返回值: 组件Id 。
TComponentId CreateConsumerComponent(TActionId action, const char *type, const char *host, const char *queue);
//功能: 开始一个消息队列消费者的数据采集 。
//调用时机: MQ消费者开始时 。
//自定义组件名称 。
//参数:
// action: 事务Id 。
// type: MQ类型: RabbitMQ, ActiveMQ, Kafka... 。
// host: MQ地址 。
// queue: 队列名 。
// 返回值: 组件Id 。
TComponentId CreateProducerComponent(TActionId action, const char *type, const char *host, const char *queue);
//功能: 开始一个消息队列生产者的数据采集 。
//调用时机: MQ生产者调用开始时 。
从Component创建Component
//方法1:
//不指定函数名过程名,自动获取当前方法名作为组件名称 。
//参数
// parent: 父级组件Id 。
// 返回值: 组件Id 。
TComponentId CCreateComponent(TComponentId parent);
//功能: 开始一个组件的数据采集 。
//调用时机: 当一个耗时的计算过程被分解为几个子过程时,我们需要采集每个子过程的耗时情况,来详细分析性能瓶颈 。
//此时通过这个API可以构建一个调用树,通过分析每个过程的耗时情况,解决性能问题 。
//方法2:
//自定义组件名称
//参数:
// parent: 父级组件Id 。
// ComponentName: 自定义组件名 。
// 返回值: 组件Id 。
TComponentId ComponentCreateComponent(TComponentId parent, const char *ComponentName);
//功能: 同上, 差别是用此API自定义过程名 。
//调用时机: 同上 。
组件错误采集
//参数:
// component: 组件id 。
// message: 错误消息 。
void ComponentSetError(TComponentId component, const char *message);
//功能: 在组件过程中发生错误时,通过这个api记录代码行和调用栈,协助错误分析 。
//调用时机: 对应组件的过程发生错误时 。
结束Component
//参数:
// component: 组件id 。
void ComponentFinish(TComponentId component);
//功能: 结束一个组件的数据采集 。
//调用时机: 对应该组件的过程执行完毕时。比如数据库过程执行完时,或者一个外部调用执行完成时 。
子过程结束时,需要调用对应的Component.Finish(),才能达到采集数据的目的。
跨应用追踪
- 应用拓扑 当一个帐号下存在多个应用的相互调用关系时, 可以利用API追踪应用之间的调用关系 。 调用者CreateTrackId, 被调用者SetTrackId, 在报表内就会产生“调用者” -> "被调用者" 的拓扑图 。
客户端:
//流程:
//1.创建一个外部调用组件 。
//2.调用ComponentCreateTrackId生成跨应用追踪id(字符串) 。
//3.发送id到server端 。
//3.1如果外部调用为私有rpc协议,请自行传输这个id 。
//3.2如果是http(s)请求,将这个id作为http头的 "X-Tingyun-Id" 字段发送 。
//4.如果http应答头里携带”X-Tingyun-Tx-Data“,调用ComponentSetTxData完成跨应用追踪 。
//需要的API:
int ComponentCreateTrackId(TComponentId component, char *idbuffer, int buffersize);
void ComponentSetTxData(TComponentId component, const char *tx_data);
//调用过程:
//1.
TComponentId external == CreateExternalComponent(action, "http://192.168.1.253/servermethod");
//2.
char cross_id[1024] = {0};
ComponentCreateTrackId(external, cross_id, sizeof(cross_id) - 1);
//添加cross_id到http请求头 (如果是http(s)) 。
...
//3.
//发送数据到服务器 。
...
//应答完成后,
//取应答头里的 ”X-Tingyun-Tx-Data“ 。
...
//4.
ComponentSetTxData(external, tingyun_txdata);
ComponentFinish(external);
服务器端:
void ActionSetTrackId(TActionId action, const char *TrackId);
char track_id[1024] = {0};
//1.解析出客户端传过来的跨应用追踪ID 。
...
//2.创建事务:
TActionId action = CreateAction(appid, "/servermethod");
//3.
ActionSetTrackId(action, track_id);
//Action其他处理过程...
...
ActionDestroy(action);
- 跨应用追踪 当产生拓扑关系的应用过程性能超过阈值时,会产生慢过程跟踪数据,同时在慢过程跟踪数据内会记录调用者和被调用者的详细追踪信息 。 通过点击慢过程跟踪图表内的链接,可以跳转到被调用者的详细追踪数据 。
API函数
异步调用API
TActionId CreateAction(const char *uri);
创建一个事务,uri可以是自定义的事务名。
void ActionAddCustomParam(TActionId action_id, const char k, const char v);
添加事务的自定义参数(uri解析参数),协助应用在报表端分析慢过程追踪和错误追踪栈。
适用情形: 需要通过参数分析慢事务或者错误原因时,请调用此接口采集参数。
void ActionAddRequestParam(TActionId action_id, const char k, const char v);
添加事务的客户端请求参数(http头),协助应用在报表端分析慢过程追踪和错误追踪栈。
适用情形: 需要通过参数分析慢事务或者错误原因时,请调用此接口采集参数。
TComponentId ACreateComponent(TActionId action);
从Action创建一个一般组件,组件名使用当前调用方函数的名字。
TComponentId ActionCreateComponent(TActionId action, const char *ComponentName);
从Action创建一个一般组件,组件名使用自定义名字。
TComponentId CreateSQLComponent(TActionId action, const char type, const char host, const char dbname, const char sql);
从Action创建一个数据库组件,参数为:数据库类型,主机名,库名,sql语句。
TComponentId CreateDBComponent(TActionId action, const char type, const char host, const char dbname, const char table, const char *op);
从Action创建一个数据库组件,参数为:数据库类型,主机名,库名,表名,操作名。
TComponentId CreateNoSQLComponent(TActionId action, const char type, const char host, const char dbname, const char object_name, const char *op);
创建NOSQL性能分解组件 参数:
type : “mongo"/"memcache"/"redis" 。
host : 主机地址,可空 。
dbname : 库名称,可空 。
object_name : 对象名 。
op : 操作类型, ("GET", "SET" ...) 。
TComponentId CreateExternalComponent(TActionId action, const char *url);
从Action创建一个外部调用组件 参数: url:外部服务的url,格式: http(s)://host/uri, 例如 http://www.tingyun.com/。
void ActionIgnore(TActionId action);
忽略这次Action的性能采集,只在ActionDestroy调用之前有效。
适用情形: 通常不需要使用者调用。
void ActionSetName(TActionId action, const char classname, const char methodname);
修改事务名 参数: 类名,方法名。
适用情形: 明确指定事务名。
void ActionSetStatus(TActionId action, int StatusCode)
设置Action对应的http事务应答的http状态码,缺省值200。
适用情形: 能取到返回状态码的情况。
void ActionSetError(TActionId action, const char error_classname, const char message);
设置事务错误类名和消息。
适用情形: 事务处理过程发生错误时调用。
void ActionSetTrackId(TActionId action, const char *trackId)
用于rpc调用或者http外部调用的跨应用追踪,trackId 由使用者从调用端传过来。
适用情形: 参考跨应用追踪。
void ActionSetUrl(TActionId action, const char *Url);
重设对应Action的 uri, 用于追踪慢过程和错误分析。
适用情形: 明确指定事务对应的url,事务的命名优先使用url,没有的情况下使用函数名。
void ActionDestroy(TActionId action)
当前事务数据采集结束。
适用情形: 事务结束。
性能分解组件
TComponentId CCreateComponent(TComponentId parent);
对本组件再进行性能分解,创建下层性能分解组件,使用调用者所处函数作为组件名。
TComponentId ComponentCreateComponent(TComponentId parent, const char *ComponentName);
对本组件再进行性能分解,创建下层性能分解组件,使用ComponentName作为组件名。
int ComponentCreateTrackId(TComponentId component, char *idbuffer, int buffersize);
用于跨应用追踪,本组件内调用了外部应用过程或者发起了rpc调用,由应用此方法返回的结果携带到server端,server端通过ActionSetTrackId使用这个结果。最终在报表端生成跨应用追踪图表。
适用情形: 参考跨应用追踪。
void ComponentSetTxData(TComponentId component, const char *tx_data);
用于跨应用追踪,如果外部调用的server端安装了基调听云的Java、PHP等其他探针,启用跨应用追踪时,响应头里会有”X-Tingyun-Tx-Data“数据,通过本接口采集这个数据,完成跨应用追踪。
适用情形: 参考跨应用追踪。
TActionId ComponentGetAction(TComponentId component);
取本组件所属的事务对象Action。
适用情形: 某些情况下,传参过程同时携带事务ID和组件ID 会令代码变的复杂,这个API提供了方便方法通过组件获取到相应的事务id。
void ComponentFinish(TComponentId component);
停止性能分解组件计时 性能分解组件时长 = Finish时刻 - CreateComponent时刻 当时长超出堆栈阈值时,记录当前组件的代码堆栈。
void ComponentSetError(TComponentId component, const char *message);
设置组件错误消息。
适用情形: 组件处理过程发生错误时调用。
同步调用API
说明:对于同步处理的事务类型(主函数开始即事务开始,主函数退出即事务结束,过程分解亦如此),我们需要更简洁的函数调用,方便用户使用,减少传递id给用户带来的困扰。我们提供如下函数完成埋点任务 。
TingYunID C_SyncTrackEnter(const char *instance);
同步执行的事务/组件调用的入口,返回事务ID/组件ID。
调用时机: 在需要关注的函数入口开始时调用。
void C_SyncTrackLeave(id_pointer);
一个事务/组件结束时调用,参数是事务/组件的id。
TComponentId C_SyncTrackRPCEnter(const char *url);
用于测量外部调用过程的执行性能,比如http/thrift/proto_buf等。在执行前调用这个方法计时,执行后调用C_SyncTrackLeave结束计时。
TComponentId C_SyncTrackNoSQLEnter(const char dbtype, const char host, const char db, const char table, const char *op);
用于测量一次NoSQL数据访问性能,dbtype可以取mongo, redis, memcache; host:=> 数据库地址; db:=>库名; table:=>对象名; op:=>操作名。
TComponentId C_SyncTrackDBEnter(const char dbtype, const char host, const char db, const char sql);
用于测量关系型数据库访问性能, dbtype取mysql/postgresql/oracle/db2/sqlite等; host:=>数据库地址; db:=>库名; sql:=> 数据库查询语句。
TComponentId C_SyncTrackConsumerEnter(const char mqtype, const char host, const char *queue);
用于测量消息队列消费者的处理过程, mqtype取RabbitMQ/ActiveMQ/Kafka 等; host:=>MQ地址; queue:=>消息队列名。
TComponentId C_SyncTrackProducerEnter(const char mqtype, const char host, const char *queue);
用于测量消息队列生产者的发送过程, mqtype取RabbitMQ/ActiveMQ/Kafka 等; host:=>MQ地址; queue:=>消息队列名。
TComponentId C_SyncTrackError(const char *message);
在组件过程中发生错误时,通过这个api记录代码行和调用栈,协助错误分析。
//调用时机: 对应组件的过程发生错误时。
跨进程事务API
int TingYunIDSerialize(const TActionId action_id, char out);
在多进程协作事务处理框架中,事务的入口框架创建事务id, 应用调用 TingYunIDSerialize 将事务id序列化成字符串,通过进程通信接口发送到协作进程。
TingYunID TingYunIDParse(const char *input);
在多进程协作事务处理框架中,协作进程收到序列化后的字符串,解析出事务id。