Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Net / System / Net / _NetworkingPerfCounters.cs / 1305376 / _NetworkingPerfCounters.cs
//------------------------------------------------------------------------------ //// Copyright (c) Microsoft Corporation. All rights reserved. // //----------------------------------------------------------------------------- namespace System.Net { using System; using System.Reflection; using System.Net.Sockets; using System.Diagnostics; using System.Security.Permissions; using System.ComponentModel; using System.Globalization; using System.Text; using System.Runtime.Versioning; using System.Threading; using System.Net.Configuration; internal enum NetworkingPerfCounterName { SocketConnectionsEstablished = 0, // these enum values are used as index SocketBytesReceived, SocketBytesSent, SocketDatagramsReceived, SocketDatagramsSent, HttpWebRequestCreated, HttpWebRequestAvgLifeTime, HttpWebRequestAvgLifeTimeBase, HttpWebRequestQueued, HttpWebRequestAvgQueueTime, HttpWebRequestAvgQueueTimeBase, HttpWebRequestAborted, HttpWebRequestFailed } internal sealed class NetworkingPerfCounters { private class CounterPair { private PerformanceCounter instanceCounter; private PerformanceCounter globalCounter; public PerformanceCounter InstanceCounter { get { return instanceCounter; } } public PerformanceCounter GlobalCounter { get { return globalCounter; } } public CounterPair(PerformanceCounter instanceCounter, PerformanceCounter globalCounter) { Debug.Assert(instanceCounter != null); Debug.Assert(globalCounter != null); this.instanceCounter = instanceCounter; this.globalCounter = globalCounter; } } private const int instanceNameMaxLength = 127; private const string categoryName = ".NET CLR Networking 4.0.0.0"; private const string globalInstanceName = "_Global_"; private static readonly string[] counterNames = { "Connections Established", "Bytes Received", "Bytes Sent", "Datagrams Received", "Datagrams Sent", "HttpWebRequests Created/Sec", "HttpWebRequests Average Lifetime", "HttpWebRequests Average Lifetime Base", "HttpWebRequests Queued/Sec", "HttpWebRequests Average Queue Time", "HttpWebRequests Average Queue Time Base", "HttpWebRequests Aborted/Sec", "HttpWebRequests Failed/Sec", }; private static NetworkingPerfCounters instance; private static object lockObject = new object(); private volatile bool initDone; // keep this volatile to prevent load-load reordering private bool initSuccessful; private CounterPair[] counters; private bool enabled; private volatile bool cleanupCalled; private NetworkingPerfCounters() { enabled = SettingsSectionInternal.Section.PerformanceCountersEnabled; } public static NetworkingPerfCounters Instance { get { if (instance == null) { lock (lockObject) { if (instance == null) { CreateInstance(); } } } return instance; } } public static long GetTimestamp() { return Stopwatch.GetTimestamp(); } public bool Enabled { get { return enabled; } } public void Increment(NetworkingPerfCounterName perfCounter) { Increment(perfCounter, 1); } public void Increment(NetworkingPerfCounterName perfCounter, long amount) { if (CounterAvailable()) { try { CounterPair cp = counters[(int)perfCounter]; Debug.Assert(cp != null); cp.InstanceCounter.IncrementBy(amount); cp.GlobalCounter.IncrementBy(amount); } // in case there is something wrong with the counter instance, just log and continue catch (InvalidOperationException e) { if (Logging.On) Logging.Exception(Logging.Web, "NetworkingPerfCounters", "Increment", e); } catch (Win32Exception e) { if (Logging.On) Logging.Exception(Logging.Web, "NetworkingPerfCounters", "Increment", e); } } } public void Decrement(NetworkingPerfCounterName perfCounter) { Increment(perfCounter, -1); } public void Decrement(NetworkingPerfCounterName perfCounter, long amount) { Increment(perfCounter, -amount); } public void IncrementAverage(NetworkingPerfCounterName perfCounter, long startTimestamp) { if (CounterAvailable()) { long stopTimestamp = GetTimestamp(); int avgCounterIndex = (int)perfCounter; Debug.Assert(avgCounterIndex + 1 < counters.Length); long duration = ((stopTimestamp - startTimestamp) * 1000) / Stopwatch.Frequency; Increment(perfCounter, duration); // base counter is always the next one (otherwise we wouldn't even be able to initialize the counters) Increment(perfCounter + 1, 1); } } private void Initialize(object state) { if (Logging.On) Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_perfcounter_initialization_started)); PerformanceCounterPermission perfCounterPermission = new PerformanceCounterPermission(PermissionState.Unrestricted); perfCounterPermission.Assert(); try { if (!PerformanceCounterCategory.Exists(categoryName)) { // if the perf. counter category doesn't exist, just log this information and exit. if (Logging.On) Logging.PrintError(Logging.Web, SR.GetString(SR.net_perfcounter_nocategory, categoryName)); return; } string instanceName = GetInstanceName(); Debug.Assert(counterNames.Length == Enum.GetValues(typeof(NetworkingPerfCounterName)).Length, "The number of NetworkingPerfCounterName items must match the number of CounterNames"); // create the counters, this will check for the right permissions (false) // means the counter is not readonly (it's read/write) and cache them while // we're under the Assert(), which will be reverted in the finally below. counters = new CounterPair[counterNames.Length]; for (int i = 0; i < counterNames.Length; i++) { counters[i] = CreateCounterPair(counterNames[i], instanceName); } AppDomain.CurrentDomain.DomainUnload += new EventHandler(UnloadEventHandler); AppDomain.CurrentDomain.ProcessExit += new EventHandler(ExitEventHandler); AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(ExceptionEventHandler); initSuccessful = true; } catch (Win32Exception e) { if (Logging.On) Logging.Exception(Logging.Web, "NetworkingPerfCounters", "Initialize", e); Cleanup(); return; } catch (InvalidOperationException e) { if (Logging.On) Logging.Exception(Logging.Web, "NetworkingPerfCounters", "Initialize", e); Cleanup(); return; } finally { PerformanceCounterPermission.RevertAssert(); initDone = true; if (Logging.On) { if (initSuccessful) { Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_perfcounter_initialized_success)); } else { Logging.PrintInfo(Logging.Web, SR.GetString(SR.net_perfcounter_initialized_error)); } } } } private static void CreateInstance() { instance = new NetworkingPerfCounters(); if (instance.Enabled) { // as recommended by the perf. counter team: initialize perf. counters in background thread // since initialization may take a long time. Therefore we should not block. if (!ThreadPool.QueueUserWorkItem(instance.Initialize)) { if (Logging.On) Logging.PrintError(Logging.Web, SR.GetString(SR.net_perfcounter_cant_queue_workitem)); } } } private static CounterPair CreateCounterPair(string counterName, string instanceName) { // first create global counter. If it throws we don't create an instance counter. If creating // the instance counter throws, we don't need to cleanup the global counter (done by perf. counter // infrastructure) // use this ctor for global counters: it makes sure the counter is actually initialized. If // we would use the ctor without params, as for the instance counters, the global counter // would not be initialized => only when we increment it the first time it gets initialized. But // at that point, we're no more under the permission assertion. PerformanceCounter globalCounter = new PerformanceCounter(categoryName, counterName, globalInstanceName, false); // for instance counters we use the default ctor, since we also need to set the lifetime. The // counter gets actually initialized when we set RawValue. PerformanceCounter instanceCounter = new PerformanceCounter(); instanceCounter.CategoryName = categoryName; instanceCounter.CounterName = counterName; instanceCounter.InstanceName = instanceName; instanceCounter.InstanceLifetime = PerformanceCounterInstanceLifetime.Process; instanceCounter.ReadOnly = false; instanceCounter.RawValue = 0; return new CounterPair(instanceCounter, globalCounter); } private void ExceptionEventHandler(object sender, UnhandledExceptionEventArgs e) { if (e.IsTerminating) { Cleanup(); } } // Keep the UnloadEventHandler and ExitEventHandler methods separate in order to // facilitate better debugging and crash troubleshooting during call stack analysis // of ProcessExit and DomainUnload events from the AppDomain. private void UnloadEventHandler(object sender, EventArgs e) { Cleanup(); } private void ExitEventHandler(object sender, EventArgs e) { Cleanup(); } // Need to check for Environment.HasShutdownStarted. This flag is ONLY // set when the CLR is running the GC Finalize thread and thus it is invalid // to access the static performanceCounter objects and their methods. private void Cleanup() { // In cases where Cleanup() gets called simultaneously on different threads, // we use the lock to make sure it gets executed only once. lock (lockObject) { if (!cleanupCalled) { cleanupCalled = true; // counters may be null if Initialize() throws before counters gets created if (counters != null) { foreach (CounterPair cp in counters) { // cp != null check: if the loop creating the counters in Initialize() throws // an excpetion, some CounterPairs may not be created yet, thus the null check below. if (!Environment.HasShutdownStarted && cp != null) { try { cp.InstanceCounter.RemoveInstance(); } // in case there is something wrong with the counter instance, just log. catch (InvalidOperationException e) { if (Logging.On) Logging.Exception(Logging.Web, "NetworkingPerfCounters", "Cleanup", e); } catch (Win32Exception e) { if (Logging.On) Logging.Exception(Logging.Web, "NetworkingPerfCounters", "Cleanup", e); } } } } // No need to clean up global counters. } } } private static string GetInstanceName() { string friendlyName = ReplaceInvalidChars(AppDomain.CurrentDomain.FriendlyName); string postfix = VersioningHelper.MakeVersionSafeName(string.Empty, ResourceScope.Machine, ResourceScope.AppDomain); string result = friendlyName + postfix; if (result.Length > instanceNameMaxLength) { result = friendlyName.Substring(0, instanceNameMaxLength - postfix.Length) + postfix; } return result; } private static string ReplaceInvalidChars(string instanceName) { // map invalid characters as suggested by MSDN (see PerformanceCounter.InstanceName Property help) StringBuilder result = new StringBuilder(instanceName); for (int i = 0; i < result.Length; i++) { switch (result[i]) { case '(': result[i] = '['; break; case ')': result[i] = ']'; break; case '/': case '\\': case '#': result[i] = '_'; break; } } return result.ToString(); } private bool CounterAvailable() { // Checking cleanupCalled below is not really necessary, since incrementing an already released // PerformanceCounter object is allowed. But since there is no point in incrementing a released // counter, we return false. // The only scenario where we increment a released counter is: Cleanup() is called after the // cleanupCalled check below, but before the counter is incremented. if (!enabled || cleanupCalled) { return false; } if (initDone) { return initSuccessful; } return false; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Speller.cs
- ReflectionUtil.cs
- SamlAudienceRestrictionCondition.cs
- XmlDataSourceNodeDescriptor.cs
- Mouse.cs
- Itemizer.cs
- RegionInfo.cs
- UIElement3D.cs
- SelectionRangeConverter.cs
- RelOps.cs
- PreservationFileReader.cs
- SQLSingle.cs
- FixedSOMTable.cs
- UpdatePanelControlTrigger.cs
- SchemaNamespaceManager.cs
- BitVector32.cs
- Rect3DConverter.cs
- CompiledXpathExpr.cs
- MultilineStringConverter.cs
- BindingValueChangedEventArgs.cs
- MemoryStream.cs
- CharEntityEncoderFallback.cs
- FreezableCollection.cs
- UrlPath.cs
- PropertyDescriptorComparer.cs
- BuildResult.cs
- IncomingWebResponseContext.cs
- BoundPropertyEntry.cs
- FileSystemEventArgs.cs
- CqlLexerHelpers.cs
- MailAddress.cs
- TextChangedEventArgs.cs
- SqlNotificationRequest.cs
- ADMembershipProvider.cs
- TableItemPatternIdentifiers.cs
- TextProviderWrapper.cs
- WindowsBrush.cs
- RuleElement.cs
- SessionEndingEventArgs.cs
- SmtpDigestAuthenticationModule.cs
- WebPartConnectionsCancelEventArgs.cs
- FileNotFoundException.cs
- DesignOnlyAttribute.cs
- ComplexBindingPropertiesAttribute.cs
- FeatureSupport.cs
- HandlerMappingMemo.cs
- Pointer.cs
- StringDictionary.cs
- CodeComment.cs
- DecimalKeyFrameCollection.cs
- XmlFormatWriterGenerator.cs
- X509AsymmetricSecurityKey.cs
- ADMembershipProvider.cs
- PointAnimationClockResource.cs
- CodeParameterDeclarationExpressionCollection.cs
- TableItemStyle.cs
- XmlIlGenerator.cs
- ConstraintStruct.cs
- XmlAnyAttributeAttribute.cs
- ImageListStreamer.cs
- TextRangeProviderWrapper.cs
- EntityClassGenerator.cs
- SafeCertificateContext.cs
- EditorAttribute.cs
- DrawListViewItemEventArgs.cs
- VectorValueSerializer.cs
- PngBitmapDecoder.cs
- StaticDataManager.cs
- CompModSwitches.cs
- ErrorInfoXmlDocument.cs
- FloaterBaseParaClient.cs
- ToolStripContentPanelRenderEventArgs.cs
- ISAPIApplicationHost.cs
- RuleInfoComparer.cs
- CfgParser.cs
- RoleGroupCollection.cs
- XmlIgnoreAttribute.cs
- ClientTargetSection.cs
- LiteralText.cs
- CriticalHandle.cs
- PowerEase.cs
- RegexTree.cs
- ItemsControl.cs
- Rect.cs
- CAGDesigner.cs
- DBCSCodePageEncoding.cs
- ExpressionCopier.cs
- TypeDelegator.cs
- UrlPath.cs
- HttpHandlersSection.cs
- AdapterDictionary.cs
- DataSourceXmlSerializer.cs
- SmiEventSink_Default.cs
- JsonWriter.cs
- BindingListCollectionView.cs
- AssemblyBuilderData.cs
- DataColumnChangeEvent.cs
- PasswordTextNavigator.cs
- GraphicsPath.cs
- XmlSubtreeReader.cs