Code For Fun

[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 : ILogger
21         {
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                 else
48                 {
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代码,大家还是自己敲吧,因为偷懒的木匠从来都不是好司机。

 

posted on 2015-06-17 09:33  我只是来看戏的  阅读(1870)  评论(3编辑  收藏  举报

导航