背景
- 基于之前基于Log4Net本地日志服务简单实现 实现本地日志服务,但是随着项目开发演进,本地日志服务满足不了需求,譬如在预发布环境或者生产环境,不可能让开发人员登录查看本地日志文件分析。
- Kafka+ELK日志服务套件,可以在线日志服务可以解决上述问题,并且提供丰富报表分析等等;
- 具体源码:MasterChief
- Nuget:Install-Package MasterChief.DotNet.Core.KafkaLog
- 欢迎Star,欢迎Issues;
源码
基于Log4Net来实现与kafka通讯Appender
public class KafkaAppender : AppenderSkeleton { #region Fields /// <summary> /// Kafka 生产者 /// </summary> private Producer _kafkaProducer; #endregion Fields #region Properties /// <summary> /// Brokers /// </summary> public string Brokers { get; set; } /// <summary> /// Topic /// </summary> public string Topic { get; set; } #endregion Properties #region Methods /// <summary> /// Initialize the appender based on the options set /// </summary> /// <remarks> /// <para> /// This is part of the <see cref="T:log4net.Core.IOptionHandler" /> delayed object /// activation scheme. The <see cref="M:log4net.Appender.AppenderSkeleton.ActivateOptions" /> method must /// be called on this object after the configuration properties have /// been set. Until <see cref="M:log4net.Appender.AppenderSkeleton.ActivateOptions" /> is called this /// object is in an undefined state and must not be used. /// </para> /// <para> /// If any of the configuration properties are modified then /// <see cref="M:log4net.Appender.AppenderSkeleton.ActivateOptions" /> must be called again. /// </para> /// </remarks> public override void ActivateOptions() { base.ActivateOptions(); InitKafkaProducer(); } /// <summary> /// Subclasses of <see cref="T:log4net.Appender.AppenderSkeleton" /> should implement this method /// to perform actual logging. /// </summary> /// <param name="loggingEvent">The event to append.</param> /// <remarks> /// <para> /// A subclass must implement this method to perform /// logging of the <paramref name="loggingEvent" />. /// </para> /// <para> /// This method will be called by <see cref="M:DoAppend(LoggingEvent)" /> /// if all the conditions listed for that method are met. /// </para> /// <para> /// To restrict the logging of events in the appender /// override the <see cref="M:PreAppendCheck()" /> method. /// </para> /// </remarks> protected override void Append(LoggingEvent loggingEvent) { try { var message = GetLogMessage(loggingEvent); var topic = GetTopic(loggingEvent); _ = _kafkaProducer.SendMessageAsync(topic, new[] {new Message(message)}); } catch (Exception ex) { ErrorHandler.Error("KafkaProducer SendMessageAsync", ex); } } /// <summary> /// Raises the Close event. /// </summary> /// <remarks> /// <para> /// Releases any resources allocated within the appender such as file handles, /// network connections, etc. /// </para> /// <para> /// It is a programming error to append to a closed appender. /// </para> /// </remarks> protected override void OnClose() { base.OnClose(); StopKafkaProducer(); } private string GetLogMessage(LoggingEvent loggingEvent) { var builder = new StringBuilder(); us