notes : This article belongs to 《 understand ASP.NET Core》 Series articles , Please check the top blog or Click here to view the full-text catalog

Quick start

Add log provider

In the article host (Host) in , speak of Host.CreateDefaultBuilder Method , The default is to call ConfigureLogging Method added ConsoleDebugEventSource and EventLog( only Windows) There are four logging providers (Logger Provider), And then on the mainframe Build In the process , adopt AddLogging() Registered log related services .

.ConfigureLogging((hostingContext, logging) =>
{
bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); if (isWindows)
{
logging.AddFilter<EventLogLoggerProvider>(level => level >= LogLevel.Warning);
} // add to Logging To configure
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); // ConsoleLoggerProvider
logging.AddConsole();
// DebugLoggerProvider
logging.AddDebug();
// EventSourceLoggerProvider
logging.AddEventSourceLogger(); if (isWindows)
{
// stay Windows On the platform , add to EventLogLoggerProvider
logging.AddEventLog();
} logging.Configure(options =>
{
options.ActivityTrackingOptions = ActivityTrackingOptions.SpanId
| ActivityTrackingOptions.TraceId
| ActivityTrackingOptions.ParentId;
});
}) public class HostBuilder : IHostBuilder
{
private void CreateServiceProvider()
{
var services = new ServiceCollection(); // ... services.AddLogging(); // ...
}
}

If you don't want to use the log provider added by default , We can go through ClearProviders Clear all added logging providers , Then add what you want , Such as Console

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.ClearProviders()
.AddConsole();
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

Log

Logging providers implement interfaces ILoggerProvider, This interface can create ILogger example .

By injecting Services ILogger<TCategoryName>, It is very convenient to log .

The service needs to specify the log category , It could be any string , But we agreed to use the name of the class to which we belong , Through generics . for example , In the controller ValuesController in , The log category is ValuesController The fully qualified type name of the class .

public class ValuesController : ControllerBase
{
private readonly ILogger<ValuesController> _logger; public ValuesController(ILogger<ValuesController> logger)
{
_logger = logger;
} [HttpGet]
public string Get()
{
_logger.LogInformation("ValuesController.Get");
return "Ok";
}
}

When requested Get After the method , You can see the output in the console “ValuesController.Get”

If you want to explicitly specify the log category , You can use ILoggerFactory.CreateLogger Method :

public class ValuesController : ControllerBase
{
private readonly ILogger _logger1; public ValuesController(ILoggerFactory loggerFactory)
{
_logger1 = loggerFactory.CreateLogger("MyCategory");
}
}

Configuration log

In the default template , The log configuration is as follows ( stay appsettings.{Environment}.json In file ):

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}

Configure for all logging providers

LogLevel, seeing the name of a thing one thinks of its function , It refers to the lowest level of logs to be recorded ( That is to record logs greater than or equal to this level ), I think everyone is familiar with . Log levels are described in detail below .

LogLevel In the field , As in the example above “Default”、“Microsoft” etc. , Indicates the category of the log , That is, we inject ILogger Generic parameters specified when . You can set the minimum logging level for each category , That is, the values corresponding to these categories .

The three log categories in the example are explained in detail below .

Default

By default , If the classification is not specially configured ( That is, not in LogLevel Middle configuration ), The application of Default Configuration of .

Microsoft

All categories are in Microsoft All logs at the beginning should be applied Microsoft Configuration of . for example ,Microsoft.AspNetCore.Routing.EndpointMiddleware The configuration will be applied to the logs of the category .

Microsoft.Hosting.Lifetime

All categories are in Microsoft.Hosting.Lifetime All logs at the beginning should be applied Microsoft.Hosting.Lifetime Configuration of . for example , classification Microsoft.Hosting.Lifetime The configuration will be applied , It doesn't apply Microsoft, because Microsoft.Hosting.Lifetime Than Microsoft More specifically .

OK, That's all for the above three log categories .

Back to the example , You may not have noticed , There is no separate configuration for a logging provider ( Such as :Console Record only Error And above , and EventSource You need to record all levels of logs ). Like this , If not configured for a specific logging provider , This configuration will be applied to all logging providers .

Windows EventLog With the exception of .EventLog Must be explicitly configured , Otherwise, it will use its default LogLevel.Warning.

Configure for the specified logging provider

Next, let's look at how to configure for the specified logging provider , Let's start with an example :

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
},
"Console": {
"LogLevel": {
"Default": "Error"
}
},
"Debug": {
"LogLevel": {
"Microsoft": "None"
}
},
"EventSource": {
"LogLevel": {
"Default": "Trace",
"Microsoft": "Trace",
"Microsoft.Hosting.Lifetime": "Trace"
}
}
}
}

It's like appsettings.{Environment}.json and appsettings.json The relationship between them is the same ,Logging.{Provider}.LogLevel The configuration in will override Logging.LogLevel Configuration in .

for example Logging.Console.LogLevel.Default Will overwrite Logging.LogLevel.Default,Console The logger will record by default Error And above .

I just mentioned ,Windows EventLog A special , It will not inherit Logging.LogLevel Configuration of .EventLog The default log level is LogLevel.Warning, If you want to modify , Must be specified explicitly , Such as :

{
"Logging": {
"EventLog": {
"LogLevel": {
"Default": "Information"
}
}
}
}

Configured filtering principle

When creating a ILogger<TCategoryName> Object instance of ,ILoggerFactory According to different logging providers , will :

  1. Find a configuration that matches the logging provider . If you can't find it , General configuration is used .
  2. Then match the configuration category with the longest prefix . If you can't find it , Then use Default To configure .
  3. If multiple configurations are matched , Then use the last .
  4. If no configuration matches , Then use MinimumLevel, This is a configuration item , The default is LogLevel.Information.

Can be in ConfigureLogging In the extension SetMinimumLevel Method setting MinimumLevel.

Log Level

The log level indicates the severity of the log , Divided into 7 etc. , From light to heavy ( final None More special ):

The level of logging value describe
Trace 0 Tracking level , Contains the most detailed information . This information may contain sensitive data , Disabled by default , And must not appear in the production environment .
Debug 1 Debug level , For developers to develop and debug . The amount of information is generally large , Be sure to use with caution in the production environment .
Information 2 Information level , This level is often used .
Warning 3 Warning level , Some unexpected events , But these events do not cause program errors .
Error 4 error level , Some unhandled errors or exceptions , These events cause the current operation or request to fail , But it will not cause errors in the whole application .
Critical 5 Fatal error level , These errors will cause errors in the whole application . For example, there is not enough memory .
None 6 Indicates that no logs are logged

Logging provider

Console

The log will be output to the console .

Debug

The log will be sent through System.Diagnostics.Debug Class to output , Can pass VS Output window view .

stay Linux On , Can be in /var/log/message or /var/log/syslog Find below

EventSource

Cross platform logging , stay Windows I use ETW

Windows EventLog

Only in Windows Effective under the system , It can be done by “ Event viewer ” Log view .

By default

  • LogName by “Application”
  • SourceName by “NET Runtime”
  • MachineName Is the name of the local computer .

These fields can be accessed through EventLogSettings Make changes :

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.AddEventLog(settings =>
{
settings.LogName = "My App";
settings.SourceName = "My Log";
settings.MachineName = "My Computer";
})
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

Logging filters

Through the logging filter , Allows you to write complex logic , To control whether to log .

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging
// For all LoggerProvider Set up Microsoft Minimum log level , It is recommended to configure through the configuration file
.AddFilter("Microsoft", LogLevel.Trace)
// in the light of ConsoleLoggerProvider Set up Microsoft Minimum log level , It is recommended to configure through the configuration file
.AddFilter<ConsoleLoggerProvider>("Microsoft", LogLevel.Debug)
// For all LoggerProvider Filter configuration
.AddFilter((provider, category, logLevel) =>
{
// Because the following is for ConsoleLoggerProvider Added filtering configuration , therefore ConsoleLoggerProvider Will not enter the method if (provider == typeof(ConsoleLoggerProvider).FullName
&& category == typeof(ValuesController).FullName
&& logLevel <= LogLevel.Warning)
{
// false: Do not log
return false;
} // true: Log
return true;
})
// in the light of ConsoleLoggerProvider Filter configuration
.AddFilter<ConsoleLoggerProvider>((category, logLevel) =>
{
if (category == typeof(ValuesController).FullName
&& logLevel <= LogLevel.Warning)
{
// false: Do not log
return false;
} // true: Log
return true;
});
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});

Log message template

In the process of application development , For a certain type of log , We want their message formats to be consistent , Just some parameters change . This requires the log message template .

for instance :

[HttpGet("{id}")]
public int Get(int id)
{
_logger.LogInformation("Get {Id}", id); return id;
}

among Get {Id} Is a log message template ,{Id} Is the template parameter ( Be careful , Please write your name in it , Not Numbers , This makes it easier to understand the meaning of parameters ).

however , It should be noted that ,{Id} This template parameter , It is only used to make its meaning easy to understand , It has nothing to do with the following parameter name , Template values care about the order of parameters . for example :

[HttpGet("{id}")]
public int Get(int id)
{
_logger.LogInformation("Get {Id} at {Time}", DateTime.Now, id); return id;
}

Suppose you pass in id = 1, Its output is :Get 11/02/2021 11:42:14 at 1

Log message template is a very important function , Among many open source logging middleware , All of them are used .

Logging during host build

ASP.NET Core The framework does not directly support logging during host build . However, you can log through a separate logging provider , for example , Use a third-party logging provider :Serilog

install Nuget package :Install-Package Serilog.AspNetCore

public static void Main(string[] args)
{
// from appsettings.json And read the configuration from the command line parameters
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddCommandLine(args)
.Build(); // establish Logger
Log.Logger = new LoggerConfiguration()
.WriteTo.Console() // Output to console
.WriteTo.File(config["Logging:File:Path"]) // Output to specified file
.CreateLogger();
try
{
CreateHostBuilder(args).Build().Run();
}
catch(Exception ex)
{
Log.Fatal(ex, "Host terminated unexpectedly"); throw;
}
finally
{
Log.CloseAndFlush();
}
}

appsettings.json

{
"Logging": {
"File": {
"Path": "logs/host.log"
}
}
}

Console log format configuration

The console logging provider is essential in our development process , From the above, we have learned that we can pass AddConsole() Add . However, it has great limitations , We can't customize the log format .

therefore , stay .NET 5 in , The console logging provider has been extended , Three log output formats are preset :Json、Simple、Systemd.

actually , There were enumerations before ConsoleLoggerFormat Provides Simple and Systemd Format , However, it cannot be customized , It has been abandoned .

these Formatter All inherited from abstract classes ConsoleFormatter, The abstract class constructor receives a “ name ” Parameters , It is required that its implementation class must have a name . You can use static classes ConsoleFormatterNames Get the names of the three built-in formats .

public abstract class ConsoleFormatter
{
protected ConsoleFormatter(string name)
{
Name = name ?? throw new ArgumentNullException(nameof(name));
} public string Name { get; } public abstract void Write<TState>(in LogEntry<TState> logEntry, IExternalScopeProvider scopeProvider, TextWriter textWriter);
} public static class ConsoleFormatterNames
{
public const string Simple = "simple"; public const string Json = "json"; public const string Systemd = "systemd";
}

You can use AddConsole() when , To configure ConsoleLoggerOptions Of FormatterName attribute , To achieve the purpose of custom format , The default value is “simple”. however , For ease of use ,.NET The framework has encapsulated the three built-in formats for us .

these Formatter All option classes inherit from the option class ConsoleFormatterOptions, The option class contains the following three properties :

public class ConsoleFormatterOptions
{
// Enable scope , Default false
public bool IncludeScopes { get; set; } // Format the timestamp , Appears at the beginning of the log message
// The default is null, Don't show timestamp
public string TimestampFormat { get; set; } // Whether to set the timestamp time zone to UTC, The default is false, Local time zone
public bool UseUtcTimestamp { get; set; }
}

SimpleConsoleFormatter

By extending the method AddSimpleConsole() Support can be added Simple Console logging provider in , Default behavior vs AddConsole() Agreement .

.ConfigureLogging(logging =>
{
logging.ClearProviders()
.AddSimpleConsole();
}

Sample output :

info: Microsoft.Hosting.Lifetime[0]
Now listening on: http://localhost:5000
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: C:\Repos\WebApplication

in addition , You can go through SimpleConsoleFormatterOptions Make some custom configuration :

.ConfigureLogging(logging =>
{
logging.ClearProviders()
.AddSimpleConsole(options =>
{
// A log message is displayed on the same line
options.SingleLine = true;
options.IncludeScopes = true;
options.TimestampFormat = "yyyy-MM-dd HH:mm:ss ";
options.UseUtcTimestamp = false;
});
}

Sample output :

2021-11-02 15:53:33 info: Microsoft.Hosting.Lifetime[0] Now listening on: http://localhost:5000
2021-11-02 15:53:33 info: Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down.
2021-11-02 15:53:33 info: Microsoft.Hosting.Lifetime[0] Hosting environment: Development
2021-11-02 15:53:33 info: Microsoft.Hosting.Lifetime[0] Content root path: C:\Repos\WebApplication

SystemdConsoleFormatter

By extending the method AddSystemdConsole() Support can be added Systemd Console logging provider in . If you are familiar with Linux, Then you must be no stranger to it .

.ConfigureLogging(logging =>
{
logging.ClearProviders()
.AddSystemdConsole();
}

Sample output :

<6>Microsoft.Hosting.Lifetime[0] Now listening on: http://localhost:5000
<6>Microsoft.Hosting.Lifetime[0] Application started. Press Ctrl+C to shut down.
<6>Microsoft.Hosting.Lifetime[0] Hosting environment: Development
<6>Microsoft.Hosting.Lifetime[0] Content root path: C:\Repos\WebApplication

Ahead <6> Indicates the log level info, If you are interested in understanding Systemd, You can visit Mr. Ruan Yifeng's Systemd Introductory tutorial : Command

JsonConsoleFormatter

By extending the method AddJsonConsole() Support can be added Json Console logging provider in .

.ConfigureLogging(logging =>
{
logging.ClearProviders()
.AddJsonConsole(options =>
{
options.JsonWriterOptions = new JsonWriterOptions
{
// Enable indent , Looks more comfortable
Indented = true
};
});
}

Sample output :

{
"EventId": 0,
"LogLevel": "Information",
"Category": "Microsoft.Hosting.Lifetime",
"Message": "Now listening on: http://localhost:5000",
"State": {
"Message": "Now listening on: http://localhost:5000",
"address": "http://localhost:5000",
"{OriginalFormat}": "Now listening on: {address}"
}
}
{
"EventId": 0,
"LogLevel": "Information",
"Category": "Microsoft.Hosting.Lifetime",
"Message": "Application started. Press Ctrl\u002BC to shut down.",
"State": {
"Message": "Application started. Press Ctrl\u002BC to shut down.",
"{OriginalFormat}": "Application started. Press Ctrl\u002BC to shut down."
}
}
{
"EventId": 0,
"LogLevel": "Information",
"Category": "Microsoft.Hosting.Lifetime",
"Message": "Hosting environment: Development",
"State": {
"Message": "Hosting environment: Development",
"envName": "Development",
"{OriginalFormat}": "Hosting environment: {envName}"
}
}
{
"EventId": 0,
"LogLevel": "Information",
"Category": "Microsoft.Hosting.Lifetime",
"Message": "Content root path: C:\\Repos\\WebApplication",
"State": {
"Message": "Content root path: C:\\Repos\\WebApplication",
"contentRoot": "C:\\Repos\\WebApplication",
"{OriginalFormat}": "Content root path: {contentRoot}"
}
}

If you add a console recorder in multiple formats at the same time , Then only the last addition will take effect .

The above describes how to set the console logging provider through code , However, I think you should prefer to set the logging provider through configuration . Here is a simple configuration example :

{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
},
"Console": {
"FormatterName": "json",
"FormatterOptions": {
"SingleLine": true,
"IncludeScopes": true,
"TimestampFormat": "yyyy-MM-dd HH:mm:ss ",
"UseUtcTimestamp": false,
"JsonWriterOptions": {
"Indented": true
}
}
}
}
}

ILogger<TCategoryName> Object instance creation

Here we are. , I wonder if you will be right ILogger<TCategoryName> There are doubts about the creation of object instances : How it was new What comes out? ?

To solve this problem , Let's start with AddLogging() Start with the extension method :

public static class LoggingServiceCollectionExtensions
{
public static IServiceCollection AddLogging(this IServiceCollection services)
{
return AddLogging(services, builder => { });
} public static IServiceCollection AddLogging(this IServiceCollection services, Action<ILoggingBuilder> configure)
{
services.AddOptions(); // Registration form example ILoggerFactory
services.TryAdd(ServiceDescriptor.Singleton<ILoggerFactory, LoggerFactory>());
// Registration form example ILogger<>
services.TryAdd(ServiceDescriptor.Singleton(typeof(ILogger<>), typeof(Logger<>))); // Batch registration single example IConfigureOptions<LoggerFilterOptions>
services.TryAddEnumerable(ServiceDescriptor.Singleton<IConfigureOptions<LoggerFilterOptions>>(
new DefaultLoggerLevelConfigureOptions(LogLevel.Information))); configure(new LoggingBuilder(services));
return services;
}
}

You may have guessed , This Logger<> Will not be LoggerFactory Create it ? Why else sign up for this thing ?

take it easy , Let's take a look at ILogger<> The implementation class of the service Logger<>

public interface ILogger
{
void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter); // Check whether logs of this log level can be recorded
bool IsEnabled(LogLevel logLevel); IDisposable BeginScope<TState>(TState state);
} public interface ILogger<out TCategoryName> : ILogger
{
} public class Logger<T> : ILogger<T>
{
// This instance is used for operation inside the interface implementation
private readonly ILogger _logger; // Sure enough , Yes ILoggerFactory example
public Logger(ILoggerFactory factory)
{
// Do you remember? ? As mentioned above, when explicitly specifying the log category , The same is true for creating ILogger Example of
_logger = factory.CreateLogger(TypeNameHelper.GetTypeDisplayName(typeof(T), includeGenericParameters: false, nestedTypeDelimiter: '.'));
} // ...
}

you 're right , You guessed it , Let's take a look at this LoggerFactory Well ( Just list the core code ):

public interface ILoggerFactory : IDisposable
{
ILogger CreateLogger(string categoryName); void AddProvider(ILoggerProvider provider);
} public class LoggerFactory : ILoggerFactory
{
// For singleton Logger<>
private readonly Dictionary<string, Logger> _loggers = new Dictionary<string, Logger>(StringComparer.Ordinal);
// Deposit ILoggerProviderRegistrations
private readonly List<ProviderRegistration> _providerRegistrations = new List<ProviderRegistration>();
private readonly object _sync = new object(); public LoggerFactory(IEnumerable<ILoggerProvider> providers, IOptionsMonitor<LoggerFilterOptions> filterOption, IOptions<LoggerFactoryOptions> options = null)
{
// ... // register ILoggerProviders
foreach (ILoggerProvider provider in providers)
{
AddProviderRegistration(provider, dispose: false);
} // ...
} public ILogger CreateLogger(string categoryName)
{
lock (_sync)
{
// If it doesn't exist , be new
if (!_loggers.TryGetValue(categoryName, out Logger logger))
{
logger = new Logger
{
Loggers = CreateLoggers(categoryName),
}; (logger.MessageLoggers, logger.ScopeLoggers) = ApplyFilters(logger.Loggers); // Uniinstantiation Logger<>
_loggers[categoryName] = logger;
} return logger;
}
} private void AddProviderRegistration(ILoggerProvider provider, bool dispose)
{
_providerRegistrations.Add(new ProviderRegistration
{
Provider = provider,
ShouldDispose = dispose
}); // ...
} private LoggerInformation[] CreateLoggers(string categoryName)
{
var loggers = new LoggerInformation[_providerRegistrations.Count];
// Loop through all ILoggerProvider
for (int i = 0; i < _providerRegistrations.Count; i++)
{
loggers[i] = new LoggerInformation(_providerRegistrations[i].Provider, categoryName);
}
return loggers;
}
}

Be careful

  • If you want to be in Startup.Configure Method , Inject... Directly on the parameters ILogger<Startup> that will do .
  • Does not support the Startup.ConfigureServices Method used in ILogger, Because at this time DI The container has not been configured .
  • There is no asynchronous logging method . The logging action should be executed quickly , Use asynchronous methods at the expense of performance . If the logging action is time-consuming , As recorded MSSQL in , Then please do not write directly MSSQL. You should consider writing logs to fast storage media first , Such as memory queue , Then it is dumped from memory to... Through the background worker thread MSSQL in .
  • Cannot use logging API Change the logging configuration while the application is running . however , Some configuration providers ( Such as file configuration provider ) Reloads the configuration , This can immediately update the logging configuration .

Summary

  • Host.CreateDefaultBuilder In the method , Default added ConsoleDebugEventSource and EventLog( only Windows) There are four logging providers (Logger Provider).
  • By injecting Services ILogger<TCategoryName>, It is convenient to log .
  • The logging provider can be set by code or configuration , Such as LogLevelFormatterName etc. .
  • You can extend the method AddFilter Add logging filter , Allows you to write complex logic , To control whether to log .
  • Support log message templates .
  • For console logging programs ,.NET Frame built in Simple( Default )、SystemdJson Three log output formats .
  • .NET 6 In the preview version, a new one called “ Compile time logging source generation ” The function of , This function is very practical , If you are interested, you can go first Get to know .
  • Last , Give you some common log open source middleware :

understand ASP.NET Core - journal (Logging) More articles about

  1. [ turn ]ASP.NET Core Development -Logging Use NLog Write a log file

    In this paper, from :http://www.cnblogs.com/Leo_wl/p/5561812.html ASP.NET Core Development -Logging Use NLog Write a log file . NLog It can be applied to  . ...

  2. ASP.NET Core Development -Logging Use NLog Write a log file

    ASP.NET Core Development -Logging Use NLog Write a log file . NLog It can be applied to  .NET Core and ASP.NET Core . ASP.NET Core Logging support has been built in , Sure ...

  3. understand ASP.NET Core - [01] Startup

    notes : This article belongs to < understand ASP.NET Core> Series articles , Please check the top blog or click here to view the full-text catalog preparation : One copy ASP.NET Core Web API Applications When we come to a strange environment , First of all ...

  4. Catalog - understand ASP.NET Core

    < understand ASP.NET Core> be based on .NET5 To organize , Designed to help people ASP.NET Core The framework has a clear understanding . Catalog [01] Startup [02] Middleware [ ...

  5. .NET Black magic - asp.net core Log system

    asp.net core How to keep a log in the library ? This is from asp.net core It's about dependency injection , stay asp.net core Dependency injection is ubiquitous , Various aspect oriented interfaces and events . ok , Some dry stuff . First , We ...

  6. understand ASP.NET Core: Processing pipeline

    understand ASP.NET Core Processing pipeline stay ASP.NET Core The pipeline processing part of , The implementation idea is no longer the traditional object-oriented pattern , Instead, I switched to functional programming mode . This greatly simplifies the code , however , For those familiar with object orientation ...

  7. asp.net core journal

    Log output is an essential part of the application ,log4net,nlog These mature components have been widely used in previous projects , stay asp.net core The corresponding... Was not found in the project log4net edition ,nlog Yes core Provided a good ...

  8. ASP.NET Core Introductory tutorial 10、ASP.NET Core logging (NLog) introduction

    One . Preface 1. The main content of this tutorial ASP.NET Core + The built-in log component records console logs ASP.NET Core + NLog Record local logs by day ASP.NET Core + NLog Customize the log by ...

  9. Customize ASP.NET Core Log Middleware

    This logging framework uses ASP.NET Core Of NLog, Used to record every request information and return information . 1. First create a Web Application project , I chose MVC Templates : 2. Use NuGet add to Microsoft.Extens ...

  10. summary : utilize asp.net core Log for error checking in the production environment (asp.net core version 2.2, use IIS Make servers )

    summary debugging asp.net core The program , In the output window , In the output source selection “ debugging ” or “xxx-ASP.NET Core Web The server ” when , You can see something like “info:Microsoft.AspNetCore. ...

Random recommendation

  1. although and although The difference between

    As a conjunction ,although and though It's interchangeable .Although Generally considered more formal . such as , The following sentences : Growth in Europe is maintaining mo ...

  2. Bootstrap_ Media target

    One . Basic media objects Media objects generally appear in groups , A set of media objects often includes the following parts : A container for media objects : Regular use “media” Class name means , Used to hold all the content of the media object The object of the media object : Regular use “media-o ...

  3. iOS The Internet -03-NSURLSession And NSURLSessionTask

    brief introduction NSURLSession Can also complete network requests NSURLConnection stay iOS9 Not recommended in ,NSURLSession yes iOS9 Recommended network request method in NSURLSession Need and NSUR ...

  4. IIS Web server performance optimization guide ( Reprint )

    Original website :http://www.phontol.com/20090507_419416_1.html       Windows Server The built-in Internet information server (Internet Informat ...

  5. Linux Use local iso As yum Source

    In the virtual machine Linux Sometimes you can't connect to the Internet , In order to facilitate the installation of various packages, So investigate and configure local yum How to install . First , Will be the source of iso To the system . mount -o loop /dev/cdr ...

  6. wander [HNOI2013]

    [ Title Description ] An undirected connected graph , Vertex from 1 Number to N, Side from 1 Number to M.  Small Z Random walk on this graph , It's small in the beginning Z stay 1 Vertex number , Every step is small Z Randomly choose... With equal probability Select an edge of the current vertex , Go along this edge to the next vertex , Get equal to this ...

  7. The first 7 God :Q Quant library ( To be continued )

    One . Outline of this article : 1.Python The built-in function calculates the price of the option 2.numpy Speed up numerical calculation 3.SciPy To simulate 4.SciPy The solver calculates the implied volatility 5.matplotlib mapping Two . Case study ( Look not to understand , A little ...

  8. 6 CLR Static constructor

    CLR Guarantee a type constructor in each AppDomain Only once in , And this execution is thread safe . effect : Is to initialize static members For example, there are several static members that need to be initialized, so where do you put the initialization code ? Put it in a normal constructor , That's for sure ...

  9. 2018 Google SEO Something to watch out for

    1.RankBrain It's a machine learning system - According to the user's behavior , Ranking the website . How long do users stay on your page ( How long the user stays ) What percentage of users click on your page ( Click through rate ) Note: Before Google Development ...

  10. ubuntu 14.4 apache2 django

    Record your configuration process and problems encountered . System : Ubuntu 14.04 64 System built in Python edition :2.7.6 First of all , I operate with root identity . If login is not root identity , Please add... Before the order sudo. ...