[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代碼,大家還是自己敲吧,因為偷懶的木匠從來都不是好司機。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM