跳到主要内容

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。