Todos os produtos
Search
Central de documentação

Simple Log Service:Início rápido para o SDK do Android

Última atualização: Oct 21, 2026

Use o Simple Log Service (SLS) Android SDK para coletar e enviar logs do seu aplicativo Android.

Pré-requisitos

Install the Android SDK.

Início rápido

Inicialize o SDK e chame o método addLog para enviar logs.

Importante
  • O SDK suporta várias instâncias. Cada instância de LogProducerConfig deve ter uma instância correspondente de LogProducerClient.

  • O envio de logs para o SLS exige o AccessKey de uma conta Alibaba Cloud ou de um usuário do Resource Access Management (RAM) para autenticação e proteção contra adulteração. Para evitar riscos de segurança ao armazenar um AccessKey no aplicativo móvel, recomendamos usar o serviço de upload direto de logs móveis para configurar o AccessKey. Para obter mais informações, consulte Collect logs - Build a mobile log direct upload service.

// We recommend that you save the LogProducerConfig and LogProducerClient instances globally.
private LogProducerConfig config = null;
private LogProducerClient client = null;

/**
 * Initialize the SDK.
 */

private void initProducer() {
    try {
        // The service endpoint of SLS. The endpoint must start with https:// or http://.
        final String endpoint = "your endpoint";
        final String project = "your project";
        final String logstore = "your logstore";

        config = new LogProducerConfig(context, endpoint, project, logstore);
        // Set the log topic.
        config.setTopic("example_topic");
        // Set the tag information. This tag is added to each log.
        config.addTag("example", "example_tag");

        // Specifies whether to discard expired logs. 0: Do not discard the logs. The log time is changed to the current time. 1: Discard the logs. Default value: 1.
        config.setDropDelayLog(0);
        // Specifies whether to discard logs that fail authentication. 0: Do not discard the logs. 1: Discard the logs. Default value: 0.
        config.setDropUnauthorizedLog(0);

        // LogProducerCallback is an optional configuration. If you do not need to follow the success or failure status of log sending, you do not need to register a callback.
        // To dynamically configure the AccessKey, set LogProducerCallback and update the AccessKey when the onCall method is invoked.
        final LogProducerCallback callback = new LogProducerCallback() {
            @Override
            public void onCall(int resultCode, String reqId, String errorMessage, int logBytes, int compressedBytes) {
                // resultCode: the status code. For more information, see Error codes.
                // reqId: the request ID. This parameter is deprecated.
                // errorMessage: the failure information.
                // logBytes: the original log size in bytes.
                // compressedBytes: the compressed log size in bytes.

                final LogProducerResult result = LogProducerResult.fromInt(resultCode);
                if (LogProducerResult.LOG_PRODUCER_SEND_UNAUTHORIZED == result || LogProducerResult.LOG_PRODUCER_PARAMETERS_INVALID == result) {
                    // Update the AccessKey or the initialization parameters of the SDK.
                }
            }
        };
      
        // To follow the success or failure status of log sending, you must pass a callback as the second parameter.
        client = new LogProducerClient(config, callback);
    } catch (LogProducerException e) {
        e.printStackTrace();
    }
}
// Request the AccessKey information.
private void requestAccessKey() {
    // We recommend that you use the mobile log direct upload service to configure the AccessKey information.
    // ...

    // After you obtain the AccessKey information, update it.
    updateAccessKey(accessKeyId, accessKeySecret, securityToken);
}

// Update the AccessKey information.
private void updateAccessKey(String accessKeyId, String accessKeySecret, String securityToken) {
    // The AccessKey obtained from Security Token Service (STS) contains a securityToken. You must update the AccessKey in the following way.
    if (null != securityToken && !"".equals(securityToken)) {
        config.resetSecurityToken(accessKeyId, accessKeySecret, securityToken);
    } else {
        // If the AccessKey is not obtained from STS, update the AccessKey in the following way.
        config.setAccessKeyId(accessKeyId);
        config.setAccessKeySecret(accessKeySecret);
    }
}

/**
 * Report logs.
 */
public void addLog() {
    Log log = new Log();
    // Adjust the fields to be reported as needed.
    log.putContent("content_key_1", 123456);
    log.putContent("content_key_2", 23.34f);
    log.putContent("content_key_3", "Chinese️");
    log.putContent(null, "null");
    log.putContent("null", (String) null);
    client.addLog(log);
}

Recursos avançados

Configurar parâmetros dinamicamente

O SDK do Android permite configurar dinamicamente parâmetros como Endpoint, ProjectName, Logstore e AccessKey.

  • Configure dinamicamente o Endpoint, ProjectName e logstore.

    // Configure parameters such as Endpoint, ProjectName, and logstore together or separately.
    // Update the endpoint.
    config.setEndpoint("your new-endpoint");
    // Update the project name.
    config.setProject("your new-project");
    // Update the logstore name.
    config.setLogstore("your new-logstore");
  • Configure o AccessKey dinamicamente.

    Ao configurar o AccessKey dinamicamente, recomendamos usá-lo com o LogProducerCallback.

    // If you have initialized LogProducerCallback when you initialized LogProducerClient, ignore the following code.
    final LogProducerCallback callback = new LogProducerCallback() {
        @Override
        public void onCall(int resultCode, String reqId, String errorMessage, int logBytes, int compressedBytes) {
            // resultCode: the status code. For more information, see Error codes.
            // reqId: the request ID. This parameter is deprecated.
            // errorMessage: the failure information.
            // logBytes: the original log size in bytes.
            // compressedBytes: the compressed log size in bytes.
    
            final LogProducerResult result = LogProducerResult.fromInt(resultCode);
            if (LogProducerResult.LOG_PRODUCER_SEND_UNAUTHORIZED == result || LogProducerResult.LOG_PRODUCER_PARAMETERS_INVALID == result) {
                // You need to update the AccessKey or the initialization parameters of the SDK.
                requestAccessKey();
            }
        }
    };
    
    // To follow the success or failure status of log sending, you must pass a callback as the second parameter.
    client = new LogProducerClient(config, callback);
    
    // Request the AccessKey information.
    private void requestAccessKey() {
        // We recommend that you use the mobile log direct upload service to configure the AccessKey information.
        // ...
    
        // After you obtain the AccessKey information, update it.
        updateAccessKey(accessKeyId, accessKeySecret, securityToken);
    }
    
    // Update the AccessKey information.
    private void updateAccessKey(String accessKeyId, String accessKeySecret, String securityToken) {
        // The AccessKey obtained from STS contains a securityToken. You must update the AccessKey in the following way.
        if (null != securityToken && !"".equals(securityToken)) {
            config.resetSecurityToken(accessKeyId, accessKeySecret, securityToken);
        } else {
            // If the AccessKey is not obtained from STS, update the AccessKey in the following way.
            config.setAccessKeyId(accessKeyId);
            config.setAccessKeySecret(accessKeySecret);
        }
    }
  • Defina dinamicamente source, topic e tag.

    Importante

    Não é possível definir source, topic ou tag para um tipo específico de log. Esses parâmetros se aplicam a todos os logs pendentes de envio para o SLS. Se você usar source, topic e tag para rastrear tipos específicos de log, os resultados podem ser imprecisos. Recomendamos adicionar campos durante a geração do log para identificar o tipo.

    // Set the log source.
    config.setSource("your new-source");
    // Set the log topic.
    config.setTopic("your new-topic");
    // Set the tag information. This tag is added to each log.
    config.addTag("test", "your new-tag");

Upload retomável

O SDK do Android oferece suporte a upload retomável. Ao ativar esse recurso, os logs adicionados pelo método addLog são salvos em um arquivo binlog local. Os dados locais são excluídos apenas após o envio bem-sucedido dos logs, garantindo a entrega pelo menos uma vez.

Adicione o código a seguir durante a inicialização do SDK para ativar o upload retomável.

Importante
  • Ao inicializar várias instâncias de LogProducerConfig, o método setPersistentFilePath de cada instância de LogProducerConfig deve receber um valor exclusivo.

  • Se o aplicativo usar vários processos com o upload retomável ativado, inicialize o SDK apenas no processo principal. Se processos secundários também precisarem coletar dados, garanta que o caminho de arquivo especificado em setPersistentFilePath seja único para cada processo. Caso contrário, pode haver perda ou corrupção de dados de log.

  • Evite reinicializar o LogProducerConfig em várias threads ao usar o SDK.

private void initProducer() {
    // 1: enables the resumable upload feature. 0: disables the feature. Default value: 0.
    config.setPersistent(1);
    // The name of the persistence file. Make sure that the folder where the file is located has been created.
    final String persistentFilePath = getFilesDir() + File.separator + "log_data";
    config.setPersistentFilePath(persistentFilePath);
    // The number of scrolling persistence files. We recommend that you set this parameter to 10.
    config.setPersistentMaxFileCount(10);
    // The size of each persistence file. Unit: bytes. The format is N*1024*1024. We recommend that you set N to a value from 1 to 10.
    config.setPersistentMaxFileSize(N*1024*1024);
    // The maximum number of logs that can be cached locally. We recommend that you do not set this parameter to a value greater than 1,048,576. Default value: 65,536.
    config.setPersistentMaxLogCount(65536);
}

Regras de obfuscação

-keep class com.aliyun.sls.android.producer.** { *; }
-keep interface com.aliyun.sls.android.producer.** { *; }

Permissões do Android

<uses-permission android:name="android.permission.INTERNET" />

Parâmetros de configuração

A classe LogProducerConfig fornece todos os parâmetros de configuração.

Parâmetro

Tipo de dados

Descrição

setTopic

String

Define o valor do campo topic. O valor padrão é uma string vazia.

addTag

String

Define uma tag. O formato é tag:xxxx. O valor padrão é uma string vazia.

setSource

String

Define o valor do campo source. O valor padrão é Android.

setPacketLogBytes

Int

Tamanho máximo de cada pacote de logs em cache. Os logs são enviados imediatamente quando esse limite é excedido.

Valores válidos: 1 a 5.242.880. Valor padrão: 1024 × 1024. Unidade: bytes.

setPacketLogCount

Int

Número máximo de logs em cada pacote de logs em cache. Os logs são enviados imediatamente quando esse limite é excedido.

Valores válidos: 1 a 4.096. Valor padrão: 1.024.

setPacketTimeout

Int

Tempo limite para logs em cache. Os logs são enviados imediatamente quando esse tempo expira.

Valor padrão: 3.000. Unidade: milissegundos.

setMaxBufferLimit

Int

Memória máxima que uma única instância do Producer Client pode usar. Quando esse limite é excedido, a interface add_log retorna falha imediatamente.

Valor padrão: 64 × 1024 × 1024.

setSendThreadCount

Int

Número de threads de envio. Se o upload retomável estiver ativado, esse parâmetro será definido forçadamente como 1.

setPersistent

Int

Indica se o recurso de upload retomável deve ser ativado.

  • 1: Ativar.

  • 0 (padrão): Desativar.

setPersistentFilePath

String

Nome do arquivo de persistência. Certifique-se de que a pasta pai exista. Ao configurar várias instâncias de LogProducerConfig, cada nome deve ser exclusivo.

O valor padrão é vazio.

setPersistentForceFlush

Int

Determina se os logs devem ser gravados em disco sempre que AddLog for chamado.

  • 1: Ativar. Isso afeta o desempenho. Ative com cautela.

  • 0 (padrão): Desativar.

Ative este recurso em cenários de alta confiabilidade.

setPersistentMaxFileCount

Int

Número de arquivos de persistência rotativos. Recomenda-se definir este parâmetro como 10. Valor padrão: 0.

setPersistentMaxFileSize

Int

Tamanho de cada arquivo de persistência. Unidade: bytes. O formato é N × 1024 × 1024. Recomenda-se definir N com um valor entre 1 e 10.

setPersistentMaxLogCount

Int

Número máximo de logs que podem ser armazenados em cache localmente. Recomenda-se não definir este parâmetro com valor superior a 1.048.576. Valor padrão: 65.536.

setConnectTimeoutSec

Int

Tempo limite de conexão de rede. Valor padrão: 10. Unidade: segundos.

setSendTimeoutSec

Int

Tempo limite para envio de logs. Valor padrão: 15. Unidade: segundos.

setDestroyFlusherWaitSec

Int

Tempo máximo de espera para destruir a thread flusher. Valor padrão: 1. Unidade: segundos.

setDestroySenderWaitSec

Int

Tempo máximo de espera para destruir o pool de threads de envio. Valor padrão: 1. Unidade: segundos.

setCompressType

Int

Tipo de compressão para upload de dados.

  • 0: Sem compressão.

  • 1 (padrão): Compressão LZ4.

setNtpTimeOffset

Int

Diferença entre a hora do dispositivo e a hora padrão. O valor é Hora Padrão - Hora do Dispositivo. Essa diferença geralmente ocorre quando a hora do dispositivo cliente do usuário não está sincronizada. Valor padrão: 0. Unidade: segundos.

setMaxLogDelayTime

Int

Diferença entre a hora do log e a hora local. Se a diferença exceder este valor, o SDK tratará o log conforme a configuração setDropDelayLog. Unidade: segundos. Valor padrão: 7.243.600 (7 dias).

setDropDelayLog

Int

Indica se logs expirados que excedem setMaxLogDelayTime devem ser descartados.

  • 0 (padrão): Não descartar os logs. A hora do log é alterada para a hora atual.

  • 1: Descartar.

setDropUnauthorizedLog

Int

Indica se logs que falham na autenticação devem ser descartados.

  • 0 (padrão): Não descartar os logs.

  • 1: Descartar.

setCallbackFromSenderThread

Boolean

Define se o callback deve ser executado a partir da thread de envio.

  • true (padrão): Executar callback a partir da thread de envio.

  • false: Executar callback a partir da thread principal.

Códigos de erro

Todos os códigos de erro estão definidos na enumeração LogProducerResult.

Código de erro

Valor

Descrição

Solução

LOG_PRODUCER_OK

0

Sucesso.

Não aplicável.

LOG_PRODUCER_INVALID

1

O SDK foi destruído ou é inválido.

  1. Verifique se o SDK foi inicializado corretamente.

  2. Verifique se o método destroy() foi chamado.

LOG_PRODUCER_WRITE_ERROR

2

Ocorreu um erro de gravação de dados. O tráfego de gravação do projeto pode ter atingido o limite superior.

Ajuste o limite superior do tráfego de gravação do projeto. Para obter mais informações, consulte Adjust resource quotas.

LOG_PRODUCER_DROP_ERROR

3

O cache de disco ou memória está cheio e não é possível gravar logs.

Ajuste os valores dos parâmetros maxBufferLimit, persistentMaxLogCount e persistentMaxFileSize e tente novamente.

LOG_PRODUCER_SEND_NETWORK_ERROR

4

Ocorreu um erro de rede.

Verifique as configurações de Endpoint, Project e logstore.

LOG_PRODUCER_SEND_QUOTA_ERROR

5

O tráfego de gravação do projeto atingiu o limite superior.

Ajuste o limite superior do tráfego de gravação do projeto. Para obter mais informações, consulte Adjust resource quotas.

LOG_PRODUCER_SEND_UNAUTHORIZED

6

O AccessKey expirou, é inválido ou a política de acesso do AccessKey está configurada incorretamente.

Verifique o AccessKey.

O usuário RAM deve ter permissões para operar recursos do SLS. Para obter mais informações, consulte Grant permissions to a RAM user.

LOG_PRODUCER_SEND_SERVER_ERROR

7

Ocorreu um erro de serviço.

Envie um ticket para entrar em contato com o suporte técnico.

LOG_PRODUCER_SEND_DISCARD_ERROR

8

Dados foram descartados. Geralmente isso ocorre porque a hora do dispositivo não está sincronizada com a hora do servidor.

O SDK reenvia os dados automaticamente.

LOG_PRODUCER_SEND_TIME_ERROR

9

A hora não está sincronizada com a hora do servidor.

O SDK corrige esse problema automaticamente.

LOG_PRODUCER_SEND_EXIT_BUFFERED

10

No momento da destruição do SDK, ainda havia dados em cache não reportados.

Recomendamos ativar o recurso de upload retomável para evitar perda de dados.

LOG_PRODUCER_PARAMETERS_INVALID

11

Os parâmetros de inicialização do SDK são inválidos.

Verifique as configurações de parâmetros como AccessKey, Endpoint, Project e logstore.

LOG_PRODUCER_PERSISTENT_ERROR

99

Falha ao gravar dados em cache no disco.

1. Verifique se o caminho do arquivo de cache está configurado corretamente.

2. Verifique se o arquivo de cache está cheio.

3. Verifique se há espaço suficiente em disco no sistema.

Perguntas frequentes

Por que existem logs duplicados?

O SDK do Android envia logs de forma assíncrona. Devido às condições de rede, um log pode falhar no envio e ser reenviado. O SDK considera uma operação de envio bem-sucedida apenas quando recebe um código de status 200, portanto alguns logs podem ser duplicados. Recomendamos usar consultas SQL e instruções de análise para deduplicar logs.

Se a taxa de duplicação de logs for alta, verifique se há problemas na inicialização do SDK. Causas comuns e soluções:

  • Configuração incorreta de upload retomável

    Se o upload retomável estiver configurado incorretamente, confirme se o caminho de arquivo passado ao método setPersistentFilePath é globalmente exclusivo.

  • Inicialização repetida do SDK

    • Uma causa comum é a implementação incorreta do padrão singleton para inicialização do SDK. Recomendamos a seguinte abordagem.

      public class AliyunLogHelper {
          private LogProducerConfig config;
          private LogProducerClient client;
      
          private static class Holder {
              private static final AliyunLogHelper INSTANCE = new AliyunLogHelper();
          }
      
          public static AliyunLogHelper getInstance() {
              return Holder.INSTANCE;
          }
      
          private AliyunLogHelper() {
              initProducer();
          }
      
          private void initProducer() {
              // Replace the following code with your initialization code.
              try {
                  config = new LogProducerConfig();
                  client = new LogProducerClient(config);
              } catch (LogProducerException e) {
                  e.printStackTrace();
              }
          }
      
          public void addLog(Log log) {
              if (null == client) {
                  return;
              }
      
              client.addLog(log);
          }
      }
    • Outra causa é o uso de vários processos. Inicialize o SDK apenas no processo principal. Se você inicializar o SDK em processos diferentes, defina um valor exclusivo para setPersistentFilePath em cada processo.

  • Otimização de configuração para ambientes de rede instável

    Se o aplicativo for executado em um ambiente de rede instável, otimize os parâmetros de configuração do SDK conforme mostrado no exemplo a seguir.

    // Initialize the SDK.
    private void initProducer() {
        // Adjust the HTTP connection and sending timeout periods to reduce the log duplication rate.
        // Adjust the specific timeout periods as needed.
        config.setConnectTimeoutSec(20);
        config.setSendTimeoutSec(20);
      
        // Other initialization parameters.
        // ...
    }

O que fazer se houver logs ausentes?

O envio de logs é assíncrono. Se o aplicativo for fechado antes que os logs sejam enviados, logs não enviados podem ser perdidos. Recomendamos ativar o recurso de upload retomável. Para obter mais informações, consulte Resumable upload.

O que fazer se houver atraso no reporte de logs?

O SDK envia logs de forma assíncrona. Os logs podem não ser enviados imediatamente devido a condições de rede ou cenários específicos do aplicativo. Atrasos em um pequeno número de dispositivos são normais. Se os atrasos forem generalizados, verifique os seguintes códigos de erro.

Código de erro

Descrição

LOG_PRODUCER_SEND_NETWORK_ERROR

Verifique se as configurações de Endpoint, Project e logstore estão corretas.

LOG_PRODUCER_SEND_UNAUTHORIZED

Verifique se o AccessKey expirou ou é inválido, ou se a política de acesso do AccessKey está configurada corretamente.

LOG_PRODUCER_SEND_QUOTA_ERROR

O tráfego de gravação do projeto atingiu o limite superior. Para obter mais informações, consulte Adjust resource quotas.

O SDK do Android suporta pré-resolução de DNS e políticas de cache?

Use o SDK do Android, o SDK HTTPDNS e o OkHttp para implementar pré-resolução de DNS e políticas de cache.

  1. Implemente uma interface DNS personalizada.

    /**
      * Implement a custom DNS parsing service based on the OkHttp Dns interface for your reference.
      */
    public class OkHttpDns implements Dns {
      private Context mContext;
    
      public OkHttpDns(Context context) {
        mContext = context;
      }
    
      @Override
      public List<InetAddress> lookup(String host) throws UnknownHostException {
        // !!Note!! 
        // Replace accountId with the value that you obtained from the HTTPDNS service. For more information, see the HTTPDNS documentation.
        HTTPDNSResult httpdnsResult = HttpDns.getService(mContext, accountId)
          .getHttpDnsResultForHostSync(host, RequestIpType.both);
        List<InetAddress> inetAddresses = new ArrayList<>();
        InetAddress address;
        try {
          if (httpdnsResult.getIps() != null) {
            // Process IPv4 addresses.
            for (String ipv4 : httpdnsResult.getIps()) {
              address = InetAddress.getByName(ipv4);
              inetAddresses.add(address);
            }
          }
    
          if (httpdnsResult.getIpv6s() != null) {
            // Process IPv6 addresses.
            for (String ipv6 : httpdnsResult.getIpv6s()) {
              address = InetAddress.getByName(ipv6);
              inetAddresses.add(address);
            }
          }
        } catch (UnknownHostException e) {
    
        }
    
        if (!inetAddresses.isEmpty()) {
          return inetAddresses;
        }
    
        return okhttp3.Dns.SYSTEM.lookup(host);
      }
    }
  2. Implemente uma NetworkInterface personalizada.

    /**
       * Implement the NetworkInterface of the SLS SDK based on OkHttp for your reference.
       */
    private static class OkHttpNetworkInterface implements LogProducerHttpTool.NetworkInterface {
    
      private OkHttpClient client;
    
      public OkHttpNetworkInterface(Context context) {
        client = new OkHttpClient.Builder()
          .connectTimeout(30, TimeUnit.SECONDS)
          .readTimeout(30, TimeUnit.SECONDS)
          .writeTimeout(30, TimeUnit.SECONDS)
          .dns(new OkHttpDns(context))
          .build();
      }
    
      @Override
      public NetworkResponse send(String urlString, String method, String[] header, byte[] body) {
        // We recommend that you first call the original implementation of the SDK and then report logs using OkHttp when log reporting fails.
        LogHttpResponse logHttpResponse = LogProducerHttpTool.android_http_post(urlString, method, header, body);
        if (logHttpResponse.getStatusCode() != -1) {
          NetworkResponse response = new NetworkResponse();
          response.statusCode = logHttpResponse.getStatusCode();
          response.errorMessage = logHttpResponse.getErrorMessage();
          return response;
        }
    
        // Report logs using OkHttp.
        Request.Builder builder = new Request.Builder();
        builder.url(urlString);
        builder.post(RequestBody.create(body));
    
        for (int i = 0; i < header.length; i += 2) {
          builder.addHeader(header[i], header[i + 1]);
        }
    
        // Regardless of whether the request is successful, you must return a NetworkResponse. Otherwise, the SDK may not run as expected.
        try (okhttp3.Response response = client.newCall(builder.build()).execute()) {
          NetworkResponse httpResponse = new NetworkResponse();
          httpResponse.statusCode = response.code();
          httpResponse.headers = response.headers().toMultimap();
          httpResponse.errorMessage = response.message();
    
          return httpResponse;
        } catch (IOException e) {
          NetworkResponse httpResponse = new NetworkResponse();
          httpResponse.statusCode = -1;
          httpResponse.headers = null;
          httpResponse.errorMessage = e.getLocalizedMessage();
    
          return httpResponse;
        }
      }
    
    }
    
  3. Inicialize o SDK do SLS.

    public class AliyunSLS {
      private void initSLS(Context context) {
        // Set a custom NetworkInterface for the SLS SDK.
        // !!!Note!!!
        // This setting takes effect for all SLS SDK instances.
        LogProducerHttpTool.setNetworkInterface(new OkHttpNetworkInterface(context));
    
        // Initialize the SLS SDK.
        initProducer();
      }
    
      private void initProducer() {
        // Implement the initialization of LogProducerConfig and LogProducerClient here.
        // ...
      }
    }