Chuyển đến nội dung chính

NLog với ASP.NET Core

Logging là 1 phần không thể thiếu khi làm phần mềm lẫn website. Logging phát huy tác dụng khi bạn cần log lại những lỗi tiềm ẩn hoặc ghi nhận lại lỗi trong quá trình sử dụng phần mềm/website của người sử dụng.

Có rất nhiều thư viện hỗ trợ cho việc logging message như SeriLog, NLog. Trong bài viết này, mình sẽ hướng dẫn các bạn sử dụng NLog.

Cài đặt

Mở NuGet Package Manager Console, cài đặt 2 packages:

Install-Package NLog.Web.AspNetCore
Install-Package NLog.Config
Sau khi cài đặt, bạn sẽ thấy file NLog.config (readonly) nằm trong trong package. Bạn copy file NLog.config từ thư mục package vào thư mục gốc của Project.
Mặc định, file sẽ được cấu hình property ‘Copy to output directory’ = ‘Copy if newer’
<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
      autoReload="true"
      throwExceptions="false"
      internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">

  <!-- optional, add some variables
  https://github.com/nlog/NLog/wiki/Configuration-file#variables
  -->
  <variable name="myvar" value="myvalue"/>

  <!--
  See https://github.com/nlog/nlog/wiki/Configuration-file
  for information on customizing logging rules and outputs.
   -->
  <targets>

    <!--
    add your targets here
    See https://github.com/nlog/NLog/wiki/Targets for possible targets.
    See https://github.com/nlog/NLog/wiki/Layout-Renderers for the possible layout renderers.
    -->

    <!--
    Write events to a file with the date in the filename.
    <target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
            layout="${longdate} ${uppercase:${level}} ${message}" />
    -->
  </targets>

  <rules>
    <!-- add your logging rules here -->

    <!--
    Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace)  to "f"
    <logger name="*" minlevel="Debug" writeTo="f" />
    -->
  </rules>
</nlog>

Giải thích

autoReload="true": cho phép reload lại file settings nếu có bất kỳ sự thay đổi nào. 

targets: là nơi để bạn ghi log. NLog hỗ trợ xuất ra nhiều nguồn khác nhau

  1. Files
  2. Console & Colored Console
  3.  Event Log
  4. Database
  5.  Email
  6.  …

Layout: định nghĩa template để xuất message log

  • ${level} – chỉ ra Log Level
  • ${exception} – exception message
  • ${logger} – trả về logger name
  • ${newline} – thêm dòng mới
  • ${stacktrace} – trả về stacktrace
  • ${date} – Current Date and Time
  • ${hostname} – Current machine name
  • ${processname} – Current Process Name 

Log level (MS Log): có 6 level: Trace = 0, Debug = 1, Information = 2, Warning = 3, Error = 4, Critical = 5, and None = 6.

Log Level chỉ định minimum level cho log của chương trình. Khi một LogLevel được chỉ định, việc ghi log sẽ được kích hoạt cho level đã chỉ định và cao hơn.

Vd: Chúng ta setup 1 chương trình cho phép ghi log từ level Information hoặc level cao hơn (warning, Error, Critical, None)

using NLog;
using NLog.Web;

var logger = LogManager
    .Setup()
    .LoadConfigurationFromAppSettings()
    .GetCurrentClassLogger();

try
{
    var builder = WebApplication.CreateBuilder(args);

    // Add services to the container.
    builder.Services.AddControllersWithViews();

    // Cleaer the build in provider
    builder.Logging.ClearProviders();

    // log your application at trace level 
    builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Information);

    // Register the NLog service
    builder.Host.UseNLog();

    var app = builder.Build();

    // Configure the HTTP request pipeline.
    //...

}
catch (Exception ex)
{
    logger.Error(ex, "Stopped program because of exception");
    throw;
}
finally
{
    // Ensure to shout downon the NLog ( Disposing )
    NLog.LogManager.Shutdown();
}
Mở file NLog.config, update target như sau:
<targets>
  <target xsi:type="File" name="fileTarget" fileName="${basedir}/logs/${shortdate}.log" layout="${longdate} ${uppercase:${level}} ${message}" />
  <target xsi:type="ColoredConsole" name="consoleTarget"  layout="${longdate} ${uppercase:${level}} ${message}" />
</targets>
Mở file HomeController.cs, thêm đoạn code sau:
public class HomeController : Controller
{
	private readonly ILogger<HomeController> _logger;

	public HomeController(ILogger<HomeController> logger)
	{
		_logger = logger;
	}

	public IActionResult Index()
	{
		_logger.LogInformation("Log Information: Nhatkyhoctap");
		_logger.LogWarning("Log Warning");
		_logger.LogError(new Exception(), "Log Error");
		return View();
	}
}
Mở folder log, mở file *.log để kiểm tra kết quả
2023-04-03 00:27:51.4230 INFO Log Information: Nhatkyhoctap
2023-04-03 00:27:51.4230 WARN Log Warning
2023-04-03 00:27:51.4230 ERROR Log Error
Trường hợp bạn mở console:
2023-04-03 00:27:51.4230 INFO Log Information: Nhatkyhoctap
2023-04-03 00:27:51.4230 WARN Log Warning
2023-04-03 00:27:51.4230 ERROR Log Error

Rule và filter

Trong NLog, có 6 level Log: Log level: có 6 level

  • Trace:Vết thông tin với nội dung rất chi tiết để chuẩn đoán, thường là về mặt nghiệp vụ
  • Debug: Thông tin gỡ rỗi kỹ thuật
  • Info: Thông tin thông báo
  • Warn: Thông tin cảnh báo
  • Error: Thông tin khi xảy lỗi ứng dụng
  • Fatal: Lỗi nghiêm trọng, trước khi ứng dụng bị crash

Việc nắm rõ Log level sẽ giúp bạn dễ dàng thực hiện filter log theo yêu cầu.

Ví dụ: Hiển thị warning message cho ConsoleTarget2, ConsoleTarget3. Hiển thị Error cho ConsoleTarget


<targets>
  <target xsi:type="File" name="fileTarget" fileName="${basedir}/logs/${shortdate}.log" layout="${longdate} ${uppercase:${level}} ${message}" />
  <target xsi:type="ColoredConsole" name="consoleTarget"  layout="${longdate} ${uppercase:${level}} ${message}">
	  <highlight-row condition="true" foregroundColor="red"/>
  </target>
  <target xsi:type="ColoredConsole" name="consoleTarget2"  layout="Yellow Log|${longdate} ${uppercase:${level}} |${logger}|${message}">
	  <highlight-row condition="true" foregroundColor="yellow"/>
  </target>
  <target xsi:type="ColoredConsole" name="consoleTarget3"  layout="Green Log|${longdate} ${uppercase:${level}} |${logger}|${message}">
	  <highlight-row condition="true" foregroundColor="green"/>
  </target>
</targets>

<rules>
  <logger name="*" minlevel="Warn" writeTo="consoleTarget2,consoleTarget3" />
  <logger name="*" minlevel="Error" writeTo="consoleTarget" />
  <logger name="*" minlevel="Trace" writeTo="fileTarget" />
<!-- add your logging rules here -->

<!--
Write all events with minimal level of Debug (So Debug, Info, Warn, Error and Fatal, but not Trace)  to "f"
<logger name="*" minlevel="Debug" writeTo="f" />
-->
</rules>

Kết quả

Yellow Log|2023-04-04 08:36:11.3456 WARN |LogTutorial.Controllers.HomeController|Log Warning
Green Log|2023-04-04 08:36:11.3456 WARN |LogTutorial.Controllers.HomeController|Log Warning
2023-04-04 08:36:11.3456 ERROR Log Error 

Ví dụ 2

Trường hợp bạn muốn filter, không hiển thị log từ Common

<targets>
  <target xsi:type="File" name="fileTarget" fileName="${basedir}/logs/${shortdate}.log" layout="${longdate} ${uppercase:${level}} ${message}" />
  <target xsi:type="ColoredConsole" name="consoleTarget"  layout="${longdate} ${uppercase:${level}} ${message}">
	  <highlight-row condition="true" foregroundColor="red"/>
  </target>
  <target xsi:type="ColoredConsole" name="consoleTarget2"  layout="Yellow Log|${longdate} ${uppercase:${level}} |${logger}|${message}">
	  <highlight-row condition="true" foregroundColor="yellow"/>
  </target>
  <target xsi:type="ColoredConsole" name="consoleTarget3"  layout="Green Log|${longdate} ${uppercase:${level}} |${logger}|${message}">
	  <highlight-row condition="true" foregroundColor="green"/>
  </target>
</targets>

<rules>
  <logger name="*" levels="Warn" writeTo="consoleTarget2,consoleTarget3" />
  <logger name="*" minlevel="Error" writeTo="consoleTarget">
	  <filters defaultAction='Log'>
		  <when condition="contains('${message}','Common')" action="Ignore" />
	  </filters>
  </logger>
  <logger name="*" minlevel="Trace" writeTo="fileTarget" />
</rules>
Cập nhật lại action Index trong HomeController
public IActionResult Index()
{
	_logger.LogInformation("Log Information: Nhatkyhoctap");
	_logger.LogWarning("Log Warning");
	_logger.LogError(new Exception(), "Log Error From HomeController");
	_logger.LogError(new Exception(), "Log Error From Common");
	return View();
}

Kết quả

Yellow Log|2023-04-04 08:42:11.6888 WARN |LogTutorial.Controllers.HomeController|Log Warning
Green Log|2023-04-04 08:42:11.6888 WARN |LogTutorial.Controllers.HomeController|Log Warning
2023-04-04 08:42:11.6888 ERROR Log Error From HomeController

Nhận xét

Bài đăng phổ biến từ blog này

[ASP.NET MVC] Authentication và Authorize

Một trong những vấn đề bảo mật cơ bản nhất là đảm bảo những người dùng hợp lệ truy cập vào hệ thống. ASP.NET đưa ra 2 khái niệm: Authentication và Authorize Authentication xác nhận bạn là ai. Ví dụ: Bạn có thể đăng nhập vào hệ thống bằng username và password hoặc bằng ssh. Authorization xác nhận những gì bạn có thể làm. Ví dụ: Bạn được phép truy cập vào website, đăng thông tin lên diễn đàn nhưng bạn không được phép truy cập vào trang mod và admin.

ASP.NET MVC: Cơ bản về Validation

Validation (chứng thực) là một tính năng quan trọng trong ASP.NET MVC và được phát triển trong một thời gian dài. Validation vắng mặt trong phiên bản đầu tiên của asp.net mvc và thật khó để tích hợp 1 framework validation của một bên thứ 3 vì không có khả năng mở rộng. ASP.NET MVC2 đã hỗ trợ framework validation do Microsoft phát triển, tên là Data Annotations. Và trong phiên bản 3, framework validation đã hỗ trợ tốt hơn việc xác thực phía máy khách, và đây là một xu hướng của việc phát triển ứng dụng web ngày nay.

Tổng hợp một số kiến thức lập trình về Amibroker

Giới thiệu về Amibroker Amibroker theo developer Tomasz Janeczko được xây dựng dựa trên ngôn ngữ C. Vì vậy bộ code Amibroker Formula Language sử dụng có syntax khá tương đồng với C, ví dụ như câu lệnh #include để import hay cách gói các object, hàm trong các block {} và kết thúc câu lệnh bằng dấu “;”. AFL trong Amibroker là ngôn ngữ xử lý mảng (an array processing language). Nó hoạt động dựa trên các mảng (các dòng/vector) số liệu, khá giống với cách hoạt động của spreadsheet trên excel.