Login
网站首页 > 文章中心 > 其它

Serilog日志同步到redis中和自定义Enricher来增加额外的记录信息

作者:小编 更新时间:2023-08-12 11:49:37 浏览量:224人看过

Serilog日志同步到redis中和自定义Enricher来增加额外的记录信息

Serilog 日志同步到redis队列中 后续可以通过队列同步到数据库、腾讯阿里等日志组件中,这里redis库用的新生命团队的NewLife.Redis组件 可以实现轻量级消息队列(轻量级消息队列RedisQueue (newlifex.com)),也可以自行替换熟悉的组件

Serilog日志同步到redis中和自定义Enricher来增加额外的记录信息-图1

类库目录 该类库需添加?Microsoft.AspNetCore.Http.Abstractions、NewLife.Redis、Newtonsoft.Json、Serilog包

Serilog日志同步到redis中和自定义Enricher来增加额外的记录信息

RedisStreamSink.cs 中的代码? 定义RedisSink 将日志记录到redis队列中

using Microsoft.AspNetCore.Http;
using NewLife.Caching;
using Newtonsoft.Json;
using Serilog.Core;
using Serilog.Events;
using Serilog.Formatting;
using Serilog.Parsing;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace SeriLog.Sinks.RedisStream.Ms
{

/// 
/// 用于序列化数据
/// 
public class LogData
    public DateTimeOffset Timestamp { get; set; }
    public LogEventLevel Level { get; set; }
    public string Message { get; set; }
    public string RequestIP { get; set; }
    public string HostName { get; set; }
    public static LogData LogEventToLogData(LogEvent logEvent)
        var data = new LogData();
        data.Timestamp = logEvent.Timestamp;
        data.Level = logEvent.Level;
        return data;

public class RedisStreamSink : ILogEventSink
    private readonly ITextFormatter _formatter;
    private readonly FullRedis _redis;
    private readonly string _redisStreamName;
    public RedisStreamSink(FullRedis fullRedis, string redisStreamName, ITextFormatter textFormatter)
        _redis = fullRedis;
        _redisStreamName = redisStreamName;
        _formatter = textFormatter;
    public void Emit(LogEvent logEvent)
        string message =string.Empty;
        using (var writer = new StringWriter())
            message = writer.ToString();
        var data = LogData.LogEventToLogData(logEvent);
        data.Message = message.Replace("\r\n","");
        //获取自定义需要记录的信息例如客户端ip地址和主机名
        data.RequestIP = logEvent.Properties.TryGetValue("RequestIP", out LogEventPropertyValue? propertyIpValue) ? propertyIpValue.ToString() : string.Empty;
        data.HostName = logEvent.Properties.TryGetValue("HostName", out LogEventPropertyValue? propertyHostNameValue) ? propertyHostNameValue.ToString() : string.Empty;
        Console.WriteLine("===================================\r\n" + JsonConvert.SerializeObject(data));
        //添加到redis 队列中
        var queue = _redis.GetQueue<string>(_redisStreamName);
}
}

RedisStreamSinkExtensions.cs?中的代码

using Serilog.Configuration;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NewLife.Caching;
using Serilog.Formatting;

namespace SeriLog.Sinks.RedisStream.Ms
{
public static class RedisStreamSinkExtensions
    //序列化时message中显示的内容 简化输出
    private const string DefaultOutputTemplate = "(RequestId:{RequestId}){Message:j}{Exception}";
    public static LoggerConfiguration RedisStreamSink(
        this LoggerSinkConfiguration loggerConfiguration,
        string redisStreamName,
        string outputTemplate = DefaultOutputTemplate,
        IFormatProvider formatProvider = null
        var formatter = new Serilog.Formatting.Display.MessageTemplateTextFormatter(outputTemplate, formatProvider);
        return loggerConfiguration.Sink(new RedisStreamSink(redis, redisStreamName, formatter));
}
}

RequestInfoEnricher.cs 中的代码? 自定义添加RequestIP和Referer信息

using Microsoft.AspNetCore.Http;
using NewLife.Model;
using Serilog.Core;
using Serilog.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SeriLog.Sinks.RedisStream.Ms
{
public class RequestInfoEnricher : ILogEventEnricher
    private readonly IServiceProvider _serviceProvider;
    public RequestInfoEnricher(IServiceProvider serviceProvider)
        _serviceProvider = serviceProvider;
    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
        var httpContext = _serviceProvider.GetService()?.HttpContext;
        if (null != httpContext)
            //这里添加自定义需记录的信息
            logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("RequestIP", httpContext.Connection.RemoteIpAddress));
            logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("Referer", httpContext.Request.Headers["Referer"]));
}
}

EnricherExtensions.cs 中的代码

using Serilog.Configuration;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SeriLog.Sinks.RedisStream.Ms
{
public static class EnricherExtensions
    public static LoggerConfiguration WithRequestInfo(this LoggerEnrichmentConfiguration enrich, IServiceProvider serviceProvider)
        if (enrich == null)
            throw new ArgumentNullException(nameof(enrich));

        return enrich.With(new  RequestInfoEnricher(serviceProvider));
}
}

在需要用到的项目中添加?SeriLog.Sinks.RedisStream.Ms 项目引用

public static void Main(string[] args)
        var fullRedis = FullRedis.Create($"server=12⑦0.0.1:6379,db=1");
        var builder = WebApplication.CreateBuilder(args);
        //这一步必须放在CreateLogger之前否则 RequestInfoEnricher中获取不到HttpContextAccessor
        builder.Services.AddSingleton();

Log.Logger
= new LoggerConfiguration() .MinimumLevel.Information() .Enrich.WithProperty("HostName", Dns.GetHostName()) .WriteTo.RedisStreamSink(fullRedis, "logger") //logger 为队列的名称 builder.Host.UseSerilog();

       .......后续忽略自行修改

    }

以上就是土嘎嘎小编为大家整理的Serilog日志同步到redis中和自定义Enricher来增加额外的记录信息相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!

版权声明:倡导尊重与保护知识产权。未经许可,任何人不得复制、转载、或以其他方式使用本站《原创》内容,违者将追究其法律责任。本站文章内容,部分图片来源于网络,如有侵权,请联系我们修改或者删除处理。

编辑推荐

热门文章