参考了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的更多相关文章

  1. Asp.net Core + Log4net + ELK 搭建日志中心

    原文:Asp.net Core + Log4net + ELK 搭建日志中心 Docker中一键安装ELK 对于这种工具类的东西,第一步就直接到docker的hub中查找了,很幸运,不仅有Elasti ...

  2. 浅谈ASP.NET Core中的DI

    DI的一些事 传送门马丁大叔的文章 什么是依赖注入(DI: Dependency Injection)?     依赖注入(DI)是一种面向对象的软件设计模式,主要是帮助开发人员开发出松耦合的应用程序 ...

  3. asp.net core 四 IOC&DI Autofac

    其实关于IOC,DI已经有了很多的文章,但是自己在使用中还是有很多困惑,而且相信自己使用下,印象还是会比较深刻的 关于这段时间一直在学习.net core,但是这篇文章是比较重要的,也是我自己觉得学习 ...

  4. 在Asp.Net Core中使用DI的方式使用Hangfire构建后台执行脚本

    最近项目中需要用到后台Job,原有在Windows中我们会使用命令行程序结合计划任务或者直接生成Windows Service,现在.Net Core跨平台了,虽然Linux下也有计划任务,但跟原有方 ...

  5. ASP.NET Core 依赖注入(DI)

    ASP.NET Core的底层设计支持和使用依赖注入.ASP.NET Core 应用程序可以利用内置的框架服务将服务注入到启动类的方法中,并且应用程序服务也可以配置注入.由ASP.NET Core 提 ...

  6. ASP.NET Core依赖注入(DI)

    ASP.NET Core允许我们指定注册服务的生存期.服务实例将根据指定的生存时间自动处理.因此,我们无需担心清理此依赖关系,他将由ASP.NET Core框架处理.有如下三种类型的生命周期. 关于依 ...

  7. asp.net core 内置DI容器的一点小理解

    DI容器本质上是一个工厂,负责提供向它请求的类型的实例. .net core内置了一个轻量级的DI容器,方便开发人员面向接口编程和依赖倒置(IOC). 具体体现为Micorosoft.Extensio ...

  8. Asp.net core 学习笔记 ( DI 依赖注入 )

    比起 Angular 的依赖注入, core 的相对简单许多, 容易明白 所有 provider 都在 startup 里配置. public void ConfigureServices(IServ ...

  9. Asp.Net Core Log4Net 配置分多个文件记录日志(不同日志级别)

    本文所有配置都是在core3.1环境下. 首先看看最终的效果. 请求监控:对每次请求的相关信息做一个记录. 全局异常:我不想我的错误信息,跟其他的信息混合在一起,查看的时候不大方便. 应用日志:这个主 ...

随机推荐

  1. 多进程使用matplotlib.pyplot绘heatmap(多线程不可以)

    数据格式如下: 8_15/l_eye/2732.png -20.5773 -5.17769 -3.34583 21.5859 9_13_1/l_eye/1211.png -10.1145 34.992 ...

  2. windows脚本-CMD和Batch

    一.DOS,CMD和batch DOS是磁盘操作系统(英文:Disk Operating System)的缩写,是个人计算机上的一类操作系统.从1981年直到1995年的15年间,DOS在IBM PC ...

  3. HTML5开源RPG游戏引擎lufylegendRPG 0.1发布

    一,小小开篇   首先不得不先介绍一下这个引擎: lufylegendRPG是lufylegend的拓展引擎,使用它时,需要引入lufylegend.同时您也需要了解lufylegend语法,这样才能 ...

  4. Git添加本地项目出现fatal: unable to get credential storage lock: File exists

    把本地项目初始化之后上传到github上出现问题:fatal: unable to get credential storage lock: File exists 解决办法:是因为我上传用的git帐 ...

  5. 20165324 实验二《Java面向对象程序设计》实验报告

    20165324 实验二<Java面向对象程序设计>实验报告 一.实验报告封面 课程:Java程序设计 班级:1653班 姓名:何春江 学号:20165324 指导教师:娄嘉鹏 实验日期: ...

  6. 我与前端之间不得不说的三天两夜之jQuery

    前端基础之jquery 一 jQuery是什么? [1] jQuery由美国人John Resig创建,至今已吸引了来自世界各地的众多 javascript高手加入其team. [2] jQuery是 ...

  7. mysql数据库从删库到跑路之mysql存储引擎

    一 什么是存储引擎 mysql中建立的库===>文件夹 库中建立的表===>文件 现实生活中我们用来存储数据的文件应该有不同的类型:比如存文本用txt类型,存表格用excel,存图片用pn ...

  8. php处理restful请求的路由(转载 http://www.jb51.net/article/47333.htm)

    <?php    class Router {        // 路由表        private $routers = array(            array("nam ...

  9. css-1,css的三种引入方式 基本选择器

    <!-- (1)CSS 层叠样式表 作用:修饰网页结构 (2)css的三种引入方式 权重: 优先级高 权重大 谁在页面谁的权重大 - 行内样式 注意:行内样式的优先级是最高的 - 内接样式 - ...

  10. (转载)sql注入实战 mysql篇

    出现的关键名词有: UNION  SELECT   load_file   hex 为了方便说明我们先创建两个表:hehe和heihei,很明显它们一个拥有2列属性,一个拥有3列属性 ======== ...