Nlog - How to log certain actions into a seperate file?

Cenk 1,036 Reputation points
2023-07-10T05:48:55.3266667+00:00

Hi there,

I am working on a Blazor Server application. I am using Nlog for logging. Here is my nlog configuration;

<?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"
      autoReload="true"
      internalLogLevel="error"
      internalLogFile="${aspnet-appbasepath}\logs\internal-nlog-AspNetCore.txt">

  <!-- enable asp.net core layout renderers -->
  <extensions>
    <add assembly="NLog.Web.AspNetCore"/>
    <add assembly="NLog.Appsettings.Standard" />
  </extensions>

  <!-- the targets to write to -->
  <targets>
    <!-- File Target for all log messages with basic details -->
    <!--target xsi:type="File" name="allfile" fileName="${aspnet-appbasepath}\logs\nlog-AspNetCore-all-${shortdate}.log"
            layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}" /-->

    <!-- File Target for own log messages with extra web details using some ASP.NET core renderers -->
    <target xsi:type="File" name="ownFile-web" fileName="${aspnet-appbasepath}\logs\nlog-AspNetCore-svc27-${shortdate}.log"
            layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}|${callsite}" />

    <!--Console Target for hosting lifetime messages to improve Docker / Visual Studio startup detection -->
    <target xsi:type="Console" name="lifetimeConsole" layout="${aspnet-item:variable=navigation-manager-uri} ${message}" />

    <target xsi:type="Database"
         name="dbPush"
         keepConnection="true"
         useTransactions="true"
          connectionString="${appsettings:name=ConnectionStrings.DefaultConnection}"
            dbProivder="Microsoft.Data.SqlClient,Microsoft.Data.SqlClient">

      <commandText>
        INSERT INTO dbo.NLogItems ([Id]
        ,[EventDateTime]
        ,[EventLevel]
        ,[UserName]
        ,[MachineName]
        ,[EventMessage]
        ,[ErrorMessage]
        ,[ErrorType]
        ,[ErrorSource]
        ,[ErrorStackTrace]
        ,[InnerErrorMessage])
        VALUES (NEWID(), @EventDateTime, @EventLevel, @UserName, @MachineName, @EventMessage,
        @ErrorMessage, @ErrorType, @ErrorSource, @ErrorStackTrace, @InnerErrorMessage)
      </commandText>

      <parameter name="@EventDateTime" layout="${date}" dbtype="DateTime" />
      <parameter name="@EventLevel" layout="${level}" />
      <parameter name="@UserName" layout="${environment-user}" />
      <parameter name="@MachineName" layout="${machinename}" />
      <parameter name="@EventMessage" layout="${message}" />
      <parameter name="@ErrorMessage" layout="${exception:format=message}" />
      <parameter name="@ErrorType" layout="${exception:format=type}" />
      <parameter name="@ErrorSource" layout="${exception:format=source}" />
      <parameter name="@ErrorStackTrace" layout="${exception:format=stacktrace}" />
      <parameter name="@InnerErrorMessage" layout="${exception:format=type,message,method,source,stacktrace:maxInnerExceptionLevel=5:innerFormat=shortType,message,method,source,stacktrace}" />
    </target>
  </targets>


  <!-- rules to map from logger name to target -->
  <rules>
    <!--All logs, including from Microsoft-->
    <logger name="*" minlevel="Trace" writeTo="allfile" />

    <!--Output hosting lifetime messages to console target for faster startup detection -->
    <logger name="Microsoft.Hosting.Lifetime" minlevel="Info" writeTo="lifetimeConsole, ownFile-web" final="true" />

    <!--Skip non-critical Microsoft logs and so log only own logs (BlackHole) -->
    <logger name="Microsoft.*" maxlevel="Info" final="true" />
    <logger name="System.Net.Http.*" maxlevel="Info" final="true" />

    <logger name="*" minlevel="Trace" writeTo="ownFile-web" />

    <logger name="*" minlevel="Trace" writeTo="dbPush" />
  </rules>
</nlog>


I wonder if I can log specific actions on a Razer file into only this specific file? Let's say I have this orders razer page, I want to write "order completed by the user" into a text file with the name of the page.

@page "/orders"
<PageTitle>Order List</PageTitle>


@inject IHttpContextAccessor httpContextAccessor
@inject ILogger<OrderList> _logger
@implements IDisposable

@code {
protected override async Task OnInitializedAsync()
async Task SaveRowDetail(ReportViewModel reportViewModel)
    {
        if (reportViewModel != null)
        {
            orderDetail.Id = reportViewModel.OrderDetailId;
            orderDetail.Quantity = reportViewModel.Quantity;
            orderDetail.CostRatio = reportViewModel.CostRatio;
            orderDetail.Description = reportViewModel.Description;
            orderDetail.ProductCode = reportViewModel.ProductCode;
            orderDetail.ProductName = reportViewModel.ProductName;
            orderDetail.BuyUnitPrice = reportViewModel.BuyUnitPrice;
            

            if (reportViewModel.OrderDetailStatus == "Completed")
            {
                orderDetail.CompletionDateTime = DateTime.Now.Date;
				//LOG order completed by user into a specific file preferably with the name of this page
            }
            else
            {
                orderDetail.CompletionDateTime = null;
            }
        }
        await _grid.UpdateRow(reportViewModel);
        await EditOrderDetailUseCase.ExecuteAsync(orderDetail);
        _orders = await GetOrdersExportUseCase.ExecuteAsync(_vendorId, _status, _startDate, _endDate, _productCode, _customerId, user);
        await _grid.Reload();
        
    }
}
Developer technologies | ASP.NET | ASP.NET Core
Developer technologies | .NET | Blazor
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. hossein jalilian 11,055 Reputation points Volunteer Moderator
    2024-02-02T03:44:54.0633333+00:00

    Thanks for posting your question in the Microsoft Q&A forum.

    To log specific actions from a Razor page into a separate file based on the name of the page, you can use the aspnet-mvc-controller and aspnet-mvc-action layout renderers in your NLog configuration. Here's a modified example of your NLog configuration to achieve this:

    <targets>        
        <target xsi:type="File" name="razorFile" fileName="${aspnet-appbasepath}\logs\nlog-AspNetCore-${shortdate}-${aspnet-mvc-controller}-${aspnet-mvc-action}.log"             layout="${longdate}|${event-properties:item=EventId_Id:whenEmpty=0}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}|${callsite}" />   
    </targets> 
    
     <rules>
         <logger name="Microsoft.AspNetCore.Mvc.Razor" minlevel="Trace" writeTo="razorFile" />   
     </rules>
    

    This configuration introduces a new target called razorFile that creates log files based on the controller and action names of the Razor page. The ${aspnet-mvc-controller} and ${aspnet-mvc-action} layout renderers extract the controller and action names from the request context. The corresponding rule instructs NLog to write logs for the Microsoft.AspNetCore.Mvc.Razor category (which includes Razor pages) to the razorFile target. Please don't forget to close up the thread here by upvoting and accept it as an answer if it is helpful

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.