1

My application can be started both as a Windows Service and in console environment. For each case, I need some log4net appenders to be active (or not, respectively) as well as some which are active in both cases. (Service: RollingFileAppender, DebugAppender (if enabled), EventLogAppender | Console: ColoredConsoleAppender, DebugAppender (if enabled))

The only way to achieve something similar is using the PropertyFilter together with ThreadContext.Properties like so:

<filter type="log4net.Filter.PropertyFilter">
    <key value="ApplicationMode" />
    <stringToMatch value="Service" />
</filter>

if(!Environment.UserInteractive)
    ThreadContext.Properties["ApplicationMode"] = "Service";

However, since the property is declared on the thread context, it only works on the current thread. If the thread changes, the configuration is being reset and I have to declare it again.

Does log4net support a way to declare a PropertyFilter in configuration to setup the desired environment automatically? Like this:

<filter type="log4net.Filter.PropertyFilter">
    <key value="{Environment.UserInteractive}" />
    <stringToMatch value="false" />
</filter>

Or... is there a better approach? Since I didn't found a solution yet.. is this an uncommon practice?

xvdiff
  • 2,179
  • 2
  • 24
  • 47
  • Is your console app and windows service under two different projects? Why not creating configuration file in each project that will do what you need? – Sergey Jul 31 '14 at 15:31

1 Answers1

1

See the last part of my answer to this question:

Capture username with log4net

To summarize, you can implement an object that contains the logic that you have above and put that object in GlobalContext.Properties. When log4net retrieves the value (your object) from the Properties, it will call ToString to get the actual value. Put your logic inside ToString.

Maybe something like this:

public class ApplicationModeProvider
{
  public override string ToString()
  {
    return Environment.UserInteractive ? "Console" : "Service";
  }
}

Put it in your dictionary at startup:

GlobalContext.Properties["ApplicationMode"] = new ApplicationModeProvider();

In effect, this is sort of like adding

if(!Environment.UserInteractive)
    ThreadContext.Properties["ApplicationMode"] = "Service";

before ever logging statement.

I'm not sure, but I think that then you can configure your filter as you describe in your post.

Community
  • 1
  • 1
wageoghe
  • 27,390
  • 13
  • 88
  • 116