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

  • 相关阅读:
    linux系统中如何进入退出vim编辑器,方法及区别
    [转]JAVA的动态代理机制及Spring的实现方式
    mybaties 缓存
    全面分析 Spring 的编程式事务管理及声明式事务管理
    面试(4)-spring-Spring面试题和答案
    vector的多套遍历方案
    【QT】QT下载与安装
    【QT】无需写connect代码关联信号和槽函数
    【QT】第一个QT程序(点击按钮,显示特定文本)
    【QT】error: 'SIGNAL' was not declared in this scope
  • 原文地址:https://www.cnblogs.com/yzi1/p/4581374.html
Copyright © 2020-2023  润新知