目录
此内容是否有帮助?

# C SDK 使用指南

提示

在接入前, 请先阅读接入前准备

您可以在 GitHub (opens new window) 获取 C SDK 源码。

最新版本为:1.3.6

更新时间为:2022-06-22

C SDK 下载地址 (opens new window)

# 一、集成并初始化 SDK

# 1.1 集成 SDK

下载C SDK (opens new window),进行解压后可将以下文件引入项目中。

(1)LoggerConsumer: 批量实时写本地文件,默认以天为分隔,需要与 LogBus 搭配使用进行数据上传。

./c-sdk_version/include/thinkingdata.h
./c-sdk_version/lib/libthinkingdata.a

(2)BatchConsumer: 批量实时向服务器传输数据,不需要搭配传输工具,有数据丢失的风险,请谨慎使用。

./c-sdk_version/include/thinkingdata.h
./c-sdk_version/lib/libthinkingdata_http.a

(3)AsyncBatchConsumer:批量异步实时向服务器传输数据,不需要搭配传输工具,有数据丢失的风险,请谨慎使用。

./c-sdk_version/include/thinkingdata.h
./c-sdk_version/lib/libthinkingdata_async_batch.a

(4)DebugConsumer: 逐条实时地向 TA 服务器传输数据,不需要搭配传输工具,如果数据出现错误,整条数据都将不会入库,并且返回详细的错误说明,不建议在生产环境中使用。

./c-sdk_version/include/thinkingdata.h
./c-sdk_version/lib/libthinkingdata_debug.a

注意,这里的静态库使用mac平台(clang编译器)进行打包,由于各平台特性不一致,建议将源代码下载后自行编译,推荐使用cmake打包,请参考 GitHub (opens new window)

# 1.2 初始化 SDK

您可以通过四种方法获得 SDK 实例:

(1)LoggerConsumer:

    //生成config
    TAConfig *config = ta_init_config();

    //配置日志路径 YOUR_LOG_PATH 需要更改为日志存储的目录
    TA_ASSERT(TA_OK == ta_add_string("file_path", "YOUR_LOG_PATH", strlen("YOUR_LOG_PATH"), config));
    //配置日志前缀
    TA_ASSERT(TA_OK == ta_add_string("file_prefix", "test", strlen("test"), config));

    //按时间切分 默认按小时切分
    //TA_ASSERT(TA_OK == ta_add_int("rotate_mode", DAILY, config)); //按天切分
    TA_ASSERT(TA_OK == ta_add_int("rotate_mode", HOURLY, config)); //按小时切分

    //按文件大小切分,单位是MB
    //TA_ASSERT(TA_OK == ta_add_int("file_size", 1024, config));

    //生成SDK实例
    struct TAConsumer *consumer = NULL;
    if (TA_OK != ta_init_logging_consumer(&consumer, config)) {
        fprintf(stderr, "Failed to initialize the consumer.");
        return 1;
    }
    ta_free_properties(config);

    ThinkingdataAnalytics *ta = NULL;
    if (TA_OK != ta_init(consumer, &ta)) {
        fprintf(stderr, "Failed to initialize the SDK.");
        return 1;
    }

TALoggingConsumer将会批量实时地生成日志文件,文件默认以小时切分,需要搭配 LogBus 进行上传。

YOUR_LOG_PATH 需要更改为日志存储的目录,您只需将 LogBus 的监听文件夹地址设置为此处的地址,即可使用 LogBus 进行数据的监听上传。

(2)BatchConsumer:

    //生成config
    TAConfig *config = ta_init_config();

    // 配置appid和url
    TA_ASSERT(TA_OK == ta_add_string("push_url", serverURL, strlen(serverURL), config));
    TA_ASSERT(TA_OK == ta_add_string("appid", appid, strlen(appid), config));
    
    //生成SDK实例
    struct TAConsumer *consumer = NULL;
    if (TA_OK != ta_init_consumer(&consumer, config)) {
        fprintf(stderr, "Failed to initialize the consumer.");
        return 1;
    }
    ta_free_properties(config);

    ThinkingdataAnalytics *ta = NULL;
    if (TA_OK != ta_init(consumer, &ta)) {
        fprintf(stderr, "Failed to initialize the SDK.");
        return 1;
    }

serverURL为传输数据的 URL,appid为您的项目的 APP ID。

(3)AsyncBatchConsumer:

参考BatchConsumer

(4)DebugConsumer :

    //生成config
    TAConfig *config = ta_init_config();

    // debug_mode,0入库,否则不入库
    TA_ASSERT(TA_OK == ta_add_int("debug_mode", 0, config));

    // 配置appid和url
    TA_ASSERT(TA_OK == ta_add_string("push_url", serverURL, strlen(serverURL), config));
    TA_ASSERT(TA_OK == ta_add_string("appid", appid, strlen(appid), config));
    
    //生成SDK实例
    struct TAConsumer *consumer = NULL;
    if (TA_OK != ta_init_consumer(&consumer, config)) {
        fprintf(stderr, "Failed to initialize the consumer.");
        return 1;
    }
    ta_free_properties(config);

    ThinkingdataAnalytics *ta = NULL;
    if (TA_OK != ta_init(consumer, &ta)) {
        fprintf(stderr, "Failed to initialize the SDK.");
        return 1;
    }

debug_mode为0时入库,否则不入库。

# 二、上报数据

在 SDK 初始化完成之后,您就可以调用track来上传事件,一般情况下,您可能需要上传十几到上百个不同的事件,如果您是第一次使用 TA 后台,我们推荐您先上传几个关键事件。

如果您对需要发送什么样的事件有疑惑,可以查看快速使用指南了解更多信息。

# 2.1 发送事件

您可以调用track来上传事件,建议您根据先前梳理的文档来设置事件的属性以及发送信息的条件,此处以用户付费作为范例:

    const char* distinct_id = "ABC123";
    const char* account_id = "TA_10001";

    //上报不带自定义属性的事件数据,注意account_id 和 distinct_id 必须至少设置其中一个
    TA_ASSERT(TA_OK == ta_track(NULL, distinct_id, "test", NULL, ta));

    // 生成自定义属性
    TAProperties *properties = ta_init_properties();

    // 设置事件发生的时间,如果不设置的话,则默认使用为当前时间,**注意** #time的类型必须是time_t
    TA_ASSERT(TA_OK == ta_add_date("#time", time(NULL), 0, properties));

    // 设置用户的ip地址,TA系统会根据IP地址解析用户的地理位置信息,如果不设置的话,则默认不上报
    TA_ASSERT(TA_OK == ta_add_string("#ip", "192.168.1.1", strlen("192.168.1.1"), properties));

    // 添加自定义属性
    TA_ASSERT(TA_OK == ta_add_string("product_name", "商品", strlen("商品"), properties));
    TA_ASSERT(TA_OK == ta_add_number("price", 30.989, properties));
    TA_ASSERT(TA_OK == ta_add_int("coin", -30, properties));
    TA_ASSERT(TA_OK == ta_add_string("order_id", "abc_123", strlen("abc_123"), properties));
    TA_ASSERT(TA_OK == ta_add_date("login_time", time(NULL), 0, properties));
    TA_ASSERT(TA_OK == ta_add_bool("is_firstBuy", true, properties));
    TA_ASSERT(TA_OK == ta_add_bool("is_test", false, properties));

    // 从 v1.1.0版本 开始,您可以调用 `ta_append_array` 对 array 类型的属性进行追加操作。
    TA_ASSERT(TA_OK == ta_append_array("product_buy", "product_name1", strlen("product_name1"), properties));
    TA_ASSERT(TA_OK == ta_append_array("product_buy", "product_name2", strlen("product_name2"), properties));

    //上报带有自定义属性的事件数据,同样account_id 和 distinct_id 必须至少设置其中一个
    TA_ASSERT(TA_OK == ta_track(account_id, distinct_id, "test", properties, ta));
    ta_free_properties(properties);
  • 事件的名称是string类型,只能以字母开头,可包含数字,字母和下划线 “_”,长度最大为 50 个字符,对字母大小写不敏感。
  • 事件的属性类型是TAProperties,可以通过ta_add_string添加字符串型属性,ta_add_number添加数值型属性,ta_add_int添加int属性,ta_add_bool添加bool值,ta_add_date添加date类型值,ta_append_array添加数组类型。
  • Key 的值为属性的名称,为 string 类型,规定只能以字母开头,包含数字,字母和下划线 “_”,长度最大为 50 个字符,对字母大小写不敏感。
  • Value 为该属性的值,可以是intnumberstringbooldate、数组类型、对象、对象组。

从 v1.3.4 版本开始支持复杂数据类型,属性可传入对象和对象组:

TAProperties *properties = ta_init_properties();

TAProperties *json = ta_init_custom_properties("json");
TAProperties *json1 = ta_init_custom_properties("json1");
TAProperties *json2 = ta_init_custom_properties("json2");

/**
 * 复杂数据类型 JSON对象
 * */
TA_ASSERT(TA_OK == ta_add_string("a1", "b1", strlen("b1"), json));
TA_ASSERT(TA_OK == ta_add_string("product_name", "月卡", strlen("月卡"), json));
TA_ASSERT(TA_OK == ta_add_number("price", 30.989, json));
TA_ASSERT(TA_OK == ta_add_int("coin", -30, json));
TA_ASSERT(TA_OK == ta_add_string("order_id", "abc_123", strlen("abc_123"), json));
TA_ASSERT(TA_OK == ta_add_date("login_time", time(NULL), 0, json));
TA_ASSERT(TA_OK == ta_add_bool("is_firstBuy", TA_TRUE, json));
TA_ASSERT(TA_OK == ta_add_bool("is_test", TA_FALSE, json));

TA_ASSERT(TA_OK == ta_add_property(json, properties));

   /**
 * 复杂数据类型 JSON—Array
 * */
TA_ASSERT(TA_OK == ta_add_string("a11", "b11", strlen("b11"), json1));
TA_ASSERT(TA_OK == ta_add_string("product_name", "月卡11", strlen("月卡11"), json1));
TA_ASSERT(TA_OK == ta_add_number("price", 3111, json1));
TA_ASSERT(TA_OK == ta_add_int("coin", -31, json1));
TA_ASSERT(TA_OK == ta_add_string("order_id", "abc_111", strlen("abc_111"), json1));
TA_ASSERT(TA_OK == ta_add_date("login_time", time(NULL), 0, json1));
TA_ASSERT(TA_OK == ta_add_bool("is_firstBuy", TA_TRUE, json1));
TA_ASSERT(TA_OK == ta_add_bool("is_test", TA_TRUE, json1));

TA_ASSERT(TA_OK == ta_add_string("a12", "b12", strlen("b12"), json2));
TA_ASSERT(TA_OK == ta_add_string("product_name", "月卡22", strlen("月卡22"), json2));
TA_ASSERT(TA_OK == ta_add_number("price", 3222, json2));
TA_ASSERT(TA_OK == ta_add_int("coin", -32, json2));
TA_ASSERT(TA_OK == ta_add_string("order_id", "abc_222", strlen("abc_222"), json2));
TA_ASSERT(TA_OK == ta_add_date("login_time", time(NULL), 0, json2));
TA_ASSERT(TA_OK == ta_add_bool("is_firstBuy", TA_FALSE, json2));
TA_ASSERT(TA_OK == ta_add_bool("is_test", TA_FALSE, json2));


TA_ASSERT(TA_OK == ta_append_properties("jsons", json1, properties));
TA_ASSERT(TA_OK == ta_append_properties("jsons", json2, properties));

# 三、用户属性

TA 平台目前支持的用户属性设置接口为ta_user_setta_user_setOnceta_user_addta_user_delta_user_append

# 3.1 ta_user_set

对于一般的用户属性,您可以调用ta_user_set来进行设置,使用该接口上传的属性将会覆盖原有的属性值,如果之前不存在该用户属性,则会新建该用户属性,类型与传入属性的类型一致:

    // 上传用户属性,"user_name"的值为"ABC"
    TAProperties *user_properties = ta_init_properties();
    TA_ASSERT(TA_OK == ta_add_string("user_name", "ABC", strlen("ABC"), user_properties));
    TA_ASSERT(TA_OK == ta_user_set(account_id, distinct_id, user_properties,ta));
    ta_free_properties(user_properties);

    //上传用户属性,该用户的"user_name"被设置成"XYZ"
    TAProperties *user_properties2 = ta_init_properties();
    TA_ASSERT(TA_OK == ta_add_string("user_name", "XYZ", strlen("XYZ"), user_properties2));
    TA_ASSERT(TA_OK == ta_user_set(account_id, distinct_id, user_properties2,ta));
    ta_free_properties(user_properties2);

属性格式要求与事件属性保持一致。

# 3.2 ta_user_setOnce

如果您要上传的用户属性只要设置一次,则可以调用ta_user_setOnce来进行设置,当该属性之前已经有值的时候,将会忽略这条信息:

    // 上传用户属性,"user_name"的值为"ABC"
    TAProperties *user_properties = ta_init_properties();
    TA_ASSERT(TA_OK == ta_add_string("user_name", "ABC", strlen("ABC"), user_properties));
    TA_ASSERT(TA_OK == ta_user_setOnce(account_id, distinct_id, user_properties,ta));
    ta_free_properties(user_properties);

    //上传用户属性,该用户的"user_name"已设置因此忽略该属性设置
    //该用户的"user_age"没有被设置,因此设置值为18
    TAProperties *user_properties2 = ta_init_properties();
    TA_ASSERT(TA_OK == ta_add_string("user_name", "XYZ", strlen("XYZ"), user_properties2));
    TA_ASSERT(TA_OK == ta_add_int("Age", 18, user_properties2));
    TA_ASSERT(TA_OK == ta_user_setOnce(account_id, distinct_id, user_properties2,ta));
    ta_free_properties(user_properties2);

属性格式要求与事件属性保持一致。

# 3.3 ta_user_add

当您要上传数值型的属性时,您可以调用ta_user_add来对该属性进行累加操作,如果该属性还未被设置,则会赋值 0 后再进行计算,可传入负值,等同于相减操作。

    //设置用户属性
    TAProperties *user_properties = ta_init_properties();
    TA_ASSERT(TA_OK == ta_add_int("Level", 3, user_properties));

    //上传用户属性,给该用户的"Level"属性加上3
    TA_ASSERT(TA_OK == ta_user_add(account_id, distinct_id, user_properties, ta));
    ta_free_properties(user_properties);

设置的属性key为字符串,Value 只允许为数值。

# 3.4 ta_user_del

如果您要删除某个用户,可以调用ta_user_del将这名用户删除,您将无法再查询该名用户的用户属性,但该用户产生的事件仍然可以被查询到

TA_ASSERT(TA_OK == ta_user_del(account_id, distinct_id, ta));

# 3.5 ta_user_append

从 v1.1.0 版本开始,您可以调用 ta_user_append 对 array 类型的用户属性进行追加操作。

TAProperties *array_properties = ta_init_properties();
TA_ASSERT(TA_OK == ta_append_array("product_buy", "product_name3", strlen("product_name3"), array_properties));
TA_ASSERT(TA_OK == ta_append_array("product_buy", "product_name4", strlen("product_name4"), array_properties));
TA_ASSERT(TA_OK == ta_user_append(account_id, distinct_id, array_properties, ta));
ta_free_properties(array_properties);

# 3.6 ta_user_unset

当您需要清空某个用户的用户属性的值时,可以调用 ta_user_unset 进行清空。

TA_ASSERT(TA_OK == ta_user_unset(account_id, distinct_id, "test", ta));

ta_user_unset: 的传入值为被清空属性的 Key 值。

# 3.7 ta_user_uniq_append

当您要为 list 类型追加用户属性值,但不希望出现重复值时,您可以调用 ta_user_uniq_append 来对指定属性进行追加操作,如果该属性还未在集群中被创建,则 ta_user_uniq_append 创建该属性

TAProperties *array_properties = ta_init_properties();
TA_ASSERT(TA_OK == ta_append_array("product_buy", "product_name3", strlen("product_name3"), array_properties));
TA_ASSERT(TA_OK == ta_append_array("product_buy", "product_name4", strlen("product_name4"), array_properties));
TA_ASSERT(TA_OK == ta_user_uniq_append(account_id, distinct_id, array_properties, ta));

# 四、其他操作

# 4.1 立即提交数据

    ta_flush(ta);

立即提交数据到相应的接收器

# 4.2 关闭 sdk

    ta_free(ta);
    ta_consumer_free(consumer);

关闭并退出 sdk,请在关闭服务器前调用本接口,以避免缓存内的数据丢失

# 五、相关预置属性

# 5.1 所有事件带有的预置属性

以下预置属性,是 C SDK 中所有事件都会带有的预置属性

属性名
中文名
说明
#ip
IP 地址
用户的 IP 地址,需要进行手动设置,TA 将以此获取用户的地理位置信息
#country
国家
用户所在国家,根据 IP 地址生成
#country_code
国家代码
用户所在国家的国家代码(ISO 3166-1 alpha-2,即两位大写英文字母),根据 IP 地址生成
#province
省份
用户所在省份,根据 IP 地址生成
#city
城市
用户所在城市,根据 IP 地址生成
#lib
SDK 类型
您接入 SDK 的类型,如 tga_c_sdk 等
#lib_version
SDK 版本
您接入 C SDK 的版本

# ChangeLog

# v1.3.6 2022/06/22

  • 提升稳定性

# v1.3.5 2022/05/16

  • 支持debug_consumer
  • 支持async_batch_consumer
  • 新增ta_user_uniq_append方法

# v1.3.4 2022/03/03

  • 支持复杂数据类型

# v1.3.3 2022/02/18

  • 修复 snprintf 可能导致的重名问题

# v1.3.2 2021/11/23

  • 优化 windows 平台里的 snprintf 方法

# v1.3.1 2021/11/10

  • malloc失败时不再直接exit

# v1.3.0 2021/10/13

  • 增加支持batch consumer

# v1.2.3 2021-09-23

  • 修复#first_check_id无法正常处理的问题

# v1.2.2 2021/07/01

  • 适配windows环境

# v1.2.1 2021/06/09

  • 不再使用stdbool库

# v1.2.0 2020/12/07

  • 支持指定 log 前缀
  • 增加自动创建目录

# v1.1.0 2020/02/12

  • 支持 array 数据
  • 新增 user_append 接口
  • 支持动态公共属性设置
  • 支持设置“#uuid”,配合后台使用

# v1.0.0 2019/09/29

  • debug consumer
  • logger consumer
  • support track/user_set/user_setOnce/user_add/user_del
  • support super properties