详情页标题前

阿里云日志服务SLSiOS SDK快速入门-云淘科技

详情页1

本文介绍如何快速使用日志服务iOS SDK采集日志数据。

前提条件

已安装iOS SDK。具体操作,请参见安装iOS SDK。

快速使用

您可以按照以下方式对SDK进行初始化,并同调用addLog方法上报日志。

重要

  • iOS SDK支持初始化多个实例,LogProducerConfig实例与LogProducerClient实例要成对使用。

  • 上报日志到日志服务时需使用阿里云账号或RAM用户的AccessKey,用于鉴权及防篡改。为避免将AccessKey保存在移动端应用中,造成安全风险,推荐您使用移动端日志直传服务配置AccessKey。具体操作,请参见采集-搭建移动端日志直传服务。

@interface ProducerExampleController ()
// 建议您全局保存LogProducerConfig实例和LogProducerClient实例。
@property(nonatomic, strong) LogProducerConfig *config;
@property(nonatomic, strong) LogProducerClient *client;
@end

@implementation ProducerExampleController


// callback为可选配置,如果您不需要关注日志的发送成功或失败状态,可以不注册callback。
// 如果需要动态化配置AccessKey,建议设置callback,并在callback被调用时更新AccessKey。
static void _on_log_send_done(const char * config_name, log_producer_result result, size_t log_bytes, size_t compressed_bytes, const char * req_id, const char * message, const unsigned char * raw_buffer, void * userparams) {
    if (result == LOG_PRODUCER_OK) {
        NSString *success = [NSString stringWithFormat:@"send success, config : %s, result : %d, log bytes : %d, compressed bytes : %d, request id : %s", config_name, (result), (int)log_bytes, (int)compressed_bytes, req_id];
        SLSLogV("%@", success);
    } else {
        NSString *fail = [NSString stringWithFormat:@"send fail   , config : %s, result : %d, log bytes : %d, compressed bytes : %d, request id : %s, error message : %s", config_name, (result), (int)log_bytes, (int)compressed_bytes, req_id, message];
        SLSLogV("%@", fail);
    }
}

- (void) initLogProducer {
    // 日志服务的服务接入点。此处必须是以https://或http://开头。
    NSString *endpoint = @"your endpoint";
    NSString *project = @"your project";
    NSString *logstore = @"your logstore";

    _config = [[LogProducerConfig alloc] initWithEndpoint:endpoint
                                                  project:project
                                                 logstore:logstore
    ];

    // 设置日志主题。
    [_config SetTopic:@"example_topic"];
    // 设置tag信息,此tag信息将被附加在每条日志上。
    [_config AddTag:@"example" value:@"example_tag"];
    //是否丢弃过期日志。0表示不丢弃,把日志时间修改为当前时间; 1表示丢弃。默认值为1。
    [_config SetDropDelayLog:1];
    // 是否丢弃鉴权失败的日志,0表示不丢弃,1表示丢弃。默认值为0。
    [_config SetDropUnauthorizedLog:0];    

    // 需要关注日志的发送成功或失败状态时, 第二个参数需要传入一个callback。
    _client = [[LogProducerClient alloc] initWithLogProducerConfig:_config callback:_on_log_send_done];
}

// 请求AccessKey信息。
- (void) requestAccessKey {
    // 推荐您先使用移动端日志直传服务配置AccessKey信息。
    // ...

    //  获取到AccessKey信息后,完成更新。
    [self updateAccessKey:accessKeyId accessKeySecret:accessKeySecret securityToken:securityToken];
}

// 更新AccessKey信息。
- (void) updateAccessKey:(NSString *)accessKeyId accessKeySecret:(NSString *)accessKeySecret securityToken:(NSString *)securityToken {
    
    // 通过STS服务获取的AccessKey会包含securitToken,需要使用以下方式更新。
    if (securityToken.length > 0) {
        if (accessKeyId.length > 0 && accessKeySecret.length > 0) {
            [_config ResetSecurityToken:accessKeyId
                        accessKeySecret:accessKeySecret
                          securityToken:securityToken
            ];
        }
    } else {
        // 不是通过STS服务获取的AccessKey,使用以下方式更新。
        if (accessKeyId.length > 0 && accessKeySecret.length > 0) {
            [_config setAccessKeyId: accessKeyId];
            [_config setAccessKeySecret: accessKeySecret];
        }
    }
}
// 上报日志。
- (void) addLog {
    Log *log = [Log log];
    // 您可以根据实际业务需要调整需上报的字段。
    [log putContent:@"content_key_1" intValue:123456];
    [log putContent:@"content_key_2" floatValue:23.34f];
    [log putContent:@"content_key_3" value:@"中文"];
    
    [_client AddLog:log];
}
@end

高级用法

动态配置参数

iOS SDK支持动态化配置Endpoint、ProjectName、Logstore、AccessKey等参数。

  • 动态化配置Endpoint、ProjectName、Logstore。

    // 支持独立配置或一起配置Endpoint、ProjectName、Logstore。
    // 更新Endpoint。
    [_config setEndpoint:@"your new-endpoint"];
    // 更新ProjectName。
    [_config setProject:@"your new-project"];
    // 更新Logstore。
    [_config setLogstore:@"your new-logstore"];
  • 动态配置AccessKey。

    动态配置AccessKey时,一般建议与callback结合使用。

    // 如果您在初始化LogProducerClient时已经完成了callback的初始化,以下代码可忽略。
    static void _on_log_send_done(const char * config_name, log_producer_result result, size_t log_bytes, size_t compressed_bytes, const char * req_id, const char * message, const unsigned char * raw_buffer, void * userparams) {
        if (LOG_PRODUCER_SEND_UNAUTHORIZED == result || LOG_PRODUCER_PARAMETERS_INVALID) {
            [selfClzz requestAccessKey]; // selfClzz为对当前类的持有。
        }
    }
    
    // 需要关注日志的发送成功或失败状态时, 第二个参数需要传入一个callback。
    _client = [[LogProducerClient alloc] initWithLogProducerConfig:_config callback:_on_log_send_done];
    
    // 请求AccessKey信息。
    - (void) requestAccessKey {
        // 推荐您先使用移动端日志直传服务配置AccessKey信息。
        // ...
    
        //  获取到AccessKey信息后,完成更新。
        [self updateAccessKey:accessKeyId accessKeySecret:accessKeySecret securityToken:securityToken];
    }
    
    // 更新AccessKey信息。
    - (void) updateAccessKey:(NSString *)accessKeyId accessKeySecret:(NSString *)accessKeySecret securityToken:(NSString *)securityToken {
        
        // 通过STS服务获取的AccessKey会包含securitToken,需要使用以下方式更新。
        if (securityToken.length > 0) {
            if (accessKeyId.length > 0 && accessKeySecret.length > 0) {
                [_config ResetSecurityToken:accessKeyId
                            accessKeySecret:accessKeySecret
                              securityToken:securityToken
                ];
            }
        } else {
            // 不是通过STS服务获取的AccessKey,使用以下方式更新。
            if (accessKeyId.length > 0 && accessKeySecret.length > 0) {
                [_config setAccessKeyId: accessKeyId];
                [_config setAccessKeySecret: accessKeySecret];
            }
        }
    }
  • 动态化配置 source、topic、tag。

    重要

    source、topic、tag无法针对某类日志进行设置。一旦设置后,所有未成功发送到日志服务的日志,都可能会更新。如果您需要通过source、topic、tag来跟踪具体类别的日志,可能会导致与您的业务预期不相符合。建议您在生成Log时新增字段来标识对应的类别信息。

    // 设置日志主题。
    [_config SetTopic:@"your new-topic"];
    // 设置日志来源。
    [_config SetSource:@"your new-source"];
    // 设置tag信息,此tag信息会附加在每条日志上。
    [_config AddTag:@"test" value:@"your new-tag"];

断点续传

iOS SDK支持断点续传。开启断点续传后,每次通过addLog方法上传成功的日志都会先保存在本地binlog文件中,只有日志发送成功后才会删除本地数据,确保日志上传实现At Least Once。

您可以在SDK初始化时加入以下代码,实现断点续传。

重要

  • 初始化多个LogProducerConfig实例时,LogProducerConfig类的setPersistentFilePath方法需要传入不同的值。

  • 如果您的App存在多进程且开启了断点续传功能,您应只在主进程初始化SDK。如果子进程也有采集数据的需求,您需要确保SetPersistentFilePath方法传入的文件路径的唯一性,否则可能会导致日志数据错乱、丢失等问题。

  • 使用时应注意多线程导致的LogProducerConfig重复初始化问题。

- (void) initLogProducer {
    //  1表示开启断点续传功能,0表示关闭。默认值为0。
    [_config SetPersistent:1];
    
    // 持久化的文件名,需要保证文件所在的文件夹已创建。
    NSArray  *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *Path = [[paths lastObject] stringByAppendingString:@"/log.dat"];
    [_config SetPersistentFilePath:Path];
    // 持久化文件滚动个数,建议设置成10。
    [_config SetPersistentMaxFileCount:10];
    // 每个持久化文件的大小,单位为Byte,格式为N*1024*1024。建议N的取值范围为1~10。
    [_config SetPersistentMaxFileSize:N*1024*1024];
    // 本地最多缓存的日志数量,不建议超过1048576,默认为65536。
    [_config SetPersistentMaxLogCount:65536];
}

配置参数说明

所有的配置参数由LogProducerConfig类提供,详见下表:

参数

数据类型

说明

SetTopic

String

设置topic字段的值。默认值为空符串。

AddTag

String

设置tag,格式为tag:xxxx。默认值为空符串。

SetSource

String

设置source字段的值。默认值为iOS。

SetPacketLogBytes

Int

每个缓存的日志包大小上限。超过上限后,日志会被立即发送。

取值范围为1~5242880,默认值为1024 * 1024,单位为字节。

SetPacketLogCount

Int

每个缓存的日志包中包含日志数量的最大值。超过上限后日志会被立即发送。

取值范围为1~4096,默认值为1024。

SetPacketTimeout

Int

被缓存日志的发送超时时间,如果缓存超时,日志会被立即发送。

默认值为3000,单位为毫秒。

SetMaxBufferLimit

Int

单个Producer Client实例可以使用的内存的上限,超出缓存时add_log接口会立即返回失败。

默认值为64 * 1024 * 1024。

SetPersistent

Int

是否开启断点续传功能。

  • 1:开启。

  • 0(默认值):关闭。

SetPersistentFilePath

String

持久化的文件名,需保证文件所在的文件夹已创建。配置多个LogProducerConfig实例时,需确保唯一性。

默认值为空。

SetPersistentForceFlush

Int

是否开启每次AddLog强制刷新功能。

  • 1:开启。开启后对性能会有影响,建议谨慎开启。

  • 0(默认值):关闭。

在高可靠性场景下建议开启。

SetPersistentMaxFileCount

Int

持久化文件滚动个数,建议取值范围为1~10,默认值为0。

SetPersistentMaxFileSize

Int

每个持久化文件的大小,单位为Byte,格式为N*1024*1024。建议N的取值范围为1~10。

SetPersistentMaxLogCount

Int

本地最多缓存的日志数量,不建议超过1048576,默认为65536。

SetConnectTimeoutSec

IntInt

网络连接超时时间。默认值为10,单位为秒。

SetSendTimeoutSec

Int

日志发送超时时间。默认值为15,单位为秒。

SetDestroyFlusherWaitSec

Int

flusher线程销毁最大等待时间。默认值为1,单位为秒。

SetDestroySenderWaitSec

Int

sender线程池销毁最大等待时间。默认值为1,单位为秒。

SetCompressType

Int

数据上传时的压缩类型。

  • 0:不压缩。

  • 1(默认值):LZ4压缩。

SetNtpTimeOffset

Int

设备时间与标准时间的差值,值为标准时间-设备时间。一般这种差值是由于用户客户端设备时间不同步场景。默认值为0,单位为秒。

SetMaxLogDelayTime

Int

日志时间与本机时间的差值。超过该差值后,SDK会根据setDropDelayLog选项进行处理。单位为秒,默认值为7243600,即7天。

SetDropDelayLog

Int

是否丢弃超过setMaxLogDelayTime的过期日志。

  • 0(默认值):不丢弃,把日志时间修改为当前时间。

  • 1:丢弃。

SetDropUnauthorizedLog

Int

是否丢弃鉴权失败的日志。

  • 0(默认值):不丢弃。

  • 1:丢弃。

错误码

全部的错误码说明如下表所示。

错误码

数值

说明

解决方案

LOG_PRODUCER_OK

0

成功。

不涉及。

LOG_PRODUCER_INVALID

1

SDK已销毁或无效。

  1. 检查是否正确初始化SDK。

  2. 检查是否调用了destroy()方法。

LOG_PRODUCER_WRITE_ERROR

2

数据写入错误,可能原因是Project写入流量已达上限。

调整Project写入流量上限。具体操作,请参见调整资源配额。

LOG_PRODUCER_DROP_ERROR

3

磁盘或内存缓存已满,日志无法写入。

调整maxBufferLimit、persistentMaxLogCount、persistentMaxFileSize参数值后重试。

LOG_PRODUCER_SEND_NETWORK_ERROR

4

网络错误。

检查Endpoint、Project、Logstore的配置情况。

LOG_PRODUCER_SEND_QUOTA_ERROR

5

Project写入流量已达上限。

调整Project写入流量上限。具体操作,请参见调整资源配额。

LOG_PRODUCER_SEND_UNAUTHORIZED

6

AccessKey过期、无效或AccessKey权限策略配置不正确。

检查AccessKey。

RAM用户需具备操作日志服务资源的权限。具体操作,请参见为RAM用户授权。

LOG_PRODUCER_SEND_SERVER_ERROR

7

服务错误

提请工单联系技术支持。

LOG_PRODUCER_SEND_DISCARD_ERROR

8

数据被丢弃,一般是设备时间与服务器时间不同步导致

SDK会自动重新发送。

LOG_PRODUCER_SEND_TIME_ERROR

9

与服务器时间不同步。

SDK会自动修复该问题。

LOG_PRODUCER_SEND_EXIT_BUFFERED

10

SDK销毁时缓存数据还没有发出。

建议开启断点续传功能可避免数据丢失。

LOG_PRODUCER_PARAMETERS_INVALID

11

SDK初始化参数错误

检查AccessKey、Endpoint、Project、Logstore等参数配置。

LOG_PRODUCER_PERSISTENT_ERROR

99

缓存数据写入磁盘失败

1、检查缓存文件路径配置不正确。

2、检查缓存文件是否写满

3、检查系统磁盘空间是否充足。

常见问题

为什么会存在重复日志?

iOS SDK发送日志的过程是异步的,受网络状态影响,日志可能会发送失败并重新发送。由于SDK只在接口返回200状态码时才认为发送成功,因此日志会存在一定的重复率。建议您通过SQL查询分析语句对数据进行去重。

如果日志重复率较高,您需要先排查下SDK初始化是否存在问题。主要原因和解决方案如下:

  • 断点续传配置错误

    针对断点续传配置错误,您需要确认下SetPersistentFilePath方法传入的文件路径是否全局唯一。

  • SDK重复初始化

    • 造成SDK重复初始化的常见原因是单个实例写法错误,或者没有使用单例模式封装SDK的初始化,建议您参考以下方式完成SDK初始化。

      // AliyunLogHelper.h
      @interface AliyunLogHelper : NSObject
      + (instancetype)sharedInstance;
      - (void) addLog:(Log *)log;
      @end
      
      
      // AliyunLogHelper.m
      @interface AliyunLogHelper ()
      @property(nonatomic, strong) LogProducerConfig *config;
      @property(nonatomic, strong) LogProducerClient *client;
      @end
      
      @implementation AliyunLogHelper
      
      + (instancetype)sharedInstance {
          static AliyunLogHelper *sharedInstance = nil;
          static dispatch_once_t onceToken;
          dispatch_once(&onceToken, ^{
              sharedInstance = [[self alloc] init];
          });
          return sharedInstance;
      }
      
      - (instancetype)init {
          self = [super init];
          if (self) {
              [self initLogProducer];
          }
          return self;
      }
      
      - (void) initLogProducer {
          // 以下代码替换为您的初始化代码。
          _config = [[LogProducerConfig alloc] initWithEndpoint:@""
                                                        project:@""
                                                       logstore:@""
                                                    accessKeyID:@""
                                                accessKeySecret:@""
                                                  securityToken:@""
          ];
      
          _client = [[LogProducerClient alloc] initWithLogProducerConfig:_config callback:_on_log_send_done];
      }
      
      - (void) addLog:(Log *)log {
          if (nil == log) {
              return;
          }
      
          [_client AddLog:log];
      }
      
      @end
    • 另外一个造成SDK重复初始化的原因是多进程。建议您只在主进程中初始化SDK,或者在不同进程中初始化SDK时,设置SetPersistentFilePath为不同的值,确保唯一性。

  • 弱网环境配置优化

    如果您的应用是在弱网环境下使用,建议您参考如下示例优化SDK配置参数。

    // 初始化SDK。
    - (void) initProducer() {
        // 调整HTTP链接和发送超时时间,有利于减少日志重复率。
        // 您可以根据实际情况调整具体的超时时间。
        [_config SetConnectTimeoutSec:20];
        [_config SetSendTimeoutSec:20];
      
        // 其他初始化参数。
        // ...
    }

日志缺失,如何处理?

日志上报的过程是异步的,如果在上报日志前App被关闭,则日志有可能无法被上报,造成日志丢失。建议您开启断点续传功能。具体操作,请参见断点续传。

日志上报延时,如何处理?

SDK发送日志的过程是异步的,受网络环境以及应用使用场景的影响,日志可能不会立即上报。如果只有个别设备出现日志上报延时,这种情况是正常的,否则请您根据如下错误码进行排查。

错误码

说明

LOG_PRODUCER_SEND_NETWORK_ERROR

检查Endpoint、Project、Logstore的配置是否正确。

LOG_PRODUCER_SEND_UNAUTHORIZED

检查AccessKey是否过期、有效或AccessKey权限策略配置是否正确。

LOG_PRODUCER_SEND_QUOTA_ERROR

调整Project写入流量已达上限。具体操作,请参见调整资源配额。

内容没看懂? 不太想学习?想快速解决? 有偿解决: 联系专家

阿里云企业补贴进行中: 马上申请

腾讯云限时活动1折起,即将结束: 马上收藏

同尘科技为腾讯云授权服务中心。

购买腾讯云产品享受折上折,更有现金返利:同意关联,立享优惠

转转请注明出处:https://www.yunxiaoer.com/163293.html

(0)
上一篇 2023年12月10日
下一篇 2023年12月10日
详情页2

相关推荐

  • 阿里云日志服务SLS快速入门-云淘科技

    本文以采集分析ECS的Nginx访问日志为例,介绍开通日志服务、创建日志项目与Logstore、Logtail采集日志、查询与分析日志等步骤,帮助您快速上手使用日志服务。 前提条件 已有可用的ECS。更多信息,请参见云服务器ECS快速入门。 ECS服务器持续产生日志。 重要 Logtail只采集增量日志。如果下发Logtail配置后,日志文件无更新,则Log…

    阿里云日志服务SLS 2023年12月10日
  • 阿里云日志服务SLS快速设置日志告警-云淘科技

    日志服务支持您为查询和分析结果设置告警监控规则,并在满足条件时触发告警。本文以网站访问日志为例,说明如何快速为日志设置告警。 前提条件 已在数据实验室中生成模拟的网站访问日志。具体操作,请参见使用数据实验室。 背景信息 日志服务数据实验室提供模拟的网站访问日志及相关仪表盘(网站审计中心、网站访问中心等),便于您熟悉查询、分析、告警等操作。本案例以监控网站审计…

    2023年12月10日
  • 腾讯云对象存储请求速率与性能优化

    注意当前 COS 已经通过底层索引打散机制实现高 QPS,如果有需要更高性能的 QPS 需求,可以 联系我们。在日常组织文件过程中,我们仍然推荐您遵循本文档的要求,避免过于集中的索引存储方式。 简介 本文探讨请求速率性能优化在腾讯云对象存储(Cloud Object Storage,COS)上的最佳实践。腾讯云对象存储提供的典型工作负载能力为每秒30000个…

    腾讯云 2023年12月9日
  • 信息流广告,信息流部分建议宽度830px,只针对默认列表样式,顺序随机
  • 腾讯云负载均衡负载均衡快速入门

    腾讯云负载均衡支持 TCP、UDP、TCP SSL、HTTP 和 HTTPS 协议,提供基于域名和 URL 路径的灵活转发能力。本文将引导您如何快速创建一个负载均衡(CLB)实例,并将来自客户端的访问请求转发到两台后端云服务器(CVM)上。 前提条件 1. 已创建两个云服务器实例(本文以 rs-1 和 rs-2 实例为例)。有关如何创建云服务器实例,请参考 …

    2023年12月9日
  • 腾讯云CVM服务器快速配置 Windows 云服务器

    说明如果您是首次使用云服务器,建议您先选择轻量应用服务器(Lighthouse)来作为云服务器使用的入门途径,详情请参见 快速配置轻量应用服务器 Windows 实例。轻量应用服务器专为云开发者及云计算入门者设计,您可前往 与云服务器 CVM 对比 了解云服务器与轻量应用服务器的区别。本文主要介绍如何从零开始,以最简单的方式搭建一个 Windows 云服务器…

    2023年12月9日

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
本站为广大会员提供阿里云、腾讯云、华为云、百度云等一线大厂的购买,续费优惠,保证底价,买贵退差。