zoukankan      html  css  js  c++  java
  • .net 日志写RabbitMQ 整合netcore ILogger

    NetCore 日志写RabbitMQ

    using System;
    using System.Collections.Concurrent;
    using System.Configuration;
    using System.IO;
    using System.Text;
    using System.Linq;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Collections.Generic;
    using RabbitMQ.Client;
    
    using Timer = System.Timers.Timer;
    
    namespace RabbitMQLog
    {
        /// <summary>
        /// 日志写RabbitMQ工具类
        /// </summary>
        public class XRabbitMQLogHelper
        {
            #region 字段、属性、构造函数
            /// <summary>线程安全队列</summary>
            private static readonly ConcurrentQueue<RabbitMQLogModel> _que = new ConcurrentQueue<RabbitMQLogModel>();
    
            /// <summary>信号</summary>
            private static readonly ManualResetEvent _mre;
    
            /// <summary>日志级别</summary>
            private static LogLevelEnum logLevel = LogLevelEnum.Info;
    
            //RabbitMQClient
            private static IConnectionFactory mqFact;
            private static DateTime mqLastErrTime;
            private static Exception mqLastErr;
    
            private static String exchangeName;
            private static String routingKey;
            private static String queueName;
    
            private static Timer timer = new Timer(10 * 1000);
    
            /// <summary>构造函数</summary>
            static XRabbitMQLogHelper()
            {
                _mre = new ManualResetEvent(false);
                timer.Elapsed += Timer_Elapsed;
                timer.Start();
    
                //配置
                {
    #if !netcoreapp
                    {
                        //日志级别
                        var loglevelStr = ConfigurationManager.AppSettings["loglevel"];
                        if (!string.IsNullOrEmpty(loglevelStr))
                        {
                            var lltype = typeof(LogLevelEnum);
                            var flag = Enum.TryParse<LogLevelEnum>(loglevelStr, out var logLevel);
                            if (flag && Enum.IsDefined(lltype, logLevel))
                            {
                                XLogHelper.logLevel = logLevel;
                            }
                        }
                    }
    #endif
                }
    
                Task.Factory.StartNew(() => Initialize());
            }
    
            private static void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
            {
                if (mqLastErrTime.Year > 2000 && mqLastErrTime.AddSeconds(16) < DateTime.Now)
                {
                    _mre.Set();
                }
            }
            #endregion
    
            /// <summary>
            /// 配置RabbitMQ
            /// </summary>
            /// <param name="factory"></param>
            /// <param name="exchangeName"></param>
            /// <param name="routingKey"></param>
            /// <param name="queueName"></param>
            public static void InitConfig(IConnectionFactory factory, String exchangeName, String routingKey, String queueName)
            {
                mqFact = factory;
                XRabbitMQLogHelper.exchangeName = exchangeName;
                XRabbitMQLogHelper.routingKey = routingKey;
                XRabbitMQLogHelper.queueName = queueName;
    
            }
    
            #region 信息日志
            /// <summary>日志,默认Info级别</summary>
            /// <param name="message">日志内容</param>
            /// <param name="logLevel"></param>
            public static void WriteLine(string message, String targetCls = "", LogLevelEnum logLevel = LogLevelEnum.Info, Exception ex = null)
            {
                try
                {
                    if (logLevel < XRabbitMQLogHelper.logLevel) return;
    
                    var threadId = Thread.CurrentThread.ManagedThreadId;
                    var taskId = Task.CurrentId.HasValue ? Task.CurrentId.Value : -1;
                    var m = FormatLog(threadId, taskId, logLevel, targetCls, message, ex);
    
                    _que.Enqueue(m);
                    _mre.Set();
                }
                catch
                {
                }
            }
    
            #endregion
    
            #region 私有方法/实体
            #region 日志初始化
            /// <summary>
            /// 日志初始化
            /// </summary>
            private static void Initialize()
            {
                while (true)
                {
                    //等待信号通知
                    _mre.WaitOne();
                    //写入日志
                    write();
                    //重新设置信号
                    _mre.Reset();
                    Thread.Sleep(1);
                }
            }
            #endregion
    
            #region 写入日志
            /// <summary>
            /// 写入日志
            /// </summary>
            private static void write()
            {
                if (mqLastErrTime.Year > 2000 && mqLastErrTime.AddSeconds(10) > DateTime.Now) return;
    
                try
                {
                    using (var conn = mqFact.CreateConnection(nameof(XRabbitMQLogHelper)))
                    {
                        mqLastErrTime = DateTime.MinValue;
                        using (var channel = conn.CreateModel())
                        {
                            //开启生产者Ack
                            channel.ConfirmSelect();
    
                            var prop = channel.CreateBasicProperties();
                            prop.Persistent = true;
    
                            //prop.MessageId = msgID;
                            //prop.Timestamp = new AmqpTimestamp(timeStamp);
    
                            //开始生产消息
                            //判断日志队列中是否有内容,从列队中获取内容,并删除列队中的内容
                            while (_que.Any() && _que.TryDequeue(out var m))
                            {
                                var str = JsonNetHelper.SerializeObject(m);
                                var arr = str.ToByteArr();
                                //发布到MQ
                                channel.BasicPublish(exchangeName, routingKey, prop, arr);
                            }
    
                            //确认生产者ACK
                            if (!channel.WaitForConfirms())
                            {
                                throw new Exception("The message is not reached to the server!");
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    mqLastErr = ex;
                    mqLastErrTime = DateTime.Now;
                }
    
            }
            #endregion
    
            #endregion
    
            #region 辅助
            /// <summary>
            /// 格式化日志
            /// </summary>
            /// <param name="threadId"></param>
            /// <param name="taskId"></param>
            /// <param name="logEnum"></param>
            /// <param name="targetCls"></param>
            /// <param name="msg"></param>
            /// <param name="ex"></param>
            /// <returns></returns>
            public static RabbitMQLogModel FormatLog(int threadId, int taskId, LogLevelEnum logEnum, String targetCls, string msg, Exception ex = null)
            {
                var taskIdStr = taskId > -1 ? taskId + "" : "-";
    
                var now = DateTime.Now;
                var m = new RabbitMQLogModel()
                {
                    CreateTime = now,
    
                    ThreadID = threadId + "",
                    TaskID = taskIdStr,
    
                    LogLevel = logEnum + "",
                    Source = targetCls,
                    Message = msg,
    
                };
    
                if (ex != null)
                {
                    var err = CreateErrorMessage(ex);
    
                    m.Error = err;
                }
    
                //扩展字段
                //{
                //    var dic = new Dictionary<String, Object>();
                //    dic["Machine"] = Environment.MachineName;
                //    dic["PID"] = MyEnvironment.ProcessID;
                //    dic["SoftVer"] = MyEnvironment.Version;
    
                //    m.ExtProp = dic;
                //}
    
                return m;
            }
    
            /// <summary>
            /// 创建异常消息
            /// </summary>
            /// <param name="ex">异常信息</param>
            /// <param name="remark">备注</param>
            /// <returns>结果</returns>
            private static RabbitMQErrLogModel CreateErrorMessage(Exception ex)
            {
                var m = new RabbitMQErrLogModel();
                if (ex == null) return null;
    
                var iex = ex.InnerException;
                if (iex != null)
                {
                    var im = new RabbitMQErrLogModel()
                    {
                        ErrType = iex.GetType().FullName,
                        Message = iex.Message,
                        Source = iex.Source,
                        StackTrace = iex.StackTrace,
                    };
    
                    m.InnerErr = im;
                }
    
                m.ErrType = ex.GetType().FullName;
                m.Message = ex.Message;
                m.Source = ex.Source;
                m.StackTrace = ex.StackTrace;
    
                return m;
            }
            #endregion
    
        }
    
        public class RabbitMQLogModel
        {
            public DateTime CreateTime { get; set; }
    
            public String ThreadID { get; set; }
            public String TaskID { get; set; }
    
            public String LogLevel { get; set; }
            public String Source { get; set; }
            public String Message { get; set; }
            public RabbitMQErrLogModel Error { get; set; }
    
            /// <summary>扩展</summary>
            public IDictionary<String, Object> ExtProp { get; set; }
            //机器名、进程ID、软件版本
            //public String MachineName { get; set; } = Environment.MachineName;
            //public Int32 ProcessID { get; set; } = MyEnvironment.ProcessID;
            //public String SoftVersion { get; set; } = MyEnvironment.Version;
        }
    
        public class RabbitMQErrLogModel
        {
            public String ErrType { get; set; }
            public String Message { get; set; }
            public String Source { get; set; }
            public String StackTrace { get; set; }
    
            public RabbitMQErrLogModel InnerErr { get; set; }
    
            /// <summary></summary>
            /// <returns></returns>
            public override string ToString()
            {
                return $"Err:{ErrType} {Message} {Source} {StackTrace} {InnerErr}";
            }
        }
    
    }

    整合ILogger

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Logging;
    using RabbitMQ.Client;
    
    namespace RabbitMQLog
    {
        /// <summary>
        /// 
        /// </summary>
        public class MyRabbitMQLogger : ILogger
        {
            private readonly string categoryName;
            private readonly MyRabbitMQLoggerProviderOptions option;
    
            /// <summary>
            /// 
            /// </summary>
            /// <param name="categoryName"></param>
            /// <param name="factory"></param>
            /// <param name="option"></param>
            public MyRabbitMQLogger(string categoryName, IConnectionFactory factory, MyRabbitMQLoggerProviderOptions option)
            {
                (this.categoryName, this.option) = (categoryName, option);
    
                if (option != null)
                {
                    XRabbitMQLogHelper.InitConfig(factory, option.ExchangeName, option.RoutingKey, option.QueueName);
                }
            }
    
            public IDisposable BeginScope<TState>(TState state)
            {
                return null;
            }
    
            public bool IsEnabled(LogLevel logLevel)
            {
                return true;
            }
    
            public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
            {
                var msg = formatter(state, exception);
                switch (logLevel)
                {
                    case LogLevel.Trace:
                    case LogLevel.Debug:
                        XRabbitMQLogHelper.WriteLine(msg, categoryName, LogLevelEnum.Debug);
                        break;
                    case LogLevel.Information:
                        XRabbitMQLogHelper.WriteLine(msg, categoryName, LogLevelEnum.Info);
                        break;
                    case LogLevel.Warning:
                        XRabbitMQLogHelper.WriteLine(msg, categoryName, LogLevelEnum.Warn);
                        break;
                    case LogLevel.Error:
                        XRabbitMQLogHelper.WriteLine(msg, categoryName, LogLevelEnum.Error, exception);
                        break;
                    case LogLevel.Critical:
                        XRabbitMQLogHelper.WriteLine(msg, categoryName, LogLevelEnum.Fatal, exception);
                        break;
                    case LogLevel.None:
                    default:
                        break;
                }
    
    
                //var msg = $"{logLevel}::{this.categoryName}::{formatter(state, exception)}::{DateTime.Now}";
    
                //using (var writer = File.AppendText(this.path))
                //{
                //    writer.WriteLine(msg);
                //}
            }
    
    
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.Extensions.Logging;
    using RabbitMQ.Client;
    
    namespace RabbitMQLog
    {
        public class MyRabbitMQLoggerProvider : ILoggerProvider
        {
            private IConnectionFactory factory;
            private MyRabbitMQLoggerProviderOptions option;
    
            public MyRabbitMQLoggerProvider(IConnectionFactory factory, MyRabbitMQLoggerProviderOptions option)
            {
                this.factory = factory;
                this.option = option;
            }
    
            public ILogger CreateLogger(string categoryName)
            {
                return new MyRabbitMQLogger(categoryName, this.factory, this.option);
            }
    
            public void Dispose()
            {
    
            }
    
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace RabbitMQLog
    {
        /// <summary>
        /// 
        /// </summary>
        public class MyRabbitMQLoggerProviderOptions
        {
            /// <summary></summary>
            public String HostName { get; set; }
            /// <summary></summary>
            public Int32 Port { get; set; }
            /// <summary></summary>
            public String UserName { get; set; }
            /// <summary></summary>
            public String Password { get; set; }
            /// <summary></summary>
            public String VirtualHost { get; set; }
    
    
            /// <summary></summary>
            public String ExchangeName { get; set; }
            /// <summary></summary>
            public String QueueName { get; set; }
            /// <summary></summary>
            public String RoutingKey { get; set; }
    
        }
    }
    {
         "RabbitMQLogger": {
        "HostName": "vmdev.hhh.xyz",
        "Port": 5672,
        "UserName": "root",
        "Password": "123",
        "VirtualHost": "log",
    
        "ExchangeName": "applog",
        "QueueName": "qqq",
        "RoutingKey": "qqq"
      }  
    }

    netcore 注入

    .ConfigureServices((hostContext, services) =>
    {
        services.AddHttpClient();
    
        services.AddTransient<IMyService, MyService>();
    
        {
            var cfg = hostContext.Configuration.GetSection(ConfigConsts.RABBITMQ_Log_CONFIG);
            var mqCfg = cfg.Get<MyRabbitMQLoggerProviderOptions>();
            var cf = new ConnectionFactory()
            {
                HostName = mqCfg.HostName,
                Port = mqCfg.Port,
    
                UserName = mqCfg.UserName,
                Password = mqCfg.Password,
    
                VirtualHost = mqCfg.VirtualHost,
            };
    
            cf.HandshakeContinuationTimeout = TimeSpan.FromSeconds(15);
    
            RabbitMQTools.Init(cf);
    
            services.AddSingleton(cf);
        }
    
        services.AddHostedService<LogToRabbitMQHostService>();
    })
    .ConfigureLogging(logbuild =>
    {
        logbuild.ClearProviders();
        //logbuild.AddConsole();
        //logbuild.SetMinimumLevel(LogLevel.Debug);//控制全部的日志输出
        //logbuild.AddNLog();
    
        // 注入 AddMyRabbitMQLog
        using (var sp = logbuild.Services.BuildServiceProvider())
        {
            var mqFact2 = sp.GetServices<ConnectionFactory>();
            var mqFact = mqFact2.First(d => d.VirtualHost.EqualIgnoreCase(RabbitMQConst.DEFAULT_LOG_VIRTUALHOST));
            var option = sp.GetService<IConfiguration>().GetSection(ConfigConsts.RABBITMQ_Log_CONFIG).Get<MyRabbitMQLoggerProviderOptions>();
    
            logbuild.AddMyRabbitMQLog(mqFact, option);
        }
    })

    over

  • 相关阅读:
    疫情信息爬取及可视化 app
    计算机组成与体系结构——校验码知识点
    计算机组成与体系结构——其他知识点(二)
    计算机组成与体系结构——其他知识点(一)
    计算机组成与体系结构——流水线相关知识点(常考计算)
    计算机组成与体系结构——数据的表示
    C语言经典试题--指针
    软件工程--个人课程总结
    学生信息管理系统--基于jsp技术和MySQL的简单增删改查
    计算最长英语单词链
  • 原文地址:https://www.cnblogs.com/huawublog/p/14510191.html
Copyright © 2011-2022 走看看