1 //------------------------------------------------------------------------------
2 // <copyright file="WebEvents.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
7 namespace System.Web.Management {
9 using System.Collections;
10 using System.Collections.Generic;
11 using System.Configuration;
12 using System.Configuration.Provider;
13 using System.Diagnostics;
14 using System.Globalization;
15 using System.Runtime.Remoting.Messaging;
16 using System.Security;
17 using System.Security.Permissions;
18 using System.Security.Principal;
20 using System.Threading;
22 using System.Web.Caching;
23 using System.Web.Configuration;
24 using System.Web.Hosting;
25 using System.Web.Security;
27 using System.Web.Util;
29 using Debug = System.Web.Util.Debug;
31 // This enum matches the native one enum WebEventType (in webevent.h).
32 internal enum WebEventType : int {
33 WEBEVENT_BASE_EVENT = 0,
34 WEBEVENT_MANAGEMENT_EVENT,
35 WEBEVENT_APP_LIFETIME_EVENT,
36 WEBEVENT_REQUEST_EVENT,
37 WEBEVENT_HEARTBEAT_EVENT,
38 WEBEVENT_BASE_ERROR_EVENT,
39 WEBEVENT_REQUEST_ERROR_EVENT,
42 WEBEVENT_SUCCESS_AUDIT_EVENT,
43 WEBEVENT_AUTHENTICATION_SUCCESS_AUDIT_EVENT,
44 WEBEVENT_FAILURE_AUDIT_EVENT,
45 WEBEVENT_AUTHENTICATION_FAILURE_AUDIT_EVENT,
46 WEBEVENT_VIEWSTATE_FAILURE_AUDIT_EVENT,
49 internal enum WebEventFieldType : int {
57 // Used for marshalling over to IIS Trace
58 internal class WebEventFieldData {
73 WebEventFieldType _type;
74 public WebEventFieldType Type {
80 public WebEventFieldData(string name, string data, WebEventFieldType type) {
88 // Interface for event provider
89 public abstract class WebEventProvider : ProviderBase {
92 public abstract void ProcessEvent(WebBaseEvent raisedEvent);
93 public abstract void Shutdown();
94 public abstract void Flush();
98 internal void LogException(Exception e) {
99 // In order to not overflow the eventlog, we only log one exception per provider instance.
100 if (Interlocked.CompareExchange( ref _exceptionLogged, 1, 0) == 0) {
101 // Log all errors in eventlog
102 UnsafeNativeMethods.LogWebeventProviderFailure(
103 HttpRuntime.AppDomainAppVirtualPath,
110 // Interface for custom event evaluator
112 public interface IWebEventCustomEvaluator {
113 bool CanFire(WebBaseEvent raisedEvent, RuleFiringRecord record);
120 public class WebBaseEvent {
121 DateTime _eventTimeUtc;
126 long _sequenceNumber;
127 long _occurrenceNumber;
128 Guid _id = Guid.Empty;
130 static long s_globalSequenceNumber = 0;
131 static WebApplicationInformation s_applicationInfo = new WebApplicationInformation();
132 const string WEBEVENT_RAISE_IN_PROGRESS = "_WEvtRIP";
134 // A array that cache the result of eventCode to SystemEventType mapping.
135 static readonly SystemEventType[,] s_eventCodeToSystemEventTypeMappings = new SystemEventType[WebEventCodes.GetEventArrayDimensionSize(0),
136 WebEventCodes.GetEventArrayDimensionSize(1)];
138 // A array that store the # of occurrence per custom event code.
139 static readonly long[,] s_eventCodeOccurrence = new long[WebEventCodes.GetEventArrayDimensionSize(0),
140 WebEventCodes.GetEventArrayDimensionSize(1)];
142 static Hashtable s_customEventCodeOccurrence = new Hashtable();
143 #pragma warning disable 0649
144 static ReadWriteSpinLock s_lockCustomEventCodeOccurrence;
145 #pragma warning restore 0649
147 static WebBaseEvent() {
149 // Initialize the mappings. We will fill up each entry on demand by calling
150 // SystemEventTypeFromEventCode().
152 for (int i = 0; i < s_eventCodeToSystemEventTypeMappings.GetLength(0); i++) {
153 for (int j = 0; j < s_eventCodeToSystemEventTypeMappings.GetLength(1); j++) {
154 s_eventCodeToSystemEventTypeMappings[i,j] = SystemEventType.Unknown;
158 for (int i = 0; i < s_eventCodeOccurrence.GetLength(0); i++) {
159 for (int j = 0; j < s_eventCodeOccurrence.GetLength(1); j++) {
160 s_eventCodeOccurrence[i,j] = 0;
165 void Init(string message, Object eventSource, int eventCode, int eventDetailCode) {
167 throw new ArgumentOutOfRangeException("eventCode",
168 SR.GetString(SR.Invalid_eventCode_error));
171 if (eventDetailCode < 0) {
172 throw new ArgumentOutOfRangeException("eventDetailCode",
173 SR.GetString(SR.Invalid_eventDetailCode_error));
177 _detailCode = eventDetailCode;
178 _source = eventSource;
179 _eventTimeUtc = DateTime.UtcNow;
182 // Creation of _id is always delayed until it's needed.
186 internal protected WebBaseEvent(string message, Object eventSource, int eventCode) {
187 Init(message, eventSource, eventCode, WebEventCodes.UndefinedEventDetailCode);
190 internal protected WebBaseEvent(string message, Object eventSource, int eventCode, int eventDetailCode) {
191 Init(message, eventSource, eventCode, eventDetailCode);
194 internal WebBaseEvent() {
195 // For creating dummy event. See GetSystemDummyEvent()
198 internal bool IsSystemEvent {
200 return (_code < WebEventCodes.WebExtendedBase);
206 public DateTime EventTime { get { return _eventTimeUtc.ToLocalTime(); } }
208 public DateTime EventTimeUtc { get { return _eventTimeUtc; } }
210 public String Message { get { return _message; } }
212 public Object EventSource { get { return _source; } }
214 public long EventSequence { get { return _sequenceNumber; } }
216 public long EventOccurrence { get { return _occurrenceNumber; } }
218 public int EventCode { get { return _code; } }
220 public int EventDetailCode { get { return _detailCode; } }
222 public Guid EventID {
224 if (_id == Guid.Empty) {
226 if (_id == Guid.Empty) {
227 _id = Guid.NewGuid();
236 public static WebApplicationInformation ApplicationInformation {
237 get { return s_applicationInfo; }
240 virtual internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
241 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_code, EventCode.ToString(CultureInfo.InstalledUICulture)));
242 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_message, Message));
243 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_time, EventTime.ToString(CultureInfo.InstalledUICulture)));
244 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_time_Utc, EventTimeUtc.ToString(CultureInfo.InstalledUICulture)));
245 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_id, EventID.ToString("N", CultureInfo.InstalledUICulture)));
246 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_sequence, EventSequence.ToString(CultureInfo.InstalledUICulture)));
247 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_occurrence, EventOccurrence.ToString(CultureInfo.InstalledUICulture)));
248 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_detail_code, EventDetailCode.ToString(CultureInfo.InstalledUICulture)));
250 if (includeAppInfo) {
251 formatter.AppendLine(String.Empty);
252 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_information));
253 formatter.IndentationLevel += 1;
254 ApplicationInformation.FormatToString(formatter);
255 formatter.IndentationLevel -= 1;
260 public override string ToString() {
261 return ToString(true, true);
264 public virtual string ToString(bool includeAppInfo, bool includeCustomEventDetails) {
265 WebEventFormatter formatter = new WebEventFormatter();
267 FormatToString(formatter, includeAppInfo);
269 if (!IsSystemEvent && includeCustomEventDetails) {
270 formatter.AppendLine(String.Empty);
271 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_custom_event_details));
272 formatter.IndentationLevel += 1;
273 FormatCustomEventDetails(formatter);
274 formatter.IndentationLevel -= 1;
277 return formatter.ToString();
280 virtual public void FormatCustomEventDetails(WebEventFormatter formatter) {
283 internal int InferEtwTraceVerbosity() {
284 WebEventType type = WebBaseEvent.WebEventTypeFromWebEvent(this);
286 case WebEventType.WEBEVENT_VIEWSTATE_FAILURE_AUDIT_EVENT:
287 case WebEventType.WEBEVENT_BASE_ERROR_EVENT:
288 case WebEventType.WEBEVENT_REQUEST_ERROR_EVENT:
289 case WebEventType.WEBEVENT_FAILURE_AUDIT_EVENT:
290 case WebEventType.WEBEVENT_AUTHENTICATION_FAILURE_AUDIT_EVENT:
291 case WebEventType.WEBEVENT_ERROR_EVENT:
292 return EtwTraceLevel.Warning;
293 case WebEventType.WEBEVENT_AUDIT_EVENT:
294 case WebEventType.WEBEVENT_SUCCESS_AUDIT_EVENT:
295 case WebEventType.WEBEVENT_AUTHENTICATION_SUCCESS_AUDIT_EVENT:
296 return EtwTraceLevel.Information;
297 case WebEventType.WEBEVENT_BASE_EVENT:
298 case WebEventType.WEBEVENT_MANAGEMENT_EVENT:
299 case WebEventType.WEBEVENT_REQUEST_EVENT:
301 return EtwTraceLevel.Verbose;
305 internal void DeconstructWebEvent(out int eventType, out int fieldCount, out string[] fieldNames, out int[] fieldTypes, out string[] fieldData) {
306 List<WebEventFieldData> fields = new List<WebEventFieldData>();
308 eventType = (int)WebBaseEvent.WebEventTypeFromWebEvent(this);
309 GenerateFieldsForMarshal(fields);
310 fieldCount = fields.Count;
311 fieldNames = new string[fieldCount];
312 fieldData = new string[fieldCount];
313 fieldTypes = new int[fieldCount];
315 for (int i = 0; i < fieldCount; ++i) {
316 fieldNames[i] = fields[i].Name;
317 fieldData[i] = fields[i].Data;
318 fieldTypes[i] = (int)fields[i].Type;
322 internal virtual void GenerateFieldsForMarshal(List<WebEventFieldData> fields) {
323 fields.Add(new WebEventFieldData("EventTime", EventTimeUtc.ToString(), WebEventFieldType.String));
324 fields.Add(new WebEventFieldData("EventID", EventID.ToString(), WebEventFieldType.String));
325 fields.Add(new WebEventFieldData("EventMessage", Message, WebEventFieldType.String));
326 fields.Add(new WebEventFieldData("ApplicationDomain", WebBaseEvent.ApplicationInformation.ApplicationDomain, WebEventFieldType.String));
327 fields.Add(new WebEventFieldData("TrustLevel", WebBaseEvent.ApplicationInformation.TrustLevel, WebEventFieldType.String));
328 fields.Add(new WebEventFieldData("ApplicationVirtualPath", WebBaseEvent.ApplicationInformation.ApplicationVirtualPath, WebEventFieldType.String));
329 fields.Add(new WebEventFieldData("ApplicationPath", WebBaseEvent.ApplicationInformation.ApplicationPath, WebEventFieldType.String));
330 fields.Add(new WebEventFieldData("MachineName", WebBaseEvent.ApplicationInformation.MachineName, WebEventFieldType.String));
331 fields.Add(new WebEventFieldData("EventCode", EventCode.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int));
332 fields.Add(new WebEventFieldData("EventDetailCode", EventDetailCode.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int));
333 fields.Add(new WebEventFieldData("SequenceNumber", EventSequence.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Long));
334 fields.Add(new WebEventFieldData("Occurrence", EventOccurrence.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Long));
337 internal virtual void PreProcessEventInit() {
340 static void FindEventCode(Exception e, ref int eventCode, ref int eventDetailsCode, ref Exception eStack) {
341 eventDetailsCode = WebEventCodes.UndefinedEventDetailCode;
343 if (e is ConfigurationException) {
344 eventCode = WebEventCodes.WebErrorConfigurationError;
346 else if (e is HttpRequestValidationException) {
347 eventCode = WebEventCodes.RuntimeErrorValidationFailure;
349 else if (e is HttpCompileException) {
350 eventCode = WebEventCodes.WebErrorCompilationError;
352 else if (e is SecurityException) {
353 eventCode = WebEventCodes.AuditUnhandledSecurityException;
355 else if (e is UnauthorizedAccessException) {
356 eventCode = WebEventCodes.AuditUnhandledAccessException;
358 else if (e is HttpParseException) {
359 eventCode = WebEventCodes.WebErrorParserError;
361 else if (e is HttpException && e.InnerException is ViewStateException) {
362 ViewStateException vse = (ViewStateException)e.InnerException;
363 eventCode = WebEventCodes.AuditInvalidViewStateFailure;
364 if (vse._macValidationError) {
365 eventDetailsCode = WebEventCodes.InvalidViewStateMac;
368 eventDetailsCode = WebEventCodes.InvalidViewState;
373 else if (e is HttpException && ((HttpException)e).WebEventCode != WebEventCodes.UndefinedEventCode) {
374 eventCode = ((HttpException)e).WebEventCode;
377 // We don't know what it is. Let's see if we can find it out by using the inner exception.
379 if (e.InnerException != null) {
380 // We will call FindEventCode recusively to find out if e.InnerException is the real one.
382 if (eStack == null) {
383 // Set eStack here. If the recursive call ends up landing in
384 // WebEventCodes.RuntimeErrorUnhandledException, we'll use the original
385 // inner exception as our final result.
386 eStack = e.InnerException;
389 FindEventCode(e.InnerException, ref eventCode, ref eventDetailsCode, ref eStack);
392 // It doesn't have an inner exception. Just return the generic unhandled-exception
393 eventCode = WebEventCodes.RuntimeErrorUnhandledException;
397 if (eStack == null) {
402 static internal void RaiseRuntimeError(Exception e, object source) {
403 Debug.Trace("WebEventRaiseError", "Error Event is raised; type=" + e.GetType().Name);
405 if (!HealthMonitoringManager.Enabled) {
410 int eventCode = WebEventCodes.UndefinedEventCode;
411 int eventDetailsCode = WebEventCodes.UndefinedEventDetailCode;
412 HttpContext context = HttpContext.Current;
413 Exception eStack = null;
415 if (context != null) {
416 Page page = context.Handler as Page;
418 // Errors from Transacted pages can be wrapped by a
422 e.GetType() == typeof(HttpException) &&
423 e.InnerException != null) {
425 e = e.InnerException;
429 FindEventCode(e, ref eventCode, ref eventDetailsCode, ref eStack);
430 WebBaseEvent.RaiseSystemEvent(source, eventCode, eventDetailsCode, eStack);
436 virtual internal protected void IncrementPerfCounters() {
437 PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_TOTAL);
440 class CustomEventCodeOccurrence {
441 internal long _occurrence;
444 internal void IncrementTotalCounters(int index0, int index1) {
445 _sequenceNumber = Interlocked.Increment(ref s_globalSequenceNumber);
448 _occurrenceNumber = Interlocked.Increment(ref s_eventCodeOccurrence[index0, index1]);
451 CustomEventCodeOccurrence ceco = (CustomEventCodeOccurrence)s_customEventCodeOccurrence[_code];
454 s_lockCustomEventCodeOccurrence.AcquireWriterLock();
456 ceco = (CustomEventCodeOccurrence)s_customEventCodeOccurrence[_code];
458 ceco = new CustomEventCodeOccurrence();
459 s_customEventCodeOccurrence[_code] = ceco;
463 s_lockCustomEventCodeOccurrence.ReleaseWriterLock();
467 _occurrenceNumber = Interlocked.Increment(ref ceco._occurrence);
471 [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)]
472 virtual public void Raise() {
476 // Internally raised events don't go thru this method. They go directly to RaiseSystemEvent --> RaiseInternal
477 [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)]
478 static public void Raise(WebBaseEvent eventRaised) {
479 if (eventRaised.EventCode < WebEventCodes.WebExtendedBase) {
480 throw new HttpException(SR.GetString(SR.System_eventCode_not_allowed,
481 eventRaised.EventCode.ToString(CultureInfo.CurrentCulture),
482 WebEventCodes.WebExtendedBase.ToString(CultureInfo.CurrentCulture)));
485 if (!HealthMonitoringManager.Enabled) {
487 "WebEventRaiseDetails", "Can't fire event because we are disabled or we can't configure HealthMonManager");
491 RaiseInternal(eventRaised, null, -1, -1);
494 static internal void RaiseInternal(WebBaseEvent eventRaised, ArrayList firingRuleInfos, int index0, int index1) {
495 bool preProcessEventInitCalled = false;
496 bool inProgressSet = false;
498 ProcessImpersonationContext ictx = null;
499 HttpContext context = HttpContext.Current;
502 "WebEventRaiseDetails", "Event is raised; event class = " + eventRaised.GetType().Name);
504 // Use CallContext to make sure we detect an infinite loop where a provider calls Raise().
505 o = CallContext.GetData(WEBEVENT_RAISE_IN_PROGRESS);
506 if (o != null && (bool)o) {
508 "WebEventRaiseDetails", "An event is raised while we're raising an event. Ignore it.");
512 eventRaised.IncrementPerfCounters();
513 eventRaised.IncrementTotalCounters(index0, index1);
515 // Find the list of rules that match this event
516 if (firingRuleInfos == null) {
517 HealthMonitoringManager manager = HealthMonitoringManager.Manager();
519 Debug.Assert(manager != null, "manager != null");
521 firingRuleInfos = manager._sectionHelper.FindFiringRuleInfos(eventRaised.GetType(), eventRaised.EventCode);
524 if (firingRuleInfos.Count == 0) {
529 bool[] matchingProviderArray = null;
531 if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null)
532 EtwTrace.Trace(EtwTraceType.ETW_TYPE_WEB_EVENT_RAISE_START,
533 context.WorkerRequest,
534 eventRaised.GetType().FullName,
535 eventRaised.EventCode.ToString(CultureInfo.InstalledUICulture),
536 eventRaised.EventDetailCode.ToString(CultureInfo.InstalledUICulture),
540 foreach (HealthMonitoringSectionHelper.FiringRuleInfo firingRuleInfo in firingRuleInfos) {
541 HealthMonitoringSectionHelper.RuleInfo ruleInfo = firingRuleInfo._ruleInfo;
542 RuleFiringRecord record = ruleInfo._ruleFiringRecord;
544 // Check if we should fire the event based on its throttling settings
545 if (!record.CheckAndUpdate(eventRaised)) {
546 Debug.Trace("WebEventRaiseDetails",
547 "Throttling settings not met; not fired");
551 // It's valid for a rule to have no referenced provider
552 if (ruleInfo._referencedProvider != null) {
553 if (!preProcessEventInitCalled) {
554 // The event may need to do pre-ProcessEvent initialization
555 eventRaised.PreProcessEventInit();
556 preProcessEventInitCalled = true;
559 // For rule infos that share the same provider, the _indexOfFirstRuleInfoWithSameProvider field
560 // is the index of the first ruleInfo among them. We use that index in the boolean array
561 // matchingProviderArray to remember if we've already fired that provider.
562 // This is for the scenario where several rules are pointing to the same provider,
563 // and even if >1 rule actually fire and pass all throttling check,
564 // the provider is stilled fired only once.
565 if (firingRuleInfo._indexOfFirstRuleInfoWithSameProvider != -1) {
566 if (matchingProviderArray == null) {
567 matchingProviderArray = new bool[firingRuleInfos.Count];
570 if (matchingProviderArray[firingRuleInfo._indexOfFirstRuleInfoWithSameProvider]) {
571 Debug.Trace("WebEventRaiseDetails",
572 "Rule with a matching provider already fired.");
576 matchingProviderArray[firingRuleInfo._indexOfFirstRuleInfoWithSameProvider] = true;
579 if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null)
580 EtwTrace.Trace(EtwTraceType.ETW_TYPE_WEB_EVENT_DELIVER_START,
581 context.WorkerRequest,
582 ruleInfo._ruleSettings.Provider,
583 ruleInfo._ruleSettings.Name,
584 ruleInfo._ruleSettings.EventName,
587 // In retail build, ignore errors from provider
590 ictx = new ProcessImpersonationContext();
593 if (!inProgressSet) {
594 CallContext.SetData(WEBEVENT_RAISE_IN_PROGRESS, true);
595 inProgressSet = true;
598 Debug.Trace("WebEventRaiseDetails", "Calling ProcessEvent under " + HttpApplication.GetCurrentWindowsIdentityWithAssert().Name);
599 ruleInfo._referencedProvider.ProcessEvent(eventRaised);
601 catch (Exception e) {
603 ruleInfo._referencedProvider.LogException(e);
610 if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null)
611 EtwTrace.Trace(EtwTraceType.ETW_TYPE_WEB_EVENT_DELIVER_END,
612 context.WorkerRequest);
618 // Resume client impersonation
624 CallContext.FreeNamedDataSlot(WEBEVENT_RAISE_IN_PROGRESS);
627 if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null)
628 EtwTrace.Trace(EtwTraceType.ETW_TYPE_WEB_EVENT_RAISE_END,
629 context.WorkerRequest);
632 catch { throw; } // Prevent Exception Filter Security Issue (ASURT 122835)
635 internal static void RaiseSystemEvent(string message, object source, int eventCode, int eventDetailCode, Exception exception) {
636 RaiseSystemEventInternal(message, source, eventCode, eventDetailCode, exception, null);
639 internal static void RaiseSystemEvent(object source, int eventCode) {
640 RaiseSystemEventInternal(null, source, eventCode, WebEventCodes.UndefinedEventDetailCode, null, null);
643 internal static void RaiseSystemEvent(object source, int eventCode, int eventDetailCode) {
644 RaiseSystemEventInternal(null, source, eventCode, eventDetailCode, null, null);
647 internal static void RaiseSystemEvent(object source, int eventCode, int eventDetailCode, Exception exception) {
648 RaiseSystemEventInternal(null, source, eventCode, eventDetailCode, exception, null);
651 internal static void RaiseSystemEvent(object source, int eventCode, string nameToAuthenticate) {
652 RaiseSystemEventInternal(null, source, eventCode, WebEventCodes.UndefinedEventDetailCode, null, nameToAuthenticate);
655 [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
656 static void RaiseSystemEventInternal(string message, object source,
657 int eventCode, int eventDetailCode, Exception exception,
658 string nameToAuthenticate) {
659 HealthMonitoringManager manager;
660 ArrayList firingRuleInfos;
661 SystemEventTypeInfo typeInfo;
662 SystemEventType systemEventType;
666 "WebEventRaiseDetails", "RaiseSystemEventInternal called; eventCode=" + eventCode + "; eventDetailCode=" + eventDetailCode);
668 if (!HealthMonitoringManager.Enabled) {
670 "WebEventRaiseDetails", "Can't fire event because we are disabled or we can't configure HealthMonManager");
674 WebEventCodes.GetEventArrayIndexsFromEventCode(eventCode, out index0, out index1);
676 GetSystemEventTypeInfo(eventCode, index0, index1, out typeInfo, out systemEventType);
677 if (typeInfo == null) {
678 Debug.Assert(false, "Unexpected system event code = " + eventCode);
682 manager = HealthMonitoringManager.Manager();
684 // Figure out if there is any provider that subscribes to it
685 firingRuleInfos = manager._sectionHelper.FindFiringRuleInfos(typeInfo._type, eventCode);
686 if (firingRuleInfos.Count == 0) {
687 // Even if we're not firing it, we still have to increment some global counters
688 typeInfo._dummyEvent.IncrementPerfCounters();
689 typeInfo._dummyEvent.IncrementTotalCounters(index0, index1);
692 // We will fire the event
693 WebBaseEvent.RaiseInternal(
694 NewEventFromSystemEventType(false, systemEventType, message, source, eventCode, eventDetailCode,
695 exception, nameToAuthenticate),
696 firingRuleInfos, index0, index1);
700 // An enum of all the types of web event we will fire
701 enum SystemEventType {
703 WebApplicationLifetimeEvent,
706 WebRequestErrorEvent,
708 WebAuthenticationSuccessAuditEvent,
709 WebSuccessAuditEvent,
710 WebAuthenticationFailureAuditEvent,
711 WebFailureAuditEvent,
712 WebViewStateFailureAuditEvent,
716 class SystemEventTypeInfo {
717 internal WebBaseEvent _dummyEvent; // For calling IncrementPerfCounters. See RaiseSystemEventInternal for details.
720 internal SystemEventTypeInfo(WebBaseEvent dummyEvent) {
721 _dummyEvent = dummyEvent;
722 _type = dummyEvent.GetType();
726 // An array to cache the event type info for each system event type
727 static SystemEventTypeInfo[] s_systemEventTypeInfos = new SystemEventTypeInfo[(int)SystemEventType.Last];
729 static void GetSystemEventTypeInfo(int eventCode, int index0, int index1,
730 out SystemEventTypeInfo info, out SystemEventType systemEventType) {
732 // Figure out what SystemEventType this eventCode maps to.
733 // For each eventCode, we store the result in a cache.
734 systemEventType = s_eventCodeToSystemEventTypeMappings[index0, index1];
735 if (systemEventType == SystemEventType.Unknown) {
736 systemEventType = SystemEventTypeFromEventCode(eventCode);
737 s_eventCodeToSystemEventTypeMappings[index0, index1] = systemEventType;
740 // Based on the systemEventType, we read the SystemEventTypeInfo. For each
741 // event type, we also cache the info
742 info = s_systemEventTypeInfos[(int)systemEventType];
747 info = new SystemEventTypeInfo(CreateDummySystemEvent(systemEventType));
748 s_systemEventTypeInfos[(int)systemEventType] = info;
751 static SystemEventType SystemEventTypeFromEventCode(int eventCode) {
752 if (eventCode >= WebEventCodes.ApplicationCodeBase &&
753 eventCode <= WebEventCodes.ApplicationCodeBaseLast) {
755 case WebEventCodes.ApplicationStart:
756 case WebEventCodes.ApplicationShutdown:
757 case WebEventCodes.ApplicationCompilationStart:
758 case WebEventCodes.ApplicationCompilationEnd:
759 return SystemEventType.WebApplicationLifetimeEvent;
761 case WebEventCodes.ApplicationHeartbeat:
762 return SystemEventType.WebHeartbeatEvent;
766 if (eventCode >= WebEventCodes.RequestCodeBase &&
767 eventCode <= WebEventCodes.RequestCodeBaseLast) {
770 case WebEventCodes.RequestTransactionComplete:
771 case WebEventCodes.RequestTransactionAbort:
772 return SystemEventType.WebRequestEvent;
776 if (eventCode >= WebEventCodes.ErrorCodeBase &&
777 eventCode <= WebEventCodes.ErrorCodeBaseLast) {
779 case WebEventCodes.RuntimeErrorRequestAbort:
780 case WebEventCodes.RuntimeErrorViewStateFailure:
781 case WebEventCodes.RuntimeErrorValidationFailure:
782 case WebEventCodes.RuntimeErrorPostTooLarge:
783 case WebEventCodes.RuntimeErrorUnhandledException:
784 case WebEventCodes.RuntimeErrorWebResourceFailure:
785 return SystemEventType.WebRequestErrorEvent;
787 case WebEventCodes.WebErrorParserError:
788 case WebEventCodes.WebErrorCompilationError:
789 case WebEventCodes.WebErrorConfigurationError:
790 case WebEventCodes.WebErrorOtherError:
791 case WebEventCodes.WebErrorPropertyDeserializationError:
792 case WebEventCodes.WebErrorObjectStateFormatterDeserializationError:
793 return SystemEventType.WebErrorEvent;
797 if (eventCode >= WebEventCodes.AuditCodeBase &&
798 eventCode <= WebEventCodes.AuditCodeBaseLast) {
800 case WebEventCodes.AuditFormsAuthenticationSuccess:
801 case WebEventCodes.AuditMembershipAuthenticationSuccess:
802 return SystemEventType.WebAuthenticationSuccessAuditEvent;
804 case WebEventCodes.AuditUrlAuthorizationSuccess:
805 case WebEventCodes.AuditFileAuthorizationSuccess:
806 return SystemEventType.WebSuccessAuditEvent;
808 case WebEventCodes.AuditFormsAuthenticationFailure:
809 case WebEventCodes.AuditMembershipAuthenticationFailure:
810 return SystemEventType.WebAuthenticationFailureAuditEvent;
812 case WebEventCodes.AuditUrlAuthorizationFailure:
813 case WebEventCodes.AuditFileAuthorizationFailure:
814 case WebEventCodes.AuditUnhandledSecurityException:
815 case WebEventCodes.AuditUnhandledAccessException:
816 return SystemEventType.WebFailureAuditEvent;
818 case WebEventCodes.AuditInvalidViewStateFailure:
819 return SystemEventType.WebViewStateFailureAuditEvent;
823 if (eventCode >= WebEventCodes.MiscCodeBase &&
824 eventCode <= WebEventCodes.MiscCodeBaseLast) {
826 case WebEventCodes.WebEventProviderInformation:
827 Debug.Assert(false, "WebEventProviderInformation shouldn't be used to Raise an event");
828 return SystemEventType.Unknown;
832 return SystemEventType.Unknown;
835 static WebBaseEvent CreateDummySystemEvent(SystemEventType systemEventType) {
836 return NewEventFromSystemEventType(true, systemEventType, null,
837 null, 0, 0, null, null);
840 static WebBaseEvent NewEventFromSystemEventType(bool createDummy, SystemEventType systemEventType, string message,
841 object source,int eventCode, int eventDetailCode, Exception exception,
842 string nameToAuthenticate) {
843 // If createDummy == true, it means we're only creating a dummy event for the sake of using
844 // it to call IncrementPerfCounters()
846 if (!createDummy && message == null) {
847 message = WebEventCodes.MessageFromEventCode(eventCode, eventDetailCode);
850 // Code view note for the future:
851 // If the number of systemEventType increases tremendoulsy, we may need to
852 // avoid using switch, and change to use a "factory" to create new event.
854 switch(systemEventType) {
855 case SystemEventType.WebApplicationLifetimeEvent:
856 return createDummy ? new WebApplicationLifetimeEvent() : new WebApplicationLifetimeEvent(message, source, eventCode, eventDetailCode);
858 case SystemEventType.WebHeartbeatEvent:
859 return createDummy ? new WebHeartbeatEvent() : new WebHeartbeatEvent(message, eventCode);
861 case SystemEventType.WebRequestEvent:
862 return createDummy ? new WebRequestEvent() : new WebRequestEvent(message, source, eventCode, eventDetailCode);
864 case SystemEventType. WebRequestErrorEvent:
865 return createDummy ? new WebRequestErrorEvent() : new WebRequestErrorEvent(message, source, eventCode, eventDetailCode, exception);
867 case SystemEventType.WebErrorEvent:
868 return createDummy ? new WebErrorEvent() : new WebErrorEvent(message, source, eventCode, eventDetailCode, exception);
870 case SystemEventType.WebAuthenticationSuccessAuditEvent:
871 return createDummy ? new WebAuthenticationSuccessAuditEvent() : new WebAuthenticationSuccessAuditEvent(message, source, eventCode, eventDetailCode, nameToAuthenticate);
873 case SystemEventType.WebSuccessAuditEvent:
874 return createDummy ? new WebSuccessAuditEvent() : new WebSuccessAuditEvent(message, source, eventCode, eventDetailCode);
876 case SystemEventType.WebAuthenticationFailureAuditEvent:
877 return createDummy ? new WebAuthenticationFailureAuditEvent() : new WebAuthenticationFailureAuditEvent(message, source, eventCode, eventDetailCode, nameToAuthenticate);
879 case SystemEventType.WebFailureAuditEvent:
880 return createDummy ? new WebFailureAuditEvent() : new WebFailureAuditEvent(message, source, eventCode, eventDetailCode);
882 case SystemEventType.WebViewStateFailureAuditEvent:
883 return createDummy ? new WebViewStateFailureAuditEvent() : new WebViewStateFailureAuditEvent(message, source, eventCode, eventDetailCode, (System.Web.UI.ViewStateException)exception);
886 Debug.Assert(false, "Unexpected event type = " + systemEventType);
891 static string CreateWebEventResourceCacheKey(String key) {
892 return CacheInternal.PrefixWebEventResource + key;
895 internal static String FormatResourceStringWithCache(String key) {
896 // HealthMonitoring, in some scenarios, can call into the cache hundreds of
897 // times during shutdown, after the cache has been disposed. To improve
898 // shutdown performance, skip the cache when it is disposed.
899 if (HealthMonitoringManager.IsCacheDisposed) {
900 return SR.Resources.GetString(key, CultureInfo.InstalledUICulture);
903 CacheStoreProvider cacheInternal = HttpRuntime.Cache.InternalCache;
906 string cacheKey = CreateWebEventResourceCacheKey(key);
908 s = (string) cacheInternal.Get(cacheKey);
913 s = SR.Resources.GetString(key, CultureInfo.InstalledUICulture);
915 cacheInternal.Insert(cacheKey, s, null);
921 internal static String FormatResourceStringWithCache(String key, String arg0) {
922 string fmt = FormatResourceStringWithCache(key);
923 return(fmt != null) ? String.Format(fmt, arg0) : null;
926 internal static WebEventType WebEventTypeFromWebEvent(WebBaseEvent eventRaised) {
928 // eventRaised can belong to one of the following classes, or can inherit from one of them.
929 // In order to figure out precisely the WebEventType closest to the type of eventRaised,
930 // we will start our comparison from the leaf nodes in the class hierarchy and work our
933 // Webevent class hierarchy (with the info contained in each class):
937 - WebBaseEvent (basic)
938 - WebManagementEvent (+ WebProcessInformation)
939 - WebHeartbeatEvent (+ WebProcessStatistics)
940 - WebApplicationLifetimeEvent
941 - WebRequestEvent (+ WebRequestInformation)
942 - WebBaseErrorEvent (+ Exception)
943 - WebRequestErrorEvent (+ WebRequestInformation + WebThreadInformation)
944 - WebErrorEvent (+ WebRequestInformation + WebThreadInformation)
945 - WebAuditEvent (+ WebRequestInformation)
946 - WebSuccessAuditEvent
947 - WebAuthenticationSuccessAuditEvent (+ NameToAuthenticate)
948 - WebFailureAuditEvent
949 - WebAuthenticationFailureAuditEvent (+ NameToAuthenticate)
950 - WebViewStateFailureAuditEvent (+ ViewStateException)
955 if (eventRaised is WebAuthenticationSuccessAuditEvent) {
956 return WebEventType.WEBEVENT_AUTHENTICATION_SUCCESS_AUDIT_EVENT;
959 if (eventRaised is WebAuthenticationFailureAuditEvent) {
960 return WebEventType.WEBEVENT_AUTHENTICATION_FAILURE_AUDIT_EVENT;
963 if (eventRaised is WebViewStateFailureAuditEvent) {
964 return WebEventType.WEBEVENT_VIEWSTATE_FAILURE_AUDIT_EVENT;
969 if (eventRaised is WebRequestErrorEvent) {
970 return WebEventType.WEBEVENT_REQUEST_ERROR_EVENT;
973 if (eventRaised is WebErrorEvent) {
974 return WebEventType.WEBEVENT_ERROR_EVENT;
977 if (eventRaised is WebSuccessAuditEvent) {
978 return WebEventType.WEBEVENT_SUCCESS_AUDIT_EVENT;
981 if (eventRaised is WebFailureAuditEvent) {
982 return WebEventType.WEBEVENT_FAILURE_AUDIT_EVENT;
987 if (eventRaised is WebHeartbeatEvent) {
988 return WebEventType.WEBEVENT_HEARTBEAT_EVENT;
991 if (eventRaised is WebApplicationLifetimeEvent) {
992 return WebEventType.WEBEVENT_APP_LIFETIME_EVENT;
995 if (eventRaised is WebRequestEvent) {
996 return WebEventType.WEBEVENT_REQUEST_EVENT;
999 if (eventRaised is WebBaseErrorEvent) {
1000 return WebEventType.WEBEVENT_BASE_ERROR_EVENT;
1003 if (eventRaised is WebAuditEvent) {
1004 return WebEventType.WEBEVENT_AUDIT_EVENT;
1007 // Hierarchy level 2
1009 if (eventRaised is WebManagementEvent) {
1010 return WebEventType.WEBEVENT_MANAGEMENT_EVENT;
1013 // Hierarchy level 1
1015 return WebEventType.WEBEVENT_BASE_EVENT;
1018 static internal void RaisePropertyDeserializationWebErrorEvent(SettingsProperty property, object source, Exception exception) {
1019 if (HttpContext.Current == null) {
1023 WebBaseEvent.RaiseSystemEvent(
1024 SR.GetString(SR.Webevent_msg_Property_Deserialization,
1025 property.Name, property.SerializeAs.ToString(), property.PropertyType.AssemblyQualifiedName ),
1027 WebEventCodes.WebErrorPropertyDeserializationError,
1028 WebEventCodes.UndefinedEventDetailCode,
1033 public class WebEventFormatter {
1042 _sb.Append(' ', _tabSize);
1047 internal WebEventFormatter() {
1049 _sb = new StringBuilder();
1053 public void AppendLine(string s) {
1059 new public string ToString() {
1060 return _sb.ToString();
1063 public int IndentationLevel {
1064 get { return _level; }
1065 set { _level = Math.Max(value, 0); }
1068 public int TabSize {
1069 get { return _tabSize; }
1070 set { _tabSize = Math.Max(value, 0); }
1074 // This class is a base class for all events that require application and process information.
1076 // WebManagementEvent is the base class for all our webevent classes (except for WebBaseEvent)
1077 // Please note that we allow customer to inherit from our webevent classes to make it easier to
1078 // create custom webevent that contains useful information.
1079 // However, WebManagementEvent (and other child events) contains sensitive information (e.g. process id, process account name)
1080 // that cannot be obtained unless in full-trust.
1082 // In non-fulltrust app, we still want code inside system.web.dll to create these webevents
1083 // even if there is user code on the stack (we either assert or call unmanaged code to get those info).
1084 // So to protect these full-trust information from non-fulltrust app, we InheritanceDemand FullTrust
1085 // if the customer wants to inherit from WebManagementEvent.
1087 // For details, see VSWhidbey 256684.
1089 [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)]
1090 public class WebManagementEvent : WebBaseEvent {
1091 static WebProcessInformation s_processInfo = new WebProcessInformation();
1093 internal protected WebManagementEvent(string message, object eventSource, int eventCode)
1094 :base(message, eventSource, eventCode) {
1097 internal protected WebManagementEvent(string message, object eventSource, int eventCode, int eventDetailCode)
1098 :base(message, eventSource, eventCode, eventDetailCode) {
1101 internal WebManagementEvent() {
1102 // For creating dummy event. See GetSystemDummyEvent()
1106 public WebProcessInformation ProcessInformation {
1107 get { return s_processInfo; }
1110 internal override void GenerateFieldsForMarshal(List<WebEventFieldData> fields) {
1111 base.GenerateFieldsForMarshal(fields);
1112 fields.Add(new WebEventFieldData("AccountName", ProcessInformation.AccountName, WebEventFieldType.String));
1113 fields.Add(new WebEventFieldData("ProcessName", ProcessInformation.ProcessName, WebEventFieldType.String));
1114 fields.Add(new WebEventFieldData("ProcessID", ProcessInformation.ProcessID.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int));
1117 override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1118 base.FormatToString(formatter, includeAppInfo);
1120 formatter.AppendLine(String.Empty);
1121 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_information));
1123 formatter.IndentationLevel += 1;
1124 ProcessInformation.FormatToString(formatter);
1125 formatter.IndentationLevel -= 1;
1131 // This event is raised at periodic intervals (default 30 seconds) and provides information
1132 // relative to the state of the running appdomin.
1134 public class WebHeartbeatEvent : WebManagementEvent {
1135 static WebProcessStatistics s_procStats = new WebProcessStatistics();
1137 internal protected WebHeartbeatEvent(string message, int eventCode)
1138 :base(message, null, eventCode)
1142 internal WebHeartbeatEvent() {
1143 // For creating dummy event. See GetSystemDummyEvent()
1147 public WebProcessStatistics ProcessStatistics {get {return s_procStats;}}
1149 override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1150 base.FormatToString(formatter, includeAppInfo);
1152 formatter.AppendLine(String.Empty);
1153 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_statistics));
1155 formatter.IndentationLevel += 1;
1156 s_procStats.FormatToString(formatter);
1157 formatter.IndentationLevel -= 1;
1162 // This event represents a notable event in the lifetime of an application (app domain)
1163 // including startup and shutdown events. When an app domain is terminated, the reason
1164 // will be expressed in the Message field (e.g. compilation threshold exceed, Shutdown
1165 // called explicitly, etc.).
1167 public class WebApplicationLifetimeEvent : WebManagementEvent {
1169 internal protected WebApplicationLifetimeEvent(string message, object eventSource, int eventCode)
1170 :base(message, eventSource, eventCode)
1175 internal protected WebApplicationLifetimeEvent(string message, object eventSource, int eventCode, int eventDetailCode)
1176 :base(message, eventSource, eventCode, eventDetailCode)
1180 internal WebApplicationLifetimeEvent() {
1181 // For creating dummy event. See GetSystemDummyEvent()
1184 static internal int DetailCodeFromShutdownReason(ApplicationShutdownReason reason) {
1186 case ApplicationShutdownReason.HostingEnvironment:
1187 return WebEventCodes.ApplicationShutdownHostingEnvironment;
1189 case ApplicationShutdownReason.ChangeInGlobalAsax:
1190 return WebEventCodes.ApplicationShutdownChangeInGlobalAsax;
1192 case ApplicationShutdownReason.ConfigurationChange:
1193 return WebEventCodes.ApplicationShutdownConfigurationChange;
1195 case ApplicationShutdownReason.UnloadAppDomainCalled:
1196 return WebEventCodes.ApplicationShutdownUnloadAppDomainCalled;
1198 case ApplicationShutdownReason.ChangeInSecurityPolicyFile:
1199 return WebEventCodes.ApplicationShutdownChangeInSecurityPolicyFile;
1201 case ApplicationShutdownReason.BinDirChangeOrDirectoryRename:
1202 return WebEventCodes.ApplicationShutdownBinDirChangeOrDirectoryRename;
1204 case ApplicationShutdownReason.BrowsersDirChangeOrDirectoryRename:
1205 return WebEventCodes.ApplicationShutdownBrowsersDirChangeOrDirectoryRename;
1207 case ApplicationShutdownReason.CodeDirChangeOrDirectoryRename:
1208 return WebEventCodes.ApplicationShutdownCodeDirChangeOrDirectoryRename;
1210 case ApplicationShutdownReason.ResourcesDirChangeOrDirectoryRename:
1211 return WebEventCodes.ApplicationShutdownResourcesDirChangeOrDirectoryRename;
1213 case ApplicationShutdownReason.IdleTimeout:
1214 return WebEventCodes.ApplicationShutdownIdleTimeout;
1216 case ApplicationShutdownReason.PhysicalApplicationPathChanged:
1217 return WebEventCodes.ApplicationShutdownPhysicalApplicationPathChanged;
1219 case ApplicationShutdownReason.HttpRuntimeClose:
1220 return WebEventCodes.ApplicationShutdownHttpRuntimeClose;
1222 case ApplicationShutdownReason.InitializationError:
1223 return WebEventCodes.ApplicationShutdownInitializationError;
1225 case ApplicationShutdownReason.MaxRecompilationsReached:
1226 return WebEventCodes.ApplicationShutdownMaxRecompilationsReached;
1228 case ApplicationShutdownReason.BuildManagerChange:
1229 return WebEventCodes.ApplicationShutdownBuildManagerChange;
1232 return WebEventCodes.ApplicationShutdownUnknown;
1236 override internal protected void IncrementPerfCounters() {
1237 base.IncrementPerfCounters();
1238 PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_APP);
1242 // This class serves as a base for non-error events that provide
1243 public class WebRequestEvent : WebManagementEvent {
1244 WebRequestInformation _requestInfo;
1246 override internal void PreProcessEventInit() {
1247 base.PreProcessEventInit();
1248 InitRequestInformation();
1251 internal protected WebRequestEvent(string message, object eventSource, int eventCode)
1252 :base(message, eventSource, eventCode)
1256 internal protected WebRequestEvent(string message, object eventSource, int eventCode, int eventDetailCode)
1257 :base(message, eventSource, eventCode, eventDetailCode)
1261 internal WebRequestEvent() {
1262 // For creating dummy event. See GetSystemDummyEvent()
1265 void InitRequestInformation() {
1266 if (_requestInfo == null) {
1267 _requestInfo = new WebRequestInformation();
1271 public WebRequestInformation RequestInformation {
1273 InitRequestInformation();
1274 return _requestInfo;
1278 internal override void GenerateFieldsForMarshal(List<WebEventFieldData> fields) {
1279 base.GenerateFieldsForMarshal(fields);
1280 fields.Add(new WebEventFieldData("RequestUrl", RequestInformation.RequestUrl, WebEventFieldType.String));
1281 fields.Add(new WebEventFieldData("RequestPath", RequestInformation.RequestPath, WebEventFieldType.String));
1282 fields.Add(new WebEventFieldData("UserHostAddress", RequestInformation.UserHostAddress, WebEventFieldType.String));
1283 fields.Add(new WebEventFieldData("UserName", RequestInformation.Principal.Identity.Name, WebEventFieldType.String));
1284 fields.Add(new WebEventFieldData("UserAuthenticated", RequestInformation.Principal.Identity.IsAuthenticated.ToString(), WebEventFieldType.Bool));
1285 fields.Add(new WebEventFieldData("UserAuthenticationType", RequestInformation.Principal.Identity.AuthenticationType, WebEventFieldType.String));
1286 fields.Add(new WebEventFieldData("RequestThreadAccountName", RequestInformation.ThreadAccountName, WebEventFieldType.String));
1289 override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1290 base.FormatToString(formatter, includeAppInfo);
1292 formatter.AppendLine(String.Empty);
1293 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information));
1295 formatter.IndentationLevel += 1;
1296 RequestInformation.FormatToString(formatter);
1297 formatter.IndentationLevel -= 1;
1300 override internal protected void IncrementPerfCounters() {
1301 base.IncrementPerfCounters();
1302 PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_WEB_REQ);
1306 // This is the base class for all error events.
1307 public class WebBaseErrorEvent : WebManagementEvent {
1308 Exception _exception;
1310 void Init(Exception e) {
1314 internal protected WebBaseErrorEvent(string message, object eventSource, int eventCode, Exception e)
1315 :base(message, eventSource, eventCode)
1320 internal protected WebBaseErrorEvent(string message, object eventSource, int eventCode, int eventDetailCode, Exception e)
1321 :base(message, eventSource, eventCode, eventDetailCode)
1326 internal WebBaseErrorEvent() {
1327 // For creating dummy event. See GetSystemDummyEvent()
1330 public Exception ErrorException {
1331 get { return _exception; }
1334 override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1335 base.FormatToString(formatter, includeAppInfo);
1337 if (_exception == null) {
1341 Exception ex = _exception;
1343 // Please note we arbitrary pick a level limit per bug VSWhidbey 143859
1345 ex != null && level <= 2;
1346 ex = ex.InnerException, level++) {
1348 formatter.AppendLine(String.Empty);
1351 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_exception_information));
1354 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_inner_exception_information, level.ToString(CultureInfo.InstalledUICulture)));
1357 formatter.IndentationLevel += 1;
1358 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_exception_type, ex.GetType().ToString()));
1359 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_exception_message, ex.Message));
1360 formatter.IndentationLevel -= 1;
1364 internal override void GenerateFieldsForMarshal(List<WebEventFieldData> fields) {
1365 base.GenerateFieldsForMarshal(fields);
1366 fields.Add(new WebEventFieldData("ExceptionType", ErrorException.GetType().ToString(), WebEventFieldType.String));
1367 fields.Add(new WebEventFieldData("ExceptionMessage", ErrorException.Message, WebEventFieldType.String));
1370 override internal protected void IncrementPerfCounters() {
1371 base.IncrementPerfCounters();
1372 PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_ERROR);
1373 PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_EVENTS_ERROR);
1377 // This class contains information about systemic errors, e.g. things related to
1378 // configuration or application code (parser errors, compilation errors).
1380 public class WebErrorEvent : WebBaseErrorEvent {
1381 WebRequestInformation _requestInfo;
1382 WebThreadInformation _threadInfo;
1384 void Init(Exception e) {
1387 override internal void PreProcessEventInit() {
1388 base.PreProcessEventInit();
1389 InitRequestInformation();
1390 InitThreadInformation();
1393 internal protected WebErrorEvent(string message, object eventSource, int eventCode, Exception exception)
1394 :base(message, eventSource, eventCode, exception)
1399 internal protected WebErrorEvent(string message, object eventSource, int eventCode, int eventDetailCode, Exception exception)
1400 :base(message, eventSource, eventCode, eventDetailCode, exception)
1405 internal WebErrorEvent() {
1406 // For creating dummy event. See GetSystemDummyEvent()
1409 void InitRequestInformation() {
1410 if (_requestInfo == null) {
1411 _requestInfo = new WebRequestInformation();
1415 public WebRequestInformation RequestInformation {
1417 InitRequestInformation();
1418 return _requestInfo;
1422 void InitThreadInformation() {
1423 if (_threadInfo == null) {
1424 _threadInfo = new WebThreadInformation(base.ErrorException);
1428 public WebThreadInformation ThreadInformation {
1430 InitThreadInformation();
1435 override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1436 base.FormatToString(formatter, includeAppInfo);
1438 formatter.AppendLine(String.Empty);
1439 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information));
1441 formatter.IndentationLevel += 1;
1442 RequestInformation.FormatToString(formatter);
1443 formatter.IndentationLevel -= 1;
1445 formatter.AppendLine(String.Empty);
1446 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_information));
1448 formatter.IndentationLevel += 1;
1449 ThreadInformation.FormatToString(formatter);
1450 formatter.IndentationLevel -= 1;
1453 internal override void GenerateFieldsForMarshal(List<WebEventFieldData> fields) {
1454 base.GenerateFieldsForMarshal(fields);
1455 fields.Add(new WebEventFieldData("RequestUrl", RequestInformation.RequestUrl, WebEventFieldType.String));
1456 fields.Add(new WebEventFieldData("RequestPath", RequestInformation.RequestPath, WebEventFieldType.String));
1457 fields.Add(new WebEventFieldData("UserHostAddress", RequestInformation.UserHostAddress, WebEventFieldType.String));
1458 fields.Add(new WebEventFieldData("UserName", RequestInformation.Principal.Identity.Name, WebEventFieldType.String));
1459 fields.Add(new WebEventFieldData("UserAuthenticated", RequestInformation.Principal.Identity.IsAuthenticated.ToString(), WebEventFieldType.Bool));
1460 fields.Add(new WebEventFieldData("UserAuthenticationType", RequestInformation.Principal.Identity.AuthenticationType, WebEventFieldType.String));
1461 fields.Add(new WebEventFieldData("RequestThreadAccountName", RequestInformation.ThreadAccountName, WebEventFieldType.String));
1462 fields.Add(new WebEventFieldData("ThreadID", ThreadInformation.ThreadID.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int));
1463 fields.Add(new WebEventFieldData("ThreadAccountName", ThreadInformation.ThreadAccountName, WebEventFieldType.String));
1464 fields.Add(new WebEventFieldData("StackTrace", ThreadInformation.StackTrace, WebEventFieldType.String));
1465 fields.Add(new WebEventFieldData("IsImpersonating", ThreadInformation.IsImpersonating.ToString(), WebEventFieldType.Bool));
1468 override internal protected void IncrementPerfCounters() {
1469 base.IncrementPerfCounters();
1470 PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_HTTP_INFRA_ERROR);
1471 PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_EVENTS_HTTP_INFRA_ERROR);
1475 // This class provides information about errors that occur while servicing a request.
1476 // This include unhandled exceptions, viewstate errors, input validation errors, etc.
1477 public class WebRequestErrorEvent : WebBaseErrorEvent {
1478 WebRequestInformation _requestInfo;
1479 WebThreadInformation _threadInfo;
1481 void Init(Exception e) {
1484 override internal void PreProcessEventInit() {
1485 base.PreProcessEventInit();
1486 InitRequestInformation();
1487 InitThreadInformation();
1490 internal protected WebRequestErrorEvent(string message, object eventSource, int eventCode, Exception exception)
1491 :base(message, eventSource, eventCode, exception)
1496 internal protected WebRequestErrorEvent(string message, object eventSource, int eventCode, int eventDetailCode, Exception exception)
1497 :base(message, eventSource, eventCode, eventDetailCode, exception)
1502 internal WebRequestErrorEvent() {
1503 // For creating dummy event. See GetSystemDummyEvent()
1508 void InitRequestInformation() {
1509 if (_requestInfo == null) {
1510 _requestInfo = new WebRequestInformation();
1514 public WebRequestInformation RequestInformation {
1516 InitRequestInformation();
1517 return _requestInfo;
1521 void InitThreadInformation() {
1522 if (_threadInfo == null) {
1523 _threadInfo = new WebThreadInformation(base.ErrorException);
1527 public WebThreadInformation ThreadInformation {
1529 InitThreadInformation();
1534 override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1535 base.FormatToString(formatter, includeAppInfo);
1537 formatter.AppendLine(String.Empty);
1538 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information));
1540 formatter.IndentationLevel += 1;
1541 RequestInformation.FormatToString(formatter);
1542 formatter.IndentationLevel -= 1;
1544 formatter.AppendLine(String.Empty);
1545 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_information));
1547 formatter.IndentationLevel += 1;
1548 ThreadInformation.FormatToString(formatter);
1549 formatter.IndentationLevel -= 1;
1552 internal override void GenerateFieldsForMarshal(List<WebEventFieldData> fields) {
1553 base.GenerateFieldsForMarshal(fields);
1554 fields.Add(new WebEventFieldData("RequestUrl", RequestInformation.RequestUrl, WebEventFieldType.String));
1555 fields.Add(new WebEventFieldData("RequestPath", RequestInformation.RequestPath, WebEventFieldType.String));
1556 fields.Add(new WebEventFieldData("UserHostAddress", RequestInformation.UserHostAddress, WebEventFieldType.String));
1557 fields.Add(new WebEventFieldData("UserName", RequestInformation.Principal.Identity.Name, WebEventFieldType.String));
1558 fields.Add(new WebEventFieldData("UserAuthenticated", RequestInformation.Principal.Identity.IsAuthenticated.ToString(), WebEventFieldType.Bool));
1559 fields.Add(new WebEventFieldData("UserAuthenticationType", RequestInformation.Principal.Identity.AuthenticationType, WebEventFieldType.String));
1560 fields.Add(new WebEventFieldData("RequestThreadAccountName", RequestInformation.ThreadAccountName, WebEventFieldType.String));
1561 fields.Add(new WebEventFieldData("ThreadID", ThreadInformation.ThreadID.ToString(CultureInfo.InstalledUICulture), WebEventFieldType.Int));
1562 fields.Add(new WebEventFieldData("ThreadAccountName", ThreadInformation.ThreadAccountName, WebEventFieldType.String));
1563 fields.Add(new WebEventFieldData("StackTrace", ThreadInformation.StackTrace, WebEventFieldType.String));
1564 fields.Add(new WebEventFieldData("IsImpersonating", ThreadInformation.IsImpersonating.ToString(), WebEventFieldType.Bool));
1567 override internal protected void IncrementPerfCounters() {
1568 base.IncrementPerfCounters();
1569 PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_HTTP_REQ_ERROR);
1570 PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_EVENTS_HTTP_REQ_ERROR);
1575 // The base class for all audit events.
1577 public class WebAuditEvent : WebManagementEvent {
1578 WebRequestInformation _requestInfo;
1580 override internal void PreProcessEventInit() {
1581 base.PreProcessEventInit();
1582 InitRequestInformation();
1585 internal protected WebAuditEvent(string message, object eventSource, int eventCode)
1586 :base(message, eventSource, eventCode)
1590 internal protected WebAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode)
1591 :base(message, eventSource, eventCode, eventDetailCode)
1595 internal WebAuditEvent() {
1596 // For creating dummy event. See GetSystemDummyEvent()
1599 void InitRequestInformation() {
1600 if (_requestInfo == null) {
1601 _requestInfo = new WebRequestInformation();
1605 public WebRequestInformation RequestInformation {
1607 InitRequestInformation();
1608 return _requestInfo;
1612 internal override void GenerateFieldsForMarshal(List<WebEventFieldData> fields) {
1613 base.GenerateFieldsForMarshal(fields);
1614 fields.Add(new WebEventFieldData("RequestUrl", RequestInformation.RequestUrl, WebEventFieldType.String));
1615 fields.Add(new WebEventFieldData("RequestPath", RequestInformation.RequestPath, WebEventFieldType.String));
1616 fields.Add(new WebEventFieldData("UserHostAddress", RequestInformation.UserHostAddress, WebEventFieldType.String));
1617 fields.Add(new WebEventFieldData("UserName", RequestInformation.Principal.Identity.Name, WebEventFieldType.String));
1618 fields.Add(new WebEventFieldData("UserAuthenticated", RequestInformation.Principal.Identity.IsAuthenticated.ToString(), WebEventFieldType.Bool));
1619 fields.Add(new WebEventFieldData("UserAuthenticationType", RequestInformation.Principal.Identity.AuthenticationType, WebEventFieldType.String));
1620 fields.Add(new WebEventFieldData("RequestThreadAccountName", RequestInformation.ThreadAccountName, WebEventFieldType.String));
1623 override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1624 base.FormatToString(formatter, includeAppInfo);
1626 formatter.AppendLine(String.Empty);
1627 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information));
1629 formatter.IndentationLevel += 1;
1630 RequestInformation.FormatToString(formatter);
1631 formatter.IndentationLevel -= 1;
1636 // This class provides information about all failure audits. In most cases,
1637 // applications will only want to enable failure audits.
1639 public class WebFailureAuditEvent : WebAuditEvent {
1640 internal protected WebFailureAuditEvent(string message, object eventSource, int eventCode)
1641 :base(message, eventSource, eventCode)
1645 internal protected WebFailureAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode)
1646 :base(message, eventSource, eventCode, eventDetailCode)
1650 internal WebFailureAuditEvent() {
1651 // For creating dummy event. See GetSystemDummyEvent()
1654 override internal protected void IncrementPerfCounters() {
1655 base.IncrementPerfCounters();
1656 PerfCounters.IncrementCounter(AppPerfCounter.AUDIT_FAIL);
1657 PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_AUDIT_FAIL);
1661 public class WebAuthenticationFailureAuditEvent : WebFailureAuditEvent {
1663 string _nameToAuthenticate;
1665 void Init(string name) {
1666 _nameToAuthenticate = name;
1669 internal protected WebAuthenticationFailureAuditEvent(string message, object eventSource, int eventCode, string nameToAuthenticate)
1670 :base(message, eventSource, eventCode)
1672 Init(nameToAuthenticate);
1676 internal protected WebAuthenticationFailureAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode, string nameToAuthenticate)
1677 :base(message, eventSource, eventCode, eventDetailCode)
1679 Init(nameToAuthenticate);
1682 internal WebAuthenticationFailureAuditEvent() {
1683 // For creating dummy event. See GetSystemDummyEvent()
1686 public string NameToAuthenticate {
1687 get { return _nameToAuthenticate; }
1690 internal override void GenerateFieldsForMarshal(List<WebEventFieldData> fields) {
1691 base.GenerateFieldsForMarshal(fields);
1692 fields.Add(new WebEventFieldData("NameToAuthenticate", NameToAuthenticate, WebEventFieldType.String));
1695 override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1696 base.FormatToString(formatter, includeAppInfo);
1698 formatter.AppendLine(String.Empty);
1699 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_name_to_authenticate, _nameToAuthenticate));
1704 public class WebViewStateFailureAuditEvent : WebFailureAuditEvent {
1706 ViewStateException _viewStateException;
1708 internal protected WebViewStateFailureAuditEvent(string message, object eventSource, int eventCode, ViewStateException viewStateException)
1709 :base(message, eventSource, eventCode)
1711 _viewStateException = viewStateException;
1715 internal protected WebViewStateFailureAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode, ViewStateException viewStateException)
1716 :base(message, eventSource, eventCode, eventDetailCode)
1718 _viewStateException = viewStateException;
1721 internal WebViewStateFailureAuditEvent() {
1722 // For creating dummy event. See GetSystemDummyEvent()
1725 public ViewStateException ViewStateException {
1726 get { return _viewStateException; }
1729 internal override void GenerateFieldsForMarshal(List<WebEventFieldData> fields) {
1730 base.GenerateFieldsForMarshal(fields);
1731 fields.Add(new WebEventFieldData("ViewStateExceptionMessage", ViewStateException.Message, WebEventFieldType.String));
1732 fields.Add(new WebEventFieldData("RemoteAddress", ViewStateException.RemoteAddress, WebEventFieldType.String));
1733 fields.Add(new WebEventFieldData("RemotePort", ViewStateException.RemotePort, WebEventFieldType.String));
1734 fields.Add(new WebEventFieldData("UserAgent", ViewStateException.UserAgent, WebEventFieldType.String));
1735 fields.Add(new WebEventFieldData("PersistedState", ViewStateException.PersistedState, WebEventFieldType.String));
1736 fields.Add(new WebEventFieldData("Path", ViewStateException.Path, WebEventFieldType.String));
1737 fields.Add(new WebEventFieldData("Referer", ViewStateException.Referer, WebEventFieldType.String));
1740 override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1741 base.FormatToString(formatter, includeAppInfo);
1743 formatter.AppendLine(String.Empty);
1744 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_ViewStateException_information));
1745 formatter.IndentationLevel += 1;
1746 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_exception_message, _viewStateException.Message));
1748 formatter.IndentationLevel -= 1;
1754 // This class provides information about all success audits. In most cases,
1755 // applications will only want to enable failure audits.
1757 public class WebSuccessAuditEvent : WebAuditEvent {
1758 internal protected WebSuccessAuditEvent(string message, object eventSource, int eventCode)
1759 :base(message, eventSource, eventCode)
1763 internal protected WebSuccessAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode)
1764 :base(message, eventSource, eventCode, eventDetailCode)
1768 internal WebSuccessAuditEvent() {
1769 // For creating dummy event. See GetSystemDummyEvent()
1772 override internal protected void IncrementPerfCounters() {
1773 base.IncrementPerfCounters();
1774 PerfCounters.IncrementCounter(AppPerfCounter.AUDIT_SUCCESS);
1775 PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_AUDIT_SUCCESS);
1779 public class WebAuthenticationSuccessAuditEvent : WebSuccessAuditEvent {
1781 string _nameToAuthenticate;
1783 void Init(string name) {
1784 _nameToAuthenticate = name;
1787 internal protected WebAuthenticationSuccessAuditEvent(string message, object eventSource, int eventCode, string nameToAuthenticate)
1788 :base(message, eventSource, eventCode)
1790 Init(nameToAuthenticate);
1793 internal protected WebAuthenticationSuccessAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode, string nameToAuthenticate)
1794 :base(message, eventSource, eventCode, eventDetailCode)
1796 Init(nameToAuthenticate);
1799 internal WebAuthenticationSuccessAuditEvent() {
1800 // For creating dummy event. See GetSystemDummyEvent()
1803 public string NameToAuthenticate {
1804 get { return _nameToAuthenticate; }
1807 internal override void GenerateFieldsForMarshal(List<WebEventFieldData> fields) {
1808 base.GenerateFieldsForMarshal(fields);
1809 fields.Add(new WebEventFieldData("NameToAuthenticate", NameToAuthenticate, WebEventFieldType.String));
1812 override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1813 base.FormatToString(formatter, includeAppInfo);
1815 formatter.AppendLine(String.Empty);
1816 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_name_to_authenticate, _nameToAuthenticate));
1825 public sealed class WebProcessInformation {
1826 // The information is per worker process instance.
1829 string _processName;
1830 string _accountName;
1832 internal WebProcessInformation() {
1833 // Can't use Process.ProcessName because it requires the running
1834 // account to be part of the Performance Monitor Users group.
1835 StringBuilder buf = new StringBuilder(256);
1836 if (UnsafeNativeMethods.GetModuleFileName(IntPtr.Zero, buf, 256) == 0) {
1837 _processName = String.Empty;
1842 _processName = buf.ToString();
1843 lastIndex = _processName.LastIndexOf('\\');
1844 if (lastIndex != -1) {
1845 _processName = _processName.Substring(lastIndex + 1);
1849 _processId = SafeNativeMethods.GetCurrentProcessId() ;
1850 _accountName = HttpRuntime.WpUserId;
1853 public int ProcessID { get { return _processId; } }
1855 public string ProcessName { get { return _processName; } }
1857 public string AccountName { get { return (_accountName != null ? _accountName : String.Empty); } }
1859 public void FormatToString(WebEventFormatter formatter) {
1860 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_id, ProcessID.ToString(CultureInfo.InstalledUICulture)));
1861 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_name, ProcessName));
1862 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_account_name, AccountName));
1866 public sealed class WebApplicationInformation {
1867 // The information is per appdomain.
1873 string _machineName;
1875 internal WebApplicationInformation() {
1876 _appDomain = Thread.GetDomain().FriendlyName;
1877 _trustLevel = HttpRuntime.TrustLevel;
1878 _appUrl = HttpRuntime.AppDomainAppVirtualPath;
1881 // We will get an exception if it's a non-ASP.NET app.
1882 _appPath = HttpRuntime.AppDomainAppPathInternal;
1887 #if FEATURE_PAL // FEATURE_PAL does not fully implement Environment.MachineName
1888 _machineName = "dummymachinename";
1889 #else // FEATURE_PAL
1890 _machineName = GetMachineNameWithAssert();
1891 #endif // FEATURE_PAL
1894 public string ApplicationDomain { get { return _appDomain; } }
1896 public string TrustLevel { get { return _trustLevel; } }
1898 public string ApplicationVirtualPath { get { return _appUrl; } }
1900 public string ApplicationPath { get { return _appPath; } }
1902 public string MachineName { get { return _machineName; } }
1904 public void FormatToString(WebEventFormatter formatter) {
1905 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_domain, ApplicationDomain));
1906 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_trust_level, TrustLevel));
1907 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_virtual_path, ApplicationVirtualPath));
1908 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_path, ApplicationPath));
1909 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_machine_name, MachineName));
1912 [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
1913 private string GetMachineNameWithAssert() {
1914 return Environment.MachineName;
1917 public override string ToString() {
1918 WebEventFormatter formatter = new WebEventFormatter();
1920 FormatToString(formatter);
1921 return formatter.ToString();
1925 public sealed class WebRequestInformation {
1928 string _requestPath;
1929 IPrincipal _iprincipal;
1930 string _userHostAddress = null;
1931 string _accountName;
1933 internal WebRequestInformation() {
1934 // Need to Assert() in order to get request information regardless of trust level. See VSWhidbey 416733
1935 InternalSecurityPermissions.ControlPrincipal.Assert();
1937 HttpContext context = HttpContext.Current;
1938 HttpRequest request = null;
1940 if (context != null) {
1941 bool hideRequestResponseOriginal = context.HideRequestResponse;
1942 context.HideRequestResponse = false;
1943 request = context.Request;
1944 context.HideRequestResponse = hideRequestResponseOriginal;
1946 _iprincipal = context.User;
1948 // Dev11 #80084 - DTS Bug
1949 // In integrated pipeline, we are very aggressive about disposing
1950 // WindowsIdentity's. If this WebRequestInformation is being used
1951 // post-request (eg, while formatting data for an email provider
1952 // that is reporting batched events), then the User.Identity is
1953 // likely to be disposed. So lets create a clone that will stick
1954 // around. This condition should vaguely match that found in
1955 // HttpContext.DisposePrincipal().
1956 if (_iprincipal is WindowsPrincipal
1957 && _iprincipal != WindowsAuthenticationModule.AnonymousPrincipal
1958 && (context.WorkerRequest is IIS7WorkerRequest)) {
1959 WindowsIdentity winIdentity = _iprincipal.Identity as WindowsIdentity;
1960 if (winIdentity != null) {
1961 _iprincipal = new WindowsPrincipal(new WindowsIdentity(winIdentity.Token, winIdentity.AuthenticationType));
1968 if (request == null) {
1969 _requestUrl = String.Empty;
1970 _requestPath = String.Empty;
1971 _userHostAddress = String.Empty;
1974 _requestUrl = request.UrlInternal;
1975 _requestPath = request.Path;
1976 _userHostAddress = request.UserHostAddress;
1978 _accountName = WindowsIdentity.GetCurrent().Name;
1981 // The information is per request.
1983 public string RequestUrl {get {return _requestUrl;}}
1985 public string RequestPath {get {return _requestPath;}}
1987 public IPrincipal Principal {get {return _iprincipal;}}
1989 public string UserHostAddress { get { return _userHostAddress;} }
1991 public string ThreadAccountName {get {return _accountName;}}
1993 public void FormatToString(WebEventFormatter formatter) {
1998 if (Principal == null) {
1999 user = String.Empty;
2000 authType = String.Empty;
2004 IIdentity id = Principal.Identity;
2007 authed = id.IsAuthenticated;
2008 authType = id.AuthenticationType;
2011 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_url, RequestUrl));
2012 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_path, RequestPath));
2013 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_user_host_address, UserHostAddress));
2014 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_user, user));
2017 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_authenticated));
2020 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_not_authenticated));
2022 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_authentication_type, authType));
2023 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_account_name, ThreadAccountName));
2029 // Note that even all the information contained in WebProcessStatistics is obtained from static variables,
2030 // but we still don't want this class to be static.
2032 // Currently, WebProcessStatistics can be obtained only thru WebHeartbeatEvent, which in turn can be
2033 // created only by Full-trust app thru class inheritance. (System.Web.dll will also internally create it
2034 // and the object will be available to our provider.) Thus, WebProcessStatistics is available only
2035 // to Full-trust app or provider.
2037 // But if we make WebProcessStatistics static, then all its public methods have to be static, and
2038 // they'll be fully available to all users. No good.
2039 public class WebProcessStatistics {
2040 static DateTime s_startTime = DateTime.MinValue;
2041 static DateTime s_lastUpdated = DateTime.MinValue;
2042 static int s_threadCount;
2043 static long s_workingSet;
2044 static long s_peakWorkingSet;
2045 static long s_managedHeapSize;
2046 static int s_appdomainCount;
2047 static int s_requestsExecuting;
2048 static int s_requestsQueued;
2049 static int s_requestsRejected;
2050 static bool s_getCurrentProcFailed = false;
2051 static object s_lockObject = new object();
2053 static TimeSpan TS_ONE_SECOND = new TimeSpan(0, 0, 1);
2055 static WebProcessStatistics() {
2057 #if !FEATURE_PAL // FEATURE_PAL does not support this. Make into a noop.
2058 s_startTime = Process.GetCurrentProcess().StartTime;
2059 #endif // !FEATURE_PAL
2062 s_getCurrentProcFailed = true;
2067 DateTime now = DateTime.Now;
2069 if (now - s_lastUpdated < TS_ONE_SECOND) {
2073 lock (s_lockObject) {
2074 if (now - s_lastUpdated < TS_ONE_SECOND) {
2078 if (!s_getCurrentProcFailed) {
2079 Process process = Process.GetCurrentProcess();
2080 #if !FEATURE_PAL // FEATURE_PAL does not support these Process properties
2082 s_threadCount = process.Threads.Count;
2083 s_workingSet = (long)process.WorkingSet64;
2084 s_peakWorkingSet = (long)process.PeakWorkingSet64;
2086 throw new NotImplementedException ("ROTORTODO");
2090 s_managedHeapSize = GC.GetTotalMemory(false);
2092 s_appdomainCount = HostingEnvironment.AppDomainsCount;
2094 s_requestsExecuting = PerfCounters.GetGlobalCounter(GlobalPerfCounter.REQUESTS_CURRENT);
2095 s_requestsQueued = PerfCounters.GetGlobalCounter(GlobalPerfCounter.REQUESTS_QUEUED);
2096 s_requestsRejected = PerfCounters.GetGlobalCounter(GlobalPerfCounter.REQUESTS_REJECTED);
2098 s_lastUpdated = now;
2103 public DateTime ProcessStartTime {get {Update(); return s_startTime;}}
2105 public int ThreadCount {get {Update(); return s_threadCount;}}
2107 public long WorkingSet {get {Update(); return s_workingSet;}}
2109 public long PeakWorkingSet {get {Update(); return s_peakWorkingSet;}}
2111 public long ManagedHeapSize {get {Update(); return s_managedHeapSize;}}
2113 public int AppDomainCount {get {Update(); return s_appdomainCount;}}
2115 public int RequestsExecuting {get {Update(); return s_requestsExecuting;}}
2117 public int RequestsQueued {get {Update(); return s_requestsQueued;}}
2119 public int RequestsRejected {get {Update(); return s_requestsRejected;}}
2122 virtual public void FormatToString(WebEventFormatter formatter) {
2123 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_start_time, ProcessStartTime.ToString(CultureInfo.InstalledUICulture)));
2124 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_count, ThreadCount.ToString(CultureInfo.InstalledUICulture)));
2125 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_working_set, WorkingSet.ToString(CultureInfo.InstalledUICulture)));
2126 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_peak_working_set, PeakWorkingSet.ToString(CultureInfo.InstalledUICulture)));
2127 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_managed_heap_size, ManagedHeapSize.ToString(CultureInfo.InstalledUICulture)));
2129 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_application_domain_count, AppDomainCount.ToString(CultureInfo.InstalledUICulture)));
2130 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_requests_executing, RequestsExecuting.ToString(CultureInfo.InstalledUICulture)));
2131 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_queued, RequestsQueued.ToString(CultureInfo.InstalledUICulture)));
2132 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_rejected, RequestsRejected.ToString(CultureInfo.InstalledUICulture)));
2136 public sealed class WebThreadInformation {
2138 string _accountName;
2140 bool _isImpersonating;
2141 internal const string IsImpersonatingKey = "ASPIMPERSONATING";
2143 internal WebThreadInformation(Exception exception) {
2144 _threadId = Thread.CurrentThread.ManagedThreadId;
2145 _accountName = HttpApplication.GetCurrentWindowsIdentityWithAssert().Name;
2147 if (exception != null) {
2148 _stackTrace = new StackTrace(exception, true).ToString();
2149 _isImpersonating = exception.Data.Contains(IsImpersonatingKey);
2152 _stackTrace = String.Empty;
2153 _isImpersonating = false;
2158 public int ThreadID {get {return _threadId;}}
2160 public string ThreadAccountName {get {return _accountName;}}
2162 public string StackTrace {get {return _stackTrace;}}
2164 public bool IsImpersonating {get {return _isImpersonating;}}
2167 public void FormatToString(WebEventFormatter formatter) {
2168 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_id, ThreadID.ToString(CultureInfo.InstalledUICulture)));
2169 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_account_name, ThreadAccountName));
2171 if (IsImpersonating) {
2172 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_impersonating));
2175 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_not_impersonating));
2178 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_stack_trace, StackTrace));
2182 // Class that represents the firing record (how many times, last firing time, etc)
2183 // for each rule that inherits from WebBaseEvent.
2185 public sealed class RuleFiringRecord {
2186 internal DateTime _lastFired;
2187 internal int _timesRaised;
2188 internal int _updatingLastFired;
2190 static TimeSpan TS_ONE_SECOND = new TimeSpan(0, 0, 1);
2192 public DateTime LastFired { get { return _lastFired; } }
2195 public int TimesRaised { get { return _timesRaised; } }
2197 // Point to the ruleInfo that is used by this class
2198 internal HealthMonitoringSectionHelper.RuleInfo _ruleInfo;
2200 internal RuleFiringRecord(HealthMonitoringSectionHelper.RuleInfo ruleInfo) {
2202 Debug.Assert(ruleInfo != null, "ruleInfo != null");
2204 _ruleInfo = ruleInfo;
2206 _lastFired = DateTime.MinValue;
2208 _updatingLastFired = 0;
2211 void UpdateLastFired(DateTime now, bool alreadyLocked) {
2212 TimeSpan tsDiff = now - _lastFired;
2214 if (tsDiff < TS_ONE_SECOND) {
2215 // If _lastFired was updated within one second, don't bother.
2219 if (!alreadyLocked) {
2220 // If several threads are firing at the same time, only one thread will
2221 // update record._lastFired.
2222 if (Interlocked.CompareExchange(ref _updatingLastFired, 1, 0) == 0) {
2227 Interlocked.Exchange(ref _updatingLastFired, 0);
2236 // Note: this method is thread safe
2237 internal bool CheckAndUpdate(WebBaseEvent eventRaised) {
2238 DateTime now = DateTime.Now;
2240 HealthMonitoringManager manager = HealthMonitoringManager.Manager();
2242 timesRaised = Interlocked.Increment(ref _timesRaised);
2244 if (manager == null) {
2245 // Won't fire because we cannot configure healthmonitor
2246 Debug.Trace("RuleFiringRecord", "Can't configure healthmonitor");
2250 // Call custom evaluator first
2251 if (_ruleInfo._customEvaluatorType != null) {
2253 IWebEventCustomEvaluator icustom = (IWebEventCustomEvaluator)
2254 manager._sectionHelper._customEvaluatorInstances[_ruleInfo._customEvaluatorType];
2259 // The event may need to do pre-ProcessEvent initialization
2260 eventRaised.PreProcessEventInit();
2262 if (!icustom.CanFire(eventRaised, this)) {
2263 Debug.Trace("RuleFiringRecord", "Custom evaluator returns false.");
2269 Debug.Trace("RuleFiringRecord", "Hit an exception when calling Custom evaluator");
2270 // Return if we hit an error
2276 if (timesRaised < _ruleInfo._minInstances) {
2277 Debug.Trace("RuleFiringRecord",
2278 "MinInterval not met; timesRaised=" + timesRaised +
2279 "; _minInstances=" + _ruleInfo._minInstances);
2283 if (timesRaised > _ruleInfo._maxLimit) {
2284 Debug.Trace("RuleFiringRecord",
2285 "MaxLimit exceeded; timesRaised=" + timesRaised +
2286 "; _maxLimit=" + _ruleInfo._maxLimit);
2290 // Last step: Check MinInterval and update _lastFired
2292 if (_ruleInfo._minInterval == TimeSpan.Zero) {
2293 UpdateLastFired(now, false);
2297 if ((now - _lastFired) <= _ruleInfo._minInterval) {
2298 Debug.Trace("RuleFiringRecord",
2299 "MinInterval not met; now=" + now +
2300 "; _lastFired=" + _lastFired +
2301 "; _ruleInfo._minInterval=" + _ruleInfo._minInterval);
2305 // The lock is to prevent multiple threads from passing the
2306 // same test simultaneously.
2308 if ((now - _lastFired) <= _ruleInfo._minInterval) {
2309 Debug.Trace("RuleFiringRecord",
2310 "MinInterval not met; now=" + now +
2311 "; _lastFired=" + _lastFired +
2312 "; _ruleInfo._tsMinInterval=" + _ruleInfo._minInterval);
2316 UpdateLastFired(now, true);
2323 internal class HealthMonitoringManager {
2324 internal HealthMonitoringSectionHelper _sectionHelper;
2325 internal bool _enabled = false;
2327 static Timer s_heartbeatTimer = null;
2328 static HealthMonitoringManager s_manager = null;
2329 static bool s_inited = false;
2330 static bool s_initing = false;
2331 static object s_lockObject = new object();
2332 static bool s_isCacheDisposed = false;
2334 // If this method returns null, it means we failed during configuration.
2335 internal static HealthMonitoringManager Manager() {
2338 Debug.Assert(!s_inited);
2339 // If this is true, that means we are calling WebEventBase.Raise while
2340 // we are initializing. That means Init() has caused a config exception.
2348 lock (s_lockObject) {
2354 Debug.Assert(s_manager == null);
2356 s_manager = new HealthMonitoringManager();;
2367 internal static bool Enabled {
2369 // DevDiv 92252: Visual Studio 2010 freezes when opening .cs file in App_Code directory
2370 // Never raise webevents from CBM process
2371 if (HostingEnvironment.InClientBuildManager) {
2375 HealthMonitoringManager manager = HealthMonitoringManager.Manager();
2376 if (manager == null) {
2380 return manager._enabled;
2384 internal static bool IsCacheDisposed { get { return s_isCacheDisposed; } set { s_isCacheDisposed = value; } }
2386 internal static void StartHealthMonitoringHeartbeat() {
2387 HealthMonitoringManager manager = Manager();
2388 if (manager == null) {
2390 "HealthMonitoringManager", "Can't fire heartbeat because we cannot configure HealthMon");
2394 if (!manager._enabled) {
2396 "WebEventRaiseDetails", "Can't fire heartbeat because we are disabled");
2400 manager.StartHeartbeatTimer();
2403 private HealthMonitoringManager() {
2404 _sectionHelper = HealthMonitoringSectionHelper.GetHelper();
2406 _enabled = _sectionHelper.Enabled;
2413 internal static void Shutdown() {
2414 WebEventManager.Shutdown();
2418 internal static void Dispose() {
2419 // Make sure this function won't throw
2421 if (s_heartbeatTimer != null) {
2422 s_heartbeatTimer.Dispose();
2423 s_heartbeatTimer = null;
2430 internal void HeartbeatCallback(object state) {
2431 Debug.Assert(HealthMonitoringManager.Enabled);
2432 WebBaseEvent.RaiseSystemEvent(null, WebEventCodes.ApplicationHeartbeat);
2435 internal void StartHeartbeatTimer() {
2436 TimeSpan interval = _sectionHelper.HealthMonitoringSection.HeartbeatInterval;
2438 if (interval == TimeSpan.Zero) {
2443 if (!Debug.IsTagPresent("Timer") || Debug.IsTagEnabled("Timer"))
2446 s_heartbeatTimer = new Timer(new TimerCallback(this.HeartbeatCallback), null,
2447 TimeSpan.Zero, interval);
2451 internal static HealthMonitoringSectionHelper.ProviderInstances ProviderInstances {
2453 HealthMonitoringManager manager = Manager();
2455 if (manager == null) {
2459 if (!manager._enabled) {
2463 return manager._sectionHelper._providerInstances;
2468 public sealed class WebBaseEventCollection : ReadOnlyCollectionBase
2470 public WebBaseEventCollection(ICollection events) {
2471 if (events == null) {
2472 throw new ArgumentNullException("events");
2475 foreach (WebBaseEvent eventRaised in events) {
2476 InnerList.Add(eventRaised);
2480 internal WebBaseEventCollection(WebBaseEvent eventRaised) {
2481 if (eventRaised == null) {
2482 throw new ArgumentNullException("eventRaised");
2485 InnerList.Add(eventRaised);
2488 // overloaded collection access methods
2489 public WebBaseEvent this[int index] {
2491 return (WebBaseEvent) InnerList[index];
2495 public int IndexOf(WebBaseEvent value) {
2496 return InnerList.IndexOf(value);
2499 public bool Contains(WebBaseEvent value) {
2500 return InnerList.Contains(value);
2504 public static class WebEventManager
2507 [SecurityPermission(SecurityAction.Demand, Unrestricted=true)]
2508 public static void Flush(string providerName) {
2509 HealthMonitoringSectionHelper.ProviderInstances providers = HealthMonitoringManager.ProviderInstances;
2511 if (providers == null) {
2515 if (!providers.ContainsKey(providerName)) {
2516 throw new ArgumentException(SR.GetString(SR.Health_mon_provider_not_found, providerName));
2519 using (new ApplicationImpersonationContext()) {
2520 providers[providerName].Flush();
2524 [SecurityPermission(SecurityAction.Demand, Unrestricted=true)]
2525 public static void Flush() {
2526 HealthMonitoringSectionHelper.ProviderInstances providers = HealthMonitoringManager.ProviderInstances;
2528 if (providers == null) {
2532 using (new ApplicationImpersonationContext()) {
2533 foreach(DictionaryEntry de in providers) {
2534 WebEventProvider provider = (WebEventProvider)de.Value;
2536 Debug.Trace("WebEventManager", "Flushing provider " + provider.Name);
2542 internal static void Shutdown() {
2543 HealthMonitoringSectionHelper.ProviderInstances providers = HealthMonitoringManager.ProviderInstances;
2545 if (providers == null) {
2549 foreach(DictionaryEntry de in providers) {
2550 WebEventProvider provider = (WebEventProvider)de.Value;
2552 Debug.Trace("WebEventManager", "Shutting down provider " + provider.Name);
2553 provider.Shutdown();