Index: Core/LoggingEvent.cs =================================================================== --- Core/LoggingEvent.cs (revision 1581269) +++ Core/LoggingEvent.cs (working copy) @@ -828,31 +828,7 @@ { if (m_data.UserName == null && this.m_cacheUpdatable) { -#if NETCF - // On compact framework there's no notion of current Windows user - m_data.UserName = SystemInfo.NotAvailableText; -#else - try - { - WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent(); - if (windowsIdentity != null && windowsIdentity.Name != null) - { - m_data.UserName = windowsIdentity.Name; - } - else - { - m_data.UserName = ""; - } - } - catch(System.Security.SecurityException) - { - // This security exception will occur if the caller does not have - // some undefined set of SecurityPermission flags. - LogLog.Debug(declaringType, "Security exception while trying to get current windows identity. Error Ignored. Empty user name."); - - m_data.UserName = ""; - } -#endif + m_data.UserName = SystemInfo.GetCurrentUserName(); } return m_data.UserName; } @@ -876,41 +852,7 @@ { if (m_data.Identity == null && this.m_cacheUpdatable) { -#if NETCF - // On compact framework there's no notion of current thread principals - m_data.Identity = SystemInfo.NotAvailableText; -#else - try - { - if (System.Threading.Thread.CurrentPrincipal != null && - System.Threading.Thread.CurrentPrincipal.Identity != null && - System.Threading.Thread.CurrentPrincipal.Identity.Name != null) - { - m_data.Identity = System.Threading.Thread.CurrentPrincipal.Identity.Name; - } - else - { - m_data.Identity = ""; - } - } - catch (ObjectDisposedException) - { - // This exception will occur if System.Threading.Thread.CurrentPrincipal.Identity is not null but - // the getter of the property Name tries to access disposed objects. - // Seen to happen on IIS 7 or greater with windows authentication. - LogLog.Debug(declaringType, "Object disposed exception while trying to get current thread principal. Error Ignored. Empty identity name."); - - m_data.Identity = ""; - } - catch (System.Security.SecurityException) - { - // This security exception will occur if the caller does not have - // some undefined set of SecurityPermission flags. - LogLog.Debug(declaringType, "Security exception while trying to get current thread principal. Error Ignored. Empty identity name."); - - m_data.Identity = ""; - } -#endif + m_data.Identity = SystemInfo.GetCurrentIdentity(); } return m_data.Identity; } @@ -1337,7 +1279,6 @@ // event properties PropertiesDictionary eventProperties = new PropertiesDictionary(); - eventProperties[UserNameProperty] = UserName; eventProperties[IdentityProperty] = Identity; m_compositeProperties.Add(eventProperties); Index: Util/CompositeProperties.cs =================================================================== --- Util/CompositeProperties.cs (revision 1581269) +++ Util/CompositeProperties.cs (working copy) @@ -36,6 +36,7 @@ { #region Private Instance Fields + private string m_currentUserName = null; private PropertiesDictionary m_flattened = null; private ArrayList m_nestedProperties = new ArrayList(); @@ -82,6 +83,17 @@ { get { + // treat the UserName property specially + if (key == log4net.Core.LoggingEvent.UserNameProperty) + { + if (m_currentUserName == null) + { + // get the current user name and cache it + m_currentUserName = SystemInfo.GetCurrentUserName(); + } + return m_currentUserName; + } + // Look in the flattened properties first if (m_flattened != null) { Index: Util/SystemInfo.cs =================================================================== --- Util/SystemInfo.cs (revision 1581269) +++ Util/SystemInfo.cs (working copy) @@ -24,6 +24,7 @@ using System.IO; using System.Runtime.InteropServices; using System.Collections; +using System.Security.Principal; namespace log4net.Util { @@ -1002,6 +1003,133 @@ return new Hashtable(StringComparer.OrdinalIgnoreCase); } + /// + /// Gets the name of the current user. + /// + /// + /// The name of the current user, or NOT AVAILABLE when the + /// underlying runtime has no support for retrieving the name of the + /// current user. + /// + /// + /// + /// Calls WindowsIdentity.GetCurrent().Name to get the name of + /// the current windows user. + /// + /// + /// To improve performance, we could cache the string representation of + /// the name, and reuse that as long as the identity stayed constant. + /// Once the identity changed, we would need to re-assign and re-render + /// the string. + /// + /// + /// However, the WindowsIdentity.GetCurrent() call seems to + /// return different objects every time, so the current implementation + /// doesn't do this type of caching. + /// + /// + /// Timing for these operations: + /// + /// + /// + /// Method + /// Results + /// + /// + /// WindowsIdentity.GetCurrent() + /// 10000 loops, 00:00:00.2031250 seconds + /// + /// + /// WindowsIdentity.GetCurrent().Name + /// 10000 loops, 00:00:08.0468750 seconds + /// + /// + /// + /// This means we could speed things up almost 40 times by caching the + /// value of the WindowsIdentity.GetCurrent().Name property, since + /// this takes (8.04-0.20) = 7.84375 seconds. + /// + /// + public static string GetCurrentUserName() + { +#if NETCF + // On compact framework there's no notion of current Windows user + return NotAvailableText; +#else + try + { + WindowsIdentity windowsIdentity = WindowsIdentity.GetCurrent(); + if (windowsIdentity != null && windowsIdentity.Name != null) + { + return windowsIdentity.Name; + } + else + { + return ""; + } + } + catch (System.Security.SecurityException) + { + // This security exception will occur if the caller does not have + // some undefined set of SecurityPermission flags. + LogLog.Debug(declaringType, "Security exception while trying to get current windows identity. Error Ignored. Empty user name."); + + return ""; + } +#endif + } + + /// + /// Gets the identity of the current thread principal. + /// + /// + /// The string name of the identity of the current thread principal. + /// + /// + /// + /// Calls System.Threading.Thread.CurrentPrincipal.Identity.Name to get + /// the name of the current thread principal. + /// + /// + public static string GetCurrentIdentity() + { +#if NETCF + // On compact framework there's no notion of current thread principals + return SystemInfo.NotAvailableText; +#else + try + { + if (System.Threading.Thread.CurrentPrincipal != null && + System.Threading.Thread.CurrentPrincipal.Identity != null && + System.Threading.Thread.CurrentPrincipal.Identity.Name != null) + { + return System.Threading.Thread.CurrentPrincipal.Identity.Name; + } + else + { + return ""; + } + } + catch (ObjectDisposedException) + { + // This exception will occur if System.Threading.Thread.CurrentPrincipal.Identity is not null but + // the getter of the property Name tries to access disposed objects. + // Seen to happen on IIS 7 or greater with windows authentication. + LogLog.Debug(declaringType, "Object disposed exception while trying to get current thread principal. Error Ignored. Empty identity name."); + + return ""; + } + catch (System.Security.SecurityException) + { + // This security exception will occur if the caller does not have + // some undefined set of SecurityPermission flags. + LogLog.Debug(declaringType, "Security exception while trying to get current thread principal. Error Ignored. Empty identity name."); + + return ""; + } +#endif + } + #endregion Public Static Methods #region Private Static Methods