Code:
/ FXUpdate3074 / FXUpdate3074 / 1.1 / DEVDIV / depot / DevDiv / releases / whidbey / QFE / ndp / fx / src / xsp / System / Web / Management / WebEvents.cs / 5 / WebEvents.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Web.Management { using System; using System.Web; using System.Diagnostics; using System.Security.Principal; using System.Threading; using System.Reflection; using System.Text; using System.Web.Util; using System.Web.Configuration; using System.Configuration.Provider; using System.Collections; using System.Collections.Generic; using System.Configuration; using System.Security; using Debug=System.Web.Util.Debug; using System.Web.Hosting; using System.Web.UI; using System.Globalization; using System.Runtime.Remoting.Messaging; using System.Security.Permissions; using System.Web.Caching; // This enum matches the native one enum WebEventType (in webevent.h). internal enum WebEventType : int { WEBEVENT_BASE_EVENT = 0, WEBEVENT_MANAGEMENT_EVENT, WEBEVENT_APP_LIFETIME_EVENT, WEBEVENT_REQUEST_EVENT, WEBEVENT_HEARTBEAT_EVENT, WEBEVENT_BASE_ERROR_EVENT, WEBEVENT_REQUEST_ERROR_EVENT, WEBEVENT_ERROR_EVENT, WEBEVENT_AUDIT_EVENT, WEBEVENT_SUCCESS_AUDIT_EVENT, WEBEVENT_AUTHENTICATION_SUCCESS_AUDIT_EVENT, WEBEVENT_FAILURE_AUDIT_EVENT, WEBEVENT_AUTHENTICATION_FAILURE_AUDIT_EVENT, WEBEVENT_VIEWSTATE_FAILURE_AUDIT_EVENT, }; internal enum WebEventFieldType : int { String = 0, Int = 1, Bool = 2, Long = 3, Date = 4, } // Used for marshalling over to IIS Trace internal class WebEventFieldData { string _name; public string Name { get { return _name; } } string _data; public string Data { get { return _data; } } WebEventFieldType _type; public WebEventFieldType Type { get { return _type; } } public WebEventFieldData(string name, string data, WebEventFieldType type) { _name = name; _data = data; _type = type; } } // Interface for event provider [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public abstract class WebEventProvider : ProviderBase { // methods public abstract void ProcessEvent(WebBaseEvent raisedEvent); public abstract void Shutdown(); public abstract void Flush(); int _exceptionLogged; internal void LogException(Exception e) { // In order to not overflow the eventlog, we only log one exception per provider instance. if (Interlocked.CompareExchange( ref _exceptionLogged, 1, 0) == 0) { // Log all errors in eventlog UnsafeNativeMethods.LogWebeventProviderFailure( HttpRuntime.AppDomainAppVirtualPath, Name, e.ToString()); } } } // Interface for custom event evaluator [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public interface IWebEventCustomEvaluator { bool CanFire(WebBaseEvent raisedEvent, RuleFiringRecord record); } //////////////// // Events //////////////// [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebBaseEvent { DateTime _eventTimeUtc; int _code; int _detailCode; Object _source; string _message; long _sequenceNumber; long _occurrenceNumber; Guid _id = Guid.Empty; static long s_globalSequenceNumber = 0; static WebApplicationInformation s_applicationInfo = new WebApplicationInformation(); const string WEBEVENT_RAISE_IN_PROGRESS = "_WEvtRIP"; // A array that cache the result of eventCode to SystemEventType mapping. static readonly SystemEventType[,] s_eventCodeToSystemEventTypeMappings = new SystemEventType[WebEventCodes.GetEventArrayDimensionSize(0), WebEventCodes.GetEventArrayDimensionSize(1)]; // A array that store the # of occurrence per custom event code. static readonly long[,] s_eventCodeOccurrence = new long[WebEventCodes.GetEventArrayDimensionSize(0), WebEventCodes.GetEventArrayDimensionSize(1)]; static Hashtable s_customEventCodeOccurrence = new Hashtable(); #pragma warning disable 0649 static ReadWriteSpinLock s_lockCustomEventCodeOccurrence; #pragma warning restore 0649 static WebBaseEvent() { // Initialize the mappings. We will fill up each entry on demand by calling // SystemEventTypeFromEventCode(). for (int i = 0; i < s_eventCodeToSystemEventTypeMappings.GetLength(0); i++) { for (int j = 0; j < s_eventCodeToSystemEventTypeMappings.GetLength(1); j++) { s_eventCodeToSystemEventTypeMappings[i,j] = SystemEventType.Unknown; } } for (int i = 0; i < s_eventCodeOccurrence.GetLength(0); i++) { for (int j = 0; j < s_eventCodeOccurrence.GetLength(1); j++) { s_eventCodeOccurrence[i,j] = 0; } } } void Init(string message, Object eventSource, int eventCode, int eventDetailCode) { if (eventCode < 0) { throw new ArgumentOutOfRangeException("eventCode", SR.GetString(SR.Invalid_eventCode_error)); } if (eventDetailCode < 0) { throw new ArgumentOutOfRangeException("eventDetailCode", SR.GetString(SR.Invalid_eventDetailCode_error)); } _code = eventCode; _detailCode = eventDetailCode; _source = eventSource; _eventTimeUtc = DateTime.UtcNow; _message = message; // Creation of _id is always delayed until it's needed. } // ctors internal protected WebBaseEvent(string message, Object eventSource, int eventCode) { Init(message, eventSource, eventCode, WebEventCodes.UndefinedEventDetailCode); } internal protected WebBaseEvent(string message, Object eventSource, int eventCode, int eventDetailCode) { Init(message, eventSource, eventCode, eventDetailCode); } internal WebBaseEvent() { // For creating dummy event. See GetSystemDummyEvent() } internal bool IsSystemEvent { get { return (_code < WebEventCodes.WebExtendedBase); } } // Properties public DateTime EventTime { get { return _eventTimeUtc.ToLocalTime(); } } public DateTime EventTimeUtc { get { return _eventTimeUtc; } } public String Message { get { return _message; } } public Object EventSource { get { return _source; } } public long EventSequence { get { return _sequenceNumber; } } public long EventOccurrence { get { return _occurrenceNumber; } } public int EventCode { get { return _code; } } public int EventDetailCode { get { return _detailCode; } } public Guid EventID { get { if (_id == Guid.Empty) { lock(this) { if (_id == Guid.Empty) { _id = Guid.NewGuid(); } } } return _id; } } public static WebApplicationInformation ApplicationInformation { get { return s_applicationInfo; } } virtual internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_code, EventCode.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_message, Message)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_time, EventTime.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_time_Utc, EventTimeUtc.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_id, EventID.ToString("N", CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_sequence, EventSequence.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_occurrence, EventOccurrence.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_detail_code, EventDetailCode.ToString(CultureInfo.InstalledUICulture))); if (includeAppInfo) { formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_information)); formatter.IndentationLevel += 1; ApplicationInformation.FormatToString(formatter); formatter.IndentationLevel -= 1; } } public override string ToString() { return ToString(true, true); } public virtual string ToString(bool includeAppInfo, bool includeCustomEventDetails) { WebEventFormatter formatter = new WebEventFormatter(); FormatToString(formatter, includeAppInfo); if (!IsSystemEvent && includeCustomEventDetails) { formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_custom_event_details)); formatter.IndentationLevel += 1; FormatCustomEventDetails(formatter); formatter.IndentationLevel -= 1; } return formatter.ToString(); } virtual public void FormatCustomEventDetails(WebEventFormatter formatter) { } internal int InferEtwTraceVerbosity() { WebEventType type = WebBaseEvent.WebEventTypeFromWebEvent(this); switch (type) { case WebEventType.WEBEVENT_VIEWSTATE_FAILURE_AUDIT_EVENT: case WebEventType.WEBEVENT_BASE_ERROR_EVENT: case WebEventType.WEBEVENT_REQUEST_ERROR_EVENT: case WebEventType.WEBEVENT_FAILURE_AUDIT_EVENT: case WebEventType.WEBEVENT_AUTHENTICATION_FAILURE_AUDIT_EVENT: case WebEventType.WEBEVENT_ERROR_EVENT: return EtwTraceLevel.Warning; case WebEventType.WEBEVENT_AUDIT_EVENT: case WebEventType.WEBEVENT_SUCCESS_AUDIT_EVENT: case WebEventType.WEBEVENT_AUTHENTICATION_SUCCESS_AUDIT_EVENT: return EtwTraceLevel.Information; case WebEventType.WEBEVENT_BASE_EVENT: case WebEventType.WEBEVENT_MANAGEMENT_EVENT: case WebEventType.WEBEVENT_REQUEST_EVENT: default: return EtwTraceLevel.Verbose; } } internal void DeconstructWebEvent(out int eventType, out int fieldCount, out string[] fieldNames, out int[] fieldTypes, out string[] fieldData) { Listfields = new List (); eventType = (int)WebBaseEvent.WebEventTypeFromWebEvent(this); GenerateFieldsForMarshal(fields); fieldCount = fields.Count; fieldNames = new string[fieldCount]; fieldData = new string[fieldCount]; fieldTypes = new int[fieldCount]; for (int i = 0; i < fieldCount; ++i) { fieldNames[i] = fields[i].Name; fieldData[i] = fields[i].Data; fieldTypes[i] = (int)fields[i].Type; } } internal virtual void GenerateFieldsForMarshal(List fields) { fields.Add(new WebEventFieldData("EventTime", EventTimeUtc.ToString(), WebEventFieldType.String)); fields.Add(new WebEventFieldData("EventID", EventID.ToString(), WebEventFieldType.String)); fields.Add(new WebEventFieldData("EventMessage", Message, WebEventFieldType.String)); fields.Add(new WebEventFieldData("ApplicationDomain", WebBaseEvent.ApplicationInformation.ApplicationDomain, WebEventFieldType.String)); fields.Add(new WebEventFieldData("TrustLevel", WebBaseEvent.ApplicationInformation.TrustLevel, WebEventFieldType.String)); fields.Add(new WebEventFieldData("ApplicationVirtualPath", WebBaseEvent.ApplicationInformation.ApplicationVirtualPath, WebEventFieldType.String)); fields.Add(new WebEventFieldData("ApplicationPath", WebBaseEvent.ApplicationInformation.ApplicationPath, WebEventFieldType.String)); fields.Add(new WebEventFieldData("MachineName", WebBaseEvent.ApplicationInformation.MachineName, WebEventFieldType.String)); fields.Add(new WebEventFieldData("EventCode", EventCode.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int)); fields.Add(new WebEventFieldData("EventDetailCode", EventDetailCode.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int)); fields.Add(new WebEventFieldData("SequenceNumber", EventSequence.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Long)); fields.Add(new WebEventFieldData("Occurrence", EventOccurrence.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Long)); } internal virtual void PreProcessEventInit() { } static void FindEventCode(Exception e, ref int eventCode, ref int eventDetailsCode, ref Exception eStack) { eventDetailsCode = WebEventCodes.UndefinedEventDetailCode; if (e is ConfigurationException) { eventCode = WebEventCodes.WebErrorConfigurationError; } else if (e is HttpRequestValidationException) { eventCode = WebEventCodes.RuntimeErrorValidationFailure; } else if (e is HttpCompileException) { eventCode = WebEventCodes.WebErrorCompilationError; } else if (e is SecurityException) { eventCode = WebEventCodes.AuditUnhandledSecurityException; } else if (e is UnauthorizedAccessException) { eventCode = WebEventCodes.AuditUnhandledAccessException; } else if (e is HttpParseException) { eventCode = WebEventCodes.WebErrorParserError; } else if (e is HttpException && e.InnerException is ViewStateException) { ViewStateException vse = (ViewStateException)e.InnerException; eventCode = WebEventCodes.AuditInvalidViewStateFailure; if (vse._macValidationError) { eventDetailsCode = WebEventCodes.InvalidViewStateMac; } else { eventDetailsCode = WebEventCodes.InvalidViewState; } eStack = vse; } else if (e is HttpException && ((HttpException)e).WebEventCode != WebEventCodes.UndefinedEventCode) { eventCode = ((HttpException)e).WebEventCode; } else { // We don't know what it is. Let's see if we can find it out by using the inner exception. if (e.InnerException != null) { // We will call FindEventCode recusively to find out if e.InnerException is the real one. if (eStack == null) { // Set eStack here. If the recursive call ends up landing in // WebEventCodes.RuntimeErrorUnhandledException, we'll use the original // inner exception as our final result. eStack = e.InnerException; } FindEventCode(e.InnerException, ref eventCode, ref eventDetailsCode, ref eStack); } else { // It doesn't have an inner exception. Just return the generic unhandled-exception eventCode = WebEventCodes.RuntimeErrorUnhandledException; } } if (eStack == null) { eStack = e; } } static internal void RaiseRuntimeError(Exception e, object source) { Debug.Trace("WebEventRaiseError", "Error Event is raised; type=" + e.GetType().Name); if (!HealthMonitoringManager.Enabled) { return; } try { int eventCode = WebEventCodes.UndefinedEventCode; int eventDetailsCode = WebEventCodes.UndefinedEventDetailCode; HttpContext context = HttpContext.Current; Exception eStack = null; if (context != null) { Page page = context.Handler as Page; // Errors from Transacted pages can be wrapped by a // HttpException if (page != null && page.IsTransacted && e.GetType() == typeof(HttpException) && e.InnerException != null) { e = e.InnerException; } } FindEventCode(e, ref eventCode, ref eventDetailsCode, ref eStack); WebBaseEvent.RaiseSystemEvent(source, eventCode, eventDetailsCode, eStack); } catch { } } virtual internal protected void IncrementPerfCounters() { PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_TOTAL); } class CustomEventCodeOccurrence { internal long _occurrence; } internal void IncrementTotalCounters(int index0, int index1) { _sequenceNumber = Interlocked.Increment(ref s_globalSequenceNumber); if (index0 != -1) { _occurrenceNumber = Interlocked.Increment(ref s_eventCodeOccurrence[index0, index1]); } else { CustomEventCodeOccurrence ceco = (CustomEventCodeOccurrence)s_customEventCodeOccurrence[_code]; if (ceco == null) { s_lockCustomEventCodeOccurrence.AcquireWriterLock(); try { ceco = (CustomEventCodeOccurrence)s_customEventCodeOccurrence[_code]; if (ceco == null) { ceco = new CustomEventCodeOccurrence(); s_customEventCodeOccurrence[_code] = ceco; } } finally { s_lockCustomEventCodeOccurrence.ReleaseWriterLock(); } } _occurrenceNumber = Interlocked.Increment(ref ceco._occurrence); } } [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)] virtual public void Raise() { Raise(this); } // Internally raised events don't go thru this method. They go directly to RaiseSystemEvent --> RaiseInternal [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)] static public void Raise(WebBaseEvent eventRaised) { if (eventRaised.EventCode < WebEventCodes.WebExtendedBase) { throw new HttpException(SR.GetString(SR.System_eventCode_not_allowed, eventRaised.EventCode.ToString(CultureInfo.CurrentCulture), WebEventCodes.WebExtendedBase.ToString(CultureInfo.CurrentCulture))); } if (!HealthMonitoringManager.Enabled) { Debug.Trace( "WebEventRaiseDetails", "Can't fire event because we are disabled or we can't configure HealthMonManager"); return; } RaiseInternal(eventRaised, null, -1, -1); } static internal void RaiseInternal(WebBaseEvent eventRaised, ArrayList firingRuleInfos, int index0, int index1) { bool preProcessEventInitCalled = false; bool inProgressSet = false; object o; ProcessImpersonationContext ictx = null; HttpContext context = HttpContext.Current; Debug.Trace( "WebEventRaiseDetails", "Event is raised; event class = " + eventRaised.GetType().Name); // Use CallContext to make sure we detect an infinite loop where a provider calls Raise(). o = CallContext.GetData(WEBEVENT_RAISE_IN_PROGRESS); if (o != null && (bool)o) { Debug.Trace( "WebEventRaiseDetails", "An event is raised while we're raising an event. Ignore it."); return; } eventRaised.IncrementPerfCounters(); eventRaised.IncrementTotalCounters(index0, index1); // Find the list of rules that match this event if (firingRuleInfos == null) { HealthMonitoringManager manager = HealthMonitoringManager.Manager(); Debug.Assert(manager != null, "manager != null"); firingRuleInfos = manager._sectionHelper.FindFiringRuleInfos(eventRaised.GetType(), eventRaised.EventCode); } if (firingRuleInfos.Count == 0) { return; } try { bool[] matchingProviderArray = null; if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null) EtwTrace.Trace(EtwTraceType.ETW_TYPE_WEB_EVENT_RAISE_START, context.WorkerRequest, eventRaised.GetType().FullName, eventRaised.EventCode.ToString(CultureInfo.InstalledUICulture), eventRaised.EventDetailCode.ToString(CultureInfo.InstalledUICulture), null); try { foreach (HealthMonitoringSectionHelper.FiringRuleInfo firingRuleInfo in firingRuleInfos) { HealthMonitoringSectionHelper.RuleInfo ruleInfo = firingRuleInfo._ruleInfo; RuleFiringRecord record = ruleInfo._ruleFiringRecord; // Check if we should fire the event based on its throttling settings if (!record.CheckAndUpdate(eventRaised)) { Debug.Trace("WebEventRaiseDetails", "Throttling settings not met; not fired"); continue; } // It's valid for a rule to have no referenced provider if (ruleInfo._referencedProvider != null) { if (!preProcessEventInitCalled) { // The event may need to do pre-ProcessEvent initialization eventRaised.PreProcessEventInit(); preProcessEventInitCalled = true; } // For rule infos that share the same provider, the _indexOfFirstRuleInfoWithSameProvider field // is the index of the first ruleInfo among them. We use that index in the boolean array // matchingProviderArray to remember if we've already fired that provider. // This is for the scenario where several rules are pointing to the same provider, // and even if >1 rule actually fire and pass all throttling if (firingRuleInfo._indexOfFirstRuleInfoWithSameProvider != -1) { if (matchingProviderArray == null) { matchingProviderArray = new bool[firingRuleInfos.Count]; } if (matchingProviderArray[firingRuleInfo._indexOfFirstRuleInfoWithSameProvider]) { Debug.Trace("WebEventRaiseDetails", "Rule with a matching provider already fired."); continue; } matchingProviderArray[firingRuleInfo._indexOfFirstRuleInfoWithSameProvider] = true; } if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null) EtwTrace.Trace(EtwTraceType.ETW_TYPE_WEB_EVENT_DELIVER_START, context.WorkerRequest, ruleInfo._ruleSettings.Provider, ruleInfo._ruleSettings.Name, ruleInfo._ruleSettings.EventName, null); // In retail build, ignore errors from provider try { if (ictx == null) { ictx = new ProcessImpersonationContext(); } if (!inProgressSet) { CallContext.SetData(WEBEVENT_RAISE_IN_PROGRESS, true); inProgressSet = true; } Debug.Trace("WebEventRaiseDetails", "Calling ProcessEvent under " + WindowsIdentity.GetCurrent().Name); ruleInfo._referencedProvider.ProcessEvent(eventRaised); } catch (Exception e) { try { ruleInfo._referencedProvider.LogException(e); } catch { // ignore all errors } } finally { if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null) EtwTrace.Trace(EtwTraceType.ETW_TYPE_WEB_EVENT_DELIVER_END, context.WorkerRequest); } } } } finally { // Resume client impersonation if (ictx != null) { ictx.Undo(); } if (inProgressSet) { CallContext.FreeNamedDataSlot(WEBEVENT_RAISE_IN_PROGRESS); } if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null) EtwTrace.Trace(EtwTraceType.ETW_TYPE_WEB_EVENT_RAISE_END, context.WorkerRequest); } } catch { throw; } // Prevent Exception Filter Security Issue (ASURT 122835) } internal static void RaiseSystemEvent(string message, object source, int eventCode, int eventDetailCode, Exception exception) { RaiseSystemEventInternal(message, source, eventCode, eventDetailCode, exception, null); } internal static void RaiseSystemEvent(object source, int eventCode) { RaiseSystemEventInternal(null, source, eventCode, WebEventCodes.UndefinedEventDetailCode, null, null); } internal static void RaiseSystemEvent(object source, int eventCode, int eventDetailCode) { RaiseSystemEventInternal(null, source, eventCode, eventDetailCode, null, null); } internal static void RaiseSystemEvent(object source, int eventCode, int eventDetailCode, Exception exception) { RaiseSystemEventInternal(null, source, eventCode, eventDetailCode, exception, null); } internal static void RaiseSystemEvent(object source, int eventCode, string nameToAuthenticate) { RaiseSystemEventInternal(null, source, eventCode, WebEventCodes.UndefinedEventDetailCode, null, nameToAuthenticate); } static void RaiseSystemEventInternal(string message, object source, int eventCode, int eventDetailCode, Exception exception, string nameToAuthenticate) { HealthMonitoringManager manager; ArrayList firingRuleInfos; SystemEventTypeInfo typeInfo; SystemEventType systemEventType; int index0, index1; Debug.Trace( "WebEventRaiseDetails", "RaiseSystemEventInternal called; eventCode=" + eventCode + "; eventDetailCode=" + eventDetailCode); if (!HealthMonitoringManager.Enabled) { Debug.Trace( "WebEventRaiseDetails", "Can't fire event because we are disabled or we can't configure HealthMonManager"); return; } WebEventCodes.GetEventArrayIndexsFromEventCode(eventCode, out index0, out index1); GetSystemEventTypeInfo(eventCode, index0, index1, out typeInfo, out systemEventType); if (typeInfo == null) { Debug.Assert(false, "Unexpected system event code = " + eventCode); return; } manager = HealthMonitoringManager.Manager(); // Figure out if there is any provider that subscribes to it firingRuleInfos = manager._sectionHelper.FindFiringRuleInfos(typeInfo._type, eventCode); if (firingRuleInfos.Count == 0) { // Even if we're not firing it, we still have to increment some global counters typeInfo._dummyEvent.IncrementPerfCounters(); typeInfo._dummyEvent.IncrementTotalCounters(index0, index1); } else { // We will fire the event WebBaseEvent.RaiseInternal( NewEventFromSystemEventType(false, systemEventType, message, source, eventCode, eventDetailCode, exception, nameToAuthenticate), firingRuleInfos, index0, index1); } } // An enum of all the types of web event we will fire enum SystemEventType { Unknown = -1, WebApplicationLifetimeEvent, WebHeartbeatEvent, WebRequestEvent, WebRequestErrorEvent, WebErrorEvent, WebAuthenticationSuccessAuditEvent, WebSuccessAuditEvent, WebAuthenticationFailureAuditEvent, WebFailureAuditEvent, WebViewStateFailureAuditEvent, Last }; class SystemEventTypeInfo { internal WebBaseEvent _dummyEvent; // For calling IncrementPerfCounters. See RaiseSystemEventInternal for details. internal Type _type; internal SystemEventTypeInfo(WebBaseEvent dummyEvent) { _dummyEvent = dummyEvent; _type = dummyEvent.GetType(); } }; // An array to cache the event type info for each system event type static SystemEventTypeInfo[] s_systemEventTypeInfos = new SystemEventTypeInfo[(int)SystemEventType.Last]; static void GetSystemEventTypeInfo(int eventCode, int index0, int index1, out SystemEventTypeInfo info, out SystemEventType systemEventType) { // Figure out what SystemEventType this eventCode maps to. // For each eventCode, we store the result in a cache. systemEventType = s_eventCodeToSystemEventTypeMappings[index0, index1]; if (systemEventType == SystemEventType.Unknown) { systemEventType = SystemEventTypeFromEventCode(eventCode); s_eventCodeToSystemEventTypeMappings[index0, index1] = systemEventType; } // Based on the systemEventType, we read the SystemEventTypeInfo. For each // event type, we also cache the info info = s_systemEventTypeInfos[(int)systemEventType]; if (info != null) { return; } info = new SystemEventTypeInfo(CreateDummySystemEvent(systemEventType)); s_systemEventTypeInfos[(int)systemEventType] = info; } static SystemEventType SystemEventTypeFromEventCode(int eventCode) { if (eventCode >= WebEventCodes.ApplicationCodeBase && eventCode <= WebEventCodes.ApplicationCodeBaseLast) { switch(eventCode) { case WebEventCodes.ApplicationStart: case WebEventCodes.ApplicationShutdown: case WebEventCodes.ApplicationCompilationStart: case WebEventCodes.ApplicationCompilationEnd: return SystemEventType.WebApplicationLifetimeEvent; case WebEventCodes.ApplicationHeartbeat: return SystemEventType.WebHeartbeatEvent; } } if (eventCode >= WebEventCodes.RequestCodeBase && eventCode <= WebEventCodes.RequestCodeBaseLast) { switch(eventCode) { case WebEventCodes.RequestTransactionComplete: case WebEventCodes.RequestTransactionAbort: return SystemEventType.WebRequestEvent; } } if (eventCode >= WebEventCodes.ErrorCodeBase && eventCode <= WebEventCodes.ErrorCodeBaseLast) { switch(eventCode) { case WebEventCodes.RuntimeErrorRequestAbort: case WebEventCodes.RuntimeErrorViewStateFailure: case WebEventCodes.RuntimeErrorValidationFailure: case WebEventCodes.RuntimeErrorPostTooLarge: case WebEventCodes.RuntimeErrorUnhandledException: return SystemEventType.WebRequestErrorEvent; case WebEventCodes.WebErrorParserError: case WebEventCodes.WebErrorCompilationError: case WebEventCodes.WebErrorConfigurationError: case WebEventCodes.WebErrorOtherError: case WebEventCodes.WebErrorPropertyDeserializationError: case WebEventCodes.WebErrorObjectStateFormatterDeserializationError: return SystemEventType.WebErrorEvent; } } if (eventCode >= WebEventCodes.AuditCodeBase && eventCode <= WebEventCodes.AuditCodeBaseLast) { switch(eventCode) { case WebEventCodes.AuditFormsAuthenticationSuccess: case WebEventCodes.AuditMembershipAuthenticationSuccess: return SystemEventType.WebAuthenticationSuccessAuditEvent; case WebEventCodes.AuditUrlAuthorizationSuccess: case WebEventCodes.AuditFileAuthorizationSuccess: return SystemEventType.WebSuccessAuditEvent; case WebEventCodes.AuditFormsAuthenticationFailure: case WebEventCodes.AuditMembershipAuthenticationFailure: return SystemEventType.WebAuthenticationFailureAuditEvent; case WebEventCodes.AuditUrlAuthorizationFailure: case WebEventCodes.AuditFileAuthorizationFailure: case WebEventCodes.AuditUnhandledSecurityException: case WebEventCodes.AuditUnhandledAccessException: return SystemEventType.WebFailureAuditEvent; case WebEventCodes.AuditInvalidViewStateFailure: return SystemEventType.WebViewStateFailureAuditEvent; } } if (eventCode >= WebEventCodes.MiscCodeBase && eventCode <= WebEventCodes.MiscCodeBaseLast) { switch(eventCode) { case WebEventCodes.WebEventProviderInformation: Debug.Assert(false, "WebEventProviderInformation shouldn't be used to Raise an event"); return SystemEventType.Unknown; } } return SystemEventType.Unknown; } static WebBaseEvent CreateDummySystemEvent(SystemEventType systemEventType) { return NewEventFromSystemEventType(true, systemEventType, null, null, 0, 0, null, null); } static WebBaseEvent NewEventFromSystemEventType(bool createDummy, SystemEventType systemEventType, string message, object source,int eventCode, int eventDetailCode, Exception exception, string nameToAuthenticate) { // If createDummy == true, it means we're only creating a dummy event for the sake of using // it to call IncrementPerfCounters() if (!createDummy && message == null) { message = WebEventCodes.MessageFromEventCode(eventCode, eventDetailCode); } // Code view switch(systemEventType) { case SystemEventType.WebApplicationLifetimeEvent: return createDummy ? new WebApplicationLifetimeEvent() : new WebApplicationLifetimeEvent(message, source, eventCode, eventDetailCode); case SystemEventType.WebHeartbeatEvent: return createDummy ? new WebHeartbeatEvent() : new WebHeartbeatEvent(message, eventCode); case SystemEventType.WebRequestEvent: return createDummy ? new WebRequestEvent() : new WebRequestEvent(message, source, eventCode, eventDetailCode); case SystemEventType. WebRequestErrorEvent: return createDummy ? new WebRequestErrorEvent() : new WebRequestErrorEvent(message, source, eventCode, eventDetailCode, exception); case SystemEventType.WebErrorEvent: return createDummy ? new WebErrorEvent() : new WebErrorEvent(message, source, eventCode, eventDetailCode, exception); case SystemEventType.WebAuthenticationSuccessAuditEvent: return createDummy ? new WebAuthenticationSuccessAuditEvent() : new WebAuthenticationSuccessAuditEvent(message, source, eventCode, eventDetailCode, nameToAuthenticate); case SystemEventType.WebSuccessAuditEvent: return createDummy ? new WebSuccessAuditEvent() : new WebSuccessAuditEvent(message, source, eventCode, eventDetailCode); case SystemEventType.WebAuthenticationFailureAuditEvent: return createDummy ? new WebAuthenticationFailureAuditEvent() : new WebAuthenticationFailureAuditEvent(message, source, eventCode, eventDetailCode, nameToAuthenticate); case SystemEventType.WebFailureAuditEvent: return createDummy ? new WebFailureAuditEvent() : new WebFailureAuditEvent(message, source, eventCode, eventDetailCode); case SystemEventType.WebViewStateFailureAuditEvent: return createDummy ? new WebViewStateFailureAuditEvent() : new WebViewStateFailureAuditEvent(message, source, eventCode, eventDetailCode, (System.Web.UI.ViewStateException)exception); default: Debug.Assert(false, "Unexpected event type = " + systemEventType); return null; } } static string CreateWebEventResourceCacheKey(String key) { return CacheInternal.PrefixWebEventResource + key; } internal static String FormatResourceStringWithCache(String key) { CacheInternal cacheInternal = HttpRuntime.CacheInternal; string s; string cacheKey = CreateWebEventResourceCacheKey(key); s = (string) cacheInternal.Get(cacheKey); if (s != null) { return s; } s = SR.Resources.GetString(key, CultureInfo.InstalledUICulture); if (s != null) { cacheInternal.UtcInsert(cacheKey, s); } return s; } internal static String FormatResourceStringWithCache(String key, String arg0) { string fmt = FormatResourceStringWithCache(key); return(fmt != null) ? String.Format(fmt, arg0) : null; } internal static WebEventType WebEventTypeFromWebEvent(WebBaseEvent eventRaised) { // Note: // eventRaised can belong to one of the following classes, or can inherit from one of them. // In order to figure out precisely the WebEventType closest to the type of eventRaised, // we will start our comparison from the leaf nodes in the class hierarchy and work our // way up. // Webevent class hierarchy (with the info contained in each class): /* - WebBaseEvent (basic) - WebManagementEvent (+ WebProcessInformation) - WebHeartbeatEvent (+ WebProcessStatistics) - WebApplicationLifetimeEvent - WebRequestEvent (+ WebRequestInformation) - WebBaseErrorEvent (+ Exception) - WebRequestErrorEvent (+ WebRequestInformation + WebThreadInformation) - WebErrorEvent (+ WebRequestInformation + WebThreadInformation) - WebAuditEvent (+ WebRequestInformation) - WebSuccessAuditEvent - WebAuthenticationSuccessAuditEvent (+ NameToAuthenticate) - WebFailureAuditEvent - WebAuthenticationFailureAuditEvent (+ NameToAuthenticate) - WebViewStateFailureAuditEvent (+ ViewStateException) */ // Hierarchy level 5 if (eventRaised is WebAuthenticationSuccessAuditEvent) { return WebEventType.WEBEVENT_AUTHENTICATION_SUCCESS_AUDIT_EVENT; } if (eventRaised is WebAuthenticationFailureAuditEvent) { return WebEventType.WEBEVENT_AUTHENTICATION_FAILURE_AUDIT_EVENT; } if (eventRaised is WebViewStateFailureAuditEvent) { return WebEventType.WEBEVENT_VIEWSTATE_FAILURE_AUDIT_EVENT; } // Hierarchy level 4 if (eventRaised is WebRequestErrorEvent) { return WebEventType.WEBEVENT_REQUEST_ERROR_EVENT; } if (eventRaised is WebErrorEvent) { return WebEventType.WEBEVENT_ERROR_EVENT; } if (eventRaised is WebSuccessAuditEvent) { return WebEventType.WEBEVENT_SUCCESS_AUDIT_EVENT; } if (eventRaised is WebFailureAuditEvent) { return WebEventType.WEBEVENT_FAILURE_AUDIT_EVENT; } // Hierarchy level 3 if (eventRaised is WebHeartbeatEvent) { return WebEventType.WEBEVENT_HEARTBEAT_EVENT; } if (eventRaised is WebApplicationLifetimeEvent) { return WebEventType.WEBEVENT_APP_LIFETIME_EVENT; } if (eventRaised is WebRequestEvent) { return WebEventType.WEBEVENT_REQUEST_EVENT; } if (eventRaised is WebBaseErrorEvent) { return WebEventType.WEBEVENT_BASE_ERROR_EVENT; } if (eventRaised is WebAuditEvent) { return WebEventType.WEBEVENT_AUDIT_EVENT; } // Hierarchy level 2 if (eventRaised is WebManagementEvent) { return WebEventType.WEBEVENT_MANAGEMENT_EVENT; } // Hierarchy level 1 return WebEventType.WEBEVENT_BASE_EVENT; } static internal void RaisePropertyDeserializationWebErrorEvent(SettingsProperty property, object source, Exception exception) { if (HttpContext.Current == null) { return; } WebBaseEvent.RaiseSystemEvent( SR.GetString(SR.Webevent_msg_Property_Deserialization, property.Name, property.SerializeAs.ToString(), property.PropertyType.AssemblyQualifiedName ), source, WebEventCodes.WebErrorPropertyDeserializationError, WebEventCodes.UndefinedEventDetailCode, exception); } } [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebEventFormatter { int _level; StringBuilder _sb; int _tabSize; void AddTab() { int level = _level; while (level > 0) { _sb.Append(' ', _tabSize); level--; } } internal WebEventFormatter() { _level = 0; _sb = new StringBuilder(); _tabSize = 4; } public void AppendLine(string s) { AddTab(); _sb.Append(s); _sb.Append('\n'); } new public string ToString() { return _sb.ToString(); } public int IndentationLevel { get { return _level; } set { _level = Math.Max(value, 0); } } public int TabSize { get { return _tabSize; } set { _tabSize = Math.Max(value, 0); } } } // This class is a base class for all events that require application and process information. // // WebManagementEvent is the base class for all our webevent classes (except for WebBaseEvent) // Please [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)] [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebManagementEvent : WebBaseEvent { static WebProcessInformation s_processInfo = new WebProcessInformation(); internal protected WebManagementEvent(string message, object eventSource, int eventCode) :base(message, eventSource, eventCode) { } internal protected WebManagementEvent(string message, object eventSource, int eventCode, int eventDetailCode) :base(message, eventSource, eventCode, eventDetailCode) { } internal WebManagementEvent() { // For creating dummy event. See GetSystemDummyEvent() } // properties public WebProcessInformation ProcessInformation { get { return s_processInfo; } } internal override void GenerateFieldsForMarshal(List fields) { base.GenerateFieldsForMarshal(fields); fields.Add(new WebEventFieldData("AccountName", ProcessInformation.AccountName, WebEventFieldType.String)); fields.Add(new WebEventFieldData("ProcessName", ProcessInformation.ProcessName, WebEventFieldType.String)); fields.Add(new WebEventFieldData("ProcessID", ProcessInformation.ProcessID.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int)); } override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_information)); formatter.IndentationLevel += 1; ProcessInformation.FormatToString(formatter); formatter.IndentationLevel -= 1; } } // This event is raised at periodic intervals (default 30 seconds) and provides information // relative to the state of the running appdomin. [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebHeartbeatEvent : WebManagementEvent { static WebProcessStatistics s_procStats = new WebProcessStatistics(); internal protected WebHeartbeatEvent(string message, int eventCode) :base(message, null, eventCode) { } internal WebHeartbeatEvent() { // For creating dummy event. See GetSystemDummyEvent() } public WebProcessStatistics ProcessStatistics {get {return s_procStats;}} override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_statistics)); formatter.IndentationLevel += 1; s_procStats.FormatToString(formatter); formatter.IndentationLevel -= 1; } } // This event represents a notable event in the lifetime of an application (app domain) // including startup and shutdown events. When an app domain is terminated, the reason // will be expressed in the Message field (e.g. compilation threshold exceed, Shutdown // called explicitly, etc.). [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebApplicationLifetimeEvent : WebManagementEvent { internal protected WebApplicationLifetimeEvent(string message, object eventSource, int eventCode) :base(message, eventSource, eventCode) { } internal protected WebApplicationLifetimeEvent(string message, object eventSource, int eventCode, int eventDetailCode) :base(message, eventSource, eventCode, eventDetailCode) { } internal WebApplicationLifetimeEvent() { // For creating dummy event. See GetSystemDummyEvent() } static internal int DetailCodeFromShutdownReason(ApplicationShutdownReason reason) { switch (reason) { case ApplicationShutdownReason.HostingEnvironment: return WebEventCodes.ApplicationShutdownHostingEnvironment; case ApplicationShutdownReason.ChangeInGlobalAsax: return WebEventCodes.ApplicationShutdownChangeInGlobalAsax; case ApplicationShutdownReason.ConfigurationChange: return WebEventCodes.ApplicationShutdownConfigurationChange; case ApplicationShutdownReason.UnloadAppDomainCalled: return WebEventCodes.ApplicationShutdownUnloadAppDomainCalled; case ApplicationShutdownReason.ChangeInSecurityPolicyFile: return WebEventCodes.ApplicationShutdownChangeInSecurityPolicyFile; case ApplicationShutdownReason.BinDirChangeOrDirectoryRename: return WebEventCodes.ApplicationShutdownBinDirChangeOrDirectoryRename; case ApplicationShutdownReason.BrowsersDirChangeOrDirectoryRename: return WebEventCodes.ApplicationShutdownBrowsersDirChangeOrDirectoryRename; case ApplicationShutdownReason.CodeDirChangeOrDirectoryRename: return WebEventCodes.ApplicationShutdownCodeDirChangeOrDirectoryRename; case ApplicationShutdownReason.ResourcesDirChangeOrDirectoryRename: return WebEventCodes.ApplicationShutdownResourcesDirChangeOrDirectoryRename; case ApplicationShutdownReason.IdleTimeout: return WebEventCodes.ApplicationShutdownIdleTimeout; case ApplicationShutdownReason.PhysicalApplicationPathChanged: return WebEventCodes.ApplicationShutdownPhysicalApplicationPathChanged; case ApplicationShutdownReason.HttpRuntimeClose: return WebEventCodes.ApplicationShutdownHttpRuntimeClose; case ApplicationShutdownReason.InitializationError: return WebEventCodes.ApplicationShutdownInitializationError; case ApplicationShutdownReason.MaxRecompilationsReached: return WebEventCodes.ApplicationShutdownMaxRecompilationsReached; case ApplicationShutdownReason.BuildManagerChange: return WebEventCodes.ApplicationShutdownBuildManagerChange; default: return WebEventCodes.ApplicationShutdownUnknown; } } override internal protected void IncrementPerfCounters() { base.IncrementPerfCounters(); PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_APP); } } // This class serves as a base for non-error events that provide [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebRequestEvent : WebManagementEvent { WebRequestInformation _requestInfo; override internal void PreProcessEventInit() { base.PreProcessEventInit(); InitRequestInformation(); } internal protected WebRequestEvent(string message, object eventSource, int eventCode) :base(message, eventSource, eventCode) { } internal protected WebRequestEvent(string message, object eventSource, int eventCode, int eventDetailCode) :base(message, eventSource, eventCode, eventDetailCode) { } internal WebRequestEvent() { // For creating dummy event. See GetSystemDummyEvent() } void InitRequestInformation() { if (_requestInfo == null) { _requestInfo = new WebRequestInformation(); } } public WebRequestInformation RequestInformation { get { InitRequestInformation(); return _requestInfo; } } internal override void GenerateFieldsForMarshal(List fields) { base.GenerateFieldsForMarshal(fields); fields.Add(new WebEventFieldData("RequestUrl", RequestInformation.RequestUrl, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RequestPath", RequestInformation.RequestPath, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserHostAddress", RequestInformation.UserHostAddress, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserName", RequestInformation.Principal.Identity.Name, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserAuthenticated", RequestInformation.Principal.Identity.IsAuthenticated.ToString(), WebEventFieldType.Bool)); fields.Add(new WebEventFieldData("UserAuthenticationType", RequestInformation.Principal.Identity.AuthenticationType, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RequestThreadAccountName", RequestInformation.ThreadAccountName, WebEventFieldType.String)); } override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information)); formatter.IndentationLevel += 1; RequestInformation.FormatToString(formatter); formatter.IndentationLevel -= 1; } override internal protected void IncrementPerfCounters() { base.IncrementPerfCounters(); PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_WEB_REQ); } } // This is the base class for all error events. [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebBaseErrorEvent : WebManagementEvent { Exception _exception; void Init(Exception e) { _exception = e; } internal protected WebBaseErrorEvent(string message, object eventSource, int eventCode, Exception e) :base(message, eventSource, eventCode) { Init(e); } internal protected WebBaseErrorEvent(string message, object eventSource, int eventCode, int eventDetailCode, Exception e) :base(message, eventSource, eventCode, eventDetailCode) { Init(e); } internal WebBaseErrorEvent() { // For creating dummy event. See GetSystemDummyEvent() } public Exception ErrorException { get { return _exception; } } override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); if (_exception == null) { return; } Exception ex = _exception; // Please for (int level = 0; ex != null && level <= 2; ex = ex.InnerException, level++) { formatter.AppendLine(String.Empty); if (level == 0) { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_exception_information)); } else { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_inner_exception_information, level.ToString(CultureInfo.InstalledUICulture))); } formatter.IndentationLevel += 1; formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_exception_type, ex.GetType().ToString())); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_exception_message, ex.Message)); formatter.IndentationLevel -= 1; } } internal override void GenerateFieldsForMarshal(List fields) { base.GenerateFieldsForMarshal(fields); fields.Add(new WebEventFieldData("ExceptionType", ErrorException.GetType().ToString(), WebEventFieldType.String)); fields.Add(new WebEventFieldData("ExceptionMessage", ErrorException.Message, WebEventFieldType.String)); } override internal protected void IncrementPerfCounters() { base.IncrementPerfCounters(); PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_ERROR); PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_EVENTS_ERROR); } } // This class contains information about systemic errors, e.g. things related to // configuration or application code (parser errors, compilation errors). [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebErrorEvent : WebBaseErrorEvent { WebRequestInformation _requestInfo; WebThreadInformation _threadInfo; void Init(Exception e) { } override internal void PreProcessEventInit() { base.PreProcessEventInit(); InitRequestInformation(); InitThreadInformation(); } internal protected WebErrorEvent(string message, object eventSource, int eventCode, Exception exception) :base(message, eventSource, eventCode, exception) { Init(exception); } internal protected WebErrorEvent(string message, object eventSource, int eventCode, int eventDetailCode, Exception exception) :base(message, eventSource, eventCode, eventDetailCode, exception) { Init(exception); } internal WebErrorEvent() { // For creating dummy event. See GetSystemDummyEvent() } void InitRequestInformation() { if (_requestInfo == null) { _requestInfo = new WebRequestInformation(); } } public WebRequestInformation RequestInformation { get { InitRequestInformation(); return _requestInfo; } } void InitThreadInformation() { if (_threadInfo == null) { _threadInfo = new WebThreadInformation(base.ErrorException); } } public WebThreadInformation ThreadInformation { get { InitThreadInformation(); return _threadInfo; } } override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information)); formatter.IndentationLevel += 1; RequestInformation.FormatToString(formatter); formatter.IndentationLevel -= 1; formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_information)); formatter.IndentationLevel += 1; ThreadInformation.FormatToString(formatter); formatter.IndentationLevel -= 1; } internal override void GenerateFieldsForMarshal(List fields) { base.GenerateFieldsForMarshal(fields); fields.Add(new WebEventFieldData("RequestUrl", RequestInformation.RequestUrl, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RequestPath", RequestInformation.RequestPath, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserHostAddress", RequestInformation.UserHostAddress, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserName", RequestInformation.Principal.Identity.Name, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserAuthenticated", RequestInformation.Principal.Identity.IsAuthenticated.ToString(), WebEventFieldType.Bool)); fields.Add(new WebEventFieldData("UserAuthenticationType", RequestInformation.Principal.Identity.AuthenticationType, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RequestThreadAccountName", RequestInformation.ThreadAccountName, WebEventFieldType.String)); fields.Add(new WebEventFieldData("ThreadID", ThreadInformation.ThreadID.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int)); fields.Add(new WebEventFieldData("ThreadAccountName", ThreadInformation.ThreadAccountName, WebEventFieldType.String)); fields.Add(new WebEventFieldData("StackTrace", ThreadInformation.StackTrace, WebEventFieldType.String)); fields.Add(new WebEventFieldData("IsImpersonating", ThreadInformation.IsImpersonating.ToString(), WebEventFieldType.Bool)); } override internal protected void IncrementPerfCounters() { base.IncrementPerfCounters(); PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_HTTP_INFRA_ERROR); PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_EVENTS_HTTP_INFRA_ERROR); } } // This class provides information about errors that occur while servicing a request. // This include unhandled exceptions, viewstate errors, input validation errors, etc. [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebRequestErrorEvent : WebBaseErrorEvent { WebRequestInformation _requestInfo; WebThreadInformation _threadInfo; void Init(Exception e) { } override internal void PreProcessEventInit() { base.PreProcessEventInit(); InitRequestInformation(); InitThreadInformation(); } internal protected WebRequestErrorEvent(string message, object eventSource, int eventCode, Exception exception) :base(message, eventSource, eventCode, exception) { Init(exception); } internal protected WebRequestErrorEvent(string message, object eventSource, int eventCode, int eventDetailCode, Exception exception) :base(message, eventSource, eventCode, eventDetailCode, exception) { Init(exception); } internal WebRequestErrorEvent() { // For creating dummy event. See GetSystemDummyEvent() } // properties void InitRequestInformation() { if (_requestInfo == null) { _requestInfo = new WebRequestInformation(); } } public WebRequestInformation RequestInformation { get { InitRequestInformation(); return _requestInfo; } } void InitThreadInformation() { if (_threadInfo == null) { _threadInfo = new WebThreadInformation(base.ErrorException); } } public WebThreadInformation ThreadInformation { get { InitThreadInformation(); return _threadInfo; } } override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information)); formatter.IndentationLevel += 1; RequestInformation.FormatToString(formatter); formatter.IndentationLevel -= 1; formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_information)); formatter.IndentationLevel += 1; ThreadInformation.FormatToString(formatter); formatter.IndentationLevel -= 1; } internal override void GenerateFieldsForMarshal(List fields) { base.GenerateFieldsForMarshal(fields); fields.Add(new WebEventFieldData("RequestUrl", RequestInformation.RequestUrl, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RequestPath", RequestInformation.RequestPath, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserHostAddress", RequestInformation.UserHostAddress, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserName", RequestInformation.Principal.Identity.Name, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserAuthenticated", RequestInformation.Principal.Identity.IsAuthenticated.ToString(), WebEventFieldType.Bool)); fields.Add(new WebEventFieldData("UserAuthenticationType", RequestInformation.Principal.Identity.AuthenticationType, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RequestThreadAccountName", RequestInformation.ThreadAccountName, WebEventFieldType.String)); fields.Add(new WebEventFieldData("ThreadID", ThreadInformation.ThreadID.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int)); fields.Add(new WebEventFieldData("ThreadAccountName", ThreadInformation.ThreadAccountName, WebEventFieldType.String)); fields.Add(new WebEventFieldData("StackTrace", ThreadInformation.StackTrace, WebEventFieldType.String)); fields.Add(new WebEventFieldData("IsImpersonating", ThreadInformation.IsImpersonating.ToString(), WebEventFieldType.Bool)); } override internal protected void IncrementPerfCounters() { base.IncrementPerfCounters(); PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_HTTP_REQ_ERROR); PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_EVENTS_HTTP_REQ_ERROR); } } // The base class for all audit events. [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebAuditEvent : WebManagementEvent { WebRequestInformation _requestInfo; override internal void PreProcessEventInit() { base.PreProcessEventInit(); InitRequestInformation(); } internal protected WebAuditEvent(string message, object eventSource, int eventCode) :base(message, eventSource, eventCode) { } internal protected WebAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode) :base(message, eventSource, eventCode, eventDetailCode) { } internal WebAuditEvent() { // For creating dummy event. See GetSystemDummyEvent() } void InitRequestInformation() { if (_requestInfo == null) { _requestInfo = new WebRequestInformation(); } } public WebRequestInformation RequestInformation { get { InitRequestInformation(); return _requestInfo; } } internal override void GenerateFieldsForMarshal(List fields) { base.GenerateFieldsForMarshal(fields); fields.Add(new WebEventFieldData("RequestUrl", RequestInformation.RequestUrl, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RequestPath", RequestInformation.RequestPath, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserHostAddress", RequestInformation.UserHostAddress, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserName", RequestInformation.Principal.Identity.Name, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserAuthenticated", RequestInformation.Principal.Identity.IsAuthenticated.ToString(), WebEventFieldType.Bool)); fields.Add(new WebEventFieldData("UserAuthenticationType", RequestInformation.Principal.Identity.AuthenticationType, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RequestThreadAccountName", RequestInformation.ThreadAccountName, WebEventFieldType.String)); } override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information)); formatter.IndentationLevel += 1; RequestInformation.FormatToString(formatter); formatter.IndentationLevel -= 1; } } // This class provides information about all failure audits. In most cases, // applications will only want to enable failure audits. [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebFailureAuditEvent : WebAuditEvent { internal protected WebFailureAuditEvent(string message, object eventSource, int eventCode) :base(message, eventSource, eventCode) { } internal protected WebFailureAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode) :base(message, eventSource, eventCode, eventDetailCode) { } internal WebFailureAuditEvent() { // For creating dummy event. See GetSystemDummyEvent() } override internal protected void IncrementPerfCounters() { base.IncrementPerfCounters(); PerfCounters.IncrementCounter(AppPerfCounter.AUDIT_FAIL); PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_AUDIT_FAIL); } } [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebAuthenticationFailureAuditEvent : WebFailureAuditEvent { string _nameToAuthenticate; void Init(string name) { _nameToAuthenticate = name; } internal protected WebAuthenticationFailureAuditEvent(string message, object eventSource, int eventCode, string nameToAuthenticate) :base(message, eventSource, eventCode) { Init(nameToAuthenticate); } internal protected WebAuthenticationFailureAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode, string nameToAuthenticate) :base(message, eventSource, eventCode, eventDetailCode) { Init(nameToAuthenticate); } internal WebAuthenticationFailureAuditEvent() { // For creating dummy event. See GetSystemDummyEvent() } public string NameToAuthenticate { get { return _nameToAuthenticate; } } internal override void GenerateFieldsForMarshal(List fields) { base.GenerateFieldsForMarshal(fields); fields.Add(new WebEventFieldData("NameToAuthenticate", NameToAuthenticate, WebEventFieldType.String)); } override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_name_to_authenticate, _nameToAuthenticate)); } } [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebViewStateFailureAuditEvent : WebFailureAuditEvent { ViewStateException _viewStateException; internal protected WebViewStateFailureAuditEvent(string message, object eventSource, int eventCode, ViewStateException viewStateException) :base(message, eventSource, eventCode) { _viewStateException = viewStateException; } internal protected WebViewStateFailureAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode, ViewStateException viewStateException) :base(message, eventSource, eventCode, eventDetailCode) { _viewStateException = viewStateException; } internal WebViewStateFailureAuditEvent() { // For creating dummy event. See GetSystemDummyEvent() } public ViewStateException ViewStateException { get { return _viewStateException; } } internal override void GenerateFieldsForMarshal(List fields) { base.GenerateFieldsForMarshal(fields); fields.Add(new WebEventFieldData("ViewStateExceptionMessage", ViewStateException.Message, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RemoteAddress", ViewStateException.RemoteAddress, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RemotePort", ViewStateException.RemotePort, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserAgent", ViewStateException.UserAgent, WebEventFieldType.String)); fields.Add(new WebEventFieldData("PersistedState", ViewStateException.PersistedState, WebEventFieldType.String)); fields.Add(new WebEventFieldData("Path", ViewStateException.Path, WebEventFieldType.String)); fields.Add(new WebEventFieldData("Referer", ViewStateException.Referer, WebEventFieldType.String)); } override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_ViewStateException_information)); formatter.IndentationLevel += 1; formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_exception_message, _viewStateException.Message)); formatter.IndentationLevel -= 1; } } // This class provides information about all success audits. In most cases, // applications will only want to enable failure audits. [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebSuccessAuditEvent : WebAuditEvent { internal protected WebSuccessAuditEvent(string message, object eventSource, int eventCode) :base(message, eventSource, eventCode) { } internal protected WebSuccessAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode) :base(message, eventSource, eventCode, eventDetailCode) { } internal WebSuccessAuditEvent() { // For creating dummy event. See GetSystemDummyEvent() } override internal protected void IncrementPerfCounters() { base.IncrementPerfCounters(); PerfCounters.IncrementCounter(AppPerfCounter.AUDIT_SUCCESS); PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_AUDIT_SUCCESS); } } [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebAuthenticationSuccessAuditEvent : WebSuccessAuditEvent { string _nameToAuthenticate; void Init(string name) { _nameToAuthenticate = name; } internal protected WebAuthenticationSuccessAuditEvent(string message, object eventSource, int eventCode, string nameToAuthenticate) :base(message, eventSource, eventCode) { Init(nameToAuthenticate); } internal protected WebAuthenticationSuccessAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode, string nameToAuthenticate) :base(message, eventSource, eventCode, eventDetailCode) { Init(nameToAuthenticate); } internal WebAuthenticationSuccessAuditEvent() { // For creating dummy event. See GetSystemDummyEvent() } public string NameToAuthenticate { get { return _nameToAuthenticate; } } internal override void GenerateFieldsForMarshal(List fields) { base.GenerateFieldsForMarshal(fields); fields.Add(new WebEventFieldData("NameToAuthenticate", NameToAuthenticate, WebEventFieldType.String)); } override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_name_to_authenticate, _nameToAuthenticate)); } } //////////////// // Information //////////////// [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] public sealed class WebProcessInformation { // The information is per worker process instance. int _processId; string _processName; string _accountName; internal WebProcessInformation() { // Can't use Process.ProcessName because it requires the running // account to be part of the Performance Monitor Users group. StringBuilder buf = new StringBuilder(256); if (UnsafeNativeMethods.GetModuleFileName(IntPtr.Zero, buf, 256) == 0) { _processName = String.Empty; } else { int lastIndex; _processName = buf.ToString(); lastIndex = _processName.LastIndexOf('\\'); if (lastIndex != -1) { _processName = _processName.Substring(lastIndex + 1); } } _processId = SafeNativeMethods.GetCurrentProcessId() ; _accountName = HttpRuntime.WpUserId; } public int ProcessID { get { return _processId; } } public string ProcessName { get { return _processName; } } public string AccountName { get { return (_accountName != null ? _accountName : String.Empty); } } public void FormatToString(WebEventFormatter formatter) { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_id, ProcessID.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_name, ProcessName)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_account_name, AccountName)); } } [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] public sealed class WebApplicationInformation { // The information is per appdomain. string _appDomain; string _trustLevel; string _appUrl; string _appPath; string _machineName; internal WebApplicationInformation() { _appDomain = Thread.GetDomain().FriendlyName; _trustLevel = HttpRuntime.TrustLevel; _appUrl = HttpRuntime.AppDomainAppVirtualPath; try { // We will get an exception if it's a non-ASP.NET app. _appPath = HttpRuntime.AppDomainAppPath; } catch { _appPath = null; } #if FEATURE_PAL // FEATURE_PAL does not fully implement Environment.MachineName _machineName = "dummymachinename"; #else // FEATURE_PAL _machineName = GetMachineNameWithAssert(); #endif // FEATURE_PAL } public string ApplicationDomain { get { return _appDomain; } } public string TrustLevel { get { return _trustLevel; } } public string ApplicationVirtualPath { get { return _appUrl; } } public string ApplicationPath { get { return _appPath; } } public string MachineName { get { return _machineName; } } public void FormatToString(WebEventFormatter formatter) { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_domain, ApplicationDomain)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_trust_level, TrustLevel)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_virtual_path, ApplicationVirtualPath)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_path, ApplicationPath)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_machine_name, MachineName)); } [PermissionSet(SecurityAction.Assert, Unrestricted = true)] private string GetMachineNameWithAssert() { return Environment.MachineName; } public override string ToString() { WebEventFormatter formatter = new WebEventFormatter(); FormatToString(formatter); return formatter.ToString(); } } [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] public sealed class WebRequestInformation { string _requestUrl; string _requestPath; IPrincipal _iprincipal; string _userHostAddress = null; string _accountName; internal WebRequestInformation() { // Need to Assert() in order to get request information regardless of trust level. See InternalSecurityPermissions.ControlPrincipal.Assert(); HttpContext context = HttpContext.Current; if (context == null) { _requestUrl = String.Empty; _requestPath = String.Empty; _iprincipal = null; _userHostAddress = String.Empty; } else { HttpRequest request = context.Request; _requestUrl = request.UrlInternal; _requestPath = request.Path; _iprincipal = context.User; _userHostAddress = request.UserHostAddress; } _accountName = WindowsIdentity.GetCurrent().Name; } // The information is per request. public string RequestUrl {get {return _requestUrl;}} public string RequestPath {get {return _requestPath;}} public IPrincipal Principal {get {return _iprincipal;}} public string UserHostAddress { get { return _userHostAddress;} } public string ThreadAccountName {get {return _accountName;}} public void FormatToString(WebEventFormatter formatter) { string user; string authType; bool authed; if (Principal == null) { user = String.Empty; authType = String.Empty; authed = false; } else { IIdentity id = Principal.Identity; user = id.Name; authed = id.IsAuthenticated; authType = id.AuthenticationType; } formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_url, RequestUrl)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_path, RequestPath)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_user_host_address, UserHostAddress)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_user, user)); if (authed) { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_authenticated)); } else { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_not_authenticated)); } formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_authentication_type, authType)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_account_name, ThreadAccountName)); } } // Note that even all the information contained in WebProcessStatistics is obtained from static variables, // but we still don't want this class to be static. // // Currently, WebProcessStatistics can be obtained only thru WebHeartbeatEvent, which in turn can be // created only by Full-trust app thru class inheritance. (System.Web.dll will also internally create it // and the object will be available to our provider.) Thus, WebProcessStatistics is available only // to Full-trust app or provider. // // But if we make WebProcessStatistics static, then all its public methods have to be static, and // they'll be fully available to all users. No good. [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebProcessStatistics { static DateTime s_startTime = DateTime.MinValue; static DateTime s_lastUpdated = DateTime.MinValue; static int s_threadCount; static long s_workingSet; static long s_peakWorkingSet; static long s_managedHeapSize; static int s_appdomainCount; static int s_requestsExecuting; static int s_requestsQueued; static int s_requestsRejected; static bool s_getCurrentProcFailed = false; static object s_lockObject = new object(); static TimeSpan TS_ONE_SECOND = new TimeSpan(0, 0, 1); static WebProcessStatistics() { try { #if !FEATURE_PAL // FEATURE_PAL does not support this. Make into a noop. s_startTime = Process.GetCurrentProcess().StartTime; #endif // !FEATURE_PAL } catch { s_getCurrentProcFailed = true; } } void Update() { DateTime now = DateTime.Now; if (now - s_lastUpdated < TS_ONE_SECOND) { return; } lock (s_lockObject) { if (now - s_lastUpdated < TS_ONE_SECOND) { return; } if (!s_getCurrentProcFailed) { Process process = Process.GetCurrentProcess(); #if !FEATURE_PAL // FEATURE_PAL does not support these Process properties s_threadCount = process.Threads.Count; s_workingSet = (long)process.WorkingSet64; s_peakWorkingSet = (long)process.PeakWorkingSet64; #else throw new NotImplementedException ("ROTORTODO"); #endif } s_managedHeapSize = GC.GetTotalMemory(false); s_appdomainCount = HostingEnvironment.AppDomainsCount; s_requestsExecuting = PerfCounters.GetGlobalCounter(GlobalPerfCounter.REQUESTS_CURRENT); s_requestsQueued = PerfCounters.GetGlobalCounter(GlobalPerfCounter.REQUESTS_QUEUED); s_requestsRejected = PerfCounters.GetGlobalCounter(GlobalPerfCounter.REQUESTS_REJECTED); s_lastUpdated = now; } } public DateTime ProcessStartTime {get {Update(); return s_startTime;}} public int ThreadCount {get {Update(); return s_threadCount;}} public long WorkingSet {get {Update(); return s_workingSet;}} public long PeakWorkingSet {get {Update(); return s_peakWorkingSet;}} public long ManagedHeapSize {get {Update(); return s_managedHeapSize;}} public int AppDomainCount {get {Update(); return s_appdomainCount;}} public int RequestsExecuting {get {Update(); return s_requestsExecuting;}} public int RequestsQueued {get {Update(); return s_requestsQueued;}} public int RequestsRejected {get {Update(); return s_requestsRejected;}} virtual public void FormatToString(WebEventFormatter formatter) { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_start_time, ProcessStartTime.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_count, ThreadCount.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_working_set, WorkingSet.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_peak_working_set, PeakWorkingSet.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_managed_heap_size, ManagedHeapSize.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_domain_count, AppDomainCount.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_requests_executing, RequestsExecuting.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_queued, RequestsQueued.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_rejected, RequestsRejected.ToString(CultureInfo.InstalledUICulture))); } } [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] public sealed class WebThreadInformation { int _threadId; string _accountName; string _stackTrace; bool _isImpersonating; internal const string IsImpersonatingKey = "AS----ERSONATING"; internal WebThreadInformation(Exception exception) { _threadId = Thread.CurrentThread.ManagedThreadId; _accountName = WindowsIdentity.GetCurrent().Name; if (exception != null) { _stackTrace = new StackTrace(exception, true).ToString(); } else { _stackTrace = String.Empty; } _isImpersonating = exception.Data.Contains(IsImpersonatingKey); } public int ThreadID {get {return _threadId;}} public string ThreadAccountName {get {return _accountName;}} public string StackTrace {get {return _stackTrace;}} public bool IsImpersonating {get {return _isImpersonating;}} public void FormatToString(WebEventFormatter formatter) { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_id, ThreadID.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_account_name, ThreadAccountName)); if (IsImpersonating) { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_impersonating)); } else { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_not_impersonating)); } formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_stack_trace, StackTrace)); } } // Class that represents the firing record (how many times, last firing time, etc) // for each rule that inherits from WebBaseEvent. [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] public sealed class RuleFiringRecord { internal DateTime _lastFired; internal int _timesRaised; internal int _updatingLastFired; static TimeSpan TS_ONE_SECOND = new TimeSpan(0, 0, 1); public DateTime LastFired { get { return _lastFired; } } public int TimesRaised { get { return _timesRaised; } } // Point to the ruleInfo that is used by this class internal HealthMonitoringSectionHelper.RuleInfo _ruleInfo; internal RuleFiringRecord(HealthMonitoringSectionHelper.RuleInfo ruleInfo) { Debug.Assert(ruleInfo != null, "ruleInfo != null"); _ruleInfo = ruleInfo; _lastFired = DateTime.MinValue; _timesRaised = 0; _updatingLastFired = 0; } void UpdateLastFired(DateTime now, bool alreadyLocked) { TimeSpan tsDiff = now - _lastFired; if (tsDiff < TS_ONE_SECOND) { // If _lastFired was updated within one second, don't bother. return; } if (!alreadyLocked) { // If several threads are firing at the same time, only one thread will // update record._lastFired. if (Interlocked.CompareExchange(ref _updatingLastFired, 1, 0) == 0) { try { _lastFired = now; } finally { Interlocked.Exchange(ref _updatingLastFired, 0); } } } else { _lastFired = now; } } // Note: this method is thread safe internal bool CheckAndUpdate(WebBaseEvent eventRaised) { DateTime now = DateTime.Now; int timesRaised; HealthMonitoringManager manager = HealthMonitoringManager.Manager(); timesRaised = Interlocked.Increment(ref _timesRaised); if (manager == null) { // Won't fire because we cannot configure healthmonitor Debug.Trace("RuleFiringRecord", "Can't configure healthmonitor"); return false; } // Call custom evaluator first if (_ruleInfo._customEvaluatorType != null) { IWebEventCustomEvaluator icustom = (IWebEventCustomEvaluator) manager._sectionHelper._customEvaluatorInstances[_ruleInfo._customEvaluatorType]; #if (!DBG) try { #endif // The event may need to do pre-ProcessEvent initialization eventRaised.PreProcessEventInit(); if (!icustom.CanFire(eventRaised, this)) { Debug.Trace("RuleFiringRecord", "Custom evaluator returns false."); return false; } #if (!DBG) } catch { Debug.Trace("RuleFiringRecord", "Hit an exception when calling Custom evaluator"); // Return if we hit an error return false; } #endif } if (timesRaised < _ruleInfo._minInstances) { Debug.Trace("RuleFiringRecord", "MinInterval not met; timesRaised=" + timesRaised + "; _minInstances=" + _ruleInfo._minInstances); return false; } if (timesRaised > _ruleInfo._maxLimit) { Debug.Trace("RuleFiringRecord", "MaxLimit exceeded; timesRaised=" + timesRaised + "; _maxLimit=" + _ruleInfo._maxLimit); return false; } // Last step: Check MinInterval and update _lastFired if (_ruleInfo._minInterval == TimeSpan.Zero) { UpdateLastFired(now, false); return true; } if ((now - _lastFired) <= _ruleInfo._minInterval) { Debug.Trace("RuleFiringRecord", "MinInterval not met; now=" + now + "; _lastFired=" + _lastFired + "; _ruleInfo._minInterval=" + _ruleInfo._minInterval); return false; } // The lock is to prevent multiple threads from passign the // same test simultaneously. lock (this) { if ((now - _lastFired) <= _ruleInfo._minInterval) { Debug.Trace("RuleFiringRecord", "MinInterval not met; now=" + now + "; _lastFired=" + _lastFired + "; _ruleInfo._tsMinInterval=" + _ruleInfo._minInterval); return false; } UpdateLastFired(now, true); return true; } } } internal class HealthMonitoringManager { internal HealthMonitoringSectionHelper _sectionHelper; internal bool _enabled = false; static Timer s_heartbeatTimer = null; static HealthMonitoringManager s_manager = null; static bool s_inited = false; static bool s_initing = false; static object s_lockObject = new object(); // If this method returns null, it means we failed during configuration. internal static HealthMonitoringManager Manager() { if (s_initing) { Debug.Assert(!s_inited); // If this is true, that means we are calling WebEventBase.Raise while // we are initializing. That means Init() has caused a config exception. return null; } if (s_inited) { return s_manager; } lock (s_lockObject) { if (s_inited) { return s_manager; } try { Debug.Assert(s_manager == null); s_initing = true; s_manager = new HealthMonitoringManager();; } finally { s_initing = false; s_inited = true; } } return s_manager; } internal static bool Enabled { get { HealthMonitoringManager manager = HealthMonitoringManager.Manager(); if (manager == null) { return false; } return manager._enabled; } } internal static void StartHealthMonitoringHeartbeat() { HealthMonitoringManager manager = Manager(); if (manager == null) { Debug.Trace( "HealthMonitoringManager", "Can't fire heartbeat because we cannot configure HealthMon"); return; } if (!manager._enabled) { Debug.Trace( "WebEventRaiseDetails", "Can't fire heartbeat because we are disabled"); return; } manager.StartHeartbeatTimer(); } private HealthMonitoringManager() { _sectionHelper = HealthMonitoringSectionHelper.GetHelper(); _enabled = _sectionHelper.Enabled; if (!_enabled) { return; } } internal static void Shutdown() { WebEventManager.Shutdown(); Dispose(); } internal static void Dispose() { // Make sure this function won't throw try { if (s_heartbeatTimer != null) { s_heartbeatTimer.Dispose(); s_heartbeatTimer = null; } } catch { } } internal void HeartbeatCallback(object state) { Debug.Assert(HealthMonitoringManager.Enabled); WebBaseEvent.RaiseSystemEvent(null, WebEventCodes.ApplicationHeartbeat); } internal void StartHeartbeatTimer() { TimeSpan interval = _sectionHelper.HealthMonitoringSection.HeartbeatInterval; if (interval == TimeSpan.Zero) { return; } #if DBG if (!Debug.IsTagPresent("Timer") || Debug.IsTagEnabled("Timer")) #endif { s_heartbeatTimer = new Timer(new TimerCallback(this.HeartbeatCallback), null, TimeSpan.Zero, interval); } } internal static HealthMonitoringSectionHelper.ProviderInstances ProviderInstances { get { HealthMonitoringManager manager = Manager(); if (manager == null) { return null; } if (!manager._enabled) { return null; } return manager._sectionHelper._providerInstances; } } } [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] public sealed class WebBaseEventCollection : ReadOnlyCollectionBase { public WebBaseEventCollection(ICollection events) { if (events == null) { throw new ArgumentNullException("events"); } foreach (WebBaseEvent eventRaised in events) { InnerList.Add(eventRaised); } } internal WebBaseEventCollection(WebBaseEvent eventRaised) { if (eventRaised == null) { throw new ArgumentNullException("eventRaised"); } InnerList.Add(eventRaised); } // overloaded collection access methods public WebBaseEvent this[int index] { get { return (WebBaseEvent) InnerList[index]; } } public int IndexOf(WebBaseEvent value) { return InnerList.IndexOf(value); } public bool Contains(WebBaseEvent value) { return InnerList.Contains(value); } } [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] public static class WebEventManager { [SecurityPermission(SecurityAction.Demand, Unrestricted=true)] public static void Flush(string providerName) { HealthMonitoringSectionHelper.ProviderInstances providers = HealthMonitoringManager.ProviderInstances; if (providers == null) { return; } if (!providers.ContainsKey(providerName)) { throw new ArgumentException(SR.GetString(SR.Health_mon_provider_not_found, providerName)); } using (new ApplicationImpersonationContext()) { providers[providerName].Flush(); } } [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)] [SecurityPermission(SecurityAction.Demand, Unrestricted=true)] public static void Flush() { HealthMonitoringSectionHelper.ProviderInstances providers = HealthMonitoringManager.ProviderInstances; if (providers == null) { return; } using (new ApplicationImpersonationContext()) { foreach(DictionaryEntry de in providers) { WebEventProvider provider = (WebEventProvider)de.Value; Debug.Trace("WebEventManager", "Flushing provider " + provider.Name); provider.Flush(); } } } internal static void Shutdown() { HealthMonitoringSectionHelper.ProviderInstances providers = HealthMonitoringManager.ProviderInstances; if (providers == null) { return; } foreach(DictionaryEntry de in providers) { WebEventProvider provider = (WebEventProvider)de.Value; Debug.Trace("WebEventManager", "Shutting down provider " + provider.Name); provider.Shutdown(); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Web.Management { using System; using System.Web; using System.Diagnostics; using System.Security.Principal; using System.Threading; using System.Reflection; using System.Text; using System.Web.Util; using System.Web.Configuration; using System.Configuration.Provider; using System.Collections; using System.Collections.Generic; using System.Configuration; using System.Security; using Debug=System.Web.Util.Debug; using System.Web.Hosting; using System.Web.UI; using System.Globalization; using System.Runtime.Remoting.Messaging; using System.Security.Permissions; using System.Web.Caching; // This enum matches the native one enum WebEventType (in webevent.h). internal enum WebEventType : int { WEBEVENT_BASE_EVENT = 0, WEBEVENT_MANAGEMENT_EVENT, WEBEVENT_APP_LIFETIME_EVENT, WEBEVENT_REQUEST_EVENT, WEBEVENT_HEARTBEAT_EVENT, WEBEVENT_BASE_ERROR_EVENT, WEBEVENT_REQUEST_ERROR_EVENT, WEBEVENT_ERROR_EVENT, WEBEVENT_AUDIT_EVENT, WEBEVENT_SUCCESS_AUDIT_EVENT, WEBEVENT_AUTHENTICATION_SUCCESS_AUDIT_EVENT, WEBEVENT_FAILURE_AUDIT_EVENT, WEBEVENT_AUTHENTICATION_FAILURE_AUDIT_EVENT, WEBEVENT_VIEWSTATE_FAILURE_AUDIT_EVENT, }; internal enum WebEventFieldType : int { String = 0, Int = 1, Bool = 2, Long = 3, Date = 4, } // Used for marshalling over to IIS Trace internal class WebEventFieldData { string _name; public string Name { get { return _name; } } string _data; public string Data { get { return _data; } } WebEventFieldType _type; public WebEventFieldType Type { get { return _type; } } public WebEventFieldData(string name, string data, WebEventFieldType type) { _name = name; _data = data; _type = type; } } // Interface for event provider [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public abstract class WebEventProvider : ProviderBase { // methods public abstract void ProcessEvent(WebBaseEvent raisedEvent); public abstract void Shutdown(); public abstract void Flush(); int _exceptionLogged; internal void LogException(Exception e) { // In order to not overflow the eventlog, we only log one exception per provider instance. if (Interlocked.CompareExchange( ref _exceptionLogged, 1, 0) == 0) { // Log all errors in eventlog UnsafeNativeMethods.LogWebeventProviderFailure( HttpRuntime.AppDomainAppVirtualPath, Name, e.ToString()); } } } // Interface for custom event evaluator [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public interface IWebEventCustomEvaluator { bool CanFire(WebBaseEvent raisedEvent, RuleFiringRecord record); } //////////////// // Events //////////////// [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebBaseEvent { DateTime _eventTimeUtc; int _code; int _detailCode; Object _source; string _message; long _sequenceNumber; long _occurrenceNumber; Guid _id = Guid.Empty; static long s_globalSequenceNumber = 0; static WebApplicationInformation s_applicationInfo = new WebApplicationInformation(); const string WEBEVENT_RAISE_IN_PROGRESS = "_WEvtRIP"; // A array that cache the result of eventCode to SystemEventType mapping. static readonly SystemEventType[,] s_eventCodeToSystemEventTypeMappings = new SystemEventType[WebEventCodes.GetEventArrayDimensionSize(0), WebEventCodes.GetEventArrayDimensionSize(1)]; // A array that store the # of occurrence per custom event code. static readonly long[,] s_eventCodeOccurrence = new long[WebEventCodes.GetEventArrayDimensionSize(0), WebEventCodes.GetEventArrayDimensionSize(1)]; static Hashtable s_customEventCodeOccurrence = new Hashtable(); #pragma warning disable 0649 static ReadWriteSpinLock s_lockCustomEventCodeOccurrence; #pragma warning restore 0649 static WebBaseEvent() { // Initialize the mappings. We will fill up each entry on demand by calling // SystemEventTypeFromEventCode(). for (int i = 0; i < s_eventCodeToSystemEventTypeMappings.GetLength(0); i++) { for (int j = 0; j < s_eventCodeToSystemEventTypeMappings.GetLength(1); j++) { s_eventCodeToSystemEventTypeMappings[i,j] = SystemEventType.Unknown; } } for (int i = 0; i < s_eventCodeOccurrence.GetLength(0); i++) { for (int j = 0; j < s_eventCodeOccurrence.GetLength(1); j++) { s_eventCodeOccurrence[i,j] = 0; } } } void Init(string message, Object eventSource, int eventCode, int eventDetailCode) { if (eventCode < 0) { throw new ArgumentOutOfRangeException("eventCode", SR.GetString(SR.Invalid_eventCode_error)); } if (eventDetailCode < 0) { throw new ArgumentOutOfRangeException("eventDetailCode", SR.GetString(SR.Invalid_eventDetailCode_error)); } _code = eventCode; _detailCode = eventDetailCode; _source = eventSource; _eventTimeUtc = DateTime.UtcNow; _message = message; // Creation of _id is always delayed until it's needed. } // ctors internal protected WebBaseEvent(string message, Object eventSource, int eventCode) { Init(message, eventSource, eventCode, WebEventCodes.UndefinedEventDetailCode); } internal protected WebBaseEvent(string message, Object eventSource, int eventCode, int eventDetailCode) { Init(message, eventSource, eventCode, eventDetailCode); } internal WebBaseEvent() { // For creating dummy event. See GetSystemDummyEvent() } internal bool IsSystemEvent { get { return (_code < WebEventCodes.WebExtendedBase); } } // Properties public DateTime EventTime { get { return _eventTimeUtc.ToLocalTime(); } } public DateTime EventTimeUtc { get { return _eventTimeUtc; } } public String Message { get { return _message; } } public Object EventSource { get { return _source; } } public long EventSequence { get { return _sequenceNumber; } } public long EventOccurrence { get { return _occurrenceNumber; } } public int EventCode { get { return _code; } } public int EventDetailCode { get { return _detailCode; } } public Guid EventID { get { if (_id == Guid.Empty) { lock(this) { if (_id == Guid.Empty) { _id = Guid.NewGuid(); } } } return _id; } } public static WebApplicationInformation ApplicationInformation { get { return s_applicationInfo; } } virtual internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_code, EventCode.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_message, Message)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_time, EventTime.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_time_Utc, EventTimeUtc.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_id, EventID.ToString("N", CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_sequence, EventSequence.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_occurrence, EventOccurrence.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_detail_code, EventDetailCode.ToString(CultureInfo.InstalledUICulture))); if (includeAppInfo) { formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_information)); formatter.IndentationLevel += 1; ApplicationInformation.FormatToString(formatter); formatter.IndentationLevel -= 1; } } public override string ToString() { return ToString(true, true); } public virtual string ToString(bool includeAppInfo, bool includeCustomEventDetails) { WebEventFormatter formatter = new WebEventFormatter(); FormatToString(formatter, includeAppInfo); if (!IsSystemEvent && includeCustomEventDetails) { formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_custom_event_details)); formatter.IndentationLevel += 1; FormatCustomEventDetails(formatter); formatter.IndentationLevel -= 1; } return formatter.ToString(); } virtual public void FormatCustomEventDetails(WebEventFormatter formatter) { } internal int InferEtwTraceVerbosity() { WebEventType type = WebBaseEvent.WebEventTypeFromWebEvent(this); switch (type) { case WebEventType.WEBEVENT_VIEWSTATE_FAILURE_AUDIT_EVENT: case WebEventType.WEBEVENT_BASE_ERROR_EVENT: case WebEventType.WEBEVENT_REQUEST_ERROR_EVENT: case WebEventType.WEBEVENT_FAILURE_AUDIT_EVENT: case WebEventType.WEBEVENT_AUTHENTICATION_FAILURE_AUDIT_EVENT: case WebEventType.WEBEVENT_ERROR_EVENT: return EtwTraceLevel.Warning; case WebEventType.WEBEVENT_AUDIT_EVENT: case WebEventType.WEBEVENT_SUCCESS_AUDIT_EVENT: case WebEventType.WEBEVENT_AUTHENTICATION_SUCCESS_AUDIT_EVENT: return EtwTraceLevel.Information; case WebEventType.WEBEVENT_BASE_EVENT: case WebEventType.WEBEVENT_MANAGEMENT_EVENT: case WebEventType.WEBEVENT_REQUEST_EVENT: default: return EtwTraceLevel.Verbose; } } internal void DeconstructWebEvent(out int eventType, out int fieldCount, out string[] fieldNames, out int[] fieldTypes, out string[] fieldData) { Listfields = new List (); eventType = (int)WebBaseEvent.WebEventTypeFromWebEvent(this); GenerateFieldsForMarshal(fields); fieldCount = fields.Count; fieldNames = new string[fieldCount]; fieldData = new string[fieldCount]; fieldTypes = new int[fieldCount]; for (int i = 0; i < fieldCount; ++i) { fieldNames[i] = fields[i].Name; fieldData[i] = fields[i].Data; fieldTypes[i] = (int)fields[i].Type; } } internal virtual void GenerateFieldsForMarshal(List fields) { fields.Add(new WebEventFieldData("EventTime", EventTimeUtc.ToString(), WebEventFieldType.String)); fields.Add(new WebEventFieldData("EventID", EventID.ToString(), WebEventFieldType.String)); fields.Add(new WebEventFieldData("EventMessage", Message, WebEventFieldType.String)); fields.Add(new WebEventFieldData("ApplicationDomain", WebBaseEvent.ApplicationInformation.ApplicationDomain, WebEventFieldType.String)); fields.Add(new WebEventFieldData("TrustLevel", WebBaseEvent.ApplicationInformation.TrustLevel, WebEventFieldType.String)); fields.Add(new WebEventFieldData("ApplicationVirtualPath", WebBaseEvent.ApplicationInformation.ApplicationVirtualPath, WebEventFieldType.String)); fields.Add(new WebEventFieldData("ApplicationPath", WebBaseEvent.ApplicationInformation.ApplicationPath, WebEventFieldType.String)); fields.Add(new WebEventFieldData("MachineName", WebBaseEvent.ApplicationInformation.MachineName, WebEventFieldType.String)); fields.Add(new WebEventFieldData("EventCode", EventCode.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int)); fields.Add(new WebEventFieldData("EventDetailCode", EventDetailCode.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int)); fields.Add(new WebEventFieldData("SequenceNumber", EventSequence.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Long)); fields.Add(new WebEventFieldData("Occurrence", EventOccurrence.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Long)); } internal virtual void PreProcessEventInit() { } static void FindEventCode(Exception e, ref int eventCode, ref int eventDetailsCode, ref Exception eStack) { eventDetailsCode = WebEventCodes.UndefinedEventDetailCode; if (e is ConfigurationException) { eventCode = WebEventCodes.WebErrorConfigurationError; } else if (e is HttpRequestValidationException) { eventCode = WebEventCodes.RuntimeErrorValidationFailure; } else if (e is HttpCompileException) { eventCode = WebEventCodes.WebErrorCompilationError; } else if (e is SecurityException) { eventCode = WebEventCodes.AuditUnhandledSecurityException; } else if (e is UnauthorizedAccessException) { eventCode = WebEventCodes.AuditUnhandledAccessException; } else if (e is HttpParseException) { eventCode = WebEventCodes.WebErrorParserError; } else if (e is HttpException && e.InnerException is ViewStateException) { ViewStateException vse = (ViewStateException)e.InnerException; eventCode = WebEventCodes.AuditInvalidViewStateFailure; if (vse._macValidationError) { eventDetailsCode = WebEventCodes.InvalidViewStateMac; } else { eventDetailsCode = WebEventCodes.InvalidViewState; } eStack = vse; } else if (e is HttpException && ((HttpException)e).WebEventCode != WebEventCodes.UndefinedEventCode) { eventCode = ((HttpException)e).WebEventCode; } else { // We don't know what it is. Let's see if we can find it out by using the inner exception. if (e.InnerException != null) { // We will call FindEventCode recusively to find out if e.InnerException is the real one. if (eStack == null) { // Set eStack here. If the recursive call ends up landing in // WebEventCodes.RuntimeErrorUnhandledException, we'll use the original // inner exception as our final result. eStack = e.InnerException; } FindEventCode(e.InnerException, ref eventCode, ref eventDetailsCode, ref eStack); } else { // It doesn't have an inner exception. Just return the generic unhandled-exception eventCode = WebEventCodes.RuntimeErrorUnhandledException; } } if (eStack == null) { eStack = e; } } static internal void RaiseRuntimeError(Exception e, object source) { Debug.Trace("WebEventRaiseError", "Error Event is raised; type=" + e.GetType().Name); if (!HealthMonitoringManager.Enabled) { return; } try { int eventCode = WebEventCodes.UndefinedEventCode; int eventDetailsCode = WebEventCodes.UndefinedEventDetailCode; HttpContext context = HttpContext.Current; Exception eStack = null; if (context != null) { Page page = context.Handler as Page; // Errors from Transacted pages can be wrapped by a // HttpException if (page != null && page.IsTransacted && e.GetType() == typeof(HttpException) && e.InnerException != null) { e = e.InnerException; } } FindEventCode(e, ref eventCode, ref eventDetailsCode, ref eStack); WebBaseEvent.RaiseSystemEvent(source, eventCode, eventDetailsCode, eStack); } catch { } } virtual internal protected void IncrementPerfCounters() { PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_TOTAL); } class CustomEventCodeOccurrence { internal long _occurrence; } internal void IncrementTotalCounters(int index0, int index1) { _sequenceNumber = Interlocked.Increment(ref s_globalSequenceNumber); if (index0 != -1) { _occurrenceNumber = Interlocked.Increment(ref s_eventCodeOccurrence[index0, index1]); } else { CustomEventCodeOccurrence ceco = (CustomEventCodeOccurrence)s_customEventCodeOccurrence[_code]; if (ceco == null) { s_lockCustomEventCodeOccurrence.AcquireWriterLock(); try { ceco = (CustomEventCodeOccurrence)s_customEventCodeOccurrence[_code]; if (ceco == null) { ceco = new CustomEventCodeOccurrence(); s_customEventCodeOccurrence[_code] = ceco; } } finally { s_lockCustomEventCodeOccurrence.ReleaseWriterLock(); } } _occurrenceNumber = Interlocked.Increment(ref ceco._occurrence); } } [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)] virtual public void Raise() { Raise(this); } // Internally raised events don't go thru this method. They go directly to RaiseSystemEvent --> RaiseInternal [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)] static public void Raise(WebBaseEvent eventRaised) { if (eventRaised.EventCode < WebEventCodes.WebExtendedBase) { throw new HttpException(SR.GetString(SR.System_eventCode_not_allowed, eventRaised.EventCode.ToString(CultureInfo.CurrentCulture), WebEventCodes.WebExtendedBase.ToString(CultureInfo.CurrentCulture))); } if (!HealthMonitoringManager.Enabled) { Debug.Trace( "WebEventRaiseDetails", "Can't fire event because we are disabled or we can't configure HealthMonManager"); return; } RaiseInternal(eventRaised, null, -1, -1); } static internal void RaiseInternal(WebBaseEvent eventRaised, ArrayList firingRuleInfos, int index0, int index1) { bool preProcessEventInitCalled = false; bool inProgressSet = false; object o; ProcessImpersonationContext ictx = null; HttpContext context = HttpContext.Current; Debug.Trace( "WebEventRaiseDetails", "Event is raised; event class = " + eventRaised.GetType().Name); // Use CallContext to make sure we detect an infinite loop where a provider calls Raise(). o = CallContext.GetData(WEBEVENT_RAISE_IN_PROGRESS); if (o != null && (bool)o) { Debug.Trace( "WebEventRaiseDetails", "An event is raised while we're raising an event. Ignore it."); return; } eventRaised.IncrementPerfCounters(); eventRaised.IncrementTotalCounters(index0, index1); // Find the list of rules that match this event if (firingRuleInfos == null) { HealthMonitoringManager manager = HealthMonitoringManager.Manager(); Debug.Assert(manager != null, "manager != null"); firingRuleInfos = manager._sectionHelper.FindFiringRuleInfos(eventRaised.GetType(), eventRaised.EventCode); } if (firingRuleInfos.Count == 0) { return; } try { bool[] matchingProviderArray = null; if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null) EtwTrace.Trace(EtwTraceType.ETW_TYPE_WEB_EVENT_RAISE_START, context.WorkerRequest, eventRaised.GetType().FullName, eventRaised.EventCode.ToString(CultureInfo.InstalledUICulture), eventRaised.EventDetailCode.ToString(CultureInfo.InstalledUICulture), null); try { foreach (HealthMonitoringSectionHelper.FiringRuleInfo firingRuleInfo in firingRuleInfos) { HealthMonitoringSectionHelper.RuleInfo ruleInfo = firingRuleInfo._ruleInfo; RuleFiringRecord record = ruleInfo._ruleFiringRecord; // Check if we should fire the event based on its throttling settings if (!record.CheckAndUpdate(eventRaised)) { Debug.Trace("WebEventRaiseDetails", "Throttling settings not met; not fired"); continue; } // It's valid for a rule to have no referenced provider if (ruleInfo._referencedProvider != null) { if (!preProcessEventInitCalled) { // The event may need to do pre-ProcessEvent initialization eventRaised.PreProcessEventInit(); preProcessEventInitCalled = true; } // For rule infos that share the same provider, the _indexOfFirstRuleInfoWithSameProvider field // is the index of the first ruleInfo among them. We use that index in the boolean array // matchingProviderArray to remember if we've already fired that provider. // This is for the scenario where several rules are pointing to the same provider, // and even if >1 rule actually fire and pass all throttling if (firingRuleInfo._indexOfFirstRuleInfoWithSameProvider != -1) { if (matchingProviderArray == null) { matchingProviderArray = new bool[firingRuleInfos.Count]; } if (matchingProviderArray[firingRuleInfo._indexOfFirstRuleInfoWithSameProvider]) { Debug.Trace("WebEventRaiseDetails", "Rule with a matching provider already fired."); continue; } matchingProviderArray[firingRuleInfo._indexOfFirstRuleInfoWithSameProvider] = true; } if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null) EtwTrace.Trace(EtwTraceType.ETW_TYPE_WEB_EVENT_DELIVER_START, context.WorkerRequest, ruleInfo._ruleSettings.Provider, ruleInfo._ruleSettings.Name, ruleInfo._ruleSettings.EventName, null); // In retail build, ignore errors from provider try { if (ictx == null) { ictx = new ProcessImpersonationContext(); } if (!inProgressSet) { CallContext.SetData(WEBEVENT_RAISE_IN_PROGRESS, true); inProgressSet = true; } Debug.Trace("WebEventRaiseDetails", "Calling ProcessEvent under " + WindowsIdentity.GetCurrent().Name); ruleInfo._referencedProvider.ProcessEvent(eventRaised); } catch (Exception e) { try { ruleInfo._referencedProvider.LogException(e); } catch { // ignore all errors } } finally { if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null) EtwTrace.Trace(EtwTraceType.ETW_TYPE_WEB_EVENT_DELIVER_END, context.WorkerRequest); } } } } finally { // Resume client impersonation if (ictx != null) { ictx.Undo(); } if (inProgressSet) { CallContext.FreeNamedDataSlot(WEBEVENT_RAISE_IN_PROGRESS); } if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null) EtwTrace.Trace(EtwTraceType.ETW_TYPE_WEB_EVENT_RAISE_END, context.WorkerRequest); } } catch { throw; } // Prevent Exception Filter Security Issue (ASURT 122835) } internal static void RaiseSystemEvent(string message, object source, int eventCode, int eventDetailCode, Exception exception) { RaiseSystemEventInternal(message, source, eventCode, eventDetailCode, exception, null); } internal static void RaiseSystemEvent(object source, int eventCode) { RaiseSystemEventInternal(null, source, eventCode, WebEventCodes.UndefinedEventDetailCode, null, null); } internal static void RaiseSystemEvent(object source, int eventCode, int eventDetailCode) { RaiseSystemEventInternal(null, source, eventCode, eventDetailCode, null, null); } internal static void RaiseSystemEvent(object source, int eventCode, int eventDetailCode, Exception exception) { RaiseSystemEventInternal(null, source, eventCode, eventDetailCode, exception, null); } internal static void RaiseSystemEvent(object source, int eventCode, string nameToAuthenticate) { RaiseSystemEventInternal(null, source, eventCode, WebEventCodes.UndefinedEventDetailCode, null, nameToAuthenticate); } static void RaiseSystemEventInternal(string message, object source, int eventCode, int eventDetailCode, Exception exception, string nameToAuthenticate) { HealthMonitoringManager manager; ArrayList firingRuleInfos; SystemEventTypeInfo typeInfo; SystemEventType systemEventType; int index0, index1; Debug.Trace( "WebEventRaiseDetails", "RaiseSystemEventInternal called; eventCode=" + eventCode + "; eventDetailCode=" + eventDetailCode); if (!HealthMonitoringManager.Enabled) { Debug.Trace( "WebEventRaiseDetails", "Can't fire event because we are disabled or we can't configure HealthMonManager"); return; } WebEventCodes.GetEventArrayIndexsFromEventCode(eventCode, out index0, out index1); GetSystemEventTypeInfo(eventCode, index0, index1, out typeInfo, out systemEventType); if (typeInfo == null) { Debug.Assert(false, "Unexpected system event code = " + eventCode); return; } manager = HealthMonitoringManager.Manager(); // Figure out if there is any provider that subscribes to it firingRuleInfos = manager._sectionHelper.FindFiringRuleInfos(typeInfo._type, eventCode); if (firingRuleInfos.Count == 0) { // Even if we're not firing it, we still have to increment some global counters typeInfo._dummyEvent.IncrementPerfCounters(); typeInfo._dummyEvent.IncrementTotalCounters(index0, index1); } else { // We will fire the event WebBaseEvent.RaiseInternal( NewEventFromSystemEventType(false, systemEventType, message, source, eventCode, eventDetailCode, exception, nameToAuthenticate), firingRuleInfos, index0, index1); } } // An enum of all the types of web event we will fire enum SystemEventType { Unknown = -1, WebApplicationLifetimeEvent, WebHeartbeatEvent, WebRequestEvent, WebRequestErrorEvent, WebErrorEvent, WebAuthenticationSuccessAuditEvent, WebSuccessAuditEvent, WebAuthenticationFailureAuditEvent, WebFailureAuditEvent, WebViewStateFailureAuditEvent, Last }; class SystemEventTypeInfo { internal WebBaseEvent _dummyEvent; // For calling IncrementPerfCounters. See RaiseSystemEventInternal for details. internal Type _type; internal SystemEventTypeInfo(WebBaseEvent dummyEvent) { _dummyEvent = dummyEvent; _type = dummyEvent.GetType(); } }; // An array to cache the event type info for each system event type static SystemEventTypeInfo[] s_systemEventTypeInfos = new SystemEventTypeInfo[(int)SystemEventType.Last]; static void GetSystemEventTypeInfo(int eventCode, int index0, int index1, out SystemEventTypeInfo info, out SystemEventType systemEventType) { // Figure out what SystemEventType this eventCode maps to. // For each eventCode, we store the result in a cache. systemEventType = s_eventCodeToSystemEventTypeMappings[index0, index1]; if (systemEventType == SystemEventType.Unknown) { systemEventType = SystemEventTypeFromEventCode(eventCode); s_eventCodeToSystemEventTypeMappings[index0, index1] = systemEventType; } // Based on the systemEventType, we read the SystemEventTypeInfo. For each // event type, we also cache the info info = s_systemEventTypeInfos[(int)systemEventType]; if (info != null) { return; } info = new SystemEventTypeInfo(CreateDummySystemEvent(systemEventType)); s_systemEventTypeInfos[(int)systemEventType] = info; } static SystemEventType SystemEventTypeFromEventCode(int eventCode) { if (eventCode >= WebEventCodes.ApplicationCodeBase && eventCode <= WebEventCodes.ApplicationCodeBaseLast) { switch(eventCode) { case WebEventCodes.ApplicationStart: case WebEventCodes.ApplicationShutdown: case WebEventCodes.ApplicationCompilationStart: case WebEventCodes.ApplicationCompilationEnd: return SystemEventType.WebApplicationLifetimeEvent; case WebEventCodes.ApplicationHeartbeat: return SystemEventType.WebHeartbeatEvent; } } if (eventCode >= WebEventCodes.RequestCodeBase && eventCode <= WebEventCodes.RequestCodeBaseLast) { switch(eventCode) { case WebEventCodes.RequestTransactionComplete: case WebEventCodes.RequestTransactionAbort: return SystemEventType.WebRequestEvent; } } if (eventCode >= WebEventCodes.ErrorCodeBase && eventCode <= WebEventCodes.ErrorCodeBaseLast) { switch(eventCode) { case WebEventCodes.RuntimeErrorRequestAbort: case WebEventCodes.RuntimeErrorViewStateFailure: case WebEventCodes.RuntimeErrorValidationFailure: case WebEventCodes.RuntimeErrorPostTooLarge: case WebEventCodes.RuntimeErrorUnhandledException: return SystemEventType.WebRequestErrorEvent; case WebEventCodes.WebErrorParserError: case WebEventCodes.WebErrorCompilationError: case WebEventCodes.WebErrorConfigurationError: case WebEventCodes.WebErrorOtherError: case WebEventCodes.WebErrorPropertyDeserializationError: case WebEventCodes.WebErrorObjectStateFormatterDeserializationError: return SystemEventType.WebErrorEvent; } } if (eventCode >= WebEventCodes.AuditCodeBase && eventCode <= WebEventCodes.AuditCodeBaseLast) { switch(eventCode) { case WebEventCodes.AuditFormsAuthenticationSuccess: case WebEventCodes.AuditMembershipAuthenticationSuccess: return SystemEventType.WebAuthenticationSuccessAuditEvent; case WebEventCodes.AuditUrlAuthorizationSuccess: case WebEventCodes.AuditFileAuthorizationSuccess: return SystemEventType.WebSuccessAuditEvent; case WebEventCodes.AuditFormsAuthenticationFailure: case WebEventCodes.AuditMembershipAuthenticationFailure: return SystemEventType.WebAuthenticationFailureAuditEvent; case WebEventCodes.AuditUrlAuthorizationFailure: case WebEventCodes.AuditFileAuthorizationFailure: case WebEventCodes.AuditUnhandledSecurityException: case WebEventCodes.AuditUnhandledAccessException: return SystemEventType.WebFailureAuditEvent; case WebEventCodes.AuditInvalidViewStateFailure: return SystemEventType.WebViewStateFailureAuditEvent; } } if (eventCode >= WebEventCodes.MiscCodeBase && eventCode <= WebEventCodes.MiscCodeBaseLast) { switch(eventCode) { case WebEventCodes.WebEventProviderInformation: Debug.Assert(false, "WebEventProviderInformation shouldn't be used to Raise an event"); return SystemEventType.Unknown; } } return SystemEventType.Unknown; } static WebBaseEvent CreateDummySystemEvent(SystemEventType systemEventType) { return NewEventFromSystemEventType(true, systemEventType, null, null, 0, 0, null, null); } static WebBaseEvent NewEventFromSystemEventType(bool createDummy, SystemEventType systemEventType, string message, object source,int eventCode, int eventDetailCode, Exception exception, string nameToAuthenticate) { // If createDummy == true, it means we're only creating a dummy event for the sake of using // it to call IncrementPerfCounters() if (!createDummy && message == null) { message = WebEventCodes.MessageFromEventCode(eventCode, eventDetailCode); } // Code view switch(systemEventType) { case SystemEventType.WebApplicationLifetimeEvent: return createDummy ? new WebApplicationLifetimeEvent() : new WebApplicationLifetimeEvent(message, source, eventCode, eventDetailCode); case SystemEventType.WebHeartbeatEvent: return createDummy ? new WebHeartbeatEvent() : new WebHeartbeatEvent(message, eventCode); case SystemEventType.WebRequestEvent: return createDummy ? new WebRequestEvent() : new WebRequestEvent(message, source, eventCode, eventDetailCode); case SystemEventType. WebRequestErrorEvent: return createDummy ? new WebRequestErrorEvent() : new WebRequestErrorEvent(message, source, eventCode, eventDetailCode, exception); case SystemEventType.WebErrorEvent: return createDummy ? new WebErrorEvent() : new WebErrorEvent(message, source, eventCode, eventDetailCode, exception); case SystemEventType.WebAuthenticationSuccessAuditEvent: return createDummy ? new WebAuthenticationSuccessAuditEvent() : new WebAuthenticationSuccessAuditEvent(message, source, eventCode, eventDetailCode, nameToAuthenticate); case SystemEventType.WebSuccessAuditEvent: return createDummy ? new WebSuccessAuditEvent() : new WebSuccessAuditEvent(message, source, eventCode, eventDetailCode); case SystemEventType.WebAuthenticationFailureAuditEvent: return createDummy ? new WebAuthenticationFailureAuditEvent() : new WebAuthenticationFailureAuditEvent(message, source, eventCode, eventDetailCode, nameToAuthenticate); case SystemEventType.WebFailureAuditEvent: return createDummy ? new WebFailureAuditEvent() : new WebFailureAuditEvent(message, source, eventCode, eventDetailCode); case SystemEventType.WebViewStateFailureAuditEvent: return createDummy ? new WebViewStateFailureAuditEvent() : new WebViewStateFailureAuditEvent(message, source, eventCode, eventDetailCode, (System.Web.UI.ViewStateException)exception); default: Debug.Assert(false, "Unexpected event type = " + systemEventType); return null; } } static string CreateWebEventResourceCacheKey(String key) { return CacheInternal.PrefixWebEventResource + key; } internal static String FormatResourceStringWithCache(String key) { CacheInternal cacheInternal = HttpRuntime.CacheInternal; string s; string cacheKey = CreateWebEventResourceCacheKey(key); s = (string) cacheInternal.Get(cacheKey); if (s != null) { return s; } s = SR.Resources.GetString(key, CultureInfo.InstalledUICulture); if (s != null) { cacheInternal.UtcInsert(cacheKey, s); } return s; } internal static String FormatResourceStringWithCache(String key, String arg0) { string fmt = FormatResourceStringWithCache(key); return(fmt != null) ? String.Format(fmt, arg0) : null; } internal static WebEventType WebEventTypeFromWebEvent(WebBaseEvent eventRaised) { // Note: // eventRaised can belong to one of the following classes, or can inherit from one of them. // In order to figure out precisely the WebEventType closest to the type of eventRaised, // we will start our comparison from the leaf nodes in the class hierarchy and work our // way up. // Webevent class hierarchy (with the info contained in each class): /* - WebBaseEvent (basic) - WebManagementEvent (+ WebProcessInformation) - WebHeartbeatEvent (+ WebProcessStatistics) - WebApplicationLifetimeEvent - WebRequestEvent (+ WebRequestInformation) - WebBaseErrorEvent (+ Exception) - WebRequestErrorEvent (+ WebRequestInformation + WebThreadInformation) - WebErrorEvent (+ WebRequestInformation + WebThreadInformation) - WebAuditEvent (+ WebRequestInformation) - WebSuccessAuditEvent - WebAuthenticationSuccessAuditEvent (+ NameToAuthenticate) - WebFailureAuditEvent - WebAuthenticationFailureAuditEvent (+ NameToAuthenticate) - WebViewStateFailureAuditEvent (+ ViewStateException) */ // Hierarchy level 5 if (eventRaised is WebAuthenticationSuccessAuditEvent) { return WebEventType.WEBEVENT_AUTHENTICATION_SUCCESS_AUDIT_EVENT; } if (eventRaised is WebAuthenticationFailureAuditEvent) { return WebEventType.WEBEVENT_AUTHENTICATION_FAILURE_AUDIT_EVENT; } if (eventRaised is WebViewStateFailureAuditEvent) { return WebEventType.WEBEVENT_VIEWSTATE_FAILURE_AUDIT_EVENT; } // Hierarchy level 4 if (eventRaised is WebRequestErrorEvent) { return WebEventType.WEBEVENT_REQUEST_ERROR_EVENT; } if (eventRaised is WebErrorEvent) { return WebEventType.WEBEVENT_ERROR_EVENT; } if (eventRaised is WebSuccessAuditEvent) { return WebEventType.WEBEVENT_SUCCESS_AUDIT_EVENT; } if (eventRaised is WebFailureAuditEvent) { return WebEventType.WEBEVENT_FAILURE_AUDIT_EVENT; } // Hierarchy level 3 if (eventRaised is WebHeartbeatEvent) { return WebEventType.WEBEVENT_HEARTBEAT_EVENT; } if (eventRaised is WebApplicationLifetimeEvent) { return WebEventType.WEBEVENT_APP_LIFETIME_EVENT; } if (eventRaised is WebRequestEvent) { return WebEventType.WEBEVENT_REQUEST_EVENT; } if (eventRaised is WebBaseErrorEvent) { return WebEventType.WEBEVENT_BASE_ERROR_EVENT; } if (eventRaised is WebAuditEvent) { return WebEventType.WEBEVENT_AUDIT_EVENT; } // Hierarchy level 2 if (eventRaised is WebManagementEvent) { return WebEventType.WEBEVENT_MANAGEMENT_EVENT; } // Hierarchy level 1 return WebEventType.WEBEVENT_BASE_EVENT; } static internal void RaisePropertyDeserializationWebErrorEvent(SettingsProperty property, object source, Exception exception) { if (HttpContext.Current == null) { return; } WebBaseEvent.RaiseSystemEvent( SR.GetString(SR.Webevent_msg_Property_Deserialization, property.Name, property.SerializeAs.ToString(), property.PropertyType.AssemblyQualifiedName ), source, WebEventCodes.WebErrorPropertyDeserializationError, WebEventCodes.UndefinedEventDetailCode, exception); } } [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebEventFormatter { int _level; StringBuilder _sb; int _tabSize; void AddTab() { int level = _level; while (level > 0) { _sb.Append(' ', _tabSize); level--; } } internal WebEventFormatter() { _level = 0; _sb = new StringBuilder(); _tabSize = 4; } public void AppendLine(string s) { AddTab(); _sb.Append(s); _sb.Append('\n'); } new public string ToString() { return _sb.ToString(); } public int IndentationLevel { get { return _level; } set { _level = Math.Max(value, 0); } } public int TabSize { get { return _tabSize; } set { _tabSize = Math.Max(value, 0); } } } // This class is a base class for all events that require application and process information. // // WebManagementEvent is the base class for all our webevent classes (except for WebBaseEvent) // Please [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)] [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebManagementEvent : WebBaseEvent { static WebProcessInformation s_processInfo = new WebProcessInformation(); internal protected WebManagementEvent(string message, object eventSource, int eventCode) :base(message, eventSource, eventCode) { } internal protected WebManagementEvent(string message, object eventSource, int eventCode, int eventDetailCode) :base(message, eventSource, eventCode, eventDetailCode) { } internal WebManagementEvent() { // For creating dummy event. See GetSystemDummyEvent() } // properties public WebProcessInformation ProcessInformation { get { return s_processInfo; } } internal override void GenerateFieldsForMarshal(List fields) { base.GenerateFieldsForMarshal(fields); fields.Add(new WebEventFieldData("AccountName", ProcessInformation.AccountName, WebEventFieldType.String)); fields.Add(new WebEventFieldData("ProcessName", ProcessInformation.ProcessName, WebEventFieldType.String)); fields.Add(new WebEventFieldData("ProcessID", ProcessInformation.ProcessID.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int)); } override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_information)); formatter.IndentationLevel += 1; ProcessInformation.FormatToString(formatter); formatter.IndentationLevel -= 1; } } // This event is raised at periodic intervals (default 30 seconds) and provides information // relative to the state of the running appdomin. [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebHeartbeatEvent : WebManagementEvent { static WebProcessStatistics s_procStats = new WebProcessStatistics(); internal protected WebHeartbeatEvent(string message, int eventCode) :base(message, null, eventCode) { } internal WebHeartbeatEvent() { // For creating dummy event. See GetSystemDummyEvent() } public WebProcessStatistics ProcessStatistics {get {return s_procStats;}} override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_statistics)); formatter.IndentationLevel += 1; s_procStats.FormatToString(formatter); formatter.IndentationLevel -= 1; } } // This event represents a notable event in the lifetime of an application (app domain) // including startup and shutdown events. When an app domain is terminated, the reason // will be expressed in the Message field (e.g. compilation threshold exceed, Shutdown // called explicitly, etc.). [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebApplicationLifetimeEvent : WebManagementEvent { internal protected WebApplicationLifetimeEvent(string message, object eventSource, int eventCode) :base(message, eventSource, eventCode) { } internal protected WebApplicationLifetimeEvent(string message, object eventSource, int eventCode, int eventDetailCode) :base(message, eventSource, eventCode, eventDetailCode) { } internal WebApplicationLifetimeEvent() { // For creating dummy event. See GetSystemDummyEvent() } static internal int DetailCodeFromShutdownReason(ApplicationShutdownReason reason) { switch (reason) { case ApplicationShutdownReason.HostingEnvironment: return WebEventCodes.ApplicationShutdownHostingEnvironment; case ApplicationShutdownReason.ChangeInGlobalAsax: return WebEventCodes.ApplicationShutdownChangeInGlobalAsax; case ApplicationShutdownReason.ConfigurationChange: return WebEventCodes.ApplicationShutdownConfigurationChange; case ApplicationShutdownReason.UnloadAppDomainCalled: return WebEventCodes.ApplicationShutdownUnloadAppDomainCalled; case ApplicationShutdownReason.ChangeInSecurityPolicyFile: return WebEventCodes.ApplicationShutdownChangeInSecurityPolicyFile; case ApplicationShutdownReason.BinDirChangeOrDirectoryRename: return WebEventCodes.ApplicationShutdownBinDirChangeOrDirectoryRename; case ApplicationShutdownReason.BrowsersDirChangeOrDirectoryRename: return WebEventCodes.ApplicationShutdownBrowsersDirChangeOrDirectoryRename; case ApplicationShutdownReason.CodeDirChangeOrDirectoryRename: return WebEventCodes.ApplicationShutdownCodeDirChangeOrDirectoryRename; case ApplicationShutdownReason.ResourcesDirChangeOrDirectoryRename: return WebEventCodes.ApplicationShutdownResourcesDirChangeOrDirectoryRename; case ApplicationShutdownReason.IdleTimeout: return WebEventCodes.ApplicationShutdownIdleTimeout; case ApplicationShutdownReason.PhysicalApplicationPathChanged: return WebEventCodes.ApplicationShutdownPhysicalApplicationPathChanged; case ApplicationShutdownReason.HttpRuntimeClose: return WebEventCodes.ApplicationShutdownHttpRuntimeClose; case ApplicationShutdownReason.InitializationError: return WebEventCodes.ApplicationShutdownInitializationError; case ApplicationShutdownReason.MaxRecompilationsReached: return WebEventCodes.ApplicationShutdownMaxRecompilationsReached; case ApplicationShutdownReason.BuildManagerChange: return WebEventCodes.ApplicationShutdownBuildManagerChange; default: return WebEventCodes.ApplicationShutdownUnknown; } } override internal protected void IncrementPerfCounters() { base.IncrementPerfCounters(); PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_APP); } } // This class serves as a base for non-error events that provide [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebRequestEvent : WebManagementEvent { WebRequestInformation _requestInfo; override internal void PreProcessEventInit() { base.PreProcessEventInit(); InitRequestInformation(); } internal protected WebRequestEvent(string message, object eventSource, int eventCode) :base(message, eventSource, eventCode) { } internal protected WebRequestEvent(string message, object eventSource, int eventCode, int eventDetailCode) :base(message, eventSource, eventCode, eventDetailCode) { } internal WebRequestEvent() { // For creating dummy event. See GetSystemDummyEvent() } void InitRequestInformation() { if (_requestInfo == null) { _requestInfo = new WebRequestInformation(); } } public WebRequestInformation RequestInformation { get { InitRequestInformation(); return _requestInfo; } } internal override void GenerateFieldsForMarshal(List fields) { base.GenerateFieldsForMarshal(fields); fields.Add(new WebEventFieldData("RequestUrl", RequestInformation.RequestUrl, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RequestPath", RequestInformation.RequestPath, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserHostAddress", RequestInformation.UserHostAddress, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserName", RequestInformation.Principal.Identity.Name, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserAuthenticated", RequestInformation.Principal.Identity.IsAuthenticated.ToString(), WebEventFieldType.Bool)); fields.Add(new WebEventFieldData("UserAuthenticationType", RequestInformation.Principal.Identity.AuthenticationType, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RequestThreadAccountName", RequestInformation.ThreadAccountName, WebEventFieldType.String)); } override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information)); formatter.IndentationLevel += 1; RequestInformation.FormatToString(formatter); formatter.IndentationLevel -= 1; } override internal protected void IncrementPerfCounters() { base.IncrementPerfCounters(); PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_WEB_REQ); } } // This is the base class for all error events. [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebBaseErrorEvent : WebManagementEvent { Exception _exception; void Init(Exception e) { _exception = e; } internal protected WebBaseErrorEvent(string message, object eventSource, int eventCode, Exception e) :base(message, eventSource, eventCode) { Init(e); } internal protected WebBaseErrorEvent(string message, object eventSource, int eventCode, int eventDetailCode, Exception e) :base(message, eventSource, eventCode, eventDetailCode) { Init(e); } internal WebBaseErrorEvent() { // For creating dummy event. See GetSystemDummyEvent() } public Exception ErrorException { get { return _exception; } } override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); if (_exception == null) { return; } Exception ex = _exception; // Please for (int level = 0; ex != null && level <= 2; ex = ex.InnerException, level++) { formatter.AppendLine(String.Empty); if (level == 0) { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_exception_information)); } else { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_inner_exception_information, level.ToString(CultureInfo.InstalledUICulture))); } formatter.IndentationLevel += 1; formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_exception_type, ex.GetType().ToString())); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_exception_message, ex.Message)); formatter.IndentationLevel -= 1; } } internal override void GenerateFieldsForMarshal(List fields) { base.GenerateFieldsForMarshal(fields); fields.Add(new WebEventFieldData("ExceptionType", ErrorException.GetType().ToString(), WebEventFieldType.String)); fields.Add(new WebEventFieldData("ExceptionMessage", ErrorException.Message, WebEventFieldType.String)); } override internal protected void IncrementPerfCounters() { base.IncrementPerfCounters(); PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_ERROR); PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_EVENTS_ERROR); } } // This class contains information about systemic errors, e.g. things related to // configuration or application code (parser errors, compilation errors). [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebErrorEvent : WebBaseErrorEvent { WebRequestInformation _requestInfo; WebThreadInformation _threadInfo; void Init(Exception e) { } override internal void PreProcessEventInit() { base.PreProcessEventInit(); InitRequestInformation(); InitThreadInformation(); } internal protected WebErrorEvent(string message, object eventSource, int eventCode, Exception exception) :base(message, eventSource, eventCode, exception) { Init(exception); } internal protected WebErrorEvent(string message, object eventSource, int eventCode, int eventDetailCode, Exception exception) :base(message, eventSource, eventCode, eventDetailCode, exception) { Init(exception); } internal WebErrorEvent() { // For creating dummy event. See GetSystemDummyEvent() } void InitRequestInformation() { if (_requestInfo == null) { _requestInfo = new WebRequestInformation(); } } public WebRequestInformation RequestInformation { get { InitRequestInformation(); return _requestInfo; } } void InitThreadInformation() { if (_threadInfo == null) { _threadInfo = new WebThreadInformation(base.ErrorException); } } public WebThreadInformation ThreadInformation { get { InitThreadInformation(); return _threadInfo; } } override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information)); formatter.IndentationLevel += 1; RequestInformation.FormatToString(formatter); formatter.IndentationLevel -= 1; formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_information)); formatter.IndentationLevel += 1; ThreadInformation.FormatToString(formatter); formatter.IndentationLevel -= 1; } internal override void GenerateFieldsForMarshal(List fields) { base.GenerateFieldsForMarshal(fields); fields.Add(new WebEventFieldData("RequestUrl", RequestInformation.RequestUrl, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RequestPath", RequestInformation.RequestPath, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserHostAddress", RequestInformation.UserHostAddress, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserName", RequestInformation.Principal.Identity.Name, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserAuthenticated", RequestInformation.Principal.Identity.IsAuthenticated.ToString(), WebEventFieldType.Bool)); fields.Add(new WebEventFieldData("UserAuthenticationType", RequestInformation.Principal.Identity.AuthenticationType, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RequestThreadAccountName", RequestInformation.ThreadAccountName, WebEventFieldType.String)); fields.Add(new WebEventFieldData("ThreadID", ThreadInformation.ThreadID.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int)); fields.Add(new WebEventFieldData("ThreadAccountName", ThreadInformation.ThreadAccountName, WebEventFieldType.String)); fields.Add(new WebEventFieldData("StackTrace", ThreadInformation.StackTrace, WebEventFieldType.String)); fields.Add(new WebEventFieldData("IsImpersonating", ThreadInformation.IsImpersonating.ToString(), WebEventFieldType.Bool)); } override internal protected void IncrementPerfCounters() { base.IncrementPerfCounters(); PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_HTTP_INFRA_ERROR); PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_EVENTS_HTTP_INFRA_ERROR); } } // This class provides information about errors that occur while servicing a request. // This include unhandled exceptions, viewstate errors, input validation errors, etc. [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebRequestErrorEvent : WebBaseErrorEvent { WebRequestInformation _requestInfo; WebThreadInformation _threadInfo; void Init(Exception e) { } override internal void PreProcessEventInit() { base.PreProcessEventInit(); InitRequestInformation(); InitThreadInformation(); } internal protected WebRequestErrorEvent(string message, object eventSource, int eventCode, Exception exception) :base(message, eventSource, eventCode, exception) { Init(exception); } internal protected WebRequestErrorEvent(string message, object eventSource, int eventCode, int eventDetailCode, Exception exception) :base(message, eventSource, eventCode, eventDetailCode, exception) { Init(exception); } internal WebRequestErrorEvent() { // For creating dummy event. See GetSystemDummyEvent() } // properties void InitRequestInformation() { if (_requestInfo == null) { _requestInfo = new WebRequestInformation(); } } public WebRequestInformation RequestInformation { get { InitRequestInformation(); return _requestInfo; } } void InitThreadInformation() { if (_threadInfo == null) { _threadInfo = new WebThreadInformation(base.ErrorException); } } public WebThreadInformation ThreadInformation { get { InitThreadInformation(); return _threadInfo; } } override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information)); formatter.IndentationLevel += 1; RequestInformation.FormatToString(formatter); formatter.IndentationLevel -= 1; formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_information)); formatter.IndentationLevel += 1; ThreadInformation.FormatToString(formatter); formatter.IndentationLevel -= 1; } internal override void GenerateFieldsForMarshal(List fields) { base.GenerateFieldsForMarshal(fields); fields.Add(new WebEventFieldData("RequestUrl", RequestInformation.RequestUrl, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RequestPath", RequestInformation.RequestPath, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserHostAddress", RequestInformation.UserHostAddress, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserName", RequestInformation.Principal.Identity.Name, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserAuthenticated", RequestInformation.Principal.Identity.IsAuthenticated.ToString(), WebEventFieldType.Bool)); fields.Add(new WebEventFieldData("UserAuthenticationType", RequestInformation.Principal.Identity.AuthenticationType, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RequestThreadAccountName", RequestInformation.ThreadAccountName, WebEventFieldType.String)); fields.Add(new WebEventFieldData("ThreadID", ThreadInformation.ThreadID.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int)); fields.Add(new WebEventFieldData("ThreadAccountName", ThreadInformation.ThreadAccountName, WebEventFieldType.String)); fields.Add(new WebEventFieldData("StackTrace", ThreadInformation.StackTrace, WebEventFieldType.String)); fields.Add(new WebEventFieldData("IsImpersonating", ThreadInformation.IsImpersonating.ToString(), WebEventFieldType.Bool)); } override internal protected void IncrementPerfCounters() { base.IncrementPerfCounters(); PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_HTTP_REQ_ERROR); PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_EVENTS_HTTP_REQ_ERROR); } } // The base class for all audit events. [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebAuditEvent : WebManagementEvent { WebRequestInformation _requestInfo; override internal void PreProcessEventInit() { base.PreProcessEventInit(); InitRequestInformation(); } internal protected WebAuditEvent(string message, object eventSource, int eventCode) :base(message, eventSource, eventCode) { } internal protected WebAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode) :base(message, eventSource, eventCode, eventDetailCode) { } internal WebAuditEvent() { // For creating dummy event. See GetSystemDummyEvent() } void InitRequestInformation() { if (_requestInfo == null) { _requestInfo = new WebRequestInformation(); } } public WebRequestInformation RequestInformation { get { InitRequestInformation(); return _requestInfo; } } internal override void GenerateFieldsForMarshal(List fields) { base.GenerateFieldsForMarshal(fields); fields.Add(new WebEventFieldData("RequestUrl", RequestInformation.RequestUrl, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RequestPath", RequestInformation.RequestPath, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserHostAddress", RequestInformation.UserHostAddress, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserName", RequestInformation.Principal.Identity.Name, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserAuthenticated", RequestInformation.Principal.Identity.IsAuthenticated.ToString(), WebEventFieldType.Bool)); fields.Add(new WebEventFieldData("UserAuthenticationType", RequestInformation.Principal.Identity.AuthenticationType, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RequestThreadAccountName", RequestInformation.ThreadAccountName, WebEventFieldType.String)); } override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information)); formatter.IndentationLevel += 1; RequestInformation.FormatToString(formatter); formatter.IndentationLevel -= 1; } } // This class provides information about all failure audits. In most cases, // applications will only want to enable failure audits. [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebFailureAuditEvent : WebAuditEvent { internal protected WebFailureAuditEvent(string message, object eventSource, int eventCode) :base(message, eventSource, eventCode) { } internal protected WebFailureAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode) :base(message, eventSource, eventCode, eventDetailCode) { } internal WebFailureAuditEvent() { // For creating dummy event. See GetSystemDummyEvent() } override internal protected void IncrementPerfCounters() { base.IncrementPerfCounters(); PerfCounters.IncrementCounter(AppPerfCounter.AUDIT_FAIL); PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_AUDIT_FAIL); } } [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebAuthenticationFailureAuditEvent : WebFailureAuditEvent { string _nameToAuthenticate; void Init(string name) { _nameToAuthenticate = name; } internal protected WebAuthenticationFailureAuditEvent(string message, object eventSource, int eventCode, string nameToAuthenticate) :base(message, eventSource, eventCode) { Init(nameToAuthenticate); } internal protected WebAuthenticationFailureAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode, string nameToAuthenticate) :base(message, eventSource, eventCode, eventDetailCode) { Init(nameToAuthenticate); } internal WebAuthenticationFailureAuditEvent() { // For creating dummy event. See GetSystemDummyEvent() } public string NameToAuthenticate { get { return _nameToAuthenticate; } } internal override void GenerateFieldsForMarshal(List fields) { base.GenerateFieldsForMarshal(fields); fields.Add(new WebEventFieldData("NameToAuthenticate", NameToAuthenticate, WebEventFieldType.String)); } override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_name_to_authenticate, _nameToAuthenticate)); } } [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebViewStateFailureAuditEvent : WebFailureAuditEvent { ViewStateException _viewStateException; internal protected WebViewStateFailureAuditEvent(string message, object eventSource, int eventCode, ViewStateException viewStateException) :base(message, eventSource, eventCode) { _viewStateException = viewStateException; } internal protected WebViewStateFailureAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode, ViewStateException viewStateException) :base(message, eventSource, eventCode, eventDetailCode) { _viewStateException = viewStateException; } internal WebViewStateFailureAuditEvent() { // For creating dummy event. See GetSystemDummyEvent() } public ViewStateException ViewStateException { get { return _viewStateException; } } internal override void GenerateFieldsForMarshal(List fields) { base.GenerateFieldsForMarshal(fields); fields.Add(new WebEventFieldData("ViewStateExceptionMessage", ViewStateException.Message, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RemoteAddress", ViewStateException.RemoteAddress, WebEventFieldType.String)); fields.Add(new WebEventFieldData("RemotePort", ViewStateException.RemotePort, WebEventFieldType.String)); fields.Add(new WebEventFieldData("UserAgent", ViewStateException.UserAgent, WebEventFieldType.String)); fields.Add(new WebEventFieldData("PersistedState", ViewStateException.PersistedState, WebEventFieldType.String)); fields.Add(new WebEventFieldData("Path", ViewStateException.Path, WebEventFieldType.String)); fields.Add(new WebEventFieldData("Referer", ViewStateException.Referer, WebEventFieldType.String)); } override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_ViewStateException_information)); formatter.IndentationLevel += 1; formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_exception_message, _viewStateException.Message)); formatter.IndentationLevel -= 1; } } // This class provides information about all success audits. In most cases, // applications will only want to enable failure audits. [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebSuccessAuditEvent : WebAuditEvent { internal protected WebSuccessAuditEvent(string message, object eventSource, int eventCode) :base(message, eventSource, eventCode) { } internal protected WebSuccessAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode) :base(message, eventSource, eventCode, eventDetailCode) { } internal WebSuccessAuditEvent() { // For creating dummy event. See GetSystemDummyEvent() } override internal protected void IncrementPerfCounters() { base.IncrementPerfCounters(); PerfCounters.IncrementCounter(AppPerfCounter.AUDIT_SUCCESS); PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_AUDIT_SUCCESS); } } [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebAuthenticationSuccessAuditEvent : WebSuccessAuditEvent { string _nameToAuthenticate; void Init(string name) { _nameToAuthenticate = name; } internal protected WebAuthenticationSuccessAuditEvent(string message, object eventSource, int eventCode, string nameToAuthenticate) :base(message, eventSource, eventCode) { Init(nameToAuthenticate); } internal protected WebAuthenticationSuccessAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode, string nameToAuthenticate) :base(message, eventSource, eventCode, eventDetailCode) { Init(nameToAuthenticate); } internal WebAuthenticationSuccessAuditEvent() { // For creating dummy event. See GetSystemDummyEvent() } public string NameToAuthenticate { get { return _nameToAuthenticate; } } internal override void GenerateFieldsForMarshal(List fields) { base.GenerateFieldsForMarshal(fields); fields.Add(new WebEventFieldData("NameToAuthenticate", NameToAuthenticate, WebEventFieldType.String)); } override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) { base.FormatToString(formatter, includeAppInfo); formatter.AppendLine(String.Empty); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_name_to_authenticate, _nameToAuthenticate)); } } //////////////// // Information //////////////// [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] public sealed class WebProcessInformation { // The information is per worker process instance. int _processId; string _processName; string _accountName; internal WebProcessInformation() { // Can't use Process.ProcessName because it requires the running // account to be part of the Performance Monitor Users group. StringBuilder buf = new StringBuilder(256); if (UnsafeNativeMethods.GetModuleFileName(IntPtr.Zero, buf, 256) == 0) { _processName = String.Empty; } else { int lastIndex; _processName = buf.ToString(); lastIndex = _processName.LastIndexOf('\\'); if (lastIndex != -1) { _processName = _processName.Substring(lastIndex + 1); } } _processId = SafeNativeMethods.GetCurrentProcessId() ; _accountName = HttpRuntime.WpUserId; } public int ProcessID { get { return _processId; } } public string ProcessName { get { return _processName; } } public string AccountName { get { return (_accountName != null ? _accountName : String.Empty); } } public void FormatToString(WebEventFormatter formatter) { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_id, ProcessID.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_name, ProcessName)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_account_name, AccountName)); } } [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] public sealed class WebApplicationInformation { // The information is per appdomain. string _appDomain; string _trustLevel; string _appUrl; string _appPath; string _machineName; internal WebApplicationInformation() { _appDomain = Thread.GetDomain().FriendlyName; _trustLevel = HttpRuntime.TrustLevel; _appUrl = HttpRuntime.AppDomainAppVirtualPath; try { // We will get an exception if it's a non-ASP.NET app. _appPath = HttpRuntime.AppDomainAppPath; } catch { _appPath = null; } #if FEATURE_PAL // FEATURE_PAL does not fully implement Environment.MachineName _machineName = "dummymachinename"; #else // FEATURE_PAL _machineName = GetMachineNameWithAssert(); #endif // FEATURE_PAL } public string ApplicationDomain { get { return _appDomain; } } public string TrustLevel { get { return _trustLevel; } } public string ApplicationVirtualPath { get { return _appUrl; } } public string ApplicationPath { get { return _appPath; } } public string MachineName { get { return _machineName; } } public void FormatToString(WebEventFormatter formatter) { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_domain, ApplicationDomain)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_trust_level, TrustLevel)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_virtual_path, ApplicationVirtualPath)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_path, ApplicationPath)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_machine_name, MachineName)); } [PermissionSet(SecurityAction.Assert, Unrestricted = true)] private string GetMachineNameWithAssert() { return Environment.MachineName; } public override string ToString() { WebEventFormatter formatter = new WebEventFormatter(); FormatToString(formatter); return formatter.ToString(); } } [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] public sealed class WebRequestInformation { string _requestUrl; string _requestPath; IPrincipal _iprincipal; string _userHostAddress = null; string _accountName; internal WebRequestInformation() { // Need to Assert() in order to get request information regardless of trust level. See InternalSecurityPermissions.ControlPrincipal.Assert(); HttpContext context = HttpContext.Current; if (context == null) { _requestUrl = String.Empty; _requestPath = String.Empty; _iprincipal = null; _userHostAddress = String.Empty; } else { HttpRequest request = context.Request; _requestUrl = request.UrlInternal; _requestPath = request.Path; _iprincipal = context.User; _userHostAddress = request.UserHostAddress; } _accountName = WindowsIdentity.GetCurrent().Name; } // The information is per request. public string RequestUrl {get {return _requestUrl;}} public string RequestPath {get {return _requestPath;}} public IPrincipal Principal {get {return _iprincipal;}} public string UserHostAddress { get { return _userHostAddress;} } public string ThreadAccountName {get {return _accountName;}} public void FormatToString(WebEventFormatter formatter) { string user; string authType; bool authed; if (Principal == null) { user = String.Empty; authType = String.Empty; authed = false; } else { IIdentity id = Principal.Identity; user = id.Name; authed = id.IsAuthenticated; authType = id.AuthenticationType; } formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_url, RequestUrl)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_path, RequestPath)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_user_host_address, UserHostAddress)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_user, user)); if (authed) { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_authenticated)); } else { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_not_authenticated)); } formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_authentication_type, authType)); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_account_name, ThreadAccountName)); } } // Note that even all the information contained in WebProcessStatistics is obtained from static variables, // but we still don't want this class to be static. // // Currently, WebProcessStatistics can be obtained only thru WebHeartbeatEvent, which in turn can be // created only by Full-trust app thru class inheritance. (System.Web.dll will also internally create it // and the object will be available to our provider.) Thus, WebProcessStatistics is available only // to Full-trust app or provider. // // But if we make WebProcessStatistics static, then all its public methods have to be static, and // they'll be fully available to all users. No good. [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)] public class WebProcessStatistics { static DateTime s_startTime = DateTime.MinValue; static DateTime s_lastUpdated = DateTime.MinValue; static int s_threadCount; static long s_workingSet; static long s_peakWorkingSet; static long s_managedHeapSize; static int s_appdomainCount; static int s_requestsExecuting; static int s_requestsQueued; static int s_requestsRejected; static bool s_getCurrentProcFailed = false; static object s_lockObject = new object(); static TimeSpan TS_ONE_SECOND = new TimeSpan(0, 0, 1); static WebProcessStatistics() { try { #if !FEATURE_PAL // FEATURE_PAL does not support this. Make into a noop. s_startTime = Process.GetCurrentProcess().StartTime; #endif // !FEATURE_PAL } catch { s_getCurrentProcFailed = true; } } void Update() { DateTime now = DateTime.Now; if (now - s_lastUpdated < TS_ONE_SECOND) { return; } lock (s_lockObject) { if (now - s_lastUpdated < TS_ONE_SECOND) { return; } if (!s_getCurrentProcFailed) { Process process = Process.GetCurrentProcess(); #if !FEATURE_PAL // FEATURE_PAL does not support these Process properties s_threadCount = process.Threads.Count; s_workingSet = (long)process.WorkingSet64; s_peakWorkingSet = (long)process.PeakWorkingSet64; #else throw new NotImplementedException ("ROTORTODO"); #endif } s_managedHeapSize = GC.GetTotalMemory(false); s_appdomainCount = HostingEnvironment.AppDomainsCount; s_requestsExecuting = PerfCounters.GetGlobalCounter(GlobalPerfCounter.REQUESTS_CURRENT); s_requestsQueued = PerfCounters.GetGlobalCounter(GlobalPerfCounter.REQUESTS_QUEUED); s_requestsRejected = PerfCounters.GetGlobalCounter(GlobalPerfCounter.REQUESTS_REJECTED); s_lastUpdated = now; } } public DateTime ProcessStartTime {get {Update(); return s_startTime;}} public int ThreadCount {get {Update(); return s_threadCount;}} public long WorkingSet {get {Update(); return s_workingSet;}} public long PeakWorkingSet {get {Update(); return s_peakWorkingSet;}} public long ManagedHeapSize {get {Update(); return s_managedHeapSize;}} public int AppDomainCount {get {Update(); return s_appdomainCount;}} public int RequestsExecuting {get {Update(); return s_requestsExecuting;}} public int RequestsQueued {get {Update(); return s_requestsQueued;}} public int RequestsRejected {get {Update(); return s_requestsRejected;}} virtual public void FormatToString(WebEventFormatter formatter) { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_start_time, ProcessStartTime.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_count, ThreadCount.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_working_set, WorkingSet.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_peak_working_set, PeakWorkingSet.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_managed_heap_size, ManagedHeapSize.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_domain_count, AppDomainCount.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_requests_executing, RequestsExecuting.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_queued, RequestsQueued.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_rejected, RequestsRejected.ToString(CultureInfo.InstalledUICulture))); } } [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] public sealed class WebThreadInformation { int _threadId; string _accountName; string _stackTrace; bool _isImpersonating; internal const string IsImpersonatingKey = "AS----ERSONATING"; internal WebThreadInformation(Exception exception) { _threadId = Thread.CurrentThread.ManagedThreadId; _accountName = WindowsIdentity.GetCurrent().Name; if (exception != null) { _stackTrace = new StackTrace(exception, true).ToString(); } else { _stackTrace = String.Empty; } _isImpersonating = exception.Data.Contains(IsImpersonatingKey); } public int ThreadID {get {return _threadId;}} public string ThreadAccountName {get {return _accountName;}} public string StackTrace {get {return _stackTrace;}} public bool IsImpersonating {get {return _isImpersonating;}} public void FormatToString(WebEventFormatter formatter) { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_id, ThreadID.ToString(CultureInfo.InstalledUICulture))); formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_account_name, ThreadAccountName)); if (IsImpersonating) { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_impersonating)); } else { formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_not_impersonating)); } formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_stack_trace, StackTrace)); } } // Class that represents the firing record (how many times, last firing time, etc) // for each rule that inherits from WebBaseEvent. [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] public sealed class RuleFiringRecord { internal DateTime _lastFired; internal int _timesRaised; internal int _updatingLastFired; static TimeSpan TS_ONE_SECOND = new TimeSpan(0, 0, 1); public DateTime LastFired { get { return _lastFired; } } public int TimesRaised { get { return _timesRaised; } } // Point to the ruleInfo that is used by this class internal HealthMonitoringSectionHelper.RuleInfo _ruleInfo; internal RuleFiringRecord(HealthMonitoringSectionHelper.RuleInfo ruleInfo) { Debug.Assert(ruleInfo != null, "ruleInfo != null"); _ruleInfo = ruleInfo; _lastFired = DateTime.MinValue; _timesRaised = 0; _updatingLastFired = 0; } void UpdateLastFired(DateTime now, bool alreadyLocked) { TimeSpan tsDiff = now - _lastFired; if (tsDiff < TS_ONE_SECOND) { // If _lastFired was updated within one second, don't bother. return; } if (!alreadyLocked) { // If several threads are firing at the same time, only one thread will // update record._lastFired. if (Interlocked.CompareExchange(ref _updatingLastFired, 1, 0) == 0) { try { _lastFired = now; } finally { Interlocked.Exchange(ref _updatingLastFired, 0); } } } else { _lastFired = now; } } // Note: this method is thread safe internal bool CheckAndUpdate(WebBaseEvent eventRaised) { DateTime now = DateTime.Now; int timesRaised; HealthMonitoringManager manager = HealthMonitoringManager.Manager(); timesRaised = Interlocked.Increment(ref _timesRaised); if (manager == null) { // Won't fire because we cannot configure healthmonitor Debug.Trace("RuleFiringRecord", "Can't configure healthmonitor"); return false; } // Call custom evaluator first if (_ruleInfo._customEvaluatorType != null) { IWebEventCustomEvaluator icustom = (IWebEventCustomEvaluator) manager._sectionHelper._customEvaluatorInstances[_ruleInfo._customEvaluatorType]; #if (!DBG) try { #endif // The event may need to do pre-ProcessEvent initialization eventRaised.PreProcessEventInit(); if (!icustom.CanFire(eventRaised, this)) { Debug.Trace("RuleFiringRecord", "Custom evaluator returns false."); return false; } #if (!DBG) } catch { Debug.Trace("RuleFiringRecord", "Hit an exception when calling Custom evaluator"); // Return if we hit an error return false; } #endif } if (timesRaised < _ruleInfo._minInstances) { Debug.Trace("RuleFiringRecord", "MinInterval not met; timesRaised=" + timesRaised + "; _minInstances=" + _ruleInfo._minInstances); return false; } if (timesRaised > _ruleInfo._maxLimit) { Debug.Trace("RuleFiringRecord", "MaxLimit exceeded; timesRaised=" + timesRaised + "; _maxLimit=" + _ruleInfo._maxLimit); return false; } // Last step: Check MinInterval and update _lastFired if (_ruleInfo._minInterval == TimeSpan.Zero) { UpdateLastFired(now, false); return true; } if ((now - _lastFired) <= _ruleInfo._minInterval) { Debug.Trace("RuleFiringRecord", "MinInterval not met; now=" + now + "; _lastFired=" + _lastFired + "; _ruleInfo._minInterval=" + _ruleInfo._minInterval); return false; } // The lock is to prevent multiple threads from passign the // same test simultaneously. lock (this) { if ((now - _lastFired) <= _ruleInfo._minInterval) { Debug.Trace("RuleFiringRecord", "MinInterval not met; now=" + now + "; _lastFired=" + _lastFired + "; _ruleInfo._tsMinInterval=" + _ruleInfo._minInterval); return false; } UpdateLastFired(now, true); return true; } } } internal class HealthMonitoringManager { internal HealthMonitoringSectionHelper _sectionHelper; internal bool _enabled = false; static Timer s_heartbeatTimer = null; static HealthMonitoringManager s_manager = null; static bool s_inited = false; static bool s_initing = false; static object s_lockObject = new object(); // If this method returns null, it means we failed during configuration. internal static HealthMonitoringManager Manager() { if (s_initing) { Debug.Assert(!s_inited); // If this is true, that means we are calling WebEventBase.Raise while // we are initializing. That means Init() has caused a config exception. return null; } if (s_inited) { return s_manager; } lock (s_lockObject) { if (s_inited) { return s_manager; } try { Debug.Assert(s_manager == null); s_initing = true; s_manager = new HealthMonitoringManager();; } finally { s_initing = false; s_inited = true; } } return s_manager; } internal static bool Enabled { get { HealthMonitoringManager manager = HealthMonitoringManager.Manager(); if (manager == null) { return false; } return manager._enabled; } } internal static void StartHealthMonitoringHeartbeat() { HealthMonitoringManager manager = Manager(); if (manager == null) { Debug.Trace( "HealthMonitoringManager", "Can't fire heartbeat because we cannot configure HealthMon"); return; } if (!manager._enabled) { Debug.Trace( "WebEventRaiseDetails", "Can't fire heartbeat because we are disabled"); return; } manager.StartHeartbeatTimer(); } private HealthMonitoringManager() { _sectionHelper = HealthMonitoringSectionHelper.GetHelper(); _enabled = _sectionHelper.Enabled; if (!_enabled) { return; } } internal static void Shutdown() { WebEventManager.Shutdown(); Dispose(); } internal static void Dispose() { // Make sure this function won't throw try { if (s_heartbeatTimer != null) { s_heartbeatTimer.Dispose(); s_heartbeatTimer = null; } } catch { } } internal void HeartbeatCallback(object state) { Debug.Assert(HealthMonitoringManager.Enabled); WebBaseEvent.RaiseSystemEvent(null, WebEventCodes.ApplicationHeartbeat); } internal void StartHeartbeatTimer() { TimeSpan interval = _sectionHelper.HealthMonitoringSection.HeartbeatInterval; if (interval == TimeSpan.Zero) { return; } #if DBG if (!Debug.IsTagPresent("Timer") || Debug.IsTagEnabled("Timer")) #endif { s_heartbeatTimer = new Timer(new TimerCallback(this.HeartbeatCallback), null, TimeSpan.Zero, interval); } } internal static HealthMonitoringSectionHelper.ProviderInstances ProviderInstances { get { HealthMonitoringManager manager = Manager(); if (manager == null) { return null; } if (!manager._enabled) { return null; } return manager._sectionHelper._providerInstances; } } } [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] public sealed class WebBaseEventCollection : ReadOnlyCollectionBase { public WebBaseEventCollection(ICollection events) { if (events == null) { throw new ArgumentNullException("events"); } foreach (WebBaseEvent eventRaised in events) { InnerList.Add(eventRaised); } } internal WebBaseEventCollection(WebBaseEvent eventRaised) { if (eventRaised == null) { throw new ArgumentNullException("eventRaised"); } InnerList.Add(eventRaised); } // overloaded collection access methods public WebBaseEvent this[int index] { get { return (WebBaseEvent) InnerList[index]; } } public int IndexOf(WebBaseEvent value) { return InnerList.IndexOf(value); } public bool Contains(WebBaseEvent value) { return InnerList.Contains(value); } } [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)] public static class WebEventManager { [SecurityPermission(SecurityAction.Demand, Unrestricted=true)] public static void Flush(string providerName) { HealthMonitoringSectionHelper.ProviderInstances providers = HealthMonitoringManager.ProviderInstances; if (providers == null) { return; } if (!providers.ContainsKey(providerName)) { throw new ArgumentException(SR.GetString(SR.Health_mon_provider_not_found, providerName)); } using (new ApplicationImpersonationContext()) { providers[providerName].Flush(); } } [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)] [SecurityPermission(SecurityAction.Demand, Unrestricted=true)] public static void Flush() { HealthMonitoringSectionHelper.ProviderInstances providers = HealthMonitoringManager.ProviderInstances; if (providers == null) { return; } using (new ApplicationImpersonationContext()) { foreach(DictionaryEntry de in providers) { WebEventProvider provider = (WebEventProvider)de.Value; Debug.Trace("WebEventManager", "Flushing provider " + provider.Name); provider.Flush(); } } } internal static void Shutdown() { HealthMonitoringSectionHelper.ProviderInstances providers = HealthMonitoringManager.ProviderInstances; if (providers == null) { return; } foreach(DictionaryEntry de in providers) { WebEventProvider provider = (WebEventProvider)de.Value; Debug.Trace("WebEventManager", "Shutting down provider " + provider.Name); provider.Shutdown(); } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- StorageEntitySetMapping.cs
- OleDbCommand.cs
- WrappedIUnknown.cs
- NaturalLanguageHyphenator.cs
- DecimalMinMaxAggregationOperator.cs
- Configuration.cs
- InputScopeManager.cs
- SafeBitVector32.cs
- ProfileManager.cs
- ObjectRef.cs
- Guid.cs
- RegexRunnerFactory.cs
- StringSorter.cs
- DrawingState.cs
- LookupBindingPropertiesAttribute.cs
- SecurityTokenAuthenticator.cs
- SQLInt32.cs
- SmtpClient.cs
- ResourceReader.cs
- TrayIconDesigner.cs
- DirectoryInfo.cs
- DataColumnMapping.cs
- DbRetry.cs
- ClosureBinding.cs
- DataGridViewCheckBoxColumn.cs
- EnterpriseServicesHelper.cs
- ChannelFactoryBase.cs
- RequestResponse.cs
- UnauthorizedWebPart.cs
- ColumnResult.cs
- PasswordBoxAutomationPeer.cs
- InfoCardBaseException.cs
- XamlClipboardData.cs
- DataTable.cs
- ProfessionalColors.cs
- WebServicesInteroperability.cs
- TypeDelegator.cs
- TextViewBase.cs
- IncomingWebRequestContext.cs
- PropertyItem.cs
- SeparatorAutomationPeer.cs
- RequestFactory.cs
- SapiRecoInterop.cs
- Roles.cs
- ProjectionAnalyzer.cs
- SymDocumentType.cs
- _LocalDataStore.cs
- DataGridViewButtonCell.cs
- StatusBar.cs
- SymmetricAlgorithm.cs
- Preprocessor.cs
- ToolStripItemCollection.cs
- CommandValueSerializer.cs
- PropertyGridView.cs
- ToolStripActionList.cs
- FlowPosition.cs
- Crc32Helper.cs
- EventToken.cs
- MemoryMappedView.cs
- ServiceReference.cs
- SkipStoryboardToFill.cs
- WebBrowserContainer.cs
- JapaneseCalendar.cs
- DataObjectEventArgs.cs
- ComboBoxItem.cs
- RangeValidator.cs
- ListViewGroup.cs
- documentation.cs
- Group.cs
- DataBindingCollection.cs
- SpellerHighlightLayer.cs
- DataBindingValueUIHandler.cs
- JpegBitmapDecoder.cs
- ICspAsymmetricAlgorithm.cs
- RemoteDebugger.cs
- ComponentFactoryHelpers.cs
- regiisutil.cs
- ToggleButtonAutomationPeer.cs
- SqlException.cs
- InkCanvasSelectionAdorner.cs
- GridView.cs
- FindCompletedEventArgs.cs
- SapiInterop.cs
- TextPenaltyModule.cs
- InputReportEventArgs.cs
- ResourceWriter.cs
- InstanceData.cs
- FontConverter.cs
- WmlListAdapter.cs
- PolyQuadraticBezierSegment.cs
- SynchronizedRandom.cs
- SqlParameterCollection.cs
- EntityDataSourceDataSelection.cs
- NativeObjectSecurity.cs
- ExpandableObjectConverter.cs
- ArrayTypeMismatchException.cs
- HybridDictionary.cs
- TypeConverterAttribute.cs
- XsltConvert.cs
- StreamGeometry.cs