This might not be what you are after, but bear with me ...
You could wrap NLog such that you can log with your own "loggers". Have a look at Common.Logging for .NET or SLF for examples of how to wrap NLog (they are full logging abstractions, so they are more complex than what you are after, but you might pick up some good ideas). Also see here (probably should look here first if you think that you might be interested in simply wrapping or subclassing the NLog Logger) for examples of how to wrap (or subclass) NLog correctly (note that the key is to pass the type of your wrapped/subclassed logger to NLog's Log method).
So, you might have something like this (abbreviated):
//Wrapped logger that you could create once in a class and use to log both
//"normal" messages and "audit" messages. NLog log level is determined by the
//logger configuration for the class.
public class MyLogger
{
private Logger logger; //NLog logger
public MyLogger(string name)
{
logger = LogManager.GetLogger(name);
}
public void Info(string message)
{
if (!logger.IsInfoEnabled) return;
Write(LogLevel.Info, LogLevel.Info.ToString(), message);
}
public void AuditSuccess(string message)
{
if (!logger.IsInfoEnabled) return;
Write(LogLevel.Info, "AuditSuccess", message);
}
private void Write(LogLevel level, string customLevel, string message)
{
LogEventInfo le = new LogEventInfo(level, logger.Name, message);
le.Context["CustomLogLevel"] = customLevel;
logger.Log(typeof(MyLogger), le);
}
}
This will give you level-specific logging methods corresponding to your custom levels. It will also give you the ability to output a custom column containing your "custom level" (using the event-context layout renderer). It does not give you the ability to turn "AuditSuccess" level logging on or off. It must still be controlled by the built-in levels.
Alternatively, you could include two loggers in your wrapped class and use one for built-in levels and the other for custom levels. Your wrapper might look like this:
//Wrapped logger that you could create once in a class and use to log both "normal"
//and "audit" messages. NLog log level for each type of message is controllable
//separately since the logger wrapper actually wraps two logger.
public class MyLogger
{
private Logger logger; //NLog logger
private Logger auditLogger;
public MyLogger(string name)
{
logger = LogManager.GetLogger(name);
auditLogger = LogManager.GetLogger("AuditLogger");
}
public void Info(string message)
{
if (!logger.IsInfoEnabled) return;
Write(logger, LogLevel.Info, LogLevel.Info.ToString(), messsage);
}
public void AuditSuccess(string message)
{
if (!auditLogger.IsInfoEnabled) return;
Write(auditLogger, LogLevel.Info, "AuditSuccess", message);
}
private void Write(Logger log, LogLevel level, string customLevel, string message)
{
LogEventInfo le = new LogEventInfo(level, log.Name, message);
le.Context["CustomLogLevel"] = customLevel;
log.Log(typeof(MyLogger), le);
}
}
You still would have the same restrictions as listed above, but you could at least control "audit/security" logging separately from "normal" logging.
In either case, you can send the output from all loggers to the same database and just do your queries on your "custom level" column rather than the "level" column. Depending on how many security/auditing "categories" you have, you might even want to make a concrete hierarchy such that you can take advantage of the logger hierarchies in the NLog config file:
Security
Security.Audit
Security.Audit.Success
Security.Audit.Failure
Security.Login
Security.Login.Success
Security.Login.Failure
Health
Health.Heartbeat
Health.Whatever
Then you could "turn on" Security or Security.Audit or ..Failure (not sure if that last one works or not).
Hope this helps.