1

I have setup log4Net ADONetAppender to a table called log.

The log4net gets configured on Application_Start() of the Global.asax.cs file.

The table and its inserts are typical

INSERT INTO log ([PCDate],[Thread],[Level],[Logger],[Message],[Exception]) 
    VALUES (@log_date, @thread, @log_level, @logger, @message, @exception)

All what is different is that i have set my Logger to be the application user that is currently logged into the system.

This in the .config file.

<parameter>
   <parameterName value="@logger"/>
   <dbType value="String"/>
   <size value="255"/>
   <layout type="log4net.Layout.PatternLayout">
     <conversionPattern value="%property{userName}"/> 
   </layout>
</parameter>

I do the logging before any insert, update or delete of user-data records in a class responsible for handling that.

logger.Info(strquery); 

The message of the logger, is the insert/update or delete query. The logger gets set to the current application logged user e.g. Bob, ash etc on login and debugging validates that it gets set to that value.

log4net.ThreadContext.Properties["userName"] = userName;

I could alternatively put the above statement in every asp that will ultimately do the insert/add/delete but that is cumbersome we looking at 12 current file not to mention that this is not scale-able.

Where/why does the property value get set to null after ??
The table records look like this

enter image description here

stuartd
  • 70,509
  • 14
  • 132
  • 163
devsahem
  • 83
  • 3
  • 15

1 Answers1

1

This is happening because ThreadContext persists the username on the current thread, and as you can see from your logs the thread changes between calls: when you set the value on login, it's valid for the current request, but the next request gets a new thread and consequently a new ThreadContext and the value is gone.

If you store the username in the session, you can set the ThreadContext property in the Application_AcquireRequestState event in your Global.asax.cs file. Then it will be valid for the whole request.

stuartd
  • 70,509
  • 14
  • 132
  • 163
  • Great point. But that username is only set once you click the login button at the login.aspx page. I do not know that value at the application_beginRequest yet. Or do I need to check for it there by saving it in a session and checking for it at the BeginREquest? – devsahem Nov 13 '15 at 09:21
  • Stuart, i used GlobalContext . The value of the logger is persistantly not null :) :) however i'm not sure if this Globally across all users? [link](https://logging.apache.org/log4net/release/manual/contexts.html) The link describes how globalcontext is across the AppDomain (which i do not understand). Does that mean it will affect other users and every recently logged user will overwrite this value? I need another machine to test it. – devsahem Nov 13 '15 at 10:32
  • Yes, GlobalContext will only hold one value, that of the last user to log in. Your previous idea of keeping the username in the session and using that to populate the ThreadContext would work though. – stuartd Nov 13 '15 at 10:39
  • Unfortunately using the "Application_BeginRequest" did not work. The system has an exception that i had to catch "Session state is not available in this context." `try { if (Session["user"] != null) log4net.ThreadContext.Properties["userName"] = ((User)Session["user"]).UserName; } catch (Exception ex) { }` – devsahem Nov 13 '15 at 11:11
  • My apologies - you need to use [`Application_AcquireRequestState`](https://msdn.microsoft.com/en-us/library/system.web.httpapplication.acquirerequeststate.aspx) to access the session for each request. See also [this answer](http://stackoverflow.com/a/5977333/43846) – stuartd Nov 13 '15 at 11:35
  • That nailed it on the head!! I even logged as two different users and the logger is tracking the username properly. Cheers! – devsahem Nov 13 '15 at 12:41