asp.net core + log4net+exceptionles+DI

参考了ABP的代码,我也用依赖注入的原则,设计了日志模块。

与abp不同之处在于:1)DI容器使用的是.net core自带的注入容器,2)集成了excetpionless日志模块,3)不依赖于abp

主要的思想就是,1)定义日志操作接口 2)使用log4net实现日志接口,3)实现注入  4)使用日志

1)定义日志接口,这里直接使用了castle的日志接口

2)使用log4net实现日志接口

    [Serializable]
    public class Log4NetLogger :
            MarshalByRefObject,
            ILogger
    {
        private static readonly Type DeclaringType = typeof(Log4NetLogger);
        
        private log4net.Core.ILogger _logger;
        private Log4NetLoggerFactory _factory;
        public Log4NetLogger()
        {
            _factory = new Log4NetLoggerFactory();
            _logger = _factory.GetLogger("cislog");
        }

        public bool IsDebugEnabled
        {
            get { return _logger.IsEnabledFor(Level.Debug); }
        }

        public bool IsErrorEnabled
        {
            get { return _logger.IsEnabledFor(Level.Error); }
        }

        public bool IsFatalEnabled
        {
            get { return _logger.IsEnabledFor(Level.Fatal); }
        }

        public bool IsInfoEnabled
        {
            get { return _logger.IsEnabledFor(Level.Info); }
        }

        public bool IsWarnEnabled
        {
            get { return _logger.IsEnabledFor(Level.Warn); }
        }



        public override string ToString()
        {
            return _logger.ToString();
        }
        
        public void Debug(string message)
        {
            if (IsDebugEnabled)
            {
                _logger.Log(DeclaringType, Level.Debug, message, null);
            }
        }

        public void Debug(Func<string> messageFactory)
        {
            if (IsDebugEnabled)
            {
                _logger.Log(DeclaringType, Level.Debug, messageFactory.Invoke(), null);
            }
        }

        public void Debug(string message, Exception exception)
        {
            if (IsDebugEnabled)
            {
                _logger.Log(DeclaringType, Level.Debug, message, exception);
            }
        }

        public void DebugFormat(string format, params Object[] args)
        {
            if (IsDebugEnabled)
            {
                _logger.Log(DeclaringType, Level.Debug, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
            }
        }

        public void DebugFormat(Exception exception, string format, params Object[] args)
        {
            if (IsDebugEnabled)
            {
                _logger.Log(DeclaringType, Level.Debug, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), exception);
            }
        }

        public void DebugFormat(IFormatProvider formatProvider, string format, params Object[] args)
        {
            if (IsDebugEnabled)
            {
                _logger.Log(DeclaringType, Level.Debug, new SystemStringFormat(formatProvider, format, args), null);
            }
        }

        public void DebugFormat(Exception exception, IFormatProvider formatProvider, string format, params Object[] args)
        {
            if (IsDebugEnabled)
            {
                _logger.Log(DeclaringType, Level.Debug, new SystemStringFormat(formatProvider, format, args), exception);
            }
        }

        public void Error(string message)
        {
            if (IsErrorEnabled)
            {
                _logger.Log(DeclaringType, Level.Error, message, null);
            }
        }

        public void Error(Func<string> messageFactory)
        {
            if (IsErrorEnabled)
            {
                _logger.Log(DeclaringType, Level.Error, messageFactory.Invoke(), null);
            }
        }

        public void Error(string message, Exception exception)
        {
            if (IsErrorEnabled)
            {
                _logger.Log(DeclaringType, Level.Error, message, exception);
            }
        }

        public void ErrorFormat(string format, params Object[] args)
        {
            if (IsErrorEnabled)
            {
                _logger.Log(DeclaringType, Level.Error, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
            }
        }

        public void ErrorFormat(Exception exception, string format, params Object[] args)
        {
            if (IsErrorEnabled)
            {
                _logger.Log(DeclaringType, Level.Error, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), exception);
            }
        }

        public void ErrorFormat(IFormatProvider formatProvider, string format, params Object[] args)
        {
            if (IsErrorEnabled)
            {
                _logger.Log(DeclaringType, Level.Error, new SystemStringFormat(formatProvider, format, args), null);
            }
        }

        public void ErrorFormat(Exception exception, IFormatProvider formatProvider, string format, params Object[] args)
        {
            if (IsErrorEnabled)
            {
                _logger.Log(DeclaringType, Level.Error, new SystemStringFormat(formatProvider, format, args), exception);
            }
        }

        public void Fatal(string message)
        {
            if (IsFatalEnabled)
            {
                _logger.Log(DeclaringType, Level.Fatal, message, null);
            }
        }

        public void Fatal(Func<string> messageFactory)
        {
            if (IsFatalEnabled)
            {
                _logger.Log(DeclaringType, Level.Fatal, messageFactory.Invoke(), null);
            }
        }

        public void Fatal(string message, Exception exception)
        {
            if (IsFatalEnabled)
            {
                _logger.Log(DeclaringType, Level.Fatal, message, exception);
            }
        }

        public void FatalFormat(string format, params Object[] args)
        {
            if (IsFatalEnabled)
            {
                _logger.Log(DeclaringType, Level.Fatal, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
            }
        }

        public void FatalFormat(Exception exception, string format, params Object[] args)
        {
            if (IsFatalEnabled)
            {
                _logger.Log(DeclaringType, Level.Fatal, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), exception);
            }
        }

        public void FatalFormat(IFormatProvider formatProvider, string format, params Object[] args)
        {
            if (IsFatalEnabled)
            {
                _logger.Log(DeclaringType, Level.Fatal, new SystemStringFormat(formatProvider, format, args), null);
            }
        }

        public void FatalFormat(Exception exception, IFormatProvider formatProvider, string format, params Object[] args)
        {
            if (IsFatalEnabled)
            {
                _logger.Log(DeclaringType, Level.Fatal, new SystemStringFormat(formatProvider, format, args), exception);
            }
        }

        public void Info(string message)
        {
            if (IsInfoEnabled)
            {
                _logger.Log(DeclaringType, Level.Info, message, null);
            }
        }

        public void Info(Func<string> messageFactory)
        {
            if (IsInfoEnabled)
            {
                _logger.Log(DeclaringType, Level.Info, messageFactory.Invoke(), null);
            }
        }

        public void Info(string message, Exception exception)
        {
            if (IsInfoEnabled)
            {
                _logger.Log(DeclaringType, Level.Info, message, exception);
            }
        }

        public void InfoFormat(string format, params Object[] args)
        {
            if (IsInfoEnabled)
            {
                _logger.Log(DeclaringType, Level.Info, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
            }
        }

        public void InfoFormat(Exception exception, string format, params Object[] args)
        {
            if (IsInfoEnabled)
            {
                _logger.Log(DeclaringType, Level.Info, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), exception);
            }
        }

        public void InfoFormat(IFormatProvider formatProvider, string format, params Object[] args)
        {
            if (IsInfoEnabled)
            {
                _logger.Log(DeclaringType, Level.Info, new SystemStringFormat(formatProvider, format, args), null);
            }
        }

        public void InfoFormat(Exception exception, IFormatProvider formatProvider, string format, params Object[] args)
        {
            if (IsInfoEnabled)
            {
                _logger.Log(DeclaringType, Level.Info, new SystemStringFormat(formatProvider, format, args), exception);
            }
        }

        public void Warn(string message)
        {
            if (IsWarnEnabled)
            {
                _logger.Log(DeclaringType, Level.Warn, message, null);
            }
        }

        public void Warn(Func<string> messageFactory)
        {
            if (IsWarnEnabled)
            {
                _logger.Log(DeclaringType, Level.Warn, messageFactory.Invoke(), null);
            }
        }

        public void Warn(string message, Exception exception)
        {
            if (IsWarnEnabled)
            {
                _logger.Log(DeclaringType, Level.Warn, message, exception);
            }
        }

        public void WarnFormat(string format, params Object[] args)
        {
            if (IsWarnEnabled)
            {
                _logger.Log(DeclaringType, Level.Warn, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
            }
        }

        public void WarnFormat(Exception exception, string format, params Object[] args)
        {
            if (IsWarnEnabled)
            {
                _logger.Log(DeclaringType, Level.Warn, new SystemStringFormat(CultureInfo.InvariantCulture, format, args), exception);
            }
        }

        public void WarnFormat(IFormatProvider formatProvider, string format, params Object[] args)
        {
            if (IsWarnEnabled)
            {
                _logger.Log(DeclaringType, Level.Warn, new SystemStringFormat(formatProvider, format, args), null);
            }
        }

        public void WarnFormat(Exception exception, IFormatProvider formatProvider, string format, params Object[] args)
        {
            if (IsWarnEnabled)
            {
                _logger.Log(DeclaringType, Level.Warn, new SystemStringFormat(formatProvider, format, args), exception);
            }
        }

        public ILogger CreateChildLogger(string loggerName)
        {
            throw new NotImplementedException();
        }
    }
    public class Log4NetLoggerFactory : AbstractLoggerFactory
    {
        internal const string DefaultConfigFileName = "log4net.config";
        private readonly ILoggerRepository _loggerRepository;

        public Log4NetLoggerFactory()
            : this(DefaultConfigFileName)
        {
        }

        public Log4NetLoggerFactory(string configFileName)
        {
            _loggerRepository = LogManager.CreateRepository(
                typeof(Log4NetLoggerFactory).GetAssembly(),
                typeof(log4net.Repository.Hierarchy.Hierarchy)
            );
            
            XmlConfigurator.Configure(_loggerRepository, new FileInfo("log4net.config"));
        }

        public log4net.Core.ILogger GetLogger(string name)
        {
            return LogManager.GetLogger(_loggerRepository.Name, name).Logger;
        }

        public override ILogger Create(string name)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }

            return new Log4NetLogger();
        }

        public override ILogger Create(string name, LoggerLevel level)
        {
            throw new NotSupportedException("Logger levels cannot be set at runtime. Please review your configuration file.");
        }
    }

    public static class TypeExtensions
    {
        public static Assembly GetAssembly(this Type type)
        {
            return type.GetTypeInfo().Assembly;
        }
    }

下面是扩展方法,这里实现注入:

    public static class Log4NetLoggerExtensions
    {
        public static IServiceCollection UseExceptionless(this IServiceCollection services)
        {
            services.AddTransient<ILogger, Log4NetLogger>();

            return services;
        }
    }

然后就可以在startup中使用了

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.UseExceptionless();
        }

比如我们在HomeController中使用:

    public class HomeController : Controller
    {
        private ILogger _logger;

        public HomeController(ILogger logger)
        {
            _logger = logger;
        }
        public IActionResult Index()
        {
           // throw new Exception("快点来!!!!!!!!!!!!!!!!!!");
            _logger.Info("index view");
            _logger.Debug("出错了!,快点来,!!");
            _logger.Error("Controller Error");
            return View();
        }
}

最后是配置文件:

最重要的是注意exceptionless的配置

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <!-- This section contains the log4net configuration settings -->
  <log4net>
    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
      <layout type="log4net.Layout.PatternLayout" value="%date [%thread] %-5level %logger - %message%newline" />
    </appender>
    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="Logs/" />
      <appendToFile value="true" />
      <rollingStyle value="Composite" />
      <staticLogFileName value="false" />
      <datePattern value="yyyy-MM-dd'.log'" />
      <maxSizeRollBackups value="10" />
      <maximumFileSize value="1MB" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
      </layout>
    </appender>
    <appender name="Exceptionless" type="Exceptionless.Log4net.ExceptionlessAppender,Exceptionless.Log4net">
      <apiKey value="d5qna1t9qTUVwrRzLFz1T3z8wSUeO3xNtxOGMHLf" />
      <serverUrl value="http://10.117.130.150:9001" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%-4timestamp [%thread] %-5level %logger %ndc - %message%newline"/>
      </layout>
    </appender>
    <!-- Setup the root category, add the appenders and set the default level -->
    <root>
      <level value="ALL" />
      <appender-ref ref="ConsoleAppender" />
      <appender-ref ref="RollingLogFileAppender" />
      <appender-ref ref="Exceptionless"/>
    </root>
  </log4net>
</configuration>

还有一点非常重要,记得引用,否则在exceptionless中也看不到日志

效果如图:

 

 最后,提一点:

现在容器技术很火,如果把这套代码放在容器中运行肯定是不行,因为在配置文件中配置了apikey和url, 所以要稍做修改如下:

添加一个类:

    public class ExceptionlessOption
    {
        /// <summary>
        /// 日志应用标识,从Exceptionless面板获取
        /// </summary>
        public string ApiKey { get; set; }

        /// <summary>
        /// 日志应用接口地址
        /// </summary>
        public string Url { get; set; }
    }
            services.AddMvc();
            
            services.UseExceptionless(() =>
            {
                return new ExceptionlessOption {
                    ApiKey = "234na1t9qTU234234234z8wSUeO3x234234HLf",
                    Url = "http://100.11.13.10:9001" };
            });
        public Log4NetLoggerFactory(ExceptionlessOption _option, string configFileName)
        {
            _loggerRepository = LogManager.CreateRepository(
                typeof(Log4NetLoggerFactory).GetAssembly(),
                typeof(log4net.Repository.Hierarchy.Hierarchy)
            );
            //读取配置
            XmlConfigurator.Configure(_loggerRepository, new FileInfo("log4net.config"));

            //TODO这里修改
            ExceptionlessClient.Default.Configuration.ApiKey = _option.ApiKey ?? "d5qna1t9qTUVwrRzLFz1T3z8wSUeO3xNtxOGMHLf";
            ExceptionlessClient.Default.Configuration.ServerUrl = _option.Url ??  "http://10.117.130.150:9001";

        }

然后你就可以在startup中通过读取配置文件,实现参数的传入了。

 

转载于:https://www.cnblogs.com/hankuikui/p/9264163.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
前言在互联网时代,分布式应用、系统变得越来越多,我们在使用 .Net 技术构建分布式系统的时候,需要使用到一些组件或者是助手库来帮助我们提高生产力以及应用程序解耦,但是纵观.Net圈,能够符合要求的这样的组件并不是 很多,并且没有一个通用的抽象组件能够将这些接口集成起来,今天就为大家介绍一款开源的组件库 Foundatio,他们同样出自于Exceptionless团队之手,下面就来看看吧。目录Foundatio 介绍Getting Started缓存队列锁消息工作任务文件存储度量日志示例程序源码总结Foundatio 介绍GitHub : https://github.com/exceptionless/FoundatioFoundatio 是一个插件式的,松耦合的一套构建分布式应用的程序库,出自于Exceptionless团队。Foundatio 同时支持 .NET Framework 4.6 和 .NET Core。通过 Foundatio 我可以获得哪些帮助呢?如果你是面对接口(抽象)构建的程序,你可以很容易的对接口实现进行切换。具有友好的依赖注入,还在使用 .Net Framework的朋友可以体验一下,它具有比Autofac,Unity等更简易的操作和更友好的接口。可以更加方便的使用缓存了,Foundatio帮助我们封装了很多缓存的客户端实现,比如RedisCache、InMemoryCache、ScopedCache等等。消息总线,你不必自己构建或者使用复杂且昂贵的NServiceBus了,很多时候我们仅仅需要的是一个可以在本地或者云上运行的简单的消息总线。存储,现在你可以很方便的通过一致的接口来使用分布式存储了,包括内存文件存储、文件夹文件存储,Azure文件存储,AWS S3文件存储。Foundatio 主要包含以下模块:缓存(Caching)队列(Queues)锁(Locks)消息(Messaging)工作任务(Jobs)文件存储(File Storage)度量(Metrics)日志(Logging)这些组件都以NuGet包的形式提供出来供我们很方便的使用,下面依次来看看每一个组件的用途和使用方法吧。Getting Started缓存缓存是一种空间换时间的技术,你可以通过缓存来快速的获取一些数据。Foundatio Cache 提供了一致的接口ICacheClient 来很容易的存储或者读取缓存数据,并且提供了4中不同的缓存客户端的实现。他们分别是:1、InMemoryCacheClient:内存缓存的实现,这种缓存的生命周期为当前进程, 有一个MaxItems属性,可以设置最多缓存多少条数据。2、HybridCacheClient:InMemoryCacheClient 具有相同的实现,但是此接口提供、IMessageBus 可以用来跨线程之间的同步。3、RedisCacheClient:一个 Redis 客户端的实现。4、RedisHybridCacheClient:一个RedisCacheClient 、InMemoryCacheClient 的混合实现,通过RedisMessageBus来保持内存缓存跨线程之间的同步。注意:如果本地缓存的项已经存在,在调用Redis进行序列化保存的时候可能会有性能问题。5、ScopedCacheClient:传入ICacheClient和scope,scope 可以设置一个字符串,来制定一个缓存键前缀,这样可以很方便的进行批量存储和删除。例子:using Foundatio.Caching; ICacheClient cache = new InMemoryCacheClient(); await cache.SetAsync("test", 1); var value = await cache.GetAsync("test");队列提供了一个先进,先出的消息管道,Foundatio 提供了一个IQueue接口,并且拥有 4 种不同的队列实现。1、InMemoryQueue:一个内存队列实现,队列的生命周期为当前进程。2、RedisQueue:一个 Redis 队列实现。3、AzureServiceBusQueue:一个基于Azure的服务消息队列实现。4、AzureStorageQueue:一个基于Azure的存储队列实现。例子:using Foundatio.Queues; IQueue queue = new InMemoryQueue();await queue.EnqueueAsync(new SimpleWorkItem {     Data = "Hello"});var
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值