Asp.net web API Nlog implementation with UnhandledExceptionHandler I have an asp.net web api. I would like to log errors into a file. So I decided to use NLog. I already have UnhandledExceptionHandler so I added NLog as follows. I removed all the try/catch in order to log from a single point, just inside the handler. 

Would you please have a look at my code? Is it good enough?

using System;
namespace Game.Handlers
{
    public class UnhandledExceptionLogger : ExceptionLogger
    {
        private static Logger logger = LogManager.GetCurrentClassLogger();

        public override void Log(ExceptionLoggerContext context)
        {
            var ex = context.Exception;

            string strLogText = FormatException(ex);

            var requestedURi = (string)context.Request.RequestUri.AbsoluteUri;
            var requestMethod = context.Request.Method.ToString();
            var timeUtc = DateTime.Now;

            SqlErrorLogging sqlErrorLogging = new SqlErrorLogging();
            ApiError apiError = new ApiError()
            {
                Message = strLogText,
                RequestUri = requestedURi,
                RequestMethod = requestMethod,
                TimeUtc = DateTime.Now
            };
            //sqlErrorLogging.InsertErrorLog(apiError);
            //NLOG
            logger.Error(strLogText + Environment.NewLine + DateTime.Now);
        }


        private string FormatException(Exception ex, int depth = 0)
        {
            var indent = "";
            if (depth &gt; 0)
                indent.PadRight(depth * 4);

            var sb = new StringBuilder();
            IndentLine($"Source --- {ex.Source}");
            IndentLine($"StackTrace --- {ex.StackTrace}");
            IndentLine($"TargetSite --- {ex.TargetSite}");

            if (ex.InnerException != null)
            {
                IndentLine("--- Inner Exception ---");
                sb.Append(FormatException(ex.InnerException, depth + 1));
                IndentLine("--- End Inner Exception ---");
            }
            if (ex.Message != null)
            {
                IndentLine($"Message --- {ex.Message}");
            }
            return sb.ToString();

            void IndentLine(string s)
            {
                sb.Append(indent);
                sb.AppendLine(s);
            }
        }

    }
}


Here is the sample NLog config:

&lt;nlog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"&gt;
    &lt;targets&gt;
      &lt;target name="logfile" xsi:type="File" fileName="${basedir}/MyLogs/${date:format=yyyy-MM-dd}-api.log" /&gt;
      &lt;target name="eventlog" xsi:type="EventLog" layout="${message}" log="Application" source=" GamePIN Api Services" /&gt;
      &lt;target name="database" type="Database" connectionString="Data Source=(localdb)\MSSQLLocalDB;Database=Game; Initial Catalog=GameAPI;MultipleActiveResultSets=True;"&gt;
        &lt;commandText&gt; insert into ExceptionLog ([TimeStamp],[Level],Logger, [Message], UserId, Exception, StackTrace) values (@TimeStamp, @Level, @Logger, @Message, case when len(@UserID) = 0 then null else @UserId end, @Exception, @StackTrace); &lt;/commandText&gt;
        &lt;parameter name="@TimeStamp" layout="${date}" /&gt;
        &lt;parameter name="@Level" layout="${level}" /&gt;
        &lt;parameter name="@Logger" layout="${logger}" /&gt;
        &lt;parameter name="@Message" layout="${message}" /&gt;
        &lt;parameter name="@UserId" layout="${mdc:user_id}" /&gt;
        &lt;parameter name="@Exception" layout="${exception}" /&gt;
        &lt;parameter name="@StackTrace" layout="${stacktrace}" /&gt;
        &lt;dbProvider&gt;System.Data.SqlClient&lt;/dbProvider&gt;
      &lt;/target&gt;
    &lt;/targets&gt;
    &lt;rules&gt;
      &lt;!-- I am adding my 3 logging rules here --&gt;
      &lt;logger name="*" minlevel="Error" writeTo="database" /&gt;
      &lt;logger name="*" minlevel="Error" writeTo="logfile" /&gt;
      &lt;logger name="*" minlevel="Error" writeTo="eventlog" /&gt;
    &lt;/rules&gt;
  &lt;/nlog&gt;
The variable ex is not used anywhere else, so it can be in-lined.

string strLogText = FormatException(context.Exception);


The multiple calls to DateTime.Now will give different time stamps.

Hold on to the timestamp in one variable early in the function and reuse that.

It was already assigned here

 var timeUtc = DateTime.Now;


so use that 

//...

ApiError apiError = new ApiError()
{
    Message = strLogText,
    RequestUri = requestedURi,
    RequestMethod = requestMethod,
    TimeUtc = timeUtc
};

//...


Given the variable name, the assumption is that the timestamp was meant to be UTC, which would mean that it should be using DateTime.UtcNow

The SQL error logging (though commented out) can be encapsulated into its own function/concern

private void LogSQL(string message, HttpRequestMessage request, DateTime timestamp) {
    var requestedURi = (string)request.RequestUri.AbsoluteUri;
    var requestMethod = request.Method.ToString();
    SqlErrorLogging sqlErrorLogging = new SqlErrorLogging();
    ApiError apiError = new ApiError() {
        Message = message,
        RequestUri = requestedURi,
        RequestMethod = requestMethod,
        TimeUtc = timestamp
    };
    //sqlErrorLogging.InsertErrorLog(apiError);
}


This can be abstracted out into its own service/concern if so desired

The above and a few minor changes results in a refactoring of

public class UnhandledExceptionLogger : ExceptionLogger {
    private static readonly Logger logger = LogManager.GetCurrentClassLogger();

    public override void Log(ExceptionLoggerContext context) {
        DateTime timestamp = DateTime.UtcNow;
        string strLogText = FormatException(context.Exception);            
        //SQL
        SqlLog(strLogText, context.Request, timestamp);
        //NLOG
        NLog(logger, strLogText, timestamp);
    }

    private void NLog(Logger logger, string message, DateTime timestamp) {
        var sb = new StringBuilder();
        sb.AppendLine(message);
        sb.AppendLine(timestamp);
        logger.Error(sb.ToString());
    }

    private void SqlLog(string message, HttpRequestMessage request, DateTime timestamp) {
        var requestedURi = (string)request.RequestUri.AbsoluteUri;
        var requestMethod = request.Method.ToString();
        SqlErrorLogging sqlErrorLogging = new SqlErrorLogging();
        ApiError apiError = new ApiError() {
            Message = message,
            RequestUri = requestedURi,
            RequestMethod = requestMethod,
            TimeUtc = timestamp
        };
        //sqlErrorLogging.InsertErrorLog(apiError);
    }

    private string FormatException(Exception ex, int depth = 0) {
        //... omitted for brevity
    }
}