
# 云日志服务Net SDK
云日志服务SDK提供了Net语言上报日志的一系列方法，方便用户直接使用编码方式上报日志到云日志服务后台。
#### 传输协议
HTTPS
#### 使用前提
- 参考[注册华为账号并开通华为云](https://support.huaweicloud.com/usermanual-account/account_id_001.html)中操作，完成注册。

- 确认云日志服务的区域，请用户根据所在区域，选择RegionName。
- [获取华为账号的AK/SK](https://support.huaweicloud.com/iam_faq/iam_01_0618.html)。
- 获取华为云账号的项目ID（project id），详细步骤请参见[API凭证](https://support.huaweicloud.com/usermanual-ca/ca_01_0002.html)。
- 获取需要上报到LTS的[日志组ID]和[日志流ID]。
 
#### 使用说明
当用户修改权限后，权限信息在一天后生效。通过SDK上报日志到LTS的时间相距当前时间不超过2天，否则上报日志会被LTS删除。
当前仅华北-北京四、华东-上海一、华南-广州区域使用SDK时支持跨云/本地上报日志，Endpoint端口使用443。
#### 注意事项
认证用的ak和sk硬编码到代码中或者明文存储都有很大的安全风险，建议在配置文件或者环境变量中密文存放，使用时解密，确保安全。
#### 操作步骤
1. 获取LTS Net SDK包源码。 
   ```
   git clone https://gitee.com/lordstar-habile/huaweicloud-lts-dotnet-sdk.git
   ```
   
   
2. 安装相关依赖。 
   ```
   dotnet add package Microsoft.Extensions.Http.Polly --version 8.0.2 
   dotnet add package RestSharp --version 110.2.0 
   dotnet add package Newtonsoft.Json --version 13.0.3
   ```
   
   
3. 编写上报日志代码。 
   可以自定义发送成功与失败时的回调方法，实现CallBack的abstract class，实现Success和Fail方法，并且在发送日志时直接使用。
   ```
   public Error SendLogWithCallBack(string groupId, string streamId, Log log, CallBack callBack)
   ```
   示例如下：
   ```
   using HuaweiCloud.SDK.LTS.Model;
   using Newtonsoft.Json;
   using System;
   using System.Collections.Generic;
   using System.Threading;
   using System.Threading.Tasks;
   namespace HuaweiCloud.SDK.LTS.Sample
   {
       public class Sample
       {
           public static void SendLogToLts(string endpoint, string accessKey, string accessSecret, string region, string projectId, string groupId, string streamId,
               int threadCount, int logItemNum, int HttpTimeout, int LingerMs, string logContent, long maxIO)
           {
               Console.WriteLine("start time is: {0}", DateTimeOffset.Now.ToUnixTimeMilliseconds());
               var producerConfig = Config.GetConfig();
               producerConfig.LingerMs = LingerMs;
               producerConfig.Endpoint = endpoint;
               producerConfig.AccessKeyID = accessKey;
               producerConfig.AccessKeySecret = accessSecret;
               producerConfig.RegionId = region;
               producerConfig.ProjectId = projectId;
               producerConfig.HttpMaxTimeout = HttpTimeout;
               producerConfig.MaxIoWorkers = maxIO;
               var producerInstance = new Producer(producerConfig);
               producerInstance.Start();
               var wg = new WaitGroup();
               for (int i = 0; i < threadCount; i++)
               {
                   wg.Add(1);
                   Task.Run(() => Handler.handle(producerInstance, wg, groupId, streamId, logItemNum, logContent));
               }
               wg.wait();
               Console.WriteLine("send all complete ...");
               Thread.Sleep(TimeSpan.FromSeconds(3000));
           }
           public class WaitGroup
           {
               private long _wg = 0;
               public long Wg
               {
                   get => _wg;
                   set => _wg = value;
               }
               public void Add(int delta)
               {
                   Interlocked.Add(ref _wg, delta);
               }
               public void Done()
               {
                   Interlocked.Decrement(ref _wg);
               }
               public void wait()
               {
                   while (Interlocked.Read(ref _wg) != 0)
                   {
                       Thread.Sleep(200);
                   }
               }
           }
           public class Handler
           {
               public static void handle(Producer producer, WaitGroup wg, string groupId, string streamId, int logItemNums, string logContent)
               {
                   for (int j = 0; j < logItemNums; j++)
                   {
                       var labels = new Dictionary<string, string>();
                       labels["keyA"] = "valueA";
                       labels["keyB"] = "valueB";
                       labels["keyC"] = "valueC";
                       var log = LTS_Store.GenerateLog(new List<string> { logContent }, labels);
                       var err = producer.SendLog(groupId, streamId, log);
                       if (err != null)
                       {
                           Console.WriteLine(JsonConvert.SerializeObject(err));
                       }
                       Thread.Sleep(TimeSpan.FromMilliseconds(0.1));
                   }
                   wg.Done();
               }
           }
       }
   }
   ```
   
   
 
#### 配置参数说明
- producer config参数说明。
  
  | 参数名称               | 描述                                                                                                                                                                                                                                                                                                                          | 类型     | 是否需要填写 | 默认值            |
  |:---|:---|:---|:---|:---|
  | ProjectId          | 华为云账号的项目ID（project id）。                                                                                                                                                                                                                                                                                                     | String | 必填     | -              |
  | AccessKeyId        | 华为云账号的AK。                                                                                                                                                                                                                                                                                                                   | String | 必填     | -              |
  | AccessKeySecret    | 华为云账号的SK。                                                                                                                                                                                                                                                                                                                   | String | 必填     | -              |
  | RegionName         | 云日志服务的区域。                                                                                                                                                                                                                                                                                                                   | String | 必填     | -              |
  | Endpoint           | 上报的服务器域名或IP。                                                                                                                                                                                                                                                                                                                | String | 必填     | -              |
  | MaxBlockSec        | 如果producer可用空间不足，调用者在send方法上的最大阻塞时间，默认为60秒。建议为0秒。 当maxBlockMs值\>=0时，则阻塞到设置的时间，如果到达阻塞时间，还是不能获取到内存，即报错且丢弃日志。 当maxBlockMs值=-1时，则一直阻塞到发送成功，且不会丢弃日志。 | long   | 选填     | 60s            |
  | MaxIoWorkers       | 执行日志发送任务的任务池大小。                                                                                                                                                                                                                                                                                                             | int    | 选填     | 默认10个          |
  | MaxBatchSize       | 当一个ProducerBatch中缓存的日志大小大于等于batchSizeThresholdInBytes时，该batch将被发送。                                                                                                                                                                                                                                                          | int    | 选填     | 524288（即0.5MB） |
  | MaxBatchCount      | 当一个ProducerBatch中缓存的日志条数大于等于batchCountThreshold时，该batch将被发送。                                                                                                                                                                                                                                                                | int    | 选填     | 4096           |
  | LingerMs           | 一个ProducerBatch从创建到可发送的逗留时间。                                                                                                                                                                                                                                                                                                | int    | 选填     | 2s             |
  | Retries            | 如果某个ProducerBatch首次发送失败，能够对其重试的次数，建议为3次。如果retries小于等于0，该ProducerBatch首次发送失败后将直接进入失败队列。                                                                                                                                                                                                                                      | int    | 选填     | 10             |
  | BaseRetryBackoffMs | 首次重试的退避时间。                                                                                                                                                                                                                                                                                                                  | long   | 选填     | 0.1s           |
  | MaxRetryBackoffMs  | 重试的最大退避时间。                                                                                                                                                                                                                                                                                                                  | long   | 选填     | 50s            |
  | HttpMaxTimeout     | HTTP请求的超时时间                                                                                                                                                                                                                                                                                                                 | int    | 选填     | 60s            |
     
  
- 日志生成GenerateLog方法类参数说明。 单次上报条数小于4096条，且小于512K。
  表1GenerateLog方法类参数说明 
  | 参数名称     | 描述          | 类型                           | 是否需要填写 |
  |:---|:---|:---|:---|
  | contents | 批量日志内容。     | List\<string\>               | 是      |
  | labels   | 日志标签，map格式。 | Dictionary\<string, string\> | 是      |
     
  
- 日志上报SendLog方法类参数说明
  表2SendLog方法类参数说明 
  |   参数名称   |  描述   |    类型     | 是否需要填写 |
  |---|---|---|---|
  | groupId  | 日志组id | string    | 是      |
  | streamId | 日志流id | string    | 是      |
  | log      | 日志结构  | class Log | 是      |
     
  
 
#### 参数获取方式
- 上线区域表，使用华为云主机时参考以下信息：
  
  | 区域名称   | 区域             | 终端节点                                                     |
  |:---|:---|:---|
  | 华北-北京四 | cn-north-4     | https://lts-access.cn-north-4.myhuaweicloud.com:8102     |
  | 华东-上海一 | cn-east-3      | https://lts-access.cn-east-3.myhuaweicloud.com:8102      |
  | 华南-广州  | cn-south-1     | https://lts-access.cn-south-1.myhuaweicloud.com:8102     |
  | 亚太-新加坡 | ap-southeast-3 | https://lts-access.ap-southeast-3.myhuaweicloud.com:8102 |
     
  当前仅华北-北京四、华东-上海一、华南-广州区域使用SDK时支持跨云/本地上报日志，Endpoint端口使用443。
  
- 日志组ID：在云日志服务控制台，选择"日志管理"，鼠标悬浮在日志组名称上，可查看日志组名称和日志组ID。
- 日志流ID：单击日志组名称对应的![](https://support.huaweicloud.com/usermanual-lts/zh-cn_image_0000002156237521.png)按钮，鼠标悬浮在日志流名称上，可查看日志流名称和日志流ID。
 
