UPDATE:
Thanks to your clarification, I better understand what you are trying to do. You would like the messages logged from the IParameterInspector implementation to reflect a call site of "Example.MyService.GetContacts" where Example.MyService is your service (as indicated by the instanceType parameter) and "GetContacts" is the operation. You could synthesize the call site information manually. You would still use NLog's Logger.Log method and you would still create a LogEventInfo object. Additionally, you can store the "class" and "method" in the LogEventInfo.Properties object. Rather than retrieving a logger (from LogManager) based on the instanceType (i.e. the service), retrieve the logger based on the type of the parameter inspector (NLogLogger in your case). Finally, you can add an additional rule to your NLog.config (and apply it to the NLogLogger type) so that rule has a different logging format. You will manually add a field to the logging format that contains the call site information (that you stored in the LogEventInfo.Properties collection) in the same position as the "real" callsite LayoutRenderer in your other logging rule configurations.
Next I will post a new version of your NLogLogger implementation that does what I described above.
public class NLogLogger : IParameterInspector
{
private static readonly NLog.Logger logger = LogManager.GetCurrentClassLogger();
private void Log(Type instanceType, string operationName, string msg)
{
NLog.Logger serviceLogger = LogManager.GetLogger(
instanceType.FullName, instanceType);
//Create LogEventInfo with the Logger.Name from the logger associated with the service
LogEventInfo le = new LogEventInfo(LogLevel.Info, serviceLogger.Name, msg);
le.Properties.Add("fakecallsite", string.Format("{0}.{1}",instanceType.ToString(),operationName);
//Log the message using the parameter inspector's logger.
logger.Log(typeof(NLogLogger), le);
}
public object BeforeCall(string operationName, object[] inputs)
{
// Retrieve the service instance type for the logger then log the call.
OperationContext operationContext = OperationContext.Current;
Type instanceType = operationContext.InstanceContext
.GetServiceInstance().GetType();
Log(instanceType, operationName, "BeforeCall");
return instanceType;
}
public void AfterCall(
string operationName, object[] outputs,
object returnValue, object correlationState
)
{
if (correlationState is Type)
Log(correlationState, operationName, "AfterCall");
}
}
Your NLog.config will have rules something like this. One rule is specifically for your NLogLogger Parameter Inspector. It logs to "f1" and is a "final" rule, meaning that logging messages from the parameter inspector won't be logged by any other rules. The other rule is for all other loggers. Each logs to a different file target, but both file targets write to the same file (which works, I think). The key is that each file has its own layout.
<logger name="Your.Full.NameSpace.NLogLogger" minlevel="*" writeTo="f1" final="true" />
<logger name="*" minlevel="*" writeTo="f2" />
Your targets and layouts would look something like this. We are defining a variable whose value is the value of the EventPropertiesLayoutRenderer, which is the fake call site that we stored in LogEventInfo.Properties["fakecallsite"].
<variable name="fakecallsite" value="${event-properties:fakecallsite}"/>
<variable name="f1layout" value="${longdate} | ${level} | ${logger} | ${fakecallsite} | ${message}"/>
<variable name="f2layout" value="${longdate} | ${level} | ${logger} | ${callsite} | ${message}"/>
<targets>
<target name="f1" xsi:type="File" layout="${f1layout}" fileName="${basedir}/${shortdate}.log" />
<target name="f2" xsi:type="File" layout="${f2layout}" fileName="${basedir}/${shortdate}.log" />
</targets>
Note that I have not tried this, but I think it should work (or should be close enough that you can get it working). One limitation is that, since we are calculating the fake call site, we cannot use the real callsite LayoutRenderer to manipulate the contents of the fakecallsite field in the output. If this important, it can probably be simulated by storing the class and method separately (in LogEventInfo.Properties) and then setting the "fakecallsite" variable in the NLog.config to contain the class, the method, or both.
END UPDATE
Your wrapper should use the Log method. Also, the type you pass to the NLog Logger.Log method should be the type of your NLog Logger wrapper, not the type of the type of the service instance. You can still use the type of your service instance to retrieve the right Logger instance. It should look something like this:
public class NLogLogger : IParameterInspector
{
private void Log(Type instanceType, string operationName, string msg)
{
NLog.Logger logger = LogManager.GetLogger(
instanceType.FullName, instanceType);
//This is the key to preserving the call site in a wrapper. Create a LogEventInfo
//then use NLog's Logger.Log method to log the message, passing the type of your
//wrapper as the first argument.
LogEventInfo le = new LogEventInfo(LogLevel.Info, logger.Name, msg);
logger.Log(typeof(NLogLogger), le);
}
public object BeforeCall(string operationName, object[] inputs)
{
// Retrieve the service instance type for the logger then log the call.
OperationContext operationContext = OperationContext.Current;
Type instanceType = operationContext.InstanceContext
.GetServiceInstance().GetType();
Log(instanceType, operationName, "BeforeCall");
return instanceType;
}
public void AfterCall(
string operationName, object[] outputs,
object returnValue, object correlationState
)
{
if (correlationState is Type)
Log(correlationState, operationName, "AfterCall");
}
}