views:

231

answers:

3

I've created a simple WF4 console app and set up log4net identically to my other apps. However, when I fire up the console and use the ILog object inside WF4 (I actually pass it into the workflow), no information is presented using my ColoredConsoleAppender. What am I doing wrong?

+2  A: 

Workflow trace output is written to trace listeners and as far as I am aware log4net doesn't log the output written to a trace listener by default. I am no expert on log4net so there might be an easier way but creating a TraceListener that just passes all data on to log4net is not hard, the following code worked just fine in a quick test.

public class Log4netTraceListener : TraceListener
{
    private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);

    public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, params object[] data)
    {
        base.TraceData(eventCache, source, eventType, id, data);
    }

    public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
    {
        var logger = LogManager.GetLogger(source);
        switch (eventType)
        {
            case TraceEventType.Critical:
                logger.Fatal(data);
                break;
            case TraceEventType.Error:
                logger.Error(data);
                break;
            case TraceEventType.Information:
                logger.Info(data);
                break;
            case TraceEventType.Verbose:
                logger.Debug(data);
                break;
            case TraceEventType.Warning:
                logger.Warn(data);
                break;
            default:
                base.TraceData(eventCache, source, eventType, id, data);
                break;
        }
    }

    public override void Write(string message)
    {
        _log.Info(message);
    }

    public override void WriteLine(string message)
    {
        _log.Info(message);
    }

Next you need to make sure the activity trace information is send to this TraceListener using the following code in you app.config.

<system.diagnostics>
  <sources>
    <source name="System.Activities"
            switchValue="Verbose">
      <listeners>
        <add name="Test"
              type="WorkflowConsoleApplication17.Log4netTraceListener, WorkflowConsoleApplication17"/>
      </listeners>
    </source>
  </sources>
</system.diagnostics>
Maurice
Thanks for that! But the problem I face is that I'm using an `ILog` right in the workflow and the output doesn't appear in my console.
Dmitri Nesteruk
If you load your logger inside of a workflow you need to specify the assembly to use. Something like: log4net.LogManager.GetLogger(System.Reflection.Assembly.GetEntryAssembly(), "System.Activities"). If you only specify a name it will try to load the configuration of a dynamic assembly and won't find anything.
Maurice
+1  A: 

Create an Extension for your workflow that your activities can get from the context.

var wf = new WorkflowApplication(myActivity);
var log = new MyLogForNetExtensionLol();
wf.Extensions.Add(log);

then, within the activity:

var log = context.GetExtension<ILog>();
log.Write("Worked!");
Will
A: 

I have an additional question. Before with WF 3.5 I was able to intercept the execution of every activity in my workflow and log it, right now if I am using the Extensions, how can I add that extension to each activity without overwriting the whole WF 4 engine? I mean, how can I extend a ParallelActivity using this extension?