How to log ODataExceptions? ExceptionLogger isn't working

647 Views Asked by At

I am attempting to log exceptions within an OData v4 service built on WebApi 2.2. I am using NLog for logging. I created a simple ExceptionLogger (NLogExceptionLogger) class for this purpose. NLogExceptionLogger does log unhandled exceptions just fine but it doesn't log all exceptions. If I manually throw an exception as a test it works just fine. (See Controller example)

The specific ones that I am looking for are Microsoft.OData.ODataExceptions that are thrown when the ODataQuery is validated. The error information is returned in the response but is not logged by the NLogExceptionLogger. Basically for queries that try to $expand or $select fields that haven't been enabled, I want to see those exceptions in the log.

My assumption is that ExceptionLogger only sees unhandled exceptions which is less helpful that I had hoped. Is there a way that I can log these exceptions?

NLogExceptionLogger:

public class NLogExceptionLogger : ExceptionLogger
{
    public override void Log(ExceptionLoggerContext context)
    {
        string loggerName;
        try
        {
            loggerName = context.ExceptionContext.ControllerContext.ControllerDescriptor.ControllerType.FullName;
        }
        catch (Exception)
        {
            loggerName = "NLogExceptionLogger";
        }

        NLog.Logger logger = NLog.LogManager.GetLogger(loggerName);

        logger.Error(context.Exception, "Exception");
    }

}

WebApiConfig.cs snippet:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {

        // Add global exception logger
        config.Services.Replace(typeof(IExceptionLogger), new NLogExceptionLogger());

            // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        ODataConventionModelBuilder builder = new ODataConventionModelBuilder();

        builder.EntitySet<Customer>("Customers");
        builder.EntityType<Customer>().Filter("Name");
[[[ The rest of ODataConventionModelBuilder removed for brevity ]]]

        config.MapODataServiceRoute("MainODataRoute", "data", builder.GetEdmModel());

    }

Controller Example:

[System.Web.Http.Description.ApiExplorerSettings(IgnoreApi = false)]
public class CustomersController : ODataController
{
    private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
    CustomerDB db = new CustomerDB();

    /// <summary>
    /// Customers
    /// </summary>
    [EnableQuery]
    public IQueryable<Customer> Get()
    {
        logger.Debug("Customer Get Test");
        //throw new Exception("BOO!");
        return db.Customers;
    }

    ... etc
0

There are 0 best solutions below