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中通过读取配置文件,实现参数的传入了。
asp.net core + log4net+exceptionles+DI的更多相关文章
- Asp.net Core + Log4net + ELK 搭建日志中心
原文:Asp.net Core + Log4net + ELK 搭建日志中心 Docker中一键安装ELK 对于这种工具类的东西,第一步就直接到docker的hub中查找了,很幸运,不仅有Elasti ...
- 浅谈ASP.NET Core中的DI
DI的一些事 传送门马丁大叔的文章 什么是依赖注入(DI: Dependency Injection)? 依赖注入(DI)是一种面向对象的软件设计模式,主要是帮助开发人员开发出松耦合的应用程序 ...
- asp.net core 四 IOC&DI Autofac
其实关于IOC,DI已经有了很多的文章,但是自己在使用中还是有很多困惑,而且相信自己使用下,印象还是会比较深刻的 关于这段时间一直在学习.net core,但是这篇文章是比较重要的,也是我自己觉得学习 ...
- 在Asp.Net Core中使用DI的方式使用Hangfire构建后台执行脚本
最近项目中需要用到后台Job,原有在Windows中我们会使用命令行程序结合计划任务或者直接生成Windows Service,现在.Net Core跨平台了,虽然Linux下也有计划任务,但跟原有方 ...
- ASP.NET Core 依赖注入(DI)
ASP.NET Core的底层设计支持和使用依赖注入.ASP.NET Core 应用程序可以利用内置的框架服务将服务注入到启动类的方法中,并且应用程序服务也可以配置注入.由ASP.NET Core 提 ...
- ASP.NET Core依赖注入(DI)
ASP.NET Core允许我们指定注册服务的生存期.服务实例将根据指定的生存时间自动处理.因此,我们无需担心清理此依赖关系,他将由ASP.NET Core框架处理.有如下三种类型的生命周期. 关于依 ...
- asp.net core 内置DI容器的一点小理解
DI容器本质上是一个工厂,负责提供向它请求的类型的实例. .net core内置了一个轻量级的DI容器,方便开发人员面向接口编程和依赖倒置(IOC). 具体体现为Micorosoft.Extensio ...
- Asp.net core 学习笔记 ( DI 依赖注入 )
比起 Angular 的依赖注入, core 的相对简单许多, 容易明白 所有 provider 都在 startup 里配置. public void ConfigureServices(IServ ...
- Asp.Net Core Log4Net 配置分多个文件记录日志(不同日志级别)
本文所有配置都是在core3.1环境下. 首先看看最终的效果. 请求监控:对每次请求的相关信息做一个记录. 全局异常:我不想我的错误信息,跟其他的信息混合在一起,查看的时候不大方便. 应用日志:这个主 ...
随机推荐
- d3.js:数据可视化利器之 交互行为:响应DOM事件
selection.on:事件监听操作符 on()操作符可以添加或移除选择集中每个 DOM元素的事件监听函数: selection.on(type[,listener[,capture]]) 参数ty ...
- 【我的Android进阶之旅】快速创建和根据不同的版本类型(Dev、Beta、Release)发布Android 开发库到Maven私服
前言 由于项目越来越多,有很多公共的代码都可以抽取出一个开发库出来传到公司搭建好的Maven私服,以供大家使用. 之前搭建的Maven仓库只有Release和Snapshot两个仓库,最近由于开发库有 ...
- birt 日志打印
在birt初始initialize 方法里,定义日志输出方法 importPackage(Packages.java.util.logging); importPackage(Packages.log ...
- 关于Unix时间戳转北京时间的问题
工具在这里:http://tool.chinaz.com/Tools/unixtime.aspx?qq-pf-to=pcqq.group 今天踩了坑,无论参数是多少,年份总是1970.才发现原来参数必 ...
- Windows服务的安装、卸载
创建一个Windows服务 http://jingyan.baidu.com/article/fa4125acb71a8628ac709226.html 安装服务 使用FramWork框架自带的Ins ...
- 002-shell变量定义、使用、字符串、数组、注释
一.变量定义 定义变量时,变量名不加美元符号($) name="lhx" 注意,变量名和等号之间不能有空格.同时,变量名的命名须遵循如下规则: 命名只能使用英文字母,数字和下划线, ...
- 用仿ActionScript的语法来编写html5——第一篇,显示一张图片
第一篇,显示一张图片 一,代码对比 as代码: public var loader:Loader; public function loadimg():void{ loader = new Loade ...
- 简单认识TCP/IP协议
HTTP协议—— 简单认识TCP/IP协议 本文转自: https://www.cnblogs.com/roverliang/p/5176456.html 大学没读计算机专业,所以很多的专业知识都 ...
- Springboot+shiro配置笔记+错误小结
软件152 尹以操 springboot不像springmvc,它没有xml配置文件,那该如何配置shiro呢,其实也不难,用java代码+注解来解决这个问题.仅以此篇记录我对shiro的学习,如有对 ...
- pytorch rnn
温习一下,写着玩. import torch import torch.nn as nn import numpy as np import torch.optim as optim class RN ...