All Products
Search
Document Center

Simple Log Service:Get started with Simple Log Service SDK for iOS

Last Updated:Nov 29, 2023

This topic describes how to use Simple Log Service SDK for iOS to collect logs.

Prerequisites

Simple Log Service SDK for iOS is installed. For more information, see Install Simple Log Service SDK for iOS.

Quick start

You can use the following method to initialize the SDK and call the addLog method to upload logs to Simple Log Service.

Important
  • You can use Simple Log Service SDK for iOS to initialize multiple instances. You must initialize the LogProducerConfig and LogProducerClient instances at a time.

  • You must use the AccessKey pair of an Alibaba Cloud account or a Resource Access Management (RAM) user for authentication and tamper proofing when you upload logs to Simple Log Service. If you store the AccessKey pair in mobile apps, risks may occur. To prevent the risks from occurring, we recommend that you configure an AccessKey pair based on the direct data transfer service to upload logs from mobile apps to Simple Log Service. For more information, see Build a service to upload logs from mobile apps to Simple Log Service.

@interface ProducerExampleController ()
// We recommend that you globally save the LogProducerConfig and LogProducerClient instances. 
@property(nonatomic, strong) LogProducerConfig *config;
@property(nonatomic, strong) LogProducerClient *client;
@end

@implementation ProducerExampleController


// The callback method is optional. You do not need to register a callback if you are not concerned about whether a log is successfully uploaded. 
// If you need to dynamically configure an AccessKey pair, we recommend that you configure the callback method and configure settings to update the AccessKey pair when you call the callback method. 
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 {
    // The Simple Log Service endpoint. The endpoint must start with https:// or http://. 
    NSString *endpoint = @"your endpoint";
    NSString *project = @"your project";
    NSString *logstore = @"your logstore";

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

    // The topic of logs. 
    [_config SetTopic:@"example_topic"];
    // The tag, which is added to all logs. 
    [_config AddTag:@"example" value:@"example_tag"];
    // Specify whether to discard an expired log. The value 0 specifies that an expired log is not discarded and the time of the log is changed to the current time. The value 1 specifies that an expired log is discarded. Default value: 1. 
    [_config SetDropDelayLog:1];
    // Specify whether to discard a log for which authentication failed. The value 0 specifies that a log is not discarded. The value 1 specifies that a log is discarded. Default value: 0. 
    [_config SetDropUnauthorizedLog:0];    

    // Pass callback as the second parameter if you are concerned about whether a log is successfully uploaded. 
    _client = [[LogProducerClient alloc] initWithLogProducerConfig:_config callback:_on_log_send_done];
}

// Query the AccessKey pair. 
- (void) requestAccessKey {
    // We recommend that you configure an AccessKey pair based on the direct data transfer service. 
    // ...

    // After you obtain the AccessKey pair, initiate a call to update the AccessKey pair. 
    [self updateAccessKey:accessKeyId accessKeySecret:accessKeySecret securityToken:securityToken];
}

// Update the AccessKey pair. 
- (void) updateAccessKey:(NSString *)accessKeyId accessKeySecret:(NSString *)accessKeySecret securityToken:(NSString *)securityToken {
    
    // If you obtain an AccessKey pair by using Security Token Service (STS), the AccessKey pair contains securityToken. In this case, you must update the AccessKey pair by using the following method: 
    if (securityToken.length > 0) {
        if (accessKeyId.length > 0 && accessKeySecret.length > 0) {
            [_config ResetSecurityToken:accessKeyId
                        accessKeySecret:accessKeySecret
                          securityToken:securityToken
            ];
        }
    } else {
        // If you obtain an AccessKey pair by using a method other than STS, update the AccessKey pair by using the following method: 
        if (accessKeyId.length > 0 && accessKeySecret.length > 0) {
            [_config setAccessKeyId: accessKeyId];
            [_config setAccessKeySecret: accessKeySecret];
        }
    }
}
// Upload logs. 
- (void) addLog {
    Log *log = [Log log];
    // Adjust the fields that you want to upload based on your business requirements. 
    [log putContent:@"content_key_1" intValue:123456];
    [log putContent:@"content_key_2" floatValue:23.34f];
    [log putContent:@"content_key_3" value:@"Chinese"];
    
    [_client AddLog:log];
}
@end

Advanced operations

Dynamically configure parameters

You can use Simple Log Service SDK for iOS to dynamically configure the Endpoint, Project, Logstore, and AccessKey parameters.

  • Dynamically configure the Endpoint, Project, and Logstore parameters.

    // You can configure one or more of the Endpoint, Project, and Logstore parameters at a time. 
    // Update the endpoint. 
    [_config setEndpoint:@"your new-endpoint"];
    // Update the project. 
    [_config setProject:@"your new-project"];
    // Update the Logstore. 
    [_config setLogstore:@"your new-logstore"];
  • Dynamically configure the AccessKey parameter.

    If you dynamically configure an AccessKey pair, we recommend that you also configure the callback method.

    // If the callback method is initialized when you initialize the LogProducerClient instance, ignore the following code: 
    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 specifies the ownership of the current class. 
        }
    }
    
    // Pass callback as the second parameter if you are concerned about whether a log is successfully uploaded. 
    _client = [[LogProducerClient alloc] initWithLogProducerConfig:_config callback:_on_log_send_done];
    
    // Query the AccessKey pair. 
    - (void) requestAccessKey {
        // We recommend that you configure an AccessKey pair based on the direct data transfer service. 
        // ...
    
        // After you obtain the AccessKey pair, initiate a call to update the AccessKey pair. 
        [self updateAccessKey:accessKeyId accessKeySecret:accessKeySecret securityToken:securityToken];
    }
    
    // Update the AccessKey pair. 
    - (void) updateAccessKey:(NSString *)accessKeyId accessKeySecret:(NSString *)accessKeySecret securityToken:(NSString *)securityToken {
        
        // If you obtain an AccessKey pair by using STS, the AccessKey pair contains securityToken. In this case, you must update the AccessKey pair by using the following method: 
        if (securityToken.length > 0) {
            if (accessKeyId.length > 0 && accessKeySecret.length > 0) {
                [_config ResetSecurityToken:accessKeyId
                            accessKeySecret:accessKeySecret
                              securityToken:securityToken
                ];
            }
        } else {
            // If you obtain an AccessKey pair by using a method other than STS, update the AccessKey pair by using the following method: 
            if (accessKeyId.length > 0 && accessKeySecret.length > 0) {
                [_config setAccessKeyId: accessKeyId];
                [_config setAccessKeySecret: accessKeySecret];
            }
        }
    }
  • Dynamically configure the Source, Topic, and Tag parameters.

    Important

    You can configure the Source, Topic, or Tag parameters only for specific types of logs. The settings of the Source, Topic, and Tag parameters take effect on logs that fail to be uploaded to Simple Log Service. If you want to trace a specific type of logs based on the Source, Topic, and Tag parameters, the result may not meet your expectations. We recommend that you add a new field to identify the type of the logs that are generated.

    // The topic of logs. 
    [_config SetTopic:@"your new-topic"];
    // The source of logs. 
    [_config SetSource:@"your new-source"];
    // The tag, which is added to all logs. 
    [_config AddTag:@"test" value:@"your new-tag"];

Perform resumable upload

Simple Log Service SDK for iOS supports resumable upload. After you enable resumable upload, the logs that are written to Simple Log Service by using the addLog method are temporarily stored in a local binlog file. If the logs are successfully uploaded to Simple Log Service, the logs are deleted from the local file. This ensures the successful implementation of the at-least-once semantics during log upload.

You can add the following code when you initialize the SDK to enable resumable upload.

Important
  • When you initialize multiple LogProducerConfig instances, you must pass different values to the setPersistentFilePath method of the LogProducerConfig class.

  • If multiple processes are running and resumable upload is enabled for your app, you need to only initialize the SDK in the main process. If child processes run to collect data, you must pass unique file paths to the setPersistentFilePath method. Otherwise, logs may be disordered or lost.

  • After resumable upload is enabled, take note of repeated initialization of LogProducerConfig instances caused by the configuration of multiple threads.

- (void) initLogProducer {
    // The value 1 specifies that resumable upload is enabled. The value 0 specifies that resumable upload is disabled. Default value: 0. 
    [_config SetPersistent:1];
    
    // The name of the persistent file. Make sure that the folder in which the file is stored is created. 
    NSArray  *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *Path = [[paths lastObject] stringByAppendingString:@"/log.dat"];
    [_config SetPersistentFilePath:Path];
    // The number of persistent files that can be rolled. We recommend that you set the parameter to 10. 
    [_config SetPersistentMaxFileCount:10];
    // The size of a persistent file. Unit: bytes. The value is calculated based on the following formula: N × 1024 × 1024. We recommend that you set N to a value ranging from 1 to 10. 
    [_config SetPersistentMaxFileSize:N*1024*1024];
    // The number of logs that can be cached on your computer. We recommend that you do not set the parameter to a value greater than 1048576. Default value: 65536. 
    [_config SetPersistentMaxLogCount:65536];
}

Parameters

The following table describes the parameters that are provided by the LogProducerConfig class.

Parameter

Type

Description

SetTopic

String

The topic. The default value is an empty string.

AddTag

String

The tag. The tag is in the tag:xxxx format. The default value is an empty string.

SetSource

String

The source. Default value: iOS.

SetPacketLogBytes

Int

The upper limit of the size for a cached log packet. If the size reaches the upper limit, logs in the log packet are immediately uploaded to Simple Log Service.

Valid values: 1 to 5242880. The default value is calculated based on the following formula: 1024 × 1024. Unit: bytes.

SetPacketLogCount

Int

The upper limit of the number of logs in a cached log packet. If the number reaches the upper limit, logs in the log packet are immediately uploaded to Simple Log Service.

Valid values: 1 to 4096. Default value: 1024.

SetPacketTimeout

Int

The timeout period for uploading cached logs. If cached logs time out, the cached logs are immediately uploaded to Simple Log Service.

Default value: 3000. Unit: milliseconds.

SetMaxBufferLimit

Int

The upper limit of memory that can be consumed by a LogProducerClient instance. If the memory that is consumed reaches the upper limit, a call of the addLog method fails, and an error message is returned.

The default value is calculated based on the following formula: 64 × 1024 × 1024.

SetPersistent

Int

Specifies whether to enable resumable upload. Valid values:

  • 1: yes.

  • 0 (default): no.

SetPersistentFilePath

String

The name of the persistent file. Make sure that the folder in which the file is stored is created. If you want to configure multiple LogProducerConfig instances, specify a unique value for the setPersistentFilePath parameter.

This parameter is empty by default.

SetPersistentForceFlush

Int

Specifies whether to enable forceful refresh for each call of the addLog method. Valid values:

  • 1: yes. If you enable forceful refresh, system performance is affected. Proceed with caution.

  • 0 (default): no.

We recommend that you enable forceful refresh in high-reliability scenarios.

SetPersistentMaxFileCount

Int

The number of persistent files that can be rolled. We recommend that you set the parameter to a value ranging from 1 to 10. Default value: 10.

SetPersistentMaxFileSize

Int

The size of a persistent file. Unit: bytes. The value is calculated based on the following formula: N × 1024 × 1024. We recommend that you set N to a value ranging from 1 to 10.

SetPersistentMaxLogCount

Int

The number of logs that can be cached on your computer. We recommend that you do not set the parameter to a value greater than 1048576. Default value: 65536.

SetConnectTimeoutSec

IntInt

The timeout period of a network connection. Default value: 10. Unit: seconds.

SetSendTimeoutSec

Int

The timeout period for uploading logs. Default value: 15. Unit: seconds.

SetDestroyFlusherWaitSec

Int

The maximum waiting time for the flusher thread to be destroyed. Default value: 1. Unit: seconds.

SetDestroySenderWaitSec

Int

The maximum waiting time for the sender thread pool to be destroyed. Default value: 1. Unit: seconds.

SetCompressType

Int

The compression method that is used during data upload. Valid values:

  • 0: Data is not compressed.

  • 1 (default): Data is compressed by using the LZ4 algorithm.

SetNtpTimeOffset

Int

The difference between the system time and standard time. The value is calculated based on the following formula: Standard time - Device time. In most cases, the difference is generated because the system time is not synchronized with the standard time. Default value: 0. Unit: seconds.

SetMaxLogDelayTime

Int

The upper limit of the difference between the time of a log and the system time. If the difference reaches the upper limit, the SDK handles the log based on the value of the setDropDelayLog parameter. Default value: 7243600, which is equivalent to 7 days. Unit: seconds.

SetDropDelayLog

Int

Specifies whether to discard an expired log. If the difference between the time of a log and the system time exceeds the value of the setMaxLogDelayTime parameter, the log is considered an expired log. Valid values:

  • 0 (default): The expired log is not discarded, and the time of the log is changed to the current time.

  • 1: The expired log is discarded.

SetDropUnauthorizedLog

Int

Specifies whether to discard a log for which authentication failed. Valid values:

  • 0 (default): no.

  • 1: yes.

Error codes

The following table describes the error codes.

Error code

Value

Description

Solution

LOG_PRODUCER_OK

0

Logs are uploaded to Simple Log Service.

N/A.

LOG_PRODUCER_INVALID

1

The SDK is destroyed or invalid.

  1. Check whether the SDK is initialized.

  2. Check whether the destroy() method is called.

LOG_PRODUCER_WRITE_ERROR

2

A data write error occurs because the write traffic of the project reaches the upper limit.

Adjust the upper limit of write traffic for the project. For more information, see Adjust resource quotas.

LOG_PRODUCER_DROP_ERROR

3

Logs fail to be uploaded to Simple Log Service because the disk space or memory is insufficient.

Modify the maxBufferLimit, persistentMaxLogCount, and persistentMaxFileSize parameters and upload the logs to Simple Log Service again.

LOG_PRODUCER_SEND_NETWORK_ERROR

4

A network error occurs.

Check the settings of the Endpoint, Project, and Logstore parameters.

LOG_PRODUCER_SEND_QUOTA_ERROR

5

The write traffic of the project reaches the upper limit.

Adjust the upper limit of write traffic for the project. For more information, see Adjust resource quotas.

LOG_PRODUCER_SEND_UNAUTHORIZED

6

The AccessKey pair is expired or invalid, or the policy of the RAM user to which the AccessKey pair belongs is incorrectly configured.

Check the AccessKey pair.

Make sure that the RAM user has the management permissions on Simple Log Service resources. For more information, see Create a RAM user and authorize the RAM user to access Simple Log Service.

LOG_PRODUCER_SEND_SERVER_ERROR

7

A service error occurs.

Submit a ticket to contact technical support.

LOG_PRODUCER_SEND_DISCARD_ERROR

8

Data is discarded because the system time is not synchronized with the server time.

The SDK automatically uploads the data again.

LOG_PRODUCER_SEND_TIME_ERROR

9

The time of the log is not synchronized with the server time.

The SDK automatically fixes the error.

LOG_PRODUCER_SEND_EXIT_BUFFERED

10

The cached data is not uploaded to Simple Log Service when the SDK is destroyed.

To prevent data loss, we recommend that you enable resumable upload.

LOG_PRODUCER_PARAMETERS_INVALID

11

A parameter error occurs during SDK initialization.

Check the settings of the AccessKey, Endpoint, Project, and Logstore parameters.

LOG_PRODUCER_PERSISTENT_ERROR

99

Cached data fails to be written to the system disk.

1. Check whether the path to the cached file is correctly configured.

2. Check whether the cached file is full.

3. Check whether the system disk space is sufficient.

FAQ

Why do duplicate logs exist?

Simple Log Service SDK for iOS asynchronously uploads logs. Logs may fail to be uploaded due to poor network conditions. In this case, the logs are uploaded again. Log upload is considered successful only if status code 200 is returned. Therefore, duplicate logs may exist. We recommend that you execute a query statement to deduplicate logs.

If the duplication rate is high, you need to check whether an error occurs during SDK initialization. The following list describes the causes and solutions to duplicate logs:

  • Invalid configuration for resumable upload

    Check whether a unique value is specified for the setPersistentFilePath parameter.

  • Duplicate SDK initialization

    • In most cases, duplicate SDK initialization is caused by invalid writing of a single instance or because SDK initialization is not encapsulated in singleton mode. We recommend that you complete SDK initialization based on the following method:

      // 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 {
          // Replace the following code with your code for SDK initialization. 
          _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
    • Multiple processes can also cause duplicate SDK initialization. We recommend that you initialize the SDK only in the main process or specify different values for the setPersistentFilePath parameter when you initialize the SDK in multiple processes.

  • Poor network conditions

    If you run an app in poor network conditions, we recommend that you reconfigure parameters for SDK initialization based on the following example:

    // Initialize the SDK. 
    - (void) initProducer() {
        // Change the timeout periods for HTTP connections and log upload to decrease the duplication rate of logs. 
        // You can change the timeout periods based on your business requirements. 
        [_config SetConnectTimeoutSec:20];
        [_config SetSendTimeoutSec:20];
      
        // Configure other parameters for SDK initialization. 
        // ...
    }

What do I do if logs are lost?

Logs are asynchronously uploaded. If your app is closed before the logs are uploaded, logs cannot be uploaded and may be lost. We recommend that you enable resumable upload. For more information, see Resumable upload.

What do I do if latency exists during log upload?

Logs are asynchronously uploaded. Logs may not be immediately uploaded due to poor network conditions and specific scenarios of apps. If latency exists only in several devices, this is normal. Otherwise, troubleshoot the issue based on the following error codes.

Error code

Description

LOG_PRODUCER_SEND_NETWORK_ERROR

Check whether the Endpoint, Project, and Logstore parameters are correctly configured.

LOG_PRODUCER_SEND_UNAUTHORIZED

Check whether the AccessKey pair is expired or valid, or whether the policy of the RAM user to which the AccessKey pair belongs is correctly configured.

LOG_PRODUCER_SEND_QUOTA_ERROR

The write traffic of the project reaches the upper limit. Adjust the upper limit of write traffic for the project. For more information, see Adjust resource quotas.