I’m having to write a file utility that will work with reading import files and creating export files. I’m looking to write to different NLog files depending on if I’m working with an import file or creating an export file. I’ve been searching and reading different articles today but I’m either not searching on the right thing I’m just not understanding how I can write to different log files using Dependency Injection.
This is the basic concept I’m trying to work out. I run a console app and it reads in a list of file settings using a JSON file. That file setting/config JSON file will have a setting letting me know this is an outbound file vs an inbound file. So, say the current file I’m working with is a outbound file I’ll write the logging for it to my OutboundFiles.log versus my InboundFiles.log.
Currently I have the following I use with most .Net Core console apps I have created and it will write it to a single log file using _log (ex: _log.LogInformation). What I’m not understanding is how I could have say an _logOutbound.LogInformation and a _logInbound.LogInformation that I would write to depending on what file time I'm working with and how I would alter my NLog.config file for the different log name and directories. Here is my current code used to write to a single file.
Program.cs
public class Program
{
static void Main(string[] args)
{
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
try
{
logger.Debug("Initializing Program.Main");
var host = Host.CreateDefaultBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(Path.Combine(AppContext.BaseDirectory));
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
})
.ConfigureServices((context, services) =>
{
services.AddTransient<IAppHost, AppHost>();
services.AddLogging(builder =>
{
builder.AddNLog("nlog.config");
});
}).Build();
var application = ActivatorUtilities.CreateInstance<AppHost>(host.Services);
application.Run();
}
catch (Exception ex)
{
logger.Error("Stopped program setup with Error. {0} | {1} | {2}", ex.Message, ex.StackTrace, ex.InnerException);
throw;
}
finally
{
// Ensure to flush and stop internal timers/threads before application-exit
NLog.LogManager.Shutdown();
}
}
}
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"
autoReload="true">
<!-- enable asp.net core layout renderers -->
<extensions>
<add assembly="NLog.Web.AspNetCore"/>
</extensions>
<variable name="LogDirectory" value="D:\logs\ApplictionName"/>
<!-- the targets to write to -->
<targets>
<target xsi:type="File"
name="DefaultTarget"
fileName="${LogDirectory}\LogFile.log"
layout="${longdate} | ${callsite} | ${message}"
archiveAboveSize="3145728"
archiveEvery="Day"
archiveFileName = "${LogDirectory}/Archive/{#}.log"
archiveNumbering = "DateAndSequence"
archiveDateFormat = "yyyyMMdd"
maxArchiveFiles = "21"
/>
<target name="ConsoleTarget"
xsi:type="Console"
layout="${longdate} ${logger:shortName=True} ${message} ${onexception:EXCEPTION OCCURRED\:${exception:format=type,message,StackTrace,method:maxInnerExceptionLevel=8:innerFormat=type,message,StackTrace,method}}"
/>
</targets>
<rules>
<logger name="Microsoft.*" maxlevel="Info" final="true" /> <!-- BlackHole without writeTo -->
<logger name="*" minlevel="Debug" writeTo="DefaultTarget,ConsoleTarget" />
</rules>
</nlog>
AppHost.cs
public class AppHost : IAppHost
{
private readonly ILogger<AppHost> _log;
private readonly IConfiguration _configuration;
public AppHost(ILogger<AppHost> log, IConfiguration config)
{
_log = log;
_configuration = config;
}
public void Run()
{
_log.LogInformation("Application START");
try
{
//*** All code goes here ***
}
catch (Exception ex)
{
_log.LogError("Error: {0} | {1} | {2}", ex.Message, ex.StackTrace, ex.InnerException);
}
_log.LogInformation("Application END");
}
}
This is a basic example of the JSON file I'll be reading through. One of the parameters tells me it will be an outbound file which is the key I'll use to write any logging to the Outbound.log file. An inbound file would work the same way.
"fileTypes": {
"FileName1":
{
"dayofweek": "MON",
"dayofmonth": "*",
"time": "23:00",
"inputFolder": "\\servername\emft\inbound",
"inputFileName": "FileName.pgp",
"maxInputFiles": "1",
"minInputFiles": "1",
"inputDecryptionKey": "d:\PgpKeys\private\keyname.asc",
"outputFolder": "\\servername\emft\outbound",
"outputFileName": "outfilename.txt.pgp",
"outputEncryptionKey": "d:\PgpKeys\public\keyname.asc",
"logFileType": "outbound"
}
}
QUESTION UPDATE
If I were to have multiple targets in my NLog.config file like the example below, how do I tell .Net Core which one I would want to target?
For example, using the targets below, how would I tell dependency injection that I want to create a object called something like _logOutgoing to use the "OutgoingTarget" target, a _logIncoming object target the "IncomingTarget" target, and then _log use the "DefaultTarget"? Then as I'm working in my console app if I'm dealing with an incoming file I would write something to _logIncoming and _logOutgoing if I'm working with my outgoing file?
The reason I'm looking for something like this is to make a makeshift report. The OutgoingTarget and IncomingTarget would be used to write more of a non-technical report that I would email out to the Business Managers so they would know what is going on whereas I would use the DefaultTarget to be used by the developers with more technical details about what is going on for debugging/support reasons.
This is from an example I found in my research.
<target xsi:type="File" name="DefaultTarget" fileName="C:/AVDS/Logs/MyApps/nlog-all-${shortdate}.log"
layout="${longdate}|${uppercase:${level}}|${aspnet-traceidentifier}|${aspnet-user-identity}|${logger}|${aspnet-request-url}|${aspnet-mvc-action}|${message} ${exception:format=ToString}"
archiveFileName="C:/AVDS/Logs/MyApps/archives/nlog-all.{#}.txt"
archiveEvery="Day"
archiveNumbering="Rolling"
maxArchiveFiles="7" />
<target xsi:type="File" name="OutgoingTarget" fileName="C:/AVDS/Logs/MyApps/nlog-own-${shortdate}.log"
layout="${longdate}|${uppercase:${level}}|${aspnet-traceidentifier}|${aspnet-user-identity}|${logger}|${aspnet-request-url}|${aspnet-mvc-action}|${message} ${exception:format=ToString}"
archiveFileName="C:/AVDS/Logs/MyApps/archives/nlog-own.{#}.txt"
archiveEvery="Day"
archiveNumbering="Rolling"
maxArchiveFiles="7" />
<target xsi:type="File" name="IncomingTarget" fileName="C:/AVDS/Logs/MyApps/nlog-errors-${shortdate}.log"
layout="${longdate}|${uppercase:${level}}|${aspnet-traceidentifier}|${aspnet-user-identity}|${logger}|${aspnet-request-url}|${aspnet-mvc-action}|${message} ${exception:format=ToString}"
archiveFileName="C:/AVDS/Logs/MyApps/archives/nlog-errors.{#}.txt"
archiveEvery="Day"
archiveNumbering="Rolling"
maxArchiveFiles="7" />
FIX ATTEMPT
I must be missing something. I added the following based on the example below but I'm getting an error with the _logIncoming.LogInformation("Testing") that says "ILoggerFactory does not contain a definition for LogInformation". I'm still new with dependency injection but I'm wondering if I need to add something to my .ConfigureServices in the Program.cs file?
Updated Apphost.cs
public class AppHost : IAppHost
{
private readonly ILogger<AppHost> _log;
private readonly IConfiguration _configuration;
private readonly ILoggerFactory _logIncoming;
private readonly ILoggerFactory _logOutgoing;
public AppHost(ILogger<AppHost> log, ILoggerFactory loggerFactory, IConfiguration config)
{
_log = log;
_logIncoming = (ILoggerFactory)loggerFactory.CreateLogger("IncomingLogger");
_logOutgoing = (ILoggerFactory)loggerFactory.CreateLogger("OutgoingLogger");
_configuration = config;
}
public void Run()
{
_log.LogInformation("Application START");
_logIncoming.LogInformation("Testing Incoming log.");
_logOutgoing.LogInformation("Testing outgoing log.");
}
}
Program.cs
var host = Host.CreateDefaultBuilder()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(Path.Combine(AppContext.BaseDirectory));
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
})
.ConfigureServices((context, services) =>
{
services.AddTransient<IAppHost, AppHost>();
services.AddLogging(builder =>
{
builder.AddNLog("nlog.config");
});
}).Build();