Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 907399
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 15, 20262026-05-15T16:32:58+00:00 2026-05-15T16:32:58+00:00

I’m trying to implement a custom log4net logger/logmanager so that I can add a

  • 0

I’m trying to implement a custom log4net logger/logmanager so that I can add a new level. I also want to have the schema of the target table (I’m using an AdoNetAppender and SQL Server 2008) to have some optional fields; for instance, the level I’m adding is used to track usage, and one of the fields needs to be a Duration (to tell us how long something took). However, other levels (INFO, DEBUG, FATAL, etc.) will not have any value for Duration. So I need to be able to insert into the table with not all fields having values–preferably without having to reimplement all of the standard levels logging to pass a null value for the irrelevant fields. Ideally, log4net would automatically pass NULL for property values that it cannot find for a particular logging event.

The code in my custom logger is as follows:

public void Usage(TimeSpan? duration, DateTime? startTime, DateTime? endTime, string message)
    {
        if (IsUsageEnabled)
        {
            LoggingEvent loggingEvent = new LoggingEvent(GetType(), Logger.Repository, Logger.Name, _currentUsageLevel,
                message, null);
            if (startTime.HasValue)
            {
                loggingEvent.Properties["StartTime"] = startTime.Value;
            }
            else
            {
                loggingEvent.Properties["StartTime"] = DBNull.Value;
            }

            if (endTime.HasValue)
            {
                loggingEvent.Properties["EndTime"] = endTime.Value;
            }
            else
            {
                loggingEvent.Properties["EndTime"] = DBNull.Value;
            }

            if (duration.HasValue)
            {
                loggingEvent.Properties["Duration"] = duration.Value.TotalMilliseconds;
            }
            else
            {
                loggingEvent.Properties["Duration"] = DBNull.Value;
            }

            Logger.Log(loggingEvent);
        }
    }

(the assignments to DBNull.Value were added in hopes that that would help log4net pass nulls when the value was not passed, but I hope they can be removed).

The appender config is as follows:

<appender name="SQLAppender" type="log4net.Appender.AdoNetAppender">
  <bufferSize value="1" />
  <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  <connectionString value="my connection string (which actually gets replaced at runtime with a connection string retrieved from a config database)" />
  <commandText value="INSERT INTO MyTable ([Date],[Thread],[Level],[Logger],[Message],[Exception], [Login], [StartTime], [EndTime], [Duration]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception, @login, @start_time, @end_time, @duration)" />
  <parameter>
    <parameterName value="@log_date" />
    <dbType value="DateTime" />
    <layout type="log4net.Layout.RawTimeStampLayout" />
  </parameter>
  <parameter>
    <parameterName value="@thread" />
    <dbType value="String" />
    <size value="255" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%thread" />
    </layout>
  </parameter>
  <parameter>
    <parameterName value="@log_level" />
    <dbType value="String" />
    <size value="50" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%level" />
    </layout>
  </parameter>
  <parameter>
    <parameterName value="@logger" />
    <dbType value="String" />
    <size value="255" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%logger" />
    </layout>
  </parameter>
  <parameter>
    <parameterName value="@message" />
    <dbType value="String" />
    <size value="4000" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%message" />
    </layout>
  </parameter>
  <parameter>
    <parameterName value="@exception" />
    <dbType value="String" />
    <size value="4000" />
    <layout type="log4net.Layout.ExceptionLayout" />
  </parameter>
  <parameter>
    <parameterName value="@login" />
    <dbType value="String" />
    <size value="255" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%property{CurrentLogin}" />
    </layout>
  </parameter>
  <parameter>
    <parameterName value="@start_time" />
    <dbType value="DateTime" />
    <layout type="log4net.Layout.PatternLayout"
      value="%property{StartTime}" />
  </parameter>
  <parameter>
    <parameterName value="@end_time" />
    <dbType value="DateTime" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%property{EndTime}" />
    </layout>
  </parameter><parameter>
    <parameterName value="@duration" />
    <dbType value="Double" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%property{Duration}" />
    </layout>
  </parameter>
</appender>

When I try to log something with my custom level, it works ONLY if I pass in duration, starttime and endtime. For anything else–including default levels–it seems to fail silently, with no clues in the output window (although logging with default levels throws exceptions saying it can’t convert String to DateTime or Double).

Any reason that anyone can see why this would fail silently like this?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-15T16:32:59+00:00Added an answer on May 15, 2026 at 4:32 pm

    I finally figured it out, after tracing through some log4net source. The problem was that I was using a PatternLayout for rendering the custom parameters. This layout coerces null to the string "(null)", which causes problems if you’re trying to insert it into, say, a nullable datetime field in the table. The solution is simple: instead of using the PatternLayout layout, use log4net.Layout.RawPropertyLayout. This will pass a null property as null, which is what you want.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.