0

I already make use of Log4Net to log DEBUG and error data to a file within my Web API v2 application. I would also like to log to a database table (SQL Server) the name of the user and the IP address they are logging in from.

I figured I would reuse Log4Net capabilities by adding a second appender instead of rolling my own service. Does this sound like a good idea or would it be better to create my own service to handle this? Log4Net has a lot of extra features to log Trace, exception details, etc. My proposed usage has nothing to do with logging errors. Would there be any performance benefit to using Log4Net as opposed to updating an entity and saving changes to save the login details?

If it is, how do I go about grabbing the username of the logged in user and passing it to Log4Net? Would I just create a message parameter and pass the username along as I have done below? Guess I am confused on how to pass specific data onto Log4Net.

<appender
  name="AdoNetAppender"
  type="log4net.Appender.AdoNetAppender">
  <threshold>INFO</threshold>
  <bufferSize
    value="50" />
  <connectionType
    value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
  <connectionString
    value="data source=DBServerName;initial catalog=MyDatabaseName;integrated security=true; />
  <commandText
    value="INSERT INTO Logs ([Date],[UserName],[HostName]) VALUES (@log_date, @username, @hostname)" />
  <parameter>
    <parameterName value="@log_date" />
    <dbType value="DateTime" />
    <layout type="log4net.Layout.RawTimeStampLayout" />
  </parameter>
  <parameter>
    <parameterName value="@hostname" />
    <dbType value="String" />
    <size value="255" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%property{log4net:HostName}" />
    </layout>
  </parameter>
  <parameter>
    <parameterName value="@username" />
    <dbType value="String" />
    <size value="-1" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%message" />
    </layout>
  </parameter>
</appender>
webworm
  • 10,587
  • 33
  • 120
  • 217
  • Possible duplicate of [Log4Net, how to add a custom field to my logging](http://stackoverflow.com/questions/12139486/log4net-how-to-add-a-custom-field-to-my-logging) – stuartd Mar 08 '16 at 09:48
  • Is Log4Net the right solution or would it be better just to update the table manually using EF? Any benefit to Log4Net as far as connection pool management? – webworm Mar 08 '16 at 13:11
  • Using the AdoNet appender with log4net lets you use buffering on the inserts, but if it is vital that the logins are saved, then use the manual way - log4net will fail silently (by design), which may not be what you want. – stuartd Mar 08 '16 at 13:32

1 Answers1

0

A nice concept in log4net is stacks (used to be Nested Diagnostic Context(NDC)). What you can do is push something on a stack and when you log a message in that stack context, print the content of the stack with the message. In your case the username, ip address etc. What you can do is make an attribute in your webapi what does push the meta values of the call to the stack. When you now log a message within the handling of your method, you can add the information to the log message.

A short sample of stacks (all logging within the using get the context):

using(log4net.ThreadContext.Stacks["NDC"].Push("context ip etc"))
{
    log.Info("Message");
}
Peter
  • 27,590
  • 8
  • 64
  • 84
  • Thanks @Peter. Other comments suggested the ThreadContext was not safe to use in a web application. Do you agree/disagree? – webworm Mar 09 '16 at 20:45