0

I have implemented a custom appender for log4net in which i am doing logging to a file and sending out mail. I want to log different message strings for each case. Below code creates two log entries in the file, one with appended string & one without appended string. It also sends out the email without the appended string.

public static void Log(this ILog log, Level level, string message)
{
    var token = string.Format("{0},{1},{2}", System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, level, message);
    int count = _tokenTimeThrottler.CheckAllow(token);
    if (count >= 0)
    {
        //only to file logger, with an appended string
        log = LogManager.GetLogger("LogFileAppender");
        log.Logger.Log(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, level, count <= 1 ? message : count + " counts of: " + message, null);
    }

    //only to mail
    log = LogManager.GetLogger("MyMailAppender");
    log.Logger.Log(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, level, message, null);
    }

But I want to don't want to log to file when I am doing.

//only to mail
log = LogManager.GetLogger("MyMailAppender");
log.Logger.Log(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, level, message, null);

My Config file, one appender is added using config file, the other appender is a dll so its added at runtime.

1st appender:

<log4net>
    <root>
      <level value="INFO" />
      <appender-ref ref="LogFileAppender" />
    </root>
    <appender name="LogFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="C:\git\logs\log.log" />
      <appendToFile value="true" />
      <rollingStyle value="Size" />
      <maxSizeRollBackups value="5" />
      <maximumFileSize value="10MB" />
      <staticLogFileName value="true" />
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%d [%t] %-5p  %m%n" />
      </layout>
    </appender>
</log4net>

2nd appender (Added at runtime):

Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository();
      PatternLayout patternLayout = new PatternLayout { ConversionPattern = "%d [%t] %-5p %m%n" };

      MyMailAppender myAppender = new MyMailAppender 
      {
        Name = "MyMailAppender",
        Layout = patternLayout,
        Access = "ghjkgj",
        Threshold = Level.Info,
      };

      myAppender .ActivateOptions();
      hierarchy.Root.AddAppender(myAppender );

      hierarchy.Root.Level = Level.All;
      hierarchy.Configured = true;
stuartd
  • 70,509
  • 14
  • 132
  • 163
PUG
  • 4,301
  • 13
  • 73
  • 115
  • can you show what your config file looks like for the Appender also take a look at the following http://stackoverflow.com/questions/21186378/log4net-logging-of-two-different-levels-to-two-different-appenders-for-the-same – MethodMan Nov 11 '14 at 00:24
  • @DJKRAZE I added the config file, The question you linked won't solve my problem because threshold for both appenders has to be same. – PUG Nov 11 '14 at 00:32

3 Answers3

0

It;s not completely clear to me what you're doing, as your examples aren't actually calling your extension method, but I think the simplest solution is to add another parameter to the extension method which specifies if you want to send the log entry by email:

public static void Log(this ILog log, Level level,
                       string message, bool sendEmail = true)
{ …

 if (sendEmail)
  { 
      //only to mail
      log = LogManager.GetLogger("MyMailAppender");
      log.Logger.Log(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, level, message, null);
  }
}

Then you just specify when you don't want it to be sent:

log = LogManager.GetLogger("MyMailAppender");

// Call extension method, specifying no email should be sent
log.Log(level, message, false);

Because sendEmail has a default value of true, if you do want send email then you don't need to pass the parameter at all, which means there is no impact on existing code.

stuartd
  • 70,509
  • 14
  • 132
  • 163
0

I would recommend using two BufferingFowardAppender with filters based on the logger name (log4net.Filter.LoggerMatchFilter):

  • one forwarding appender would filter messages for the mailing logger based on the logger name: root at INFO level -> fowarding appender with filter for MyMailAppender logger name -> mail appender
  • one forwarding appender would filter messages for the standard logger: root at INFO level -> fowarding appender with filter NOT letting MyMailAppender logger name pass -> other appender

You don't need to use in code configuration, this is entirely doable through configuration only

samy
  • 14,832
  • 2
  • 54
  • 82
0

The solution was to use two logger elements instead of root, as root applies to all appenders. So anything appended added to root will be written creating duplicate entries.

    <log4net>
         <logger name="MyMailAppender">
          <level value="INFO" />
        </logger>
        <logger name="LogFileAppender">
          <level value="INFO" />
          <appender-ref ref="LogFileAppender" />
        </logger>
</log4net>

Then at runtime i create the appender from dll and add it to MyMailAppender logger.

PUG
  • 4,301
  • 13
  • 73
  • 115