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
- RowToFieldTransformer.cs
- DirectoryInfo.cs
- _Connection.cs
- SqlBuffer.cs
- AssemblyLoader.cs
- BamlLocalizer.cs
- WebRequest.cs
- InfiniteIntConverter.cs
- TypeElement.cs
- SchemaNames.cs
- VectorKeyFrameCollection.cs
- GCHandleCookieTable.cs
- HtmlElementEventArgs.cs
- ListViewPagedDataSource.cs
- Single.cs
- Image.cs
- PageCache.cs
- SocketInformation.cs
- Merger.cs
- ExpressionQuoter.cs
- OptimalBreakSession.cs
- SecurityUtils.cs
- LinqDataSourceView.cs
- ActivityCodeDomReferenceService.cs
- TempFiles.cs
- ComponentEditorForm.cs
- Baml2006ReaderSettings.cs
- CssClassPropertyAttribute.cs
- StandardToolWindows.cs
- ServiceProviders.cs
- ObjectFactoryCodeDomTreeGenerator.cs
- DSACryptoServiceProvider.cs
- CodeCommentStatement.cs
- ProcessManager.cs
- SmiMetaDataProperty.cs
- Label.cs
- UdpUtility.cs
- HashRepartitionStream.cs
- DesignRelation.cs
- ClientScriptManagerWrapper.cs
- RedirectionProxy.cs
- AppDomainAttributes.cs
- DBSqlParser.cs
- AttributeSetAction.cs
- PageSetupDialog.cs
- PersistenceTypeAttribute.cs
- DataTableReaderListener.cs
- TreeViewItem.cs
- MemberPathMap.cs
- BitmapEffectGroup.cs
- RectAnimationUsingKeyFrames.cs
- SiteMapNode.cs
- CopyCodeAction.cs
- UserControlBuildProvider.cs
- NullExtension.cs
- DivideByZeroException.cs
- CultureInfoConverter.cs
- StrongNamePublicKeyBlob.cs
- XmlDictionaryReaderQuotas.cs
- ControlBuilder.cs
- PresentationAppDomainManager.cs
- HttpApplicationStateWrapper.cs
- Bitmap.cs
- TextProperties.cs
- RepeatInfo.cs
- BitmapDownload.cs
- HttpGetProtocolReflector.cs
- OracleParameterBinding.cs
- SecureStringHasher.cs
- AsyncResult.cs
- ConnectionConsumerAttribute.cs
- WindowsUserNameSecurityTokenAuthenticator.cs
- CodeEntryPointMethod.cs
- HashAlgorithm.cs
- Array.cs
- StatusStrip.cs
- Identifier.cs
- XhtmlTextWriter.cs
- TextPointerBase.cs
- PerformanceCounterPermissionEntry.cs
- Substitution.cs
- CellTreeNodeVisitors.cs
- Documentation.cs
- ArrayHelper.cs
- SchemeSettingElement.cs
- GridViewDeletedEventArgs.cs
- odbcmetadatacollectionnames.cs
- smtpconnection.cs
- _NestedMultipleAsyncResult.cs
- RectValueSerializer.cs
- SoapIgnoreAttribute.cs
- COM2ExtendedTypeConverter.cs
- CodeBinaryOperatorExpression.cs
- UIElementParaClient.cs
- FormViewRow.cs
- ColorPalette.cs
- AppSettingsExpressionBuilder.cs
- SeparatorAutomationPeer.cs
- _FixedSizeReader.cs
- FontFamilyIdentifier.cs