JakeFromStateFarm
JakeFromStateFarm

Reputation: 371

NLog: How to add 2 different database targets and rules under one configuration?

I have been researching how to programmatically add multiple database targets. I only need 2, and I cannot seem to figure out how to get them to work.

I can only get 1 target and logger to work. For example, the 2 code blocks below work:

My configuration code (1 target):

    var config = new LoggingConfiguration();
    // Add another NLog Target (ChangeTracking)
    var changeTrackingDbTarget = new DatabaseTarget()
    {
        Name = "ChangeTracking",
        ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["NLogConnection"].ConnectionString,
        CommandText = "INSERT INTO Common.ChangeTracking (ApplicationID, UserName, EntityName, PropertyName, PrimaryKeyValue, OldValue, NewValue, DateChanged) " +
                      "VALUES (@ApplicationID, @UserName, @EntityName, @PropertyName, @PrimaryKeyValue, @OldValue, @NewValue, @DateChanged);"
    };

    changeTrackingDbTarget.Parameters.Add(new DatabaseParameterInfo() { Name = "@ApplicationID", Layout = "${appsetting:name=AppID:default=null}" });
    changeTrackingDbTarget.Parameters.Add(new DatabaseParameterInfo() { Name = "@UserName", Layout = "${identity:authType=false:isAuthenticated=false}" });
    changeTrackingDbTarget.Parameters.Add(new DatabaseParameterInfo() { Name = "@EntityName", Layout = "${event-properties:item=ENTITYNAME}" });
    changeTrackingDbTarget.Parameters.Add(new DatabaseParameterInfo() { Name = "@PropertyName", Layout = "${event-properties:item=PROPNAME}" });
    changeTrackingDbTarget.Parameters.Add(new DatabaseParameterInfo() { Name = "@PrimaryKeyValue", Layout = "${event-properties:item=PRIMARYKEY}" });
    changeTrackingDbTarget.Parameters.Add(new DatabaseParameterInfo() { Name = "@OldValue", Layout = "${event-properties:item=OLDVALUE}" });
    changeTrackingDbTarget.Parameters.Add(new DatabaseParameterInfo() { Name = "@NewValue", Layout = "${event-properties:item=NEWVALUE}" });
    changeTrackingDbTarget.Parameters.Add(new DatabaseParameterInfo() { Name = "@DateChanged", Layout = "${date}" });

    config.LoggingRules.Add(new LoggingRule("*", LogLevel.Info, changeTrackingDbTarget));

    //LogManager.Configuration.AddTarget("ExceptionTracking", dbTarget);
    LogManager.Configuration = config;

My code that calls the logs (1 target):

private static Logger _logger = LogManager.GetLogger("ChangeTracking");
                        LogEventInfo changeEvent = new LogEventInfo(LogLevel.Info, "ChangeTracking", "A change event has been fired");
                        changeEvent.Properties["ENTITYNAME"] = entityName;
                        changeEvent.Properties["PROPNAME"] = prop;
                        changeEvent.Properties["PRIMARYKEY"] = primaryKey;
                        changeEvent.Properties["OLDVALUE"] = originalValueString;
                        changeEvent.Properties["NEWVALUE"] = currentValueString;
                        _logger.Log(changeEvent);

My configuration code (2 targets):

    // Setup NLOG Database Target for Exception Tracking
    LogManager.ThrowExceptions = true;
    var dbTargetExceptions = new DatabaseTarget()
    {
        Name = "ExceptionTracking",
        ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["NLogConnection"].ConnectionString,
        CommandText = "INSERT INTO Common.ExceptionTracking ( ApplicationID,  Url,  IP,  Referrer,  UserName,  ExceptionDescription,  Action,  Controller,  InsertedBy,  InsertedDate) " +
                                                    "VALUES (@ApplicationID, @Url, @IP, @Referrer, @UserName, @ExceptionDescription, @Action, @Controller, @InsertedBy, @InsertedDate);"
    };
    dbTargetExceptions.Parameters.Add(new DatabaseParameterInfo() { Name = "@ApplicationID", Layout = "${appsetting:name=AppID:default=null}" });
    dbTargetExceptions.Parameters.Add(new DatabaseParameterInfo() { Name = "@Url", Layout = "${aspnet-Request-Url}" });
    dbTargetExceptions.Parameters.Add(new DatabaseParameterInfo() { Name = "@IP", Layout = "${aspnet-Request-IP}" });
    dbTargetExceptions.Parameters.Add(new DatabaseParameterInfo() { Name = "@Referrer", Layout = "${aspnet-Request-Referrer}" });
    dbTargetExceptions.Parameters.Add(new DatabaseParameterInfo() { Name = "@UserName", Layout = "${identity:authType=false:isAuthenticated=false}" });
    dbTargetExceptions.Parameters.Add(new DatabaseParameterInfo() { Name = "@ExceptionDescription", Layout = "${exception:tostring}" });
    dbTargetExceptions.Parameters.Add(new DatabaseParameterInfo() { Name = "@Action", Layout = "${aspnet-MVC-Action}" });
    dbTargetExceptions.Parameters.Add(new DatabaseParameterInfo() { Name = "@Controller", Layout = "${aspnet-MVC-Controller}" });
    dbTargetExceptions.Parameters.Add(new DatabaseParameterInfo() { Name = "@InsertedBy", Layout = "${gdc:BEMSID}" });
    dbTargetExceptions.Parameters.Add(new DatabaseParameterInfo() { Name = "@InsertedDate", Layout = "${date}" });

    // Setup NLOG Database Target for Change Tracking
        var changeTrackingDbTarget = new DatabaseTarget()
        {
            Name = "ChangeTracking",
            ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["NLogConnection"].ConnectionString,
            CommandText = "INSERT INTO Common.ChangeTracking (ApplicationID, UserName, EntityName, PropertyName, PrimaryKeyValue, OldValue, NewValue, DateChanged) " +
                          "VALUES (@ApplicationID, @UserName, @EntityName, @PropertyName, @PrimaryKeyValue, @OldValue, @NewValue, @DateChanged);"
        };

        changeTrackingDbTarget.Parameters.Add(new DatabaseParameterInfo() { Name = "@ApplicationID", Layout = "${appsetting:name=AppID:default=null}" });
        changeTrackingDbTarget.Parameters.Add(new DatabaseParameterInfo() { Name = "@UserName", Layout = "${identity:authType=false:isAuthenticated=false}" });
        changeTrackingDbTarget.Parameters.Add(new DatabaseParameterInfo() { Name = "@EntityName", Layout = "${event-properties:item=ENTITYNAME}" });
        changeTrackingDbTarget.Parameters.Add(new DatabaseParameterInfo() { Name = "@PropertyName", Layout = "${event-properties:item=PROPNAME}" });
        changeTrackingDbTarget.Parameters.Add(new DatabaseParameterInfo() { Name = "@PrimaryKeyValue", Layout = "${event-properties:item=PRIMARYKEY}" });
        changeTrackingDbTarget.Parameters.Add(new DatabaseParameterInfo() { Name = "@OldValue", Layout = "${event-properties:item=OLDVALUE}" });
        changeTrackingDbTarget.Parameters.Add(new DatabaseParameterInfo() { Name = "@NewValue", Layout = "${event-properties:item=NEWVALUE}" });
        changeTrackingDbTarget.Parameters.Add(new DatabaseParameterInfo() { Name = "@DateChanged", Layout = "${date}" });

    //Setup NLOG Configuration. Adding DB Targets and Rules for Targets
    LoggingConfiguration nLogConfig = new LoggingConfiguration();
    nLogConfig.AddTarget("ExceptionTracking", dbTargetExceptions);
    nLogConfig.AddTarget("ChangeTracking", dbTargetChanges);
    nLogConfig.LoggingRules.Add(new LoggingRule("ChangeLogger", LogLevel.Info, dbTargetChanges));
    nLogConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, dbTargetExceptions));

    //Finally set the configuration above to the LogManager config property
    LogManager.Configuration = nLogConfig;

My code that calls the log(2 targets):

 private static Logger _logger = LogManager.GetLogger("ChangeTracking");
                        LogEventInfo changeEvent = new LogEventInfo(LogLevel.Info, "ChangeTracking", "A change event has been fired");
                        changeEvent.Properties["ENTITYNAME"] = entityName;
                        changeEvent.Properties["PROPNAME"] = prop;
                        changeEvent.Properties["PRIMARYKEY"] = primaryKey;
                        changeEvent.Properties["OLDVALUE"] = originalValueString;
                        changeEvent.Properties["NEWVALUE"] = currentValueString;
                        _logger.Log(changeEvent);

Upvotes: 0

Views: 667

Answers (1)

Julian
Julian

Reputation: 36750

Your config is correct. The AddTarget is not really necessary as you pass the Target to the rule and the Target has the same name property. So this should be enough:

LoggingConfiguration nLogConfig = new LoggingConfiguration();
nLogConfig.LoggingRules.Add(new LoggingRule("ChangeLogger", LogLevel.Info, dbTargetChanges));
nLogConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, dbTargetExceptions));

//Finally set the configuration above to the LogManager config property
LogManager.Configuration = nLogConfig;

I personally prefer the AddRule on LoggingConfiguration. This is the same as above, but AddRule-style:

LoggingConfiguration nLogConfig = new LoggingConfiguration();
nLogConfig.AddRule(LogLevel.Info, LogLevel.Fatal, dbTargetChanges, "ChangeLogger");
nLogConfig.AddRule(LogLevel.Trace, LogLevel.Fatal, dbTargetExceptions);

//Finally set the configuration above to the LogManager config property
LogManager.Configuration = nLogConfig;

If this won't work in your change, enable and check the internal log on trace level.

and the other I want to call by default everywhere else

Please note is that the rules are processed from top to bottom and will only stop if you add "final" (or a condition that won't match).

So for above config, writing to the "ChangeLogger" will write to both targets. I'm not sure if that is what you need. If not then:

  • Or add Final = true to the first rule

    // Old style
    nLogConfig.LoggingRules.Add(new LoggingRule("ChangeLogger", LogLevel.Info, dbTargetChanges){Final = true});
    nLogConfig.LoggingRules.Add(new LoggingRule("*", LogLevel.Trace, dbTargetExceptions));
    // Or AddRule style:
    nLogConfig.AddRule(LogLevel.Info, LogLevel.Fatal, dbTargetChanges, "ChangeLogger", true);  
    nLogConfig.AddRule(LogLevel.Trace, LogLevel.Fatal, dbTargetExceptions);
    
  • Or add a condition/filter to the 2nd rule.

after update

I think your issue was here, it add the target under the name "ExceptionTracking", while the rule is made to "ChangeTracking". I think this was enabled when testing:

 //LogManager.Configuration.AddTarget("ExceptionTracking", dbTarget);

I added some comments to make things clear:

var changeTrackingDbTarget = new DatabaseTarget()
{
    Name = "ChangeTracking",
  ...
};

...

// add rule to target with name ChangeTracking
config.LoggingRules.Add(new LoggingRule("*", LogLevel.Info, changeTrackingDbTarget));

// register target not under ChangeTracking, but under ExceptionTracking
LogManager.Configuration.AddTarget("ExceptionTracking", dbTarget);
LogManager.Configuration = config;

Upvotes: 2

Related Questions