'Create sub-folder that contains log-files for each request
I have an application that listens for a hash input, processes that input, and serves it back. I would like to create a separate log directory for each input with the following structure:
- hashcode1
- input1.txt
- output1.txt
- log1.txt
- hashcode2
- input2.txt
- output2.txt
- log2.txt
I've looked into the NLog library but it seems the config requires a hardcoded log location, whereas my implementation requires the hashcode as an input. How can I achieve this with NLog, or any other logging library?
Solution 1:[1]
You can create the NLog configuration from code. This allows you to dynamically create targets in your processing loop for the appropriate log outputs:
using NLog;
using NLog.Targets;
// Init the config if we don't have a nlog.config
LogManager.Configuration = new();
// Do the work
var work = new List<string> { "5dd2ec2f", "24e1e841", "05137e70" };
work.ForEach(ProcessHash);
void ProcessHash(string hash)
{
// Create dynamic configuration and logger
var fileTarget = new FileTarget(hash) { FileName = $"{hash}/log.txt" };
LogManager.Configuration.AddRuleForAllLevels(fileTarget, hash);
LogManager.ReconfigExistingLoggers();
var logger = LogManager.GetLogger(hash);
// Process...
logger.Info($"Processing hash {hash}");
/* ... your code here ... */
// Remove the logging target
LogManager.Configuration.RemoveTarget(fileTarget.Name);
}
Solution 2:[2]
You can create a scope-property like this:
void ProcessHashCode(string hashInput)
{
using (NLog.MappedDiagnosticsLogicalContext.SetScoped("HashCode", hashInput))
{
NLog.LogManager.GetLogger("HashInput").Info(hashInput);
NLog.LogManager.GetCurrentClassLogger().Info("Received Hashcode");
var hashOutput = hashInput.GetHashCode();
NLog.LogManager.GetLogger("HashOuput").Info(hashOutput);
}
}
Then you can do this in NLog.config
<nlog>
<variable name="logdir" value="${mdlc:HashCode:whenEmpty=${basedir}}" />
<targets>
<target name="hashinput" type="file" filename="${logdir}/input.txt" />
<target name="hashouput" type="file" filename="${logdir}/output.txt" />
<target name="hashlog" type="file" filename="${logdir}/log.txt" />
</target>
<rules>
<logger name="HashInput" writeTo="hashinput" final="true" />
<logger name="HashOuput" writeTo="hashouput" final="true" />
<logger name="*" writeTo="hashlog" />
</rules>
</nlog>
See also: https://github.com/NLog/NLog/wiki/MDLC-Layout-Renderer
Alternative you can use Logger.WithProperty("HashCode", hashInput) like this:
void ProcessHashCode(string hashInput)
{
var inputLogger = NLog.LogManager.GetLogger("HashInput").WithProperty("HashCode", hashInput);
var outputLogger =
NLog.LogManager.GetLogger("HashOutput").WithProperty("HashCode", hashInput);
var hashLogger =
NLog.LogManager.GetCurrentClassLogger.WithProperty("HashCode", hashInput);
inputLogger.Info(hashCode);
hashLogger.Info("Received Hashcode");
var hashOutput = hashInput.GetHashCode();
outputLogger.Info(hashOutput);
}
And instead use variable like this:
<variable name="logdir" value="${event-properties:HashCode:whenEmpty=${basedir}}" />
See also: https://github.com/NLog/NLog/wiki/Context#logevent-properties
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Jann Westermann |
| Solution 2 |
