# .NetCore NLog 配置 ( 跟原生 Microsoft.Extensions.Logging 配合使用 )
###### tags: `.NetCore`
## 套件
NLog.Web.AspNetCore
## Startup.cs
```
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseMiddleware<ErrorHandlingMiddleware>();
// .....
}
```
## Program.cs
```
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.UseNLog();
```
## ErrorHandlingMiddleware
```
namespace App.Middleware
{
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ErrorHandlingMiddleware> _logger;
public ErrorHandlingMiddleware(RequestDelegate next, ILogger<ErrorHandlingMiddleware> logger)
{
_logger = logger;
_next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex, _logger);
}
}
private async Task HandleExceptionAsync(HttpContext context, Exception ex, ILogger<ErrorHandlingMiddleware> logger)
{
object errors = null;
switch (ex)
{
case RestException re:
logger.LogError($"REST ERROR: {ex.ToString()}");
errors = re.Errors;
context.Response.StatusCode = (int)re.Code;
break;
case Exception e:
//這樣傳 NLog.Config 配置 ${exception:format=tostring} 卻解析不出堆疊追蹤,放棄
//logger.LogError(ex, "SERVER ERROR");
logger.LogError($"SERVER ERROR: {ex.ToString()}");
errors = string.IsNullOrWhiteSpace(e.Message) ? "Error" : e.Message;
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
break;
}
context.Response.ContentType = "application/json";
if (errors != null)
{
var result = JsonConvert.SerializeObject(new
{
errors
});
await context.Response.WriteAsync(result);
}
}
}
}
```
## NLog.Config
```
<?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">
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<!-- the targets to write to -->
<targets>
<!-- write logs to file -->
<target xsi:type="File" name="LogFile" encoding="utf-8" fileName="${basedir}\LogFiles\LogFile${shortdate}.txt"
layout="-----Log Start----- ${newline}${newline} [${level:uppercase=true}] ${logger} ${newline} Time: ${longdate} ${newline} Request IP: ${aspnet-request-ip} ${newline} Url: [${aspnet-request-method}] ${aspnet-request-url} ${aspnet-request-querystring} ${newline} ${message} ${newline}${exception:format=tostring}${newline}-----Log End-----${newline}" />
</targets>
<!-- rules to map from logger name to target -->
<rules>
<!--由上到下匹配-->
<!--All logs, including from Microsoft-->
<!--<logger name="*" minlevel="Info" writeTo="LogFile" />-->
<!--寫下 Microsoft.AspNetCore.Server 相關 Log ( Ex. 執行 Server.exe 時無法啟動的錯誤 )-->
<logger name="Microsoft.AspNetCore.Server.*" minlevel="Info" final="true" writeTo="LogFile" />
<!--跳過微軟 Log,沒 writeTo ( Skip non-critical Microsoft logs )-->
<logger name="Microsoft.*" minlevel="Info" final="true" />
<!--剩下的 Log 全寫這-->
<logger name="*" minlevel="Info" writeTo="LogFile" />
</rules>
</nlog>
```
## 結果
```
-----Log Start-----
[ERROR] ECTransfer.Middleware.ErrorHandlingMiddleware
Time: 2021-03-26 15:10:53.7105
Request IP: ::1
Url: [GET] https://localhost/Stock/TestGetStock code=C01A01601
SERVER ERROR: System.AggregateException: One or more errors occurred. (A task was canceled.)
---> System.Threading.Tasks.TaskCanceledException: A task was canceled.
--- End of inner exception stack trace ---
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)
at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)
at System.Threading.Tasks.Task`1.get_Result()
at ECTransfer.Services.BOMDataService.SetBOMData() in C:\Users\user\Desktop\AllPower\Project\ECTransfer\ECTransfer\ECTransfer\ECTransfer\Services\BOMDataService.cs:line 32
at ECTransfer.Services.BOMDataService..ctor(HttpClient httpClient) in C:\Users\user\Desktop\AllPower\Project\ECTransfer\ECTransfer\ECTransfer\ECTransfer\Services\BOMDataService.cs:line 24
at ECTransfer.Controllers.StockController.TestGetStock(String code) in C:\Users\user\Desktop\AllPower\Project\ECTransfer\ECTransfer\ECTransfer\ECTransfer\Controllers\StockController.cs:line 168
at lambda_method(Closure , Object , Object[] )
at Microsoft.Extensions.Internal.ObjectMethodExecutor.Execute(Object target, Object[] parameters)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeActionMethodAsync()
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeNextActionFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location where exception was thrown ---
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.<Invoke>g__AwaitMatcher|8_0(EndpointRoutingMiddleware middleware, HttpContext httpContext, Task`1 matcherTask)
at ECTransfer.Middleware.ErrorHandlingMiddleware.Invoke(HttpContext context) in C:\Users\user\Desktop\AllPower\Project\ECTransfer\ECTransfer\ECTransfer\ECTransfer\MiddleWare\ErrorHandlingMiddleware.cs:line 25
-----Log End-----
```