Reputation: 371
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
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.
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