Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Filtering Serilog logs to different sinks depending on Property

I am attempting to integrate Serilog into my ASP.NET Core API project to log specific types of entries to different sinks based on their propertry. My goal is to configure the logger so that when the Serilog Context includes a specific property, the logs are written to a file; otherwise, they should be directed to SEQ . But this not working for me.
Please find below my Code

Appsettings.json

{
  "Serilog": {
    "Using": [ "Serilog.Exceptions" ],
    "LevelSwitches": { "$controlSwitch": "Error" },
    "MinimumLevel": { "ControlledBy": "$controlSwitch" },
    "Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId", "WithExceptionDetails" ],
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          "pathFormat": "C:\\Logs\\MicrologicAPILog-{Date}.log",
          "rollingInterval": "Day",
          "outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}"
        },
        "Filter": [
          {
            "Name": "ByIncluding",
            "Args": {
              "Expression": "Matching.WithProperty('LogType', 'File')"
            }
          }
        ]
      },
      {
        "Name": "Seq",
        "Args": {
          "serverUrl": "sequrl",
          "apiKey": "api key",
          "controlLevelSwitch": "$controlSwitch"
        },
        "Filter": [
          {
            "Name": "ByExcluding",
            "Args": {
              "Expression": "Matching.WithProperty('LogType', 'File')"
            }
          }
        ]
      }
    ],
    "Properties": {
      "MLEnvironment": "Local",
      "Client": "Unknown"
    }
  },

BaseController

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

//below method is specifically to write logs to file.

internal void LogAuthInfo(string requestUrl, string authToken, string formattedAuth)
        {
            var hostName = Dns.GetHostName();
            var ipAddress = Dns.GetHostAddresses(hostName);
            using (LogContext.PushProperty("LogType", "File"))
            {

                _logger
                    .ForContext("CallingApplication", this.CallingApplication)
                    .ForContext("CustomerCode", this.CustomerCode)
                    .ForContext("LocationId", this.LocationId.ToString())
                    .ForContext("LocationDescription", this.LocationDescription)
                    .ForContext("Version", Assembly.GetExecutingAssembly().GetName().Version)
                    .ForContext("ServerIP", string.Join(",", ipAddress.Select(x => x.ToString())))
                    .ForContext("RequestUrl", requestUrl)
                    .ForContext("AuthToken", authToken)
                    .ForContext("FormattedAuthToken", formattedAuth)
                    .Error("AuthToken Info");

            }
        }
    }

Below one is used to log details in seq. Since both logs needs to save different info, I have given different methods

protected internal void LogInfo(string message, [CallerMemberName] string memberName = null, bool detailedTracking = false)
    {
        var hostName = Dns.GetHostName();
        var ipAddress = Dns.GetHostAddresses(hostName);
        _logger
            .ForContext("CallingApplication", this.CallingApplication)
            .ForContext("CustomerCode", this.CustomerCode)
            .ForContext("LocationId", this.LocationId.ToString())
            .ForContext("LocationDescription", this.LocationDescription)
            .ForContext("Version", Assembly.GetExecutingAssembly().GetName().Version)
            .ForContext("ServerIP", string.Join(",", ipAddress.Select(x => x.ToString())))
             .ForContext("DetailedTracking", detailedTracking.ToString())
            .Information(message);

    }

Then I am calling this code in the BasicAuthorizeAttribute class

  public class BasicAuthorizeAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext actionContext)var configuration = actionContext.HttpContext.RequestServices.GetRequiredService<Microsoft.Extensions.Configuration.IConfiguration>();


            var logDebugAccess = configuration.GetValue<string>("AppSettings:LogAuthToken:DebugAccessCodeEnabled");
            string customerCodes = configuration.GetValue<string>("AppSettings:LogAuthToken:CustomerCodes");
            BaseController controller = (BaseController)actionContext.Controller;
 

    if (logDebugAccess != null && logDebugAccess == "true" && !string.IsNullOrEmpty(customerCodes)) //These are configurations to control the logging
                        {
                            var customerCodeList = customerCodes.Split(',').Select(code => code.ToUpper().Trim());
                            if (customerCodeList.Contains(siteCode.ToUpper()))
                            {
                                controller.LogAuthInfo(url, encryptetransactioncode, formattedAuth);
                            }
                        }
    }
}

In Serilog Logger Extension class, I have the below logic given

public static class SerilogLoggerExtension
    {
        public static void Initialize(ILoggerFactory loggerFactory, IConfiguration configuration)
        {
            var mlEnvironment = configuration.GetValue<string>("MLEnvironment");
            var productName = "MicrologicAPI";

            // Read Seq server URL and API key from appsettings.json
            var seqServerUrl = configuration.GetValue<string>("Serilog:WriteTo:1:Args:serverUrl");
            var seqApiKey = configuration.GetValue<string>("Serilog:WriteTo:1:Args:apiKey");

            Log.Logger = new LoggerConfiguration()
                .ReadFrom.Configuration(configuration)
                .Enrich.FromLogContext()
                .Enrich.WithEnvironmentUserName()
                .Enrich.WithExceptionDetails()

                    
                      .CreateLogger();

            loggerFactory.WithFilter(new FilterLoggerSettings
            {
                {"Trace",LogLevel.Trace },
                {"Default", LogLevel.Trace},
                {"Microsoft", LogLevel.Warning},
                {"System", LogLevel.Warning}
            })
            .AddSerilog();
        }
    }

I am using Serilog Version – 2.10.1.
Can anyone please help to identify the issue with my code?

>Solution :

Please update the appsettings file as given below

{
  
  "Serilog": {
    "Using": [
      "Serilog",
      "Serilog.Enrichers.Thread",
      "Serilog.Settings.Configuration",
      "Serilog.Sinks.Console",
      "Serilog.Sinks.File"
    ],
    "LevelSwitches": { "$controlSwitch": "Information" },
    "MinimumLevel": { "ControlledBy": "$controlSwitch" },
    "Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId", "WithExceptionDetails" ],
    "WriteTo": [
      { "Name": "Console" },
      {
        "Name": "Seq",
        "MinimumLevel": "$controlSwitch",
        "Args": {
          "serverUrl": "seq url",
          "apiKey": "seq key",
          "controlLevelSwitch": "$controlSwitch"
        }
      },
      {
        "Name": "Logger",
        "Args": {
          "MinimumLevel": "Information",
          "configureLogger": {
            "Filter": [
              {
                "Name": "ByIncludingOnly",
                "Args": {
                  "expression": "LogType is not null"
                }
              }
            ],
            "WriteTo": [
              {
                "Name": "File",
                "Args": {
                  "rollingInterval": "Day",
                  "path": "Logs/DEBUGACCESSLOG_.log",
                  "outputTemplate": "{Timestamp:HH:mm:ss.fff zzz}|{Level}|{ThreadId}|{SourceContext}|{Message:lj}|{NewLine}"
                }
              }
            ]
          }
        }
      }
    ],
    "Properties": {
      "MLEnvironment": "Local",
      "Client": "Unknown"
    }
  },

Rest of the codes are looking good.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading