Introduction
The importance of logging in enterprise software application development, cannot be overemphasized. Logging is the process of recording events, inner workings, and operations, warnings and errors of software applications. Logging libraries and frameworks can generate log files, database entries, queues messages which can be used to debug, trace and monitor enterprise applications in real time.
Log entries generated can be used to troubleshoot, monitor, debug and resolve issues. Logging has also been referred to as the most powerful tool any software engineer can ever process - I totally agree with this.
NLog
Logging is a software development cross-cutting concern that has been made easier over the years in with the continuous introduction of new logging libraries and improvement of existing robust libraries available on Nuget.
One of such libraries is NLog - a logging library that provides support for the different .Net platforms and gives the flexibility to write log entries to numerous targets which include file, console, database and AWS console. Also, NLog flexibility permits on the fly changing of logging configuration. Read more on NLog capabilities at
https://nlog-project.org
AWS Console Logging
Using Amazon Cloudwatch Logs service, log entries generated by logging frameworks in .Net can now be written, monitored and accessed through AWS console. AWS Cloudwatch Logs service supports NLog and other .Net logging frameworks.console.
In order to write logs to AWS cloudwatch, Nlog and AWS.Logger.NLog Nuget packages will be added to the .Net project. Afterwhich the NLog.config file generated when NLog library is added to a .Net project will have to be updated to use CloudWatch Logs as target. See the NLog configuration file below.
<nlog xmlns="http:www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http:www.w3.org/2001/XMLSchema-instance"
throwExceptions="true">
<targets>
<target name="aws" type="AWSTarget" logGroup="NLog.ConfigPOC"
region="us-east-1" />
<target name="logfile" xsi:type="Console" layout="${callsite} ${message}" />
</targets>
<rules>
<logger name="*" minlevel="Info" writeTo="aws" />
</rules>
<extensions>
<add assembly="NLog.AWS.Logger" />
</extensions>
</nlog>
Once the configuration file is set, a wrapper class can be created around the logging library where the AWS keys are set and the logging specific configurations can be initialized. See the code snippet for NLogWrapper class below.
public class NLogWrapper
{
private readonly Logger logger;
public NLogWrapper()
{
Configure();
}
public void Configure()
{
var config = new LoggingConfiguration();
string accessKey = "put your access key here";
string secretKey = "put your secret key here";
var awsTarget = new AWSTarget()
{
LogGroup = "Log.ConfigPOC",
Region = "us-east-1",
Credentials = new Amazon.Runtime.BasicAWSCredentials(accessKey,secretKey)
};
config.AddTarget("aws", awsTarget);
config.LoggingRules.Add(new LoggingRule("*", LogLevel.Debug, awsTarget));
LogManager.Configuration = config;
}
public void Info(object message)
{
logger.Info(message);
}
public void Error(Exception exception)
{
logger.Error(exception);
}
}
A much cleaner approach without having to hard code the credentials will be to have the AWS credentials in a file placed in a location in the project or the application server. The path to the credential file will then be added to app.config or web.config file like below. Where
AWSProfileName will have the same value as the heading contained in the credential file and
AWSProfilesLocation
will contain the path to the credential file.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="AWSProfileName" value="test" />
<add key="AWSProfilesLocation" value="C:\credentials.txt" />
</appSettings>
</configuration>
The content of the credential files will have the format below:
[test]
aws_access_key_id = put key here
aws_secret_access_key = put key here
The Nlog.config file will be updated with configuration entries like what is below.
<?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">
<targets>
<target name="bw"
xsi:type="BufferingWrapper" slidingTimeout="true" bufferSize="100" flushTimeout="60000">
<target name="cwl" xsi:type="CloudWatchLogs" AWSRegion="aws-region" AWSAccessKeyId="access-id" AWSSecretKey="secret-key" LogGroupName="log-group" LogStreamName="log-stream" layout="${longdate} [${threadid}] ${level} ${logger} [${ndc}] - ${message}" />
</target>
</targets>
<rules>
<logger name="*" minLevel="Info" appendTo="bw" />
</rules>
</nlog>
Also, the NLogWrapper class will be updated and the hard coded AWS credentials and configurations will be removed, the class will be modified to to what is in the snippet below.
public class NLogWrapper
{
private readonly Logger logger;
public NLogWrapper()
{
logger = LogManager.GetCurrentClassLogger();
}
public void Info(object message)
{
logger.Info(message);
}
public void Error(Exception exception)
{
logger.Error(exception);
}
}
This will begin to write the log entries to AWS console. The log entries can be reviewed from the AWS dashboard and metrics can be built and around the logs.