你的位置:首页 > ASP.net教程

[ASP.net教程][walkthrough] 在Asp.net MVC6 RC里使用NLog,并且把配置集成到config.json


说明一下:本文基于随visual studio 2015 RC公开的DNX1.0.0-beta4,git上最新的aspnet的开发版本已经发生了很大变化。

 首先,理论部分看[汤姆大叔的博客] 解读ASP.NET 5 & MVC6系列(9):日志框架

 

实际上aspnet的开发人员已经在最近版的系统里开始集成nlog了。 本文的目的主要帮助大家理解aspnet mvc 6的框架。

新建工程 "NlogTest"

选“asp.net 5”的”web site”,  然后不要认证模块,我们主要演示NLog的用法,对auth认证没兴趣。

 

◎添加Nlog参照

打开project.json, 添加 NLog,同时删除dnxcore50,Nlog还没有支持coreclr,所以先删了。

修改frameworks部分,修改后的样子。

 "frameworks": {  "dnx451": {   "dependencies": { "NLog": "3.2.0" }  } },

◎添加nlog的配置到config.json里,5行以下为本次追加内容。

 1 { 2  "AppSettings": { 3   "SiteTitle": "NLogTest" 4  }, 5  "nlog": { 6   "targets": { 7    "file": { 8     "type": "File", 9     "layout": "${date:format=HH\\:MM\\:ss} ${logger} ${message}",10     "fileName": "c:\\work\\aaa.txt"11    },12    "file2": {13     "type": "File",14     "fileName": "c:\\work\\bbb.txt"15    }16    "mail1": {17 18    }19   },20   "rules": {21    "rule1": {22     "minlevel": "Debug",23     "writeTo": "file"24    },25    "rule2": {26     "name": "*",27     "minlevel": "Info",28     "writeTo": "file2"29    }30   }31  }32 }

配置到此为止,下面开始编程。

◎添加一个NLogProvider类, 实现ILoggerProvider并在其内部实现ILogger

先上代码,我是微软的实现中搬过来的,做了一些修改。

 1 using Microsoft.Framework.Logging; 2 using System; 3  4 namespace NLogTest 5 { 6   public class NLogProvider:ILoggerProvider 7   { 8     private readonly global::NLog.LogFactory _logFactory; 9 10     public NLogProvider(global::NLog.LogFactory logFactory)11     {12       _logFactory = logFactory;13     }14 15     public ILogger CreateLogger(string name)16     {17       return new Logger(_logFactory.GetLogger(name));18     }19 20     private class Logger : ILogger21     {22       private readonly global::NLog.Logger _logger;23 24       public Logger(global::NLog.Logger logger)25       {26         _logger = logger;27       }28 29       public IDisposable BeginScope(object state)30       {31         return global::NLog.NestedDiagnosticsContext.Push(state.ToString());32       }33 34       public bool IsEnabled(LogLevel logLevel)35       {36         return _logger.IsEnabled(GetLogLevel(logLevel));37       }38 39       public void Log(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)40       {41         var nLogLogLevel = GetLogLevel(logLevel);42         var message = string.Empty;43         if (formatter != null)44         {45           message = formatter(state, exception);46         }47         else48         {49           message = LogFormatter.Formatter(state, exception);50         }51 52         if (!string.IsNullOrEmpty(message))53         {54           var eventInfo = global::NLog.LogEventInfo.Create(nLogLogLevel, _logger.Name, message);55           eventInfo.Properties["EventId"] = eventId;56           _logger.Log(eventInfo);57         }58       }59 60       private global::NLog.LogLevel GetLogLevel(LogLevel logLevel)61       {62         switch (logLevel)63         {64           case LogLevel.Verbose: return global::NLog.LogLevel.Debug;65           case LogLevel.Information: return global::NLog.LogLevel.Info;66           case LogLevel.Warning: return global::NLog.LogLevel.Warn;67           case LogLevel.Error: return global::NLog.LogLevel.Error;68           case LogLevel.Critical: return global::NLog.LogLevel.Fatal;69         }70         return global::NLog.LogLevel.Debug;71       }72     }73   }74 }

View Code

代码很简单,就是在微软的日志框架和NLog的函数间实现一个桥接。

◎添加一个NLogLoggerFactoryExtensions类,追加ILoggerFactory的扩张函数,这里是本次演示的重点了。

using Microsoft.Framework.ConfigurationModel;using Microsoft.Framework.Logging;using System;using System.Linq;using System.Text;namespace NLogTest{  public static class NLogLoggerFactoryExtensions  {    public static ILoggerFactory AddNLog(        this ILoggerFactory factory,        IConfiguration configuration)    {      var config = new global::NLog.Config.LoggingConfiguration();      var targets = configuration.GetSubKey("targets");      foreach (var item in targets.GetSubKeys())      {        AddTargets(config, item.Key, item.Value);      }      var rules = configuration.GetSubKey("rules");      foreach (var item in rules.GetSubKeys())      {        AddLoggingRule(config, item.Value);      }      factory.AddProvider(new NLogProvider(new global::NLog.LogFactory(config)));      return factory;    }    private static void AddTargets(global::NLog.Config.LoggingConfiguration configuration, string targetName, IConfiguration targetConf)    {      string targetType = "";      if (targetConf.TryGet("type", out targetType))      {        switch (targetType.ToLower())        {          case "file":            configuration.AddTarget(targetName, GenFileTarget(targetName, targetConf));            break;          case "mail":            configuration.AddTarget(targetName, GenMailTarget(targetName, targetConf));            break;          default:            break;        }      }    }    private static global::NLog.Targets.Target GenFileTarget(string targetName, IConfiguration targetConf)    {      var fileTarget = new global::NLog.Targets.FileTarget();      fileTarget.Name = targetName;      string confVal = GetVal(targetConf, "fileName");      if (string.IsNullOrEmpty(confVal))      {        //Filename is not setting , throw exception!        throw new ArgumentNullException("fileTarget's filename is empty.");      }      fileTarget.FileName = confVal;      confVal = GetVal(targetConf, "layout");      if (!string.IsNullOrEmpty(confVal))      {        fileTarget.Layout = confVal;      }      confVal = GetVal(targetConf, "keepfileopen");      if (!string.IsNullOrEmpty(confVal))      {        fileTarget.KeepFileOpen = (confVal.ToLower() == "true");      }      confVal = GetVal(targetConf, "encoding");      if (!string.IsNullOrEmpty(confVal))      {        fileTarget.Encoding = Encoding.GetEncoding(confVal);      }      fileTarget.AutoFlush = true;      return fileTarget;    }    private static global::NLog.Targets.Target GenMailTarget(string targetName, IConfiguration targetConf)    {      var mailTarget = new global::NLog.Targets.MailTarget();      mailTarget.Name = targetName;      string confVal = GetVal(targetConf, "to");      if (string.IsNullOrEmpty(confVal))      {        //to is not setting , throw exception!        throw new ArgumentNullException("mailTarget's [to] is empty.");      }      mailTarget.To = confVal;      confVal = GetVal(targetConf, "from");      if (string.IsNullOrEmpty(confVal))      {        //to is not setting , throw exception!        throw new ArgumentNullException("mailTarget's [from] is empty.");      }      mailTarget.From = confVal;      confVal = GetVal(targetConf, "layout");      if (!string.IsNullOrEmpty(confVal))      {        mailTarget.Layout = confVal;      }      confVal = GetVal(targetConf, "subject");      if (!string.IsNullOrEmpty(confVal))      {        mailTarget.Subject = confVal;      }      confVal = GetVal(targetConf, "smtpusername");      if (!string.IsNullOrEmpty(confVal))      {        mailTarget.SmtpUserName = confVal;      }      confVal = GetVal(targetConf, "smtppassword");      if (!string.IsNullOrEmpty(confVal))      {        mailTarget.SmtpPassword = confVal;      }      confVal = GetVal(targetConf, "smtpserver");      if (!string.IsNullOrEmpty(confVal))      {        mailTarget.SmtpServer = confVal;      }      confVal = GetVal(targetConf, "smtpport");      if (!string.IsNullOrEmpty(confVal))      {        int nPort = 25;        if (int.TryParse(confVal, out nPort))        {          mailTarget.SmtpPort = nPort;        }      }      return mailTarget;    }    private static void AddLoggingRule(global::NLog.Config.LoggingConfiguration configuration, IConfiguration ruleConf)    {      string namePattern = "*";      string confVal = GetVal(ruleConf, " name");      if (!string.IsNullOrEmpty(confVal))      {        namePattern = confVal;      }      confVal = GetVal(ruleConf, "minlevel");      global::NLog.LogLevel minLevel = global::NLog.LogLevel.Debug;      if (!string.IsNullOrEmpty(confVal))      {        minLevel = GetLogLevel(confVal, global::NLog.LogLevel.Trace);      }      confVal = GetVal(ruleConf, "writeto");      global::NLog.Targets.Target target = null;      if (!string.IsNullOrEmpty(confVal))      {        target = configuration.ConfiguredNamedTargets.Where(t => t.Name == confVal).FirstOrDefault();      }      if (target != null)      {        configuration.LoggingRules.Add(new global::NLog.Config.LoggingRule(namePattern, minLevel, target));      }    }    private static string GetVal(IConfiguration configuration, string key)    {      string val = "";      if (configuration.TryGet(key, out val))      {        return val;      }      else      {        return null;      }    }    private static global::NLog.LogLevel GetLogLevel(string logLevel, global::NLog.LogLevel defaultLevel = null)    {      switch (logLevel.ToLower())      {        case "debug": return global::NLog.LogLevel.Debug;        case "info": return global::NLog.LogLevel.Info;        case "warn": return global::NLog.LogLevel.Warn;        case "error": return global::NLog.LogLevel.Error;        case "fatal": return global::NLog.LogLevel.Fatal;      }      return defaultLevel;    }  }}

View Code

实例化Nlog.LogFactory类,并从config里读取的配置,设置到该LogFactory里。

下面是NLog的使用了。

 

◎打开 Startup.cs文件,并在Configure函数里AddLog。

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory)    {      // Configure the HTTP request pipeline.      // Add the console logger.      loggerfactory.AddConsole();      //Add the NLog logger      loggerfactory.AddNLog(Configuration.GetSubKey("nlog"));      //Log Output Test.      var logger = loggerfactory.CreateLogger("NLogTest");      logger.LogInformation("this is infomation from startup");      try      {        var i = 100 - 100;        var j = 100 / i;      }      catch (DivideByZeroException ex)      {        logger.LogError("error log test", ex);      }      。。。。。。。。。。以下略          }

 

◎在Controller里使用

打开HomeController.cs文件,并追加代码。

public class HomeController : Controller  {    private ILogger _logger = null;    public HomeController(ILoggerFactory logFactory)    {      _logger = logFactory.CreateLogger(nameof(HomeController));      _logger.LogWarning("I am created.");    }    public IActionResult Index()    {      _logger.LogWarning("hello from index of home control... ");      return View();    }  ・・・・・・・・・・・以下略 }

 

 编译通过后,F5一下,看看自己的成果吧。

 

本文完结。

另外,俺不会提供完整的project代码,大家还是自己敲吧,因为偷懒的木匠从来都不是好司机。