1 //------------------------------------------------------------------------------
2 // <copyright file="WebEvents.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6 
7 namespace System.Web.Management {
8     using System;
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;
19     using System.Text;
20     using System.Threading;
21     using System.Web;
22     using System.Web.Caching;
23     using System.Web.Configuration;
24     using System.Web.Hosting;
25     using System.Web.Security;
26     using System.Web.UI;
27     using System.Web.Util;
28 
29     using Debug = System.Web.Util.Debug;
30 
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,
40         WEBEVENT_ERROR_EVENT,
41         WEBEVENT_AUDIT_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,
47     };
48 
49     internal enum WebEventFieldType : int {
50         String = 0,
51         Int = 1,
52         Bool = 2,
53         Long = 3,
54         Date = 4,
55     }
56 
57     // Used for marshalling over to IIS Trace
58     internal class WebEventFieldData {
59         string _name;
60         public string Name {
61             get {
62                 return _name;
63             }
64         }
65 
66         string _data;
67         public string Data {
68             get {
69                 return _data;
70             }
71         }
72 
73         WebEventFieldType _type;
74         public WebEventFieldType Type {
75             get {
76                 return _type;
77             }
78         }
79 
WebEventFieldData(string name, string data, WebEventFieldType type)80         public WebEventFieldData(string name, string data, WebEventFieldType type) {
81             _name = name;
82             _data = data;
83             _type = type;
84         }
85     }
86 
87 
88     // Interface for event provider
89     public abstract class WebEventProvider : ProviderBase {
90 
91         // methods
ProcessEvent(WebBaseEvent raisedEvent)92         public abstract void ProcessEvent(WebBaseEvent raisedEvent);
Shutdown()93         public abstract void Shutdown();
Flush()94         public abstract void Flush();
95 
96         int _exceptionLogged;
97 
LogException(Exception e)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,
104                                         Name,
105                                         e.ToString());
106             }
107         }
108     }
109 
110     // Interface for custom event evaluator
111 
112     public interface IWebEventCustomEvaluator {
CanFire(WebBaseEvent raisedEvent, RuleFiringRecord record)113         bool CanFire(WebBaseEvent raisedEvent, RuleFiringRecord record);
114     }
115 
116     ////////////////
117     // Events
118     ////////////////
119 
120     public class WebBaseEvent {
121         DateTime        _eventTimeUtc;
122         int             _code;
123         int             _detailCode;
124         Object          _source;
125         string          _message;
126         long            _sequenceNumber;
127         long            _occurrenceNumber;
128         Guid            _id  = Guid.Empty;
129 
130         static long                         s_globalSequenceNumber = 0;
131         static WebApplicationInformation    s_applicationInfo = new WebApplicationInformation();
132         const string                        WEBEVENT_RAISE_IN_PROGRESS = "_WEvtRIP";
133 
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)];
137 
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)];
141 
142         static Hashtable                    s_customEventCodeOccurrence = new Hashtable();
143         #pragma warning disable 0649
144         static ReadWriteSpinLock            s_lockCustomEventCodeOccurrence;
145         #pragma warning restore 0649
146 
WebBaseEvent()147         static WebBaseEvent() {
148 
149             // Initialize the mappings.  We will fill up each entry on demand by calling
150             // SystemEventTypeFromEventCode().
151 
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;
155                 }
156             }
157 
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;
161                 }
162             }
163         }
164 
Init(string message, Object eventSource, int eventCode, int eventDetailCode)165         void Init(string message, Object eventSource, int eventCode, int eventDetailCode) {
166             if (eventCode < 0) {
167                 throw new ArgumentOutOfRangeException("eventCode",
168                     SR.GetString(SR.Invalid_eventCode_error));
169             }
170 
171             if (eventDetailCode < 0) {
172                 throw new ArgumentOutOfRangeException("eventDetailCode",
173                     SR.GetString(SR.Invalid_eventDetailCode_error));
174             }
175 
176             _code = eventCode;
177             _detailCode = eventDetailCode;
178             _source = eventSource;
179             _eventTimeUtc = DateTime.UtcNow;
180             _message = message;
181 
182             // Creation of _id is always delayed until it's needed.
183         }
184 
185         // ctors
WebBaseEvent(string message, Object eventSource, int eventCode)186         internal protected WebBaseEvent(string message, Object eventSource, int eventCode) {
187             Init(message, eventSource, eventCode, WebEventCodes.UndefinedEventDetailCode);
188         }
189 
WebBaseEvent(string message, Object eventSource, int eventCode, int eventDetailCode)190         internal protected WebBaseEvent(string message, Object eventSource, int eventCode, int eventDetailCode) {
191             Init(message, eventSource, eventCode, eventDetailCode);
192         }
193 
WebBaseEvent()194         internal WebBaseEvent() {
195             // For creating dummy event.  See GetSystemDummyEvent()
196         }
197 
198         internal bool IsSystemEvent {
199             get {
200                 return (_code < WebEventCodes.WebExtendedBase);
201             }
202         }
203 
204         // Properties
205 
206         public DateTime EventTime { get { return _eventTimeUtc.ToLocalTime(); } }
207 
208         public DateTime EventTimeUtc { get { return _eventTimeUtc; } }
209 
210         public String Message { get { return _message; } }
211 
212         public Object EventSource { get { return _source; } }
213 
214         public long EventSequence { get { return _sequenceNumber; } }
215 
216         public long EventOccurrence { get { return _occurrenceNumber; } }
217 
218         public int EventCode { get { return _code; } }
219 
220         public int EventDetailCode { get { return _detailCode; } }
221 
222         public Guid EventID {
223             get {
224                 if (_id == Guid.Empty) {
225                     lock(this) {
226                         if (_id == Guid.Empty) {
227                             _id = Guid.NewGuid();
228                         }
229                     }
230                 }
231 
232                 return _id;
233             }
234         }
235 
236         public static WebApplicationInformation ApplicationInformation {
237             get { return s_applicationInfo; }
238         }
239 
FormatToString(WebEventFormatter formatter, bool includeAppInfo)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)));
249 
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;
256             }
257         }
258 
259 
ToString()260         public override string ToString() {
261             return ToString(true, true);
262         }
263 
ToString(bool includeAppInfo, bool includeCustomEventDetails)264         public virtual string ToString(bool includeAppInfo, bool includeCustomEventDetails) {
265             WebEventFormatter   formatter = new WebEventFormatter();
266 
267             FormatToString(formatter, includeAppInfo);
268 
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;
275             }
276 
277             return formatter.ToString();
278         }
279 
FormatCustomEventDetails(WebEventFormatter formatter)280         virtual public void FormatCustomEventDetails(WebEventFormatter formatter) {
281         }
282 
InferEtwTraceVerbosity()283         internal int InferEtwTraceVerbosity() {
284             WebEventType type = WebBaseEvent.WebEventTypeFromWebEvent(this);
285             switch (type) {
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:
300                 default:
301                     return EtwTraceLevel.Verbose;
302             }
303         }
304 
DeconstructWebEvent(out int eventType, out int fieldCount, out string[] fieldNames, out int[] fieldTypes, out string[] fieldData)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>();
307 
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];
314 
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;
319             }
320         }
321 
GenerateFieldsForMarshal(List<WebEventFieldData> fields)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));
335         }
336 
PreProcessEventInit()337         internal virtual void PreProcessEventInit() {
338         }
339 
FindEventCode(Exception e, ref int eventCode, ref int eventDetailsCode, ref Exception eStack)340         static void FindEventCode(Exception e, ref int eventCode, ref int eventDetailsCode, ref Exception eStack) {
341             eventDetailsCode = WebEventCodes.UndefinedEventDetailCode;
342 
343             if (e is ConfigurationException) {
344                 eventCode = WebEventCodes.WebErrorConfigurationError;
345             }
346             else if (e is HttpRequestValidationException) {
347                 eventCode = WebEventCodes.RuntimeErrorValidationFailure;
348             }
349             else if (e is HttpCompileException) {
350                 eventCode = WebEventCodes.WebErrorCompilationError;
351             }
352             else if (e is SecurityException) {
353                 eventCode = WebEventCodes.AuditUnhandledSecurityException;
354             }
355             else if (e is UnauthorizedAccessException) {
356                 eventCode = WebEventCodes.AuditUnhandledAccessException;
357             }
358             else  if (e is HttpParseException) {
359                 eventCode = WebEventCodes.WebErrorParserError;
360             }
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;
366                 }
367                 else {
368                     eventDetailsCode = WebEventCodes.InvalidViewState;
369                 }
370 
371                 eStack = vse;
372             }
373             else if (e is HttpException && ((HttpException)e).WebEventCode != WebEventCodes.UndefinedEventCode) {
374                 eventCode = ((HttpException)e).WebEventCode;
375             }
376             else {
377                 // We don't know what it is.  Let's see if we can find it out by using the inner exception.
378 
379                 if (e.InnerException != null) {
380                     // We will call FindEventCode recusively to find out if e.InnerException is the real one.
381 
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;
387                     }
388 
389                     FindEventCode(e.InnerException, ref eventCode, ref eventDetailsCode, ref eStack);
390                 }
391                 else {
392                     // It doesn't have an inner exception.  Just return the generic unhandled-exception
393                     eventCode = WebEventCodes.RuntimeErrorUnhandledException;
394                 }
395             }
396 
397             if (eStack == null) {
398                 eStack = e;
399             }
400         }
401 
RaiseRuntimeError(Exception e, object source)402         static internal void RaiseRuntimeError(Exception e, object source) {
403             Debug.Trace("WebEventRaiseError", "Error Event is raised; type=" + e.GetType().Name);
404 
405             if (!HealthMonitoringManager.Enabled) {
406                 return;
407             }
408 
409             try {
410                 int         eventCode = WebEventCodes.UndefinedEventCode;
411                 int         eventDetailsCode = WebEventCodes.UndefinedEventDetailCode;
412                 HttpContext context = HttpContext.Current;
413                 Exception   eStack = null;
414 
415                 if (context != null) {
416                     Page    page = context.Handler as Page;
417 
418                     // Errors from Transacted pages can be wrapped by a
419                     // HttpException
420                     if (page != null &&
421                         page.IsTransacted &&
422                         e.GetType() == typeof(HttpException) &&
423                         e.InnerException != null) {
424 
425                         e = e.InnerException;
426                     }
427                 }
428 
429                 FindEventCode(e, ref eventCode, ref eventDetailsCode, ref eStack);
430                 WebBaseEvent.RaiseSystemEvent(source, eventCode, eventDetailsCode, eStack);
431             }
432             catch {
433             }
434         }
435 
IncrementPerfCounters()436         virtual internal protected void IncrementPerfCounters() {
437             PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_TOTAL);
438         }
439 
440         class CustomEventCodeOccurrence {
441             internal long    _occurrence;
442         }
443 
IncrementTotalCounters(int index0, int index1)444         internal void IncrementTotalCounters(int index0, int index1) {
445             _sequenceNumber = Interlocked.Increment(ref s_globalSequenceNumber);
446 
447             if (index0 != -1) {
448                 _occurrenceNumber = Interlocked.Increment(ref s_eventCodeOccurrence[index0, index1]);
449             }
450             else {
451                 CustomEventCodeOccurrence ceco = (CustomEventCodeOccurrence)s_customEventCodeOccurrence[_code];
452 
453                 if (ceco == null) {
454                     s_lockCustomEventCodeOccurrence.AcquireWriterLock();
455                     try {
456                         ceco = (CustomEventCodeOccurrence)s_customEventCodeOccurrence[_code];
457                         if (ceco == null) {
458                             ceco = new CustomEventCodeOccurrence();
459                             s_customEventCodeOccurrence[_code] = ceco;
460                         }
461                     }
462                     finally {
463                         s_lockCustomEventCodeOccurrence.ReleaseWriterLock();
464                     }
465                 }
466 
467                 _occurrenceNumber = Interlocked.Increment(ref ceco._occurrence);
468             }
469         }
470 
471         [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)]
Raise()472         virtual public void Raise() {
473             Raise(this);
474         }
475 
476         // Internally raised events don't go thru this method.  They go directly to RaiseSystemEvent --> RaiseInternal
477         [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Medium)]
Raise(WebBaseEvent eventRaised)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)));
483             }
484 
485             if (!HealthMonitoringManager.Enabled) {
486                 Debug.Trace(
487                     "WebEventRaiseDetails", "Can't fire event because we are disabled or we can't configure HealthMonManager");
488                 return;
489             }
490 
491             RaiseInternal(eventRaised, null, -1, -1);
492         }
493 
RaiseInternal(WebBaseEvent eventRaised, ArrayList firingRuleInfos, int index0, int index1)494         static internal void RaiseInternal(WebBaseEvent eventRaised, ArrayList firingRuleInfos, int index0, int index1) {
495             bool    preProcessEventInitCalled = false;
496             bool    inProgressSet = false;
497             object  o;
498             ProcessImpersonationContext ictx = null;
499             HttpContext context = HttpContext.Current;
500 
501             Debug.Trace(
502                 "WebEventRaiseDetails", "Event is raised; event class = " + eventRaised.GetType().Name);
503 
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) {
507                 Debug.Trace(
508                     "WebEventRaiseDetails", "An event is raised while we're raising an event.  Ignore it.");
509                 return;
510             }
511 
512             eventRaised.IncrementPerfCounters();
513             eventRaised.IncrementTotalCounters(index0, index1);
514 
515             // Find the list of rules that match this event
516             if (firingRuleInfos == null) {
517                 HealthMonitoringManager manager = HealthMonitoringManager.Manager();
518 
519                 Debug.Assert(manager != null, "manager != null");
520 
521                 firingRuleInfos = manager._sectionHelper.FindFiringRuleInfos(eventRaised.GetType(), eventRaised.EventCode);
522             }
523 
524             if (firingRuleInfos.Count == 0) {
525                 return;
526             }
527 
528             try {
529                 bool[]  matchingProviderArray = null;
530 
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),
537                                    null);
538 
539                 try {
540                     foreach (HealthMonitoringSectionHelper.FiringRuleInfo firingRuleInfo in firingRuleInfos) {
541                         HealthMonitoringSectionHelper.RuleInfo  ruleInfo = firingRuleInfo._ruleInfo;
542                         RuleFiringRecord record = ruleInfo._ruleFiringRecord;
543 
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");
548                             continue;
549                         }
550 
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;
557                             }
558 
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];
568                                 }
569 
570                                 if (matchingProviderArray[firingRuleInfo._indexOfFirstRuleInfoWithSameProvider]) {
571                                     Debug.Trace("WebEventRaiseDetails",
572                                             "Rule with a matching provider already fired.");
573                                     continue;
574                                 }
575 
576                                 matchingProviderArray[firingRuleInfo._indexOfFirstRuleInfoWithSameProvider] = true;
577                             }
578 
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,
585                                                null);
586 
587                             // In retail build, ignore errors from provider
588                             try {
589                                 if (ictx == null) {
590                                     ictx = new ProcessImpersonationContext();
591                                 }
592 
593                                 if (!inProgressSet) {
594                                     CallContext.SetData(WEBEVENT_RAISE_IN_PROGRESS, true);
595                                     inProgressSet = true;
596                                 }
597 
598                                 Debug.Trace("WebEventRaiseDetails", "Calling ProcessEvent under " + HttpApplication.GetCurrentWindowsIdentityWithAssert().Name);
599                                 ruleInfo._referencedProvider.ProcessEvent(eventRaised);
600                             }
601                             catch (Exception e) {
602                                 try {
603                                     ruleInfo._referencedProvider.LogException(e);
604                                 }
605                                 catch {
606                                     // ignore all errors
607                                 }
608                             }
609                             finally {
610                                 if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null)
611                                     EtwTrace.Trace(EtwTraceType.ETW_TYPE_WEB_EVENT_DELIVER_END,
612                                                    context.WorkerRequest);
613                             }
614                         }
615                     }
616                 }
617                 finally {
618                     // Resume client impersonation
619                     if (ictx != null) {
620                         ictx.Undo();
621                     }
622 
623                     if (inProgressSet) {
624                         CallContext.FreeNamedDataSlot(WEBEVENT_RAISE_IN_PROGRESS);
625                     }
626 
627                     if (EtwTrace.IsTraceEnabled(EtwTraceLevel.Verbose, EtwTraceFlags.Infrastructure) && context != null)
628                         EtwTrace.Trace(EtwTraceType.ETW_TYPE_WEB_EVENT_RAISE_END,
629                                        context.WorkerRequest);
630                 }
631             }
632             catch { throw; }    // Prevent Exception Filter Security Issue (ASURT 122835)
633         }
634 
RaiseSystemEvent(string message, object source, int eventCode, int eventDetailCode, Exception exception)635         internal static void RaiseSystemEvent(string message, object source, int eventCode, int eventDetailCode, Exception exception) {
636             RaiseSystemEventInternal(message, source, eventCode, eventDetailCode, exception, null);
637         }
638 
RaiseSystemEvent(object source, int eventCode)639         internal static void RaiseSystemEvent(object source, int eventCode) {
640             RaiseSystemEventInternal(null, source, eventCode, WebEventCodes.UndefinedEventDetailCode, null, null);
641         }
642 
RaiseSystemEvent(object source, int eventCode, int eventDetailCode)643         internal static void RaiseSystemEvent(object source, int eventCode, int eventDetailCode) {
644             RaiseSystemEventInternal(null, source, eventCode, eventDetailCode, null, null);
645         }
646 
RaiseSystemEvent(object source, int eventCode, int eventDetailCode, Exception exception)647         internal static void RaiseSystemEvent(object source, int eventCode, int eventDetailCode, Exception exception) {
648             RaiseSystemEventInternal(null, source, eventCode, eventDetailCode, exception, null);
649         }
650 
RaiseSystemEvent(object source, int eventCode, string nameToAuthenticate)651         internal static void RaiseSystemEvent(object source, int eventCode, string nameToAuthenticate) {
652             RaiseSystemEventInternal(null, source, eventCode, WebEventCodes.UndefinedEventDetailCode, null, nameToAuthenticate);
653         }
654 
655         [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
RaiseSystemEventInternal(string message, object source, int eventCode, int eventDetailCode, Exception exception, string nameToAuthenticate)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;
663             int                 index0, index1;
664 
665             Debug.Trace(
666                 "WebEventRaiseDetails", "RaiseSystemEventInternal called; eventCode=" + eventCode + "; eventDetailCode=" + eventDetailCode);
667 
668             if (!HealthMonitoringManager.Enabled) {
669                 Debug.Trace(
670                     "WebEventRaiseDetails", "Can't fire event because we are disabled or we can't configure HealthMonManager");
671                 return;
672             }
673 
674             WebEventCodes.GetEventArrayIndexsFromEventCode(eventCode, out index0, out index1);
675 
676             GetSystemEventTypeInfo(eventCode, index0, index1, out typeInfo, out systemEventType);
677             if (typeInfo == null) {
678                 Debug.Assert(false, "Unexpected system event code = " + eventCode);
679                 return;
680             }
681 
682             manager = HealthMonitoringManager.Manager();
683 
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);
690             }
691             else {
692                 // We will fire the event
693                 WebBaseEvent.RaiseInternal(
694                                 NewEventFromSystemEventType(false, systemEventType, message, source, eventCode, eventDetailCode,
695                                                         exception, nameToAuthenticate),
696                                 firingRuleInfos, index0, index1);
697             }
698         }
699 
700         // An enum of all the types of web event we will fire
701         enum SystemEventType {
702             Unknown = -1,
703             WebApplicationLifetimeEvent,
704             WebHeartbeatEvent,
705             WebRequestEvent,
706             WebRequestErrorEvent,
707             WebErrorEvent,
708             WebAuthenticationSuccessAuditEvent,
709             WebSuccessAuditEvent,
710             WebAuthenticationFailureAuditEvent,
711             WebFailureAuditEvent,
712             WebViewStateFailureAuditEvent,
713             Last
714         };
715 
716         class SystemEventTypeInfo {
717             internal WebBaseEvent       _dummyEvent;    // For calling IncrementPerfCounters. See RaiseSystemEventInternal for details.
718             internal Type               _type;
719 
SystemEventTypeInfo(WebBaseEvent dummyEvent)720             internal SystemEventTypeInfo(WebBaseEvent dummyEvent) {
721                 _dummyEvent = dummyEvent;
722                 _type = dummyEvent.GetType();
723             }
724         };
725 
726         // An array to cache the event type info for each system event type
727         static SystemEventTypeInfo[]    s_systemEventTypeInfos = new SystemEventTypeInfo[(int)SystemEventType.Last];
728 
GetSystemEventTypeInfo(int eventCode, int index0, int index1, out SystemEventTypeInfo info, out SystemEventType systemEventType)729         static void GetSystemEventTypeInfo(int eventCode, int index0, int index1,
730                         out SystemEventTypeInfo info, out SystemEventType systemEventType) {
731 
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;
738             }
739 
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];
743             if (info != null) {
744                 return;
745             }
746 
747             info = new SystemEventTypeInfo(CreateDummySystemEvent(systemEventType));
748             s_systemEventTypeInfos[(int)systemEventType] = info;
749         }
750 
SystemEventTypeFromEventCode(int eventCode)751         static SystemEventType SystemEventTypeFromEventCode(int eventCode) {
752             if (eventCode >= WebEventCodes.ApplicationCodeBase &&
753                 eventCode <= WebEventCodes.ApplicationCodeBaseLast) {
754                 switch(eventCode) {
755                     case WebEventCodes.ApplicationStart:
756                     case WebEventCodes.ApplicationShutdown:
757                     case WebEventCodes.ApplicationCompilationStart:
758                     case WebEventCodes.ApplicationCompilationEnd:
759                         return SystemEventType.WebApplicationLifetimeEvent;
760 
761                     case WebEventCodes.ApplicationHeartbeat:
762                         return SystemEventType.WebHeartbeatEvent;
763                 }
764             }
765 
766             if (eventCode >= WebEventCodes.RequestCodeBase &&
767                 eventCode <= WebEventCodes.RequestCodeBaseLast) {
768                 switch(eventCode) {
769 
770                     case WebEventCodes.RequestTransactionComplete:
771                     case WebEventCodes.RequestTransactionAbort:
772                         return SystemEventType.WebRequestEvent;
773                 }
774             }
775 
776             if (eventCode >= WebEventCodes.ErrorCodeBase &&
777                 eventCode <= WebEventCodes.ErrorCodeBaseLast) {
778                 switch(eventCode) {
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;
786 
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;
794                 }
795             }
796 
797             if (eventCode >= WebEventCodes.AuditCodeBase &&
798                 eventCode <= WebEventCodes.AuditCodeBaseLast) {
799                 switch(eventCode) {
800                     case WebEventCodes.AuditFormsAuthenticationSuccess:
801                     case WebEventCodes.AuditMembershipAuthenticationSuccess:
802                         return SystemEventType.WebAuthenticationSuccessAuditEvent;
803 
804                     case WebEventCodes.AuditUrlAuthorizationSuccess:
805                     case WebEventCodes.AuditFileAuthorizationSuccess:
806                         return SystemEventType.WebSuccessAuditEvent;
807 
808                     case WebEventCodes.AuditFormsAuthenticationFailure:
809                     case WebEventCodes.AuditMembershipAuthenticationFailure:
810                         return SystemEventType.WebAuthenticationFailureAuditEvent;
811 
812                     case WebEventCodes.AuditUrlAuthorizationFailure:
813                     case WebEventCodes.AuditFileAuthorizationFailure:
814                     case WebEventCodes.AuditUnhandledSecurityException:
815                     case WebEventCodes.AuditUnhandledAccessException:
816                         return SystemEventType.WebFailureAuditEvent;
817 
818                     case WebEventCodes.AuditInvalidViewStateFailure:
819                         return SystemEventType.WebViewStateFailureAuditEvent;
820                 }
821             }
822 
823             if (eventCode >= WebEventCodes.MiscCodeBase &&
824                 eventCode <= WebEventCodes.MiscCodeBaseLast) {
825                 switch(eventCode) {
826                     case WebEventCodes.WebEventProviderInformation:
827                         Debug.Assert(false, "WebEventProviderInformation shouldn't be used to Raise an event");
828                         return SystemEventType.Unknown;
829                 }
830             }
831 
832             return SystemEventType.Unknown;
833         }
834 
CreateDummySystemEvent(SystemEventType systemEventType)835         static WebBaseEvent CreateDummySystemEvent(SystemEventType systemEventType) {
836             return NewEventFromSystemEventType(true, systemEventType, null,
837                         null, 0, 0, null, null);
838         }
839 
NewEventFromSystemEventType(bool createDummy, SystemEventType systemEventType, string message, object source,int eventCode, int eventDetailCode, Exception exception, string nameToAuthenticate)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()
845 
846             if (!createDummy && message == null) {
847                 message = WebEventCodes.MessageFromEventCode(eventCode, eventDetailCode);
848             }
849 
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.
853 
854             switch(systemEventType) {
855                 case SystemEventType.WebApplicationLifetimeEvent:
856                     return createDummy ? new WebApplicationLifetimeEvent() : new WebApplicationLifetimeEvent(message, source, eventCode, eventDetailCode);
857 
858                 case SystemEventType.WebHeartbeatEvent:
859                     return createDummy ? new WebHeartbeatEvent() : new WebHeartbeatEvent(message, eventCode);
860 
861                 case SystemEventType.WebRequestEvent:
862                     return createDummy ? new WebRequestEvent() : new WebRequestEvent(message, source, eventCode, eventDetailCode);
863 
864                 case SystemEventType. WebRequestErrorEvent:
865                     return createDummy ? new WebRequestErrorEvent() : new WebRequestErrorEvent(message, source, eventCode, eventDetailCode, exception);
866 
867                 case SystemEventType.WebErrorEvent:
868                     return createDummy ? new WebErrorEvent() : new WebErrorEvent(message, source, eventCode, eventDetailCode, exception);
869 
870                 case SystemEventType.WebAuthenticationSuccessAuditEvent:
871                     return createDummy ? new WebAuthenticationSuccessAuditEvent() : new WebAuthenticationSuccessAuditEvent(message, source, eventCode, eventDetailCode, nameToAuthenticate);
872 
873                 case SystemEventType.WebSuccessAuditEvent:
874                     return createDummy ? new WebSuccessAuditEvent() : new WebSuccessAuditEvent(message, source, eventCode, eventDetailCode);
875 
876                 case SystemEventType.WebAuthenticationFailureAuditEvent:
877                     return createDummy ? new WebAuthenticationFailureAuditEvent() : new WebAuthenticationFailureAuditEvent(message, source, eventCode, eventDetailCode, nameToAuthenticate);
878 
879                 case SystemEventType.WebFailureAuditEvent:
880                     return createDummy ? new WebFailureAuditEvent() : new WebFailureAuditEvent(message, source, eventCode, eventDetailCode);
881 
882                 case SystemEventType.WebViewStateFailureAuditEvent:
883                     return createDummy ? new WebViewStateFailureAuditEvent() : new WebViewStateFailureAuditEvent(message, source, eventCode, eventDetailCode, (System.Web.UI.ViewStateException)exception);
884 
885                 default:
886                     Debug.Assert(false, "Unexpected event type = " + systemEventType);
887                     return null;
888             }
889         }
890 
CreateWebEventResourceCacheKey(String key)891         static string CreateWebEventResourceCacheKey(String key) {
892             return CacheInternal.PrefixWebEventResource + key;
893         }
894 
FormatResourceStringWithCache(String 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);
901             }
902 
903             CacheStoreProvider cacheInternal = HttpRuntime.Cache.InternalCache;
904             string s;
905 
906             string cacheKey = CreateWebEventResourceCacheKey(key);
907 
908             s = (string) cacheInternal.Get(cacheKey);
909             if (s != null) {
910                 return s;
911             }
912 
913             s = SR.Resources.GetString(key, CultureInfo.InstalledUICulture);
914             if (s != null) {
915                 cacheInternal.Insert(cacheKey, s, null);
916             }
917 
918             return s;
919         }
920 
FormatResourceStringWithCache(String key, String arg0)921         internal static String FormatResourceStringWithCache(String key, String arg0) {
922             string fmt = FormatResourceStringWithCache(key);
923             return(fmt != null) ? String.Format(fmt, arg0) : null;
924         }
925 
WebEventTypeFromWebEvent(WebBaseEvent eventRaised)926         internal static WebEventType WebEventTypeFromWebEvent(WebBaseEvent eventRaised) {
927             // Note:
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
931             // way up.
932 
933             // Webevent class hierarchy (with the info contained in each class):
934 
935             /*
936 
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)
951             */
952 
953             // Hierarchy level 5
954 
955             if (eventRaised is WebAuthenticationSuccessAuditEvent) {
956                 return WebEventType.WEBEVENT_AUTHENTICATION_SUCCESS_AUDIT_EVENT;
957             }
958 
959             if (eventRaised is WebAuthenticationFailureAuditEvent) {
960                 return WebEventType.WEBEVENT_AUTHENTICATION_FAILURE_AUDIT_EVENT;
961             }
962 
963             if (eventRaised is WebViewStateFailureAuditEvent) {
964                 return WebEventType.WEBEVENT_VIEWSTATE_FAILURE_AUDIT_EVENT;
965             }
966 
967             // Hierarchy level 4
968 
969             if (eventRaised is WebRequestErrorEvent) {
970                 return WebEventType.WEBEVENT_REQUEST_ERROR_EVENT;
971             }
972 
973             if (eventRaised is WebErrorEvent) {
974                 return WebEventType.WEBEVENT_ERROR_EVENT;
975             }
976 
977             if (eventRaised is WebSuccessAuditEvent) {
978                 return WebEventType.WEBEVENT_SUCCESS_AUDIT_EVENT;
979             }
980 
981             if (eventRaised is WebFailureAuditEvent) {
982                 return WebEventType.WEBEVENT_FAILURE_AUDIT_EVENT;
983             }
984 
985             // Hierarchy level 3
986 
987             if (eventRaised is WebHeartbeatEvent) {
988                 return WebEventType.WEBEVENT_HEARTBEAT_EVENT;
989             }
990 
991             if (eventRaised is WebApplicationLifetimeEvent) {
992                 return WebEventType.WEBEVENT_APP_LIFETIME_EVENT;
993             }
994 
995             if (eventRaised is WebRequestEvent) {
996                 return WebEventType.WEBEVENT_REQUEST_EVENT;
997             }
998 
999             if (eventRaised is WebBaseErrorEvent) {
1000                 return WebEventType.WEBEVENT_BASE_ERROR_EVENT;
1001             }
1002 
1003             if (eventRaised is WebAuditEvent) {
1004                 return WebEventType.WEBEVENT_AUDIT_EVENT;
1005             }
1006 
1007             // Hierarchy level 2
1008 
1009             if (eventRaised is WebManagementEvent) {
1010                 return WebEventType.WEBEVENT_MANAGEMENT_EVENT;
1011             }
1012 
1013             // Hierarchy level 1
1014 
1015             return WebEventType.WEBEVENT_BASE_EVENT;
1016         }
1017 
RaisePropertyDeserializationWebErrorEvent(SettingsProperty property, object source, Exception exception)1018         static internal void RaisePropertyDeserializationWebErrorEvent(SettingsProperty property, object source, Exception exception) {
1019             if (HttpContext.Current == null) {
1020                 return;
1021             }
1022 
1023             WebBaseEvent.RaiseSystemEvent(
1024                 SR.GetString(SR.Webevent_msg_Property_Deserialization,
1025                             property.Name, property.SerializeAs.ToString(), property.PropertyType.AssemblyQualifiedName ),
1026                 source,
1027                 WebEventCodes.WebErrorPropertyDeserializationError,
1028                 WebEventCodes.UndefinedEventDetailCode,
1029                 exception);
1030         }
1031     }
1032 
1033     public class WebEventFormatter {
1034         int             _level;
1035         StringBuilder   _sb;
1036         int             _tabSize;
1037 
AddTab()1038         void AddTab() {
1039             int level = _level;
1040 
1041             while (level > 0) {
1042                 _sb.Append(' ', _tabSize);
1043                 level--;
1044             }
1045         }
1046 
WebEventFormatter()1047         internal WebEventFormatter() {
1048             _level = 0;
1049             _sb = new StringBuilder();
1050             _tabSize = 4;
1051         }
1052 
AppendLine(string s)1053         public void AppendLine(string s) {
1054             AddTab();
1055             _sb.Append(s);
1056             _sb.Append('\n');
1057         }
1058 
ToString()1059         new public string ToString() {
1060             return _sb.ToString();
1061         }
1062 
1063         public int IndentationLevel {
1064             get { return _level; }
1065             set { _level = Math.Max(value, 0); }
1066         }
1067 
1068         public int TabSize {
1069             get { return _tabSize; }
1070             set { _tabSize = Math.Max(value, 0); }
1071         }
1072     }
1073 
1074     // This class is a base class for all events that require application and process information.
1075     //
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.
1081     //
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.
1086     //
1087     // For details, see VSWhidbey 256684.
1088     //
1089     [PermissionSet(SecurityAction.InheritanceDemand, Unrestricted = true)]
1090     public class WebManagementEvent : WebBaseEvent {
1091         static WebProcessInformation        s_processInfo = new WebProcessInformation();
1092 
WebManagementEvent(string message, object eventSource, int eventCode)1093         internal protected WebManagementEvent(string message, object eventSource, int eventCode)
1094             :base(message, eventSource, eventCode) {
1095         }
1096 
WebManagementEvent(string message, object eventSource, int eventCode, int eventDetailCode)1097         internal protected WebManagementEvent(string message, object eventSource, int eventCode, int eventDetailCode)
1098             :base(message, eventSource, eventCode, eventDetailCode) {
1099         }
1100 
WebManagementEvent()1101         internal WebManagementEvent() {
1102             // For creating dummy event.  See GetSystemDummyEvent()
1103         }
1104 
1105         // properties
1106         public WebProcessInformation ProcessInformation {
1107             get { return s_processInfo; }
1108         }
1109 
GenerateFieldsForMarshal(List<WebEventFieldData> fields)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));
1115         }
1116 
FormatToString(WebEventFormatter formatter, bool includeAppInfo)1117         override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1118             base.FormatToString(formatter, includeAppInfo);
1119 
1120             formatter.AppendLine(String.Empty);
1121             formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_information));
1122 
1123             formatter.IndentationLevel += 1;
1124             ProcessInformation.FormatToString(formatter);
1125             formatter.IndentationLevel -= 1;
1126         }
1127 
1128     }
1129 
1130 
1131     // This event is raised at periodic intervals (default 30 seconds) and provides information
1132     // relative to the state of the running appdomin.
1133 
1134     public class WebHeartbeatEvent : WebManagementEvent {
1135         static WebProcessStatistics    s_procStats = new WebProcessStatistics();
1136 
WebHeartbeatEvent(string message, int eventCode)1137         internal protected WebHeartbeatEvent(string message, int eventCode)
1138             :base(message, null, eventCode)
1139         {
1140         }
1141 
WebHeartbeatEvent()1142         internal WebHeartbeatEvent() {
1143             // For creating dummy event.  See GetSystemDummyEvent()
1144         }
1145 
1146 
1147         public WebProcessStatistics ProcessStatistics {get {return s_procStats;}}
1148 
FormatToString(WebEventFormatter formatter, bool includeAppInfo)1149         override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1150             base.FormatToString(formatter, includeAppInfo);
1151 
1152             formatter.AppendLine(String.Empty);
1153             formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_process_statistics));
1154 
1155             formatter.IndentationLevel += 1;
1156             s_procStats.FormatToString(formatter);
1157             formatter.IndentationLevel -= 1;
1158         }
1159     }
1160 
1161 
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.).
1166 
1167     public class WebApplicationLifetimeEvent : WebManagementEvent {
1168 
WebApplicationLifetimeEvent(string message, object eventSource, int eventCode)1169         internal protected WebApplicationLifetimeEvent(string message, object eventSource, int eventCode)
1170             :base(message, eventSource, eventCode)
1171         {
1172         }
1173 
1174 
WebApplicationLifetimeEvent(string message, object eventSource, int eventCode, int eventDetailCode)1175         internal protected WebApplicationLifetimeEvent(string message, object eventSource, int eventCode, int eventDetailCode)
1176             :base(message, eventSource, eventCode, eventDetailCode)
1177         {
1178         }
1179 
WebApplicationLifetimeEvent()1180         internal WebApplicationLifetimeEvent() {
1181             // For creating dummy event.  See GetSystemDummyEvent()
1182         }
1183 
DetailCodeFromShutdownReason(ApplicationShutdownReason reason)1184         static internal int DetailCodeFromShutdownReason(ApplicationShutdownReason reason) {
1185             switch (reason) {
1186             case ApplicationShutdownReason.HostingEnvironment:
1187                 return WebEventCodes.ApplicationShutdownHostingEnvironment;
1188 
1189             case ApplicationShutdownReason.ChangeInGlobalAsax:
1190                 return WebEventCodes.ApplicationShutdownChangeInGlobalAsax;
1191 
1192             case ApplicationShutdownReason.ConfigurationChange:
1193                 return WebEventCodes.ApplicationShutdownConfigurationChange;
1194 
1195             case ApplicationShutdownReason.UnloadAppDomainCalled:
1196                 return WebEventCodes.ApplicationShutdownUnloadAppDomainCalled;
1197 
1198             case ApplicationShutdownReason.ChangeInSecurityPolicyFile:
1199                 return WebEventCodes.ApplicationShutdownChangeInSecurityPolicyFile;
1200 
1201             case ApplicationShutdownReason.BinDirChangeOrDirectoryRename:
1202                 return WebEventCodes.ApplicationShutdownBinDirChangeOrDirectoryRename;
1203 
1204             case ApplicationShutdownReason.BrowsersDirChangeOrDirectoryRename:
1205                 return WebEventCodes.ApplicationShutdownBrowsersDirChangeOrDirectoryRename;
1206 
1207             case ApplicationShutdownReason.CodeDirChangeOrDirectoryRename:
1208                 return WebEventCodes.ApplicationShutdownCodeDirChangeOrDirectoryRename;
1209 
1210             case ApplicationShutdownReason.ResourcesDirChangeOrDirectoryRename:
1211                 return WebEventCodes.ApplicationShutdownResourcesDirChangeOrDirectoryRename;
1212 
1213             case ApplicationShutdownReason.IdleTimeout:
1214                 return WebEventCodes.ApplicationShutdownIdleTimeout;
1215 
1216             case ApplicationShutdownReason.PhysicalApplicationPathChanged:
1217                 return WebEventCodes.ApplicationShutdownPhysicalApplicationPathChanged;
1218 
1219             case ApplicationShutdownReason.HttpRuntimeClose:
1220                 return WebEventCodes.ApplicationShutdownHttpRuntimeClose;
1221 
1222             case ApplicationShutdownReason.InitializationError:
1223                 return WebEventCodes.ApplicationShutdownInitializationError;
1224 
1225             case ApplicationShutdownReason.MaxRecompilationsReached:
1226                 return WebEventCodes.ApplicationShutdownMaxRecompilationsReached;
1227 
1228             case ApplicationShutdownReason.BuildManagerChange:
1229                 return WebEventCodes.ApplicationShutdownBuildManagerChange;
1230 
1231             default:
1232                 return WebEventCodes.ApplicationShutdownUnknown;
1233             }
1234         }
1235 
IncrementPerfCounters()1236         override internal protected void IncrementPerfCounters() {
1237             base.IncrementPerfCounters();
1238             PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_APP);
1239         }
1240     }
1241 
1242     // This class serves as a base for non-error events that provide
1243     public class WebRequestEvent : WebManagementEvent {
1244         WebRequestInformation   _requestInfo;
1245 
PreProcessEventInit()1246         override internal void PreProcessEventInit() {
1247             base.PreProcessEventInit();
1248             InitRequestInformation();
1249         }
1250 
WebRequestEvent(string message, object eventSource, int eventCode)1251         internal protected WebRequestEvent(string message, object eventSource, int eventCode)
1252         :base(message, eventSource, eventCode)
1253         {
1254         }
1255 
WebRequestEvent(string message, object eventSource, int eventCode, int eventDetailCode)1256         internal protected WebRequestEvent(string message, object eventSource, int eventCode, int eventDetailCode)
1257             :base(message, eventSource, eventCode, eventDetailCode)
1258         {
1259         }
1260 
WebRequestEvent()1261         internal WebRequestEvent() {
1262             // For creating dummy event.  See GetSystemDummyEvent()
1263         }
1264 
InitRequestInformation()1265         void InitRequestInformation() {
1266             if (_requestInfo == null) {
1267                 _requestInfo = new WebRequestInformation();
1268             }
1269         }
1270 
1271         public WebRequestInformation RequestInformation {
1272             get {
1273                 InitRequestInformation();
1274                 return _requestInfo;
1275             }
1276         }
1277 
GenerateFieldsForMarshal(List<WebEventFieldData> fields)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));
1287         }
1288 
FormatToString(WebEventFormatter formatter, bool includeAppInfo)1289         override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1290             base.FormatToString(formatter, includeAppInfo);
1291 
1292             formatter.AppendLine(String.Empty);
1293             formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information));
1294 
1295             formatter.IndentationLevel += 1;
1296             RequestInformation.FormatToString(formatter);
1297             formatter.IndentationLevel -= 1;
1298         }
1299 
IncrementPerfCounters()1300         override internal protected void IncrementPerfCounters() {
1301             base.IncrementPerfCounters();
1302             PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_WEB_REQ);
1303         }
1304     }
1305 
1306     // This is the base class for all error events.
1307     public class WebBaseErrorEvent : WebManagementEvent {
1308         Exception               _exception;
1309 
Init(Exception e)1310         void Init(Exception e) {
1311             _exception = e;
1312         }
1313 
WebBaseErrorEvent(string message, object eventSource, int eventCode, Exception e)1314         internal protected WebBaseErrorEvent(string message, object eventSource, int eventCode, Exception e)
1315             :base(message, eventSource, eventCode)
1316         {
1317             Init(e);
1318         }
1319 
WebBaseErrorEvent(string message, object eventSource, int eventCode, int eventDetailCode, Exception e)1320         internal protected WebBaseErrorEvent(string message, object eventSource, int eventCode, int eventDetailCode, Exception e)
1321             :base(message, eventSource, eventCode, eventDetailCode)
1322         {
1323             Init(e);
1324         }
1325 
WebBaseErrorEvent()1326         internal WebBaseErrorEvent() {
1327             // For creating dummy event.  See GetSystemDummyEvent()
1328         }
1329 
1330         public Exception ErrorException {
1331             get { return _exception; }
1332         }
1333 
FormatToString(WebEventFormatter formatter, bool includeAppInfo)1334         override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1335             base.FormatToString(formatter, includeAppInfo);
1336 
1337             if (_exception == null) {
1338                 return;
1339             }
1340 
1341             Exception   ex = _exception;
1342 
1343             // Please note we arbitrary pick a level limit per bug VSWhidbey 143859
1344             for (int level = 0;
1345                   ex != null && level <= 2;
1346                   ex = ex.InnerException, level++)  {
1347 
1348                 formatter.AppendLine(String.Empty);
1349 
1350                 if (level == 0) {
1351                     formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_exception_information));
1352                 }
1353                 else {
1354                     formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_inner_exception_information, level.ToString(CultureInfo.InstalledUICulture)));
1355                 }
1356 
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;
1361             }
1362         }
1363 
GenerateFieldsForMarshal(List<WebEventFieldData> fields)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));
1368         }
1369 
IncrementPerfCounters()1370         override internal protected void IncrementPerfCounters() {
1371             base.IncrementPerfCounters();
1372             PerfCounters.IncrementCounter(AppPerfCounter.EVENTS_ERROR);
1373             PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_EVENTS_ERROR);
1374         }
1375     }
1376 
1377     // This class contains information about systemic errors, e.g. things related to
1378     // configuration or application code (parser errors, compilation errors).
1379 
1380     public class WebErrorEvent : WebBaseErrorEvent {
1381         WebRequestInformation   _requestInfo;
1382         WebThreadInformation    _threadInfo;
1383 
Init(Exception e)1384         void Init(Exception e) {
1385         }
1386 
PreProcessEventInit()1387         override internal void PreProcessEventInit() {
1388             base.PreProcessEventInit();
1389             InitRequestInformation();
1390             InitThreadInformation();
1391         }
1392 
WebErrorEvent(string message, object eventSource, int eventCode, Exception exception)1393         internal protected WebErrorEvent(string message, object eventSource, int eventCode, Exception exception)
1394             :base(message, eventSource, eventCode, exception)
1395         {
1396             Init(exception);
1397         }
1398 
WebErrorEvent(string message, object eventSource, int eventCode, int eventDetailCode, Exception exception)1399         internal protected WebErrorEvent(string message, object eventSource, int eventCode, int eventDetailCode, Exception exception)
1400             :base(message, eventSource, eventCode, eventDetailCode, exception)
1401         {
1402             Init(exception);
1403         }
1404 
WebErrorEvent()1405         internal WebErrorEvent() {
1406             // For creating dummy event.  See GetSystemDummyEvent()
1407         }
1408 
InitRequestInformation()1409         void InitRequestInformation() {
1410             if (_requestInfo == null) {
1411                 _requestInfo = new WebRequestInformation();
1412             }
1413         }
1414 
1415         public WebRequestInformation RequestInformation {
1416             get {
1417                 InitRequestInformation();
1418                 return _requestInfo;
1419             }
1420         }
1421 
InitThreadInformation()1422         void InitThreadInformation() {
1423             if (_threadInfo == null) {
1424                 _threadInfo = new WebThreadInformation(base.ErrorException);
1425             }
1426         }
1427 
1428         public WebThreadInformation ThreadInformation {
1429             get {
1430                 InitThreadInformation();
1431                 return _threadInfo;
1432             }
1433         }
1434 
FormatToString(WebEventFormatter formatter, bool includeAppInfo)1435         override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1436             base.FormatToString(formatter, includeAppInfo);
1437 
1438             formatter.AppendLine(String.Empty);
1439             formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information));
1440 
1441             formatter.IndentationLevel += 1;
1442             RequestInformation.FormatToString(formatter);
1443             formatter.IndentationLevel -= 1;
1444 
1445             formatter.AppendLine(String.Empty);
1446             formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_information));
1447 
1448             formatter.IndentationLevel += 1;
1449             ThreadInformation.FormatToString(formatter);
1450             formatter.IndentationLevel -= 1;
1451         }
1452 
GenerateFieldsForMarshal(List<WebEventFieldData> fields)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));
1466         }
1467 
IncrementPerfCounters()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);
1472         }
1473     }
1474 
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;
1480 
Init(Exception e)1481         void Init(Exception e) {
1482         }
1483 
PreProcessEventInit()1484         override internal void PreProcessEventInit() {
1485             base.PreProcessEventInit();
1486             InitRequestInformation();
1487             InitThreadInformation();
1488         }
1489 
WebRequestErrorEvent(string message, object eventSource, int eventCode, Exception exception)1490         internal protected WebRequestErrorEvent(string message, object eventSource, int eventCode, Exception exception)
1491             :base(message, eventSource, eventCode, exception)
1492         {
1493             Init(exception);
1494         }
1495 
WebRequestErrorEvent(string message, object eventSource, int eventCode, int eventDetailCode, Exception exception)1496         internal protected WebRequestErrorEvent(string message, object eventSource, int eventCode, int eventDetailCode, Exception exception)
1497             :base(message, eventSource, eventCode, eventDetailCode, exception)
1498         {
1499             Init(exception);
1500         }
1501 
WebRequestErrorEvent()1502         internal WebRequestErrorEvent() {
1503             // For creating dummy event.  See GetSystemDummyEvent()
1504         }
1505 
1506         // properties
1507 
InitRequestInformation()1508         void InitRequestInformation() {
1509             if (_requestInfo == null) {
1510                 _requestInfo = new WebRequestInformation();
1511             }
1512         }
1513 
1514         public WebRequestInformation RequestInformation {
1515             get {
1516                 InitRequestInformation();
1517                 return _requestInfo;
1518             }
1519         }
1520 
InitThreadInformation()1521         void InitThreadInformation() {
1522             if (_threadInfo == null) {
1523                 _threadInfo = new WebThreadInformation(base.ErrorException);
1524             }
1525         }
1526 
1527         public WebThreadInformation ThreadInformation {
1528             get {
1529                 InitThreadInformation();
1530                 return _threadInfo;
1531             }
1532         }
1533 
FormatToString(WebEventFormatter formatter, bool includeAppInfo)1534         override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1535             base.FormatToString(formatter, includeAppInfo);
1536 
1537             formatter.AppendLine(String.Empty);
1538             formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information));
1539 
1540             formatter.IndentationLevel += 1;
1541             RequestInformation.FormatToString(formatter);
1542             formatter.IndentationLevel -= 1;
1543 
1544             formatter.AppendLine(String.Empty);
1545             formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_information));
1546 
1547             formatter.IndentationLevel += 1;
1548             ThreadInformation.FormatToString(formatter);
1549             formatter.IndentationLevel -= 1;
1550         }
1551 
GenerateFieldsForMarshal(List<WebEventFieldData> fields)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));
1565         }
1566 
IncrementPerfCounters()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);
1571         }
1572     }
1573 
1574 
1575     // The base class for all audit events.
1576 
1577     public class WebAuditEvent : WebManagementEvent {
1578         WebRequestInformation   _requestInfo;
1579 
PreProcessEventInit()1580         override internal void PreProcessEventInit() {
1581             base.PreProcessEventInit();
1582             InitRequestInformation();
1583         }
1584 
WebAuditEvent(string message, object eventSource, int eventCode)1585         internal protected WebAuditEvent(string message, object eventSource, int eventCode)
1586             :base(message, eventSource, eventCode)
1587         {
1588         }
1589 
WebAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode)1590         internal protected WebAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode)
1591             :base(message, eventSource, eventCode, eventDetailCode)
1592         {
1593         }
1594 
WebAuditEvent()1595         internal WebAuditEvent() {
1596             // For creating dummy event.  See GetSystemDummyEvent()
1597         }
1598 
InitRequestInformation()1599         void InitRequestInformation() {
1600             if (_requestInfo == null) {
1601                 _requestInfo = new WebRequestInformation();
1602             }
1603         }
1604 
1605         public WebRequestInformation RequestInformation {
1606             get {
1607                 InitRequestInformation();
1608                 return _requestInfo;
1609             }
1610         }
1611 
GenerateFieldsForMarshal(List<WebEventFieldData> fields)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));
1621         }
1622 
FormatToString(WebEventFormatter formatter, bool includeAppInfo)1623         override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1624             base.FormatToString(formatter, includeAppInfo);
1625 
1626             formatter.AppendLine(String.Empty);
1627             formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_request_information));
1628 
1629             formatter.IndentationLevel += 1;
1630             RequestInformation.FormatToString(formatter);
1631             formatter.IndentationLevel -= 1;
1632         }
1633     }
1634 
1635 
1636     // This class provides information about all failure audits.  In most cases,
1637     // applications will only want to enable failure audits.
1638 
1639     public class WebFailureAuditEvent : WebAuditEvent {
WebFailureAuditEvent(string message, object eventSource, int eventCode)1640         internal protected WebFailureAuditEvent(string message, object eventSource, int eventCode)
1641             :base(message, eventSource, eventCode)
1642         {
1643         }
1644 
WebFailureAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode)1645         internal protected WebFailureAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode)
1646             :base(message, eventSource, eventCode, eventDetailCode)
1647         {
1648         }
1649 
WebFailureAuditEvent()1650         internal WebFailureAuditEvent() {
1651             // For creating dummy event.  See GetSystemDummyEvent()
1652         }
1653 
IncrementPerfCounters()1654         override internal protected void IncrementPerfCounters() {
1655             base.IncrementPerfCounters();
1656             PerfCounters.IncrementCounter(AppPerfCounter.AUDIT_FAIL);
1657             PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_AUDIT_FAIL);
1658         }
1659     }
1660 
1661     public class WebAuthenticationFailureAuditEvent : WebFailureAuditEvent {
1662 
1663         string  _nameToAuthenticate;
1664 
Init(string name)1665         void Init(string name) {
1666             _nameToAuthenticate = name;
1667         }
1668 
WebAuthenticationFailureAuditEvent(string message, object eventSource, int eventCode, string nameToAuthenticate)1669         internal protected WebAuthenticationFailureAuditEvent(string message, object eventSource, int eventCode, string nameToAuthenticate)
1670             :base(message, eventSource, eventCode)
1671         {
1672             Init(nameToAuthenticate);
1673         }
1674 
1675 
WebAuthenticationFailureAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode, string nameToAuthenticate)1676         internal protected WebAuthenticationFailureAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode, string nameToAuthenticate)
1677             :base(message, eventSource, eventCode, eventDetailCode)
1678         {
1679             Init(nameToAuthenticate);
1680         }
1681 
WebAuthenticationFailureAuditEvent()1682         internal WebAuthenticationFailureAuditEvent() {
1683             // For creating dummy event.  See GetSystemDummyEvent()
1684         }
1685 
1686         public string NameToAuthenticate {
1687             get { return _nameToAuthenticate; }
1688         }
1689 
GenerateFieldsForMarshal(List<WebEventFieldData> fields)1690         internal override void GenerateFieldsForMarshal(List<WebEventFieldData> fields) {
1691             base.GenerateFieldsForMarshal(fields);
1692             fields.Add(new WebEventFieldData("NameToAuthenticate", NameToAuthenticate, WebEventFieldType.String));
1693         }
1694 
FormatToString(WebEventFormatter formatter, bool includeAppInfo)1695         override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1696             base.FormatToString(formatter, includeAppInfo);
1697 
1698             formatter.AppendLine(String.Empty);
1699             formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_name_to_authenticate, _nameToAuthenticate));
1700 
1701         }
1702     }
1703 
1704     public class WebViewStateFailureAuditEvent : WebFailureAuditEvent {
1705 
1706         ViewStateException  _viewStateException;
1707 
WebViewStateFailureAuditEvent(string message, object eventSource, int eventCode, ViewStateException viewStateException)1708         internal protected WebViewStateFailureAuditEvent(string message, object eventSource, int eventCode, ViewStateException viewStateException)
1709             :base(message, eventSource, eventCode)
1710         {
1711             _viewStateException = viewStateException;
1712         }
1713 
1714 
WebViewStateFailureAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode, ViewStateException viewStateException)1715         internal protected WebViewStateFailureAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode, ViewStateException viewStateException)
1716             :base(message, eventSource, eventCode, eventDetailCode)
1717         {
1718             _viewStateException = viewStateException;
1719         }
1720 
WebViewStateFailureAuditEvent()1721         internal WebViewStateFailureAuditEvent() {
1722             // For creating dummy event.  See GetSystemDummyEvent()
1723         }
1724 
1725         public ViewStateException ViewStateException {
1726             get { return _viewStateException; }
1727         }
1728 
GenerateFieldsForMarshal(List<WebEventFieldData> fields)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));
1738         }
1739 
FormatToString(WebEventFormatter formatter, bool includeAppInfo)1740         override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1741             base.FormatToString(formatter, includeAppInfo);
1742 
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));
1747 
1748             formatter.IndentationLevel -= 1;
1749         }
1750 
1751     }
1752 
1753 
1754     // This class provides information about all success audits.  In most cases,
1755     // applications will only want to enable failure audits.
1756 
1757     public class WebSuccessAuditEvent : WebAuditEvent {
WebSuccessAuditEvent(string message, object eventSource, int eventCode)1758         internal protected WebSuccessAuditEvent(string message, object eventSource, int eventCode)
1759             :base(message, eventSource, eventCode)
1760         {
1761         }
1762 
WebSuccessAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode)1763         internal protected WebSuccessAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode)
1764             :base(message, eventSource, eventCode, eventDetailCode)
1765         {
1766         }
1767 
WebSuccessAuditEvent()1768         internal WebSuccessAuditEvent() {
1769             // For creating dummy event.  See GetSystemDummyEvent()
1770         }
1771 
IncrementPerfCounters()1772         override internal protected void IncrementPerfCounters() {
1773             base.IncrementPerfCounters();
1774             PerfCounters.IncrementCounter(AppPerfCounter.AUDIT_SUCCESS);
1775             PerfCounters.IncrementGlobalCounter(GlobalPerfCounter.GLOBAL_AUDIT_SUCCESS);
1776         }
1777     }
1778 
1779     public class WebAuthenticationSuccessAuditEvent : WebSuccessAuditEvent {
1780 
1781         string  _nameToAuthenticate;
1782 
Init(string name)1783         void Init(string name) {
1784             _nameToAuthenticate = name;
1785         }
1786 
WebAuthenticationSuccessAuditEvent(string message, object eventSource, int eventCode, string nameToAuthenticate)1787         internal protected WebAuthenticationSuccessAuditEvent(string message, object eventSource, int eventCode, string nameToAuthenticate)
1788             :base(message, eventSource, eventCode)
1789         {
1790             Init(nameToAuthenticate);
1791         }
1792 
WebAuthenticationSuccessAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode, string nameToAuthenticate)1793         internal protected WebAuthenticationSuccessAuditEvent(string message, object eventSource, int eventCode, int eventDetailCode, string nameToAuthenticate)
1794             :base(message, eventSource, eventCode, eventDetailCode)
1795         {
1796             Init(nameToAuthenticate);
1797         }
1798 
WebAuthenticationSuccessAuditEvent()1799         internal WebAuthenticationSuccessAuditEvent() {
1800             // For creating dummy event.  See GetSystemDummyEvent()
1801         }
1802 
1803         public string NameToAuthenticate {
1804             get { return _nameToAuthenticate; }
1805         }
1806 
GenerateFieldsForMarshal(List<WebEventFieldData> fields)1807         internal override void GenerateFieldsForMarshal(List<WebEventFieldData> fields) {
1808             base.GenerateFieldsForMarshal(fields);
1809             fields.Add(new WebEventFieldData("NameToAuthenticate", NameToAuthenticate, WebEventFieldType.String));
1810         }
1811 
FormatToString(WebEventFormatter formatter, bool includeAppInfo)1812         override internal void FormatToString(WebEventFormatter formatter, bool includeAppInfo) {
1813             base.FormatToString(formatter, includeAppInfo);
1814 
1815             formatter.AppendLine(String.Empty);
1816             formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_name_to_authenticate, _nameToAuthenticate));
1817         }
1818     }
1819 
1820 
1821     ////////////////
1822     // Information
1823     ////////////////
1824 
1825     public sealed class WebProcessInformation {
1826         // The information is per worker process instance.
1827 
1828         int     _processId;
1829         string  _processName;
1830         string  _accountName;
1831 
WebProcessInformation()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;
1838             }
1839             else {
1840                 int lastIndex;
1841 
1842                 _processName = buf.ToString();
1843                 lastIndex = _processName.LastIndexOf('\\');
1844                 if (lastIndex != -1) {
1845                     _processName = _processName.Substring(lastIndex + 1);
1846                 }
1847             }
1848 
1849             _processId = SafeNativeMethods.GetCurrentProcessId() ;
1850             _accountName = HttpRuntime.WpUserId;
1851         }
1852 
1853         public int ProcessID { get { return _processId; } }
1854 
1855         public string ProcessName { get { return _processName; } }
1856 
1857         public string AccountName { get { return (_accountName != null ? _accountName : String.Empty); } }
1858 
FormatToString(WebEventFormatter formatter)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));
1863         }
1864     }
1865 
1866     public sealed class WebApplicationInformation {
1867         // The information is per appdomain.
1868 
1869         string  _appDomain;
1870         string  _trustLevel;
1871         string  _appUrl;
1872         string  _appPath;
1873         string  _machineName;
1874 
WebApplicationInformation()1875         internal WebApplicationInformation() {
1876             _appDomain = Thread.GetDomain().FriendlyName;
1877             _trustLevel = HttpRuntime.TrustLevel;
1878             _appUrl = HttpRuntime.AppDomainAppVirtualPath;
1879 
1880             try {
1881                 // We will get an exception if it's a non-ASP.NET app.
1882                 _appPath = HttpRuntime.AppDomainAppPathInternal;
1883             }
1884             catch {
1885                 _appPath = null;
1886             }
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
1892         }
1893 
1894         public string ApplicationDomain { get { return _appDomain; } }
1895 
1896         public string TrustLevel { get { return _trustLevel; } }
1897 
1898         public string ApplicationVirtualPath { get { return _appUrl; } }
1899 
1900         public string ApplicationPath { get { return _appPath; } }
1901 
1902         public string MachineName { get { return _machineName; } }
1903 
FormatToString(WebEventFormatter formatter)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));
1910         }
1911 
1912         [PermissionSet(SecurityAction.Assert, Unrestricted = true)]
GetMachineNameWithAssert()1913         private string GetMachineNameWithAssert() {
1914             return Environment.MachineName;
1915         }
1916 
ToString()1917         public override string ToString() {
1918             WebEventFormatter formatter = new WebEventFormatter();
1919 
1920             FormatToString(formatter);
1921             return formatter.ToString();
1922         }
1923     }
1924 
1925     public sealed class WebRequestInformation {
1926 
1927         string      _requestUrl;
1928         string      _requestPath;
1929         IPrincipal  _iprincipal;
1930         string      _userHostAddress = null;
1931         string      _accountName;
1932 
WebRequestInformation()1933         internal    WebRequestInformation() {
1934             // Need to Assert() in order to get request information regardless of trust level. See VSWhidbey 416733
1935             InternalSecurityPermissions.ControlPrincipal.Assert();
1936 
1937             HttpContext context = HttpContext.Current;
1938             HttpRequest request = null;
1939 
1940             if (context != null) {
1941                 bool hideRequestResponseOriginal = context.HideRequestResponse;
1942                 context.HideRequestResponse = false;
1943                 request = context.Request;
1944                 context.HideRequestResponse = hideRequestResponseOriginal;
1945 
1946                 _iprincipal = context.User;
1947 
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));
1962                     }
1963                 }
1964             } else {
1965                 _iprincipal = null;
1966             }
1967 
1968             if (request == null) {
1969                 _requestUrl = String.Empty;
1970                 _requestPath = String.Empty;
1971                 _userHostAddress = String.Empty;
1972             }
1973             else {
1974                 _requestUrl = request.UrlInternal;
1975                 _requestPath = request.Path;
1976                 _userHostAddress = request.UserHostAddress;
1977             }
1978             _accountName = WindowsIdentity.GetCurrent().Name;
1979         }
1980 
1981         // The information is per request.
1982 
1983         public string RequestUrl {get {return _requestUrl;}}
1984 
1985         public string RequestPath {get {return _requestPath;}}
1986 
1987         public IPrincipal Principal {get {return _iprincipal;}}
1988 
1989         public string UserHostAddress { get { return _userHostAddress;} }
1990 
1991         public string ThreadAccountName {get {return _accountName;}}
1992 
FormatToString(WebEventFormatter formatter)1993         public void FormatToString(WebEventFormatter formatter) {
1994             string      user;
1995             string      authType;
1996             bool        authed;
1997 
1998             if (Principal == null) {
1999                 user = String.Empty;
2000                 authType = String.Empty;
2001                 authed = false;
2002             }
2003             else {
2004                 IIdentity    id = Principal.Identity;
2005 
2006                 user = id.Name;
2007                 authed = id.IsAuthenticated;
2008                 authType = id.AuthenticationType;
2009             }
2010 
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));
2015 
2016             if (authed) {
2017                 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_authenticated));
2018             }
2019             else {
2020                 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_not_authenticated));
2021             }
2022             formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_authentication_type, authType));
2023             formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_thread_account_name, ThreadAccountName));
2024 
2025         }
2026     }
2027 
2028 
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.
2031     //
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.
2036     //
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();
2052 
2053         static TimeSpan      TS_ONE_SECOND = new TimeSpan(0, 0, 1);
2054 
WebProcessStatistics()2055         static WebProcessStatistics() {
2056             try {
2057 #if !FEATURE_PAL // FEATURE_PAL does not support this.  Make into a noop.
2058                 s_startTime = Process.GetCurrentProcess().StartTime;
2059 #endif // !FEATURE_PAL
2060             }
2061             catch {
2062                 s_getCurrentProcFailed = true;
2063             }
2064         }
2065 
Update()2066         void Update() {
2067             DateTime    now = DateTime.Now;
2068 
2069             if (now - s_lastUpdated < TS_ONE_SECOND) {
2070                 return;
2071             }
2072 
2073             lock (s_lockObject) {
2074                 if (now - s_lastUpdated < TS_ONE_SECOND) {
2075                     return;
2076                 }
2077 
2078                 if (!s_getCurrentProcFailed) {
2079                     Process process = Process.GetCurrentProcess();
2080 #if !FEATURE_PAL // FEATURE_PAL does not support these Process properties
2081 
2082                     s_threadCount = process.Threads.Count;
2083                     s_workingSet = (long)process.WorkingSet64;
2084                     s_peakWorkingSet = (long)process.PeakWorkingSet64;
2085 #else
2086                     throw new NotImplementedException ("ROTORTODO");
2087 #endif
2088                 }
2089 
2090                 s_managedHeapSize = GC.GetTotalMemory(false);
2091 
2092                 s_appdomainCount = HostingEnvironment.AppDomainsCount;
2093 
2094                 s_requestsExecuting = PerfCounters.GetGlobalCounter(GlobalPerfCounter.REQUESTS_CURRENT);
2095                 s_requestsQueued = PerfCounters.GetGlobalCounter(GlobalPerfCounter.REQUESTS_QUEUED);
2096                 s_requestsRejected = PerfCounters.GetGlobalCounter(GlobalPerfCounter.REQUESTS_REJECTED);
2097 
2098                 s_lastUpdated = now;
2099             }
2100         }
2101 
2102 
2103         public DateTime ProcessStartTime {get {Update(); return s_startTime;}}
2104 
2105         public int ThreadCount {get {Update(); return s_threadCount;}}
2106 
2107         public long WorkingSet {get {Update(); return s_workingSet;}}
2108 
2109         public long PeakWorkingSet {get {Update(); return s_peakWorkingSet;}}
2110 
2111         public long ManagedHeapSize {get {Update(); return s_managedHeapSize;}}
2112 
2113         public int AppDomainCount {get {Update(); return s_appdomainCount;}}
2114 
2115         public int RequestsExecuting {get {Update(); return s_requestsExecuting;}}
2116 
2117         public int RequestsQueued {get {Update(); return s_requestsQueued;}}
2118 
2119         public int RequestsRejected {get {Update(); return s_requestsRejected;}}
2120 
2121 
FormatToString(WebEventFormatter formatter)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)));
2128 
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)));
2133         }
2134     }
2135 
2136     public sealed class WebThreadInformation {
2137         int     _threadId;
2138         string  _accountName;
2139         string  _stackTrace;
2140         bool    _isImpersonating;
2141         internal const string IsImpersonatingKey = "ASPIMPERSONATING";
2142 
WebThreadInformation(Exception exception)2143         internal WebThreadInformation(Exception exception) {
2144             _threadId = Thread.CurrentThread.ManagedThreadId;
2145             _accountName = HttpApplication.GetCurrentWindowsIdentityWithAssert().Name;
2146 
2147             if (exception != null) {
2148                 _stackTrace = new StackTrace(exception, true).ToString();
2149                 _isImpersonating = exception.Data.Contains(IsImpersonatingKey);
2150             }
2151             else {
2152                 _stackTrace = String.Empty;
2153                 _isImpersonating = false;
2154             }
2155         }
2156 
2157 
2158         public int ThreadID {get {return _threadId;}}
2159 
2160         public string ThreadAccountName {get {return _accountName;}}
2161 
2162         public string StackTrace {get {return _stackTrace;}}
2163 
2164         public bool IsImpersonating {get {return _isImpersonating;}}
2165 
2166 
FormatToString(WebEventFormatter formatter)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));
2170 
2171             if (IsImpersonating) {
2172                 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_impersonating));
2173             }
2174             else {
2175                 formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_is_not_impersonating));
2176             }
2177 
2178             formatter.AppendLine(WebBaseEvent.FormatResourceStringWithCache(SR.Webevent_event_stack_trace, StackTrace));
2179         }
2180     }
2181 
2182     // Class that represents the firing record (how many times, last firing time, etc)
2183     // for each rule that inherits from WebBaseEvent.
2184 
2185     public sealed class RuleFiringRecord {
2186         internal DateTime   _lastFired;
2187         internal int        _timesRaised;
2188         internal int        _updatingLastFired;
2189 
2190         static TimeSpan     TS_ONE_SECOND = new TimeSpan(0, 0, 1);
2191 
2192         public DateTime LastFired { get { return _lastFired; } }
2193 
2194 
2195         public int TimesRaised { get { return _timesRaised; } }
2196 
2197         // Point to the ruleInfo that is used by this class
2198         internal HealthMonitoringSectionHelper.RuleInfo    _ruleInfo;
2199 
RuleFiringRecord(HealthMonitoringSectionHelper.RuleInfo ruleInfo)2200         internal RuleFiringRecord(HealthMonitoringSectionHelper.RuleInfo ruleInfo) {
2201 
2202             Debug.Assert(ruleInfo != null, "ruleInfo != null");
2203 
2204             _ruleInfo = ruleInfo;
2205 
2206             _lastFired = DateTime.MinValue;
2207             _timesRaised = 0;
2208             _updatingLastFired = 0;
2209         }
2210 
UpdateLastFired(DateTime now, bool alreadyLocked)2211         void UpdateLastFired(DateTime now, bool alreadyLocked) {
2212             TimeSpan    tsDiff = now - _lastFired;
2213 
2214             if (tsDiff < TS_ONE_SECOND) {
2215                 // If _lastFired was updated within one second, don't bother.
2216                 return;
2217             }
2218 
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) {
2223                     try {
2224                         _lastFired = now;
2225                     }
2226                     finally {
2227                         Interlocked.Exchange(ref _updatingLastFired, 0);
2228                     }
2229                 }
2230             }
2231             else {
2232                 _lastFired = now;
2233             }
2234         }
2235 
2236         // Note: this method is thread safe
CheckAndUpdate(WebBaseEvent eventRaised)2237         internal bool CheckAndUpdate(WebBaseEvent eventRaised) {
2238             DateTime    now = DateTime.Now;
2239             int         timesRaised;
2240             HealthMonitoringManager manager = HealthMonitoringManager.Manager();
2241 
2242             timesRaised = Interlocked.Increment(ref _timesRaised);
2243 
2244             if (manager == null) {
2245                 // Won't fire because we cannot configure healthmonitor
2246                 Debug.Trace("RuleFiringRecord", "Can't configure healthmonitor");
2247                 return false;
2248             }
2249 
2250             // Call custom evaluator first
2251             if (_ruleInfo._customEvaluatorType != null) {
2252 
2253                 IWebEventCustomEvaluator    icustom = (IWebEventCustomEvaluator)
2254                         manager._sectionHelper._customEvaluatorInstances[_ruleInfo._customEvaluatorType];
2255 
2256 #if (!DBG)
2257                 try {
2258 #endif
2259                     // The event may need to do pre-ProcessEvent initialization
2260                     eventRaised.PreProcessEventInit();
2261 
2262                     if (!icustom.CanFire(eventRaised, this)) {
2263                         Debug.Trace("RuleFiringRecord", "Custom evaluator returns false.");
2264                         return false;
2265                     }
2266 #if (!DBG)
2267                 }
2268                 catch {
2269                     Debug.Trace("RuleFiringRecord", "Hit an exception when calling Custom evaluator");
2270                     // Return if we hit an error
2271                     return false;
2272                 }
2273 #endif
2274             }
2275 
2276             if (timesRaised < _ruleInfo._minInstances) {
2277                 Debug.Trace("RuleFiringRecord",
2278                         "MinInterval not met; timesRaised=" + timesRaised +
2279                         "; _minInstances=" + _ruleInfo._minInstances);
2280                 return false;
2281             }
2282 
2283             if (timesRaised > _ruleInfo._maxLimit) {
2284                 Debug.Trace("RuleFiringRecord",
2285                         "MaxLimit exceeded; timesRaised=" + timesRaised +
2286                         "; _maxLimit=" + _ruleInfo._maxLimit);
2287                 return false;
2288             }
2289 
2290             // Last step: Check MinInterval and update _lastFired
2291 
2292             if (_ruleInfo._minInterval == TimeSpan.Zero) {
2293                 UpdateLastFired(now, false);
2294                 return true;
2295             }
2296 
2297             if ((now - _lastFired) <= _ruleInfo._minInterval) {
2298                 Debug.Trace("RuleFiringRecord",
2299                         "MinInterval not met; now=" + now +
2300                         "; _lastFired=" + _lastFired +
2301                         "; _ruleInfo._minInterval=" + _ruleInfo._minInterval);
2302                 return false;
2303             }
2304 
2305             // The lock is to prevent multiple threads from passing the
2306             // same test simultaneously.
2307             lock (this) {
2308                 if ((now - _lastFired) <= _ruleInfo._minInterval) {
2309                     Debug.Trace("RuleFiringRecord",
2310                             "MinInterval not met; now=" + now +
2311                             "; _lastFired=" + _lastFired +
2312                             "; _ruleInfo._tsMinInterval=" + _ruleInfo._minInterval);
2313                     return false;
2314                 }
2315 
2316                 UpdateLastFired(now, true);
2317                 return true;
2318             }
2319         }
2320 
2321     }
2322 
2323     internal class HealthMonitoringManager {
2324         internal HealthMonitoringSectionHelper          _sectionHelper;
2325         internal bool           _enabled = false;
2326 
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;
2333 
2334         // If this method returns null, it means we failed during configuration.
Manager()2335         internal static HealthMonitoringManager Manager() {
2336 
2337             if (s_initing) {
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.
2341                 return null;
2342             }
2343 
2344             if (s_inited) {
2345                 return s_manager;
2346             }
2347 
2348             lock (s_lockObject) {
2349                 if (s_inited) {
2350                     return s_manager;
2351                 }
2352 
2353                 try {
2354                     Debug.Assert(s_manager == null);
2355                     s_initing = true;
2356                     s_manager = new HealthMonitoringManager();;
2357                 }
2358                 finally {
2359                     s_initing = false;
2360                     s_inited = true;
2361                 }
2362             }
2363 
2364             return s_manager;
2365         }
2366 
2367         internal static bool Enabled {
2368             get {
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) {
2372                     return false;
2373                 }
2374 
2375                 HealthMonitoringManager manager = HealthMonitoringManager.Manager();
2376                 if (manager == null) {
2377                     return false;
2378                 }
2379 
2380                 return manager._enabled;
2381             }
2382         }
2383 
2384         internal static bool IsCacheDisposed { get { return s_isCacheDisposed; } set { s_isCacheDisposed = value; } }
2385 
StartHealthMonitoringHeartbeat()2386         internal static void StartHealthMonitoringHeartbeat() {
2387             HealthMonitoringManager manager = Manager();
2388             if (manager == null) {
2389                 Debug.Trace(
2390                     "HealthMonitoringManager", "Can't fire heartbeat because we cannot configure HealthMon");
2391                 return;
2392             }
2393 
2394             if (!manager._enabled) {
2395                 Debug.Trace(
2396                     "WebEventRaiseDetails", "Can't fire heartbeat because we are disabled");
2397                 return;
2398             }
2399 
2400             manager.StartHeartbeatTimer();
2401         }
2402 
HealthMonitoringManager()2403         private HealthMonitoringManager() {
2404             _sectionHelper = HealthMonitoringSectionHelper.GetHelper();
2405 
2406             _enabled = _sectionHelper.Enabled;
2407 
2408             if (!_enabled) {
2409                 return;
2410             }
2411         }
2412 
Shutdown()2413         internal static void Shutdown() {
2414             WebEventManager.Shutdown();
2415             Dispose();
2416         }
2417 
Dispose()2418         internal static void Dispose() {
2419             // Make sure this function won't throw
2420             try {
2421                 if (s_heartbeatTimer != null) {
2422                     s_heartbeatTimer.Dispose();
2423                     s_heartbeatTimer = null;
2424                 }
2425             }
2426             catch {
2427             }
2428         }
2429 
HeartbeatCallback(object state)2430         internal void HeartbeatCallback(object state) {
2431             Debug.Assert(HealthMonitoringManager.Enabled);
2432             WebBaseEvent.RaiseSystemEvent(null, WebEventCodes.ApplicationHeartbeat);
2433         }
2434 
StartHeartbeatTimer()2435         internal void StartHeartbeatTimer() {
2436             TimeSpan interval = _sectionHelper.HealthMonitoringSection.HeartbeatInterval;
2437 
2438             if (interval == TimeSpan.Zero) {
2439                 return;
2440             }
2441 
2442 #if DBG
2443             if (!Debug.IsTagPresent("Timer") || Debug.IsTagEnabled("Timer"))
2444 #endif
2445             {
2446                 s_heartbeatTimer = new Timer(new TimerCallback(this.HeartbeatCallback), null,
2447                     TimeSpan.Zero, interval);
2448             }
2449         }
2450 
2451         internal static HealthMonitoringSectionHelper.ProviderInstances ProviderInstances {
2452             get {
2453                 HealthMonitoringManager manager = Manager();
2454 
2455                 if (manager == null) {
2456                     return null;
2457                 }
2458 
2459                 if (!manager._enabled) {
2460                     return null;
2461                 }
2462 
2463                 return manager._sectionHelper._providerInstances;
2464             }
2465         }
2466     }
2467 
2468     public sealed class WebBaseEventCollection : ReadOnlyCollectionBase
2469     {
WebBaseEventCollection(ICollection events)2470         public WebBaseEventCollection(ICollection events) {
2471             if (events == null) {
2472                 throw new ArgumentNullException("events");
2473             }
2474 
2475             foreach (WebBaseEvent eventRaised in events) {
2476                 InnerList.Add(eventRaised);
2477             }
2478         }
2479 
WebBaseEventCollection(WebBaseEvent eventRaised)2480         internal WebBaseEventCollection(WebBaseEvent eventRaised) {
2481             if (eventRaised == null) {
2482                 throw new ArgumentNullException("eventRaised");
2483             }
2484 
2485             InnerList.Add(eventRaised);
2486         }
2487 
2488         // overloaded collection access methods
2489         public WebBaseEvent this[int index] {
2490             get {
2491                 return (WebBaseEvent) InnerList[index];
2492             }
2493         }
2494 
IndexOf(WebBaseEvent value)2495         public int IndexOf(WebBaseEvent value) {
2496             return InnerList.IndexOf(value);
2497         }
2498 
Contains(WebBaseEvent value)2499         public bool Contains(WebBaseEvent value) {
2500             return InnerList.Contains(value);
2501         }
2502     }
2503 
2504     public static class WebEventManager
2505     {
2506 
2507         [SecurityPermission(SecurityAction.Demand, Unrestricted=true)]
Flush(string providerName)2508         public static void Flush(string providerName) {
2509             HealthMonitoringSectionHelper.ProviderInstances   providers = HealthMonitoringManager.ProviderInstances;
2510 
2511             if (providers == null) {
2512                 return;
2513             }
2514 
2515             if (!providers.ContainsKey(providerName)) {
2516                 throw new ArgumentException(SR.GetString(SR.Health_mon_provider_not_found, providerName));
2517             }
2518 
2519             using (new ApplicationImpersonationContext()) {
2520                 providers[providerName].Flush();
2521             }
2522         }
2523 
2524         [SecurityPermission(SecurityAction.Demand, Unrestricted=true)]
Flush()2525         public static void Flush() {
2526             HealthMonitoringSectionHelper.ProviderInstances providers = HealthMonitoringManager.ProviderInstances;
2527 
2528             if (providers == null) {
2529                 return;
2530             }
2531 
2532             using (new ApplicationImpersonationContext()) {
2533                 foreach(DictionaryEntry de in providers) {
2534                     WebEventProvider    provider = (WebEventProvider)de.Value;
2535 
2536                     Debug.Trace("WebEventManager", "Flushing provider " + provider.Name);
2537                     provider.Flush();
2538                 }
2539             }
2540         }
2541 
Shutdown()2542         internal static void Shutdown() {
2543             HealthMonitoringSectionHelper.ProviderInstances   providers = HealthMonitoringManager.ProviderInstances;
2544 
2545             if (providers == null) {
2546                 return;
2547             }
2548 
2549             foreach(DictionaryEntry de in providers) {
2550                 WebEventProvider    provider = (WebEventProvider)de.Value;
2551 
2552                 Debug.Trace("WebEventManager", "Shutting down provider " + provider.Name);
2553                 provider.Shutdown();
2554             }
2555         }
2556     }
2557 
2558 }
2559 
2560