阿里云 日志服务在.NET项目中的使用

        云服务技术的应用已十分常见,不仅仅指将项目部署在公有云,我们还可以利用云服务厂商提供的各种技术,来提高系统性能,做好站点监控预警等。本篇博客为大家介绍阿里云日志服务。

传统日志记录

我们可能会在项目数据库当中创建一些日志表,比如:客户信息查看记录,核心信息修改日志等。通常这些日志内容价值较低,而且属于只读,但是存放在sql server, my sql, pgsql等数据库当中,不仅会占用大量系统资源,而且伴随着数据量的增加,查询效率也会降低,并且可能需要dba定期清理维护等。

云日志服务

其实众多云服务厂商都有提供相当廉价的日志存储服务,比如阿里云日志,azure table storage

我们只需要对相关sdk稍加封装,即可在项目中使用。

阿里云日志介绍

  • 阿里云日志属于NOSQL存储,意味着你可以任意新增或删除日志字段,而不需要像关系型数据库那样必须进行数据库表结构调整。
  •  可以直接登录阿里云控制台进行查看,按照语法进行日志查询,并且可以对日志进行导出,也可以使用sdk,在程序中进行日志查询。
  • 根据官方介绍,支持千亿级数据秒级查询,性能远高于关系型数据库。
  • 支持冷热存储,通常热存储主要应用于查询频率较高的场景
  • 支持日志自动过期机制,你可以指定日志记录的存活时间,不需要手动维护。

 常用概念

  1. Project           项目,相当于一个数据库
  2. LogStore       日志库,相当于数据库中的表
  3. Shard            分区,相当于日志表的物理分区,分区的目的是为了提高日志写入/读取效率。每个分区可以提供5 MB/s或500次/s的写入能力,或者10 MB/s或100次/s读取能力。分区可以分裂或者合并,可以将LogStore 设置为自动分裂。
  4. Topic             主题,日志表的逻辑分区,当不同模块的日志被采集到的同一个Logstore中后,可通过Topic进行区分。
  5. LogGroup     日志组,是使用sdk写入日志的最小单位。它可以包含多条日志记录,可以指定一个topic和source(日志来源,如产生日志的服务器IP地址)
  6. Log               日志,日志服务采用半结构化的数据模式定义一条日志,包含Topic、Time、Content、Source和Tags五个数据域。通常我们需要将一条日志内容拆分为键值对的形式保存于Content当中。  

阿里云日志索引

日志保存到LogStore之后,必须开启索引才能进行查询。

阿里云日志索引分为全文索引-IndexLineInfo字段索引-IndexKeyInfo两种类型。

  • 全文索引通过设置分词符,来为日志提供查询功能。设置了全文索引之后,你可以直接在查询框输入: error, 来查询包含error的日志记录
  • 字段索引支持text,long,double和json等四种类型。可以缩小查询范围,比如:level:error。如果要使用统计分析等功能,则必须开启字段索引。

阿里云日志在.NET 项目中的使用

  1. 安装Nuget包:Aliyun.SLS.SDK
  2. 在Startup中注册 
services.AddSingleton<ILogServiceClient>(sp => LogServiceClientBuilders.HttpBuilder
                .Credential(Configuration["AliyunLog:AccessKeyId"], Configuration["AliyunLog:AccessKeySecret"]) 
                .Endpoint(Configuration["AliyunLog:Endpoint"], Configuration["AliyunLog:Project"])
                .Build());

 可以将插入,批量插入,查询等操作封装一下,使用起来更方便

例如安居客房源发布之后,将图片处理状态回调信息写入阿里云日志

        [HttpPost("picture/callback")]
        public Task<string> PictureStatusCallbackAsync([FromBody] PictureCallBackDto pictureCallBackDto)
        {
            return _logService.InsertLogAsync(PictureCallBackDto.LogStoreName, pictureCallBackDto);
        }

        [HttpGet("log/query")]
        public Task<IList<IDictionary<string, string>>> QueryPictureCallBackDto(DateTime from, DateTime to)
        {
            return _logService.QueryAsync(PictureCallBackDto.LogStoreName, from, to);
        }
using Aliyun.Api.LogService;
using Aliyun.Api.LogService.Domain.Log;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Core.Push._58.API.Infrastructure.LogService
{
    public class AliyunLogService : IAliyunLogService
    {
        private readonly ILogServiceClient _logServiceClient;
        private readonly DateTime UtcTime = new DateTime(1970, 1, 1);

        public AliyunLogService(ILogServiceClient logServiceClient)
        {
            _logServiceClient = logServiceClient;
        }

        public async Task<IList<IDictionary<string, string>>> QueryAsync(string logStoreName, DateTime from, DateTime to)
        {
            var response = await _logServiceClient.GetLogsAsync(
                new GetLogsRequest(logStoreName, (int)(from - UtcTime).TotalSeconds, (int)(to - UtcTime).TotalSeconds)
                {
                    Offset = 1,
                    Line = 100,
                });
            return response.IsSuccess ? response.Result.Logs : throw new Exception(response.Error.ErrorMessage);
        }

        public async Task<string> InsertLogAsync<T>(string logStoreName, T item)
        {
            var response = await _logServiceClient.PostLogStoreLogsAsync(new PostLogsRequest(logStoreName, CreateGroupInfo(item)));
            return response.IsSuccess ? "保存成功" : response.Error.ErrorMessage;
        }

        public async Task<string> BatchInsertLogAsync<T>(string logStoreName, List<T> items)
        {
            var response = await _logServiceClient.PostLogStoreLogsAsync(new PostLogsRequest(logStoreName, BatchCreateGroupInfo(items)));
            return response.IsSuccess ? await response.ReadAsAsync<string>() : response.Error.ErrorMessage;
        }

        private LogGroupInfo CreateGroupInfo<T>(T item)
        {
            var group = new LogGroupInfo 
            {
                Source = "58-picture-callback-log",
                Topic = DateTime.Now.ToString("yyyy-MM-dd")
            };
            group.Logs.Add(CreateLogInfo(item));
            return group;
        }

        private LogGroupInfo BatchCreateGroupInfo<T>(List<T> items)
        {
            var group = new LogGroupInfo();
            group.Logs = BatchCreateLogInfo(items);
            return group;
        }

        private LogInfo CreateLogInfo<T>(T item)
        {
            var logInfo = new LogInfo { Time = DateTime.Now };
            foreach(var property in typeof(T).GetProperties())
            {
                if (property.PropertyType.IsPrimitive || property.PropertyType.Equals(typeof(string)))
                {
                    logInfo.Contents.Add(property.Name, property.GetValue(item)?.ToString());
                    continue;
                }

                logInfo.Contents.Add(property.Name, JsonConvert.SerializeObject(property.GetValue(item)));
            }

            return logInfo;
        }

        private List<LogInfo> BatchCreateLogInfo<T>(List<T> items)
        {
            var logInfos = new List<LogInfo>();
            var propertys = typeof(T).GetProperties();
            foreach(var item in items)
            {
                var logInfo = new LogInfo { Time = DateTime.Now };
                foreach (var property in propertys)
                {
                    if (property.PropertyType.IsPrimitive || property.PropertyType.Equals(typeof(string)))
                    {
                        logInfo.Contents.Add(property.Name, property.GetValue(item)?.ToString());
                        continue;
                    }

                    logInfo.Contents.Add(property.Name, JsonConvert.SerializeObject(property.GetValue(item)));
                }
            }
            return logInfos;
        }
    }
}

猜你喜欢

转载自blog.csdn.net/qq_40404477/article/details/120262761
今日推荐