| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- //------------------------------------------------------------------------------
- // <copyright file="DbConnectionPoolCounters.cs" company="Microsoft">
- // Copyright (c) Microsoft Corporation. All rights reserved.
- // </copyright>
- // <owner current="true" primary="true">[....]</owner>
- //------------------------------------------------------------------------------
- namespace System.Data.ProviderBase {
- using System;
- using System.Collections;
- using System.Data.Common;
- using System.Diagnostics;
- using System.Globalization;
- using System.Reflection;
- using System.Runtime.ConstrainedExecution;
- using System.Security;
- using System.Security.Permissions;
- using System.Security.Principal;
- using System.Runtime.Versioning;
- internal abstract class DbConnectionPoolCounters {
- private static class CreationData {
- static internal readonly CounterCreationData HardConnectsPerSecond = new CounterCreationData(
- "HardConnectsPerSecond",
- "The number of actual connections per second that are being made to servers",
- PerformanceCounterType.RateOfCountsPerSecond32);
- static internal readonly CounterCreationData HardDisconnectsPerSecond = new CounterCreationData(
- "HardDisconnectsPerSecond",
- "The number of actual disconnects per second that are being made to servers",
- PerformanceCounterType.RateOfCountsPerSecond32);
- static internal readonly CounterCreationData SoftConnectsPerSecond = new CounterCreationData(
- "SoftConnectsPerSecond",
- "The number of connections we get from the pool per second",
- PerformanceCounterType.RateOfCountsPerSecond32);
- static internal readonly CounterCreationData SoftDisconnectsPerSecond = new CounterCreationData(
- "SoftDisconnectsPerSecond",
- "The number of connections we return to the pool per second",
- PerformanceCounterType.RateOfCountsPerSecond32);
- static internal readonly CounterCreationData NumberOfNonPooledConnections = new CounterCreationData(
- "NumberOfNonPooledConnections",
- "The number of connections that are not using connection pooling",
- PerformanceCounterType.NumberOfItems32);
- static internal readonly CounterCreationData NumberOfPooledConnections = new CounterCreationData(
- "NumberOfPooledConnections",
- "The number of connections that are managed by the connection pooler",
- PerformanceCounterType.NumberOfItems32);
- static internal readonly CounterCreationData NumberOfActiveConnectionPoolGroups = new CounterCreationData(
- "NumberOfActiveConnectionPoolGroups",
- "The number of unique connection strings",
- PerformanceCounterType.NumberOfItems32);
- static internal readonly CounterCreationData NumberOfInactiveConnectionPoolGroups = new CounterCreationData(
- "NumberOfInactiveConnectionPoolGroups",
- "The number of unique connection strings waiting for pruning",
- PerformanceCounterType.NumberOfItems32);
- static internal readonly CounterCreationData NumberOfActiveConnectionPools = new CounterCreationData(
- "NumberOfActiveConnectionPools",
- "The number of connection pools",
- PerformanceCounterType.NumberOfItems32);
- static internal readonly CounterCreationData NumberOfInactiveConnectionPools = new CounterCreationData(
- "NumberOfInactiveConnectionPools",
- "The number of connection pools",
- PerformanceCounterType.NumberOfItems32);
- static internal readonly CounterCreationData NumberOfActiveConnections = new CounterCreationData(
- "NumberOfActiveConnections",
- "The number of connections currently in-use",
- PerformanceCounterType.NumberOfItems32);
- static internal readonly CounterCreationData NumberOfFreeConnections = new CounterCreationData(
- "NumberOfFreeConnections",
- "The number of connections currently available for use",
- PerformanceCounterType.NumberOfItems32);
- static internal readonly CounterCreationData NumberOfStasisConnections = new CounterCreationData(
- "NumberOfStasisConnections",
- "The number of connections currently waiting to be made ready for use",
- PerformanceCounterType.NumberOfItems32);
- static internal readonly CounterCreationData NumberOfReclaimedConnections = new CounterCreationData(
- "NumberOfReclaimedConnections",
- "The number of connections we reclaim from GC'd external connections",
- PerformanceCounterType.NumberOfItems32);
- };
- sealed internal class Counter {
- private PerformanceCounter _instance;
-
- internal Counter (string categoryName, string instanceName, string counterName, PerformanceCounterType counterType) {
- if (ADP.IsPlatformNT5) {
- try {
- if (!ADP.IsEmpty(categoryName) && !ADP.IsEmpty(instanceName)) {
- PerformanceCounter instance = new PerformanceCounter();
- instance.CategoryName = categoryName;
- instance.CounterName = counterName;
- instance.InstanceName = instanceName;
- instance.InstanceLifetime = PerformanceCounterInstanceLifetime.Process;
- instance.ReadOnly = false;
- instance.RawValue = 0; // make sure we start out at zero
- _instance = instance;
- }
- }
- catch (InvalidOperationException e) {
- ADP.TraceExceptionWithoutRethrow(e);
- //
- }
- }
- }
- internal void Decrement() {
- PerformanceCounter instance = _instance;
- if (null != instance) {
- instance.Decrement();
- }
- }
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
- internal void Dispose () { //
- PerformanceCounter instance = _instance;
- _instance = null;
- if (null != instance) {
- instance.RemoveInstance();
- // should we be calling instance.Close?
- // if we do will it exacerbate the Dispose vs. Decrement race condition
- //instance.Close();
- }
- }
- internal void Increment() {
- PerformanceCounter instance = _instance;
- if (null != instance) {
- instance.Increment();
- }
- }
- };
- const int CounterInstanceNameMaxLength = 127;
- internal readonly Counter HardConnectsPerSecond;
- internal readonly Counter HardDisconnectsPerSecond;
- internal readonly Counter SoftConnectsPerSecond;
- internal readonly Counter SoftDisconnectsPerSecond;
- internal readonly Counter NumberOfNonPooledConnections;
- internal readonly Counter NumberOfPooledConnections;
- internal readonly Counter NumberOfActiveConnectionPoolGroups;
- internal readonly Counter NumberOfInactiveConnectionPoolGroups;
- internal readonly Counter NumberOfActiveConnectionPools;
- internal readonly Counter NumberOfInactiveConnectionPools;
- internal readonly Counter NumberOfActiveConnections;
- internal readonly Counter NumberOfFreeConnections;
- internal readonly Counter NumberOfStasisConnections;
- internal readonly Counter NumberOfReclaimedConnections;
-
- protected DbConnectionPoolCounters() : this(null, null) {
- }
- protected DbConnectionPoolCounters(string categoryName, string categoryHelp) {
- AppDomain.CurrentDomain.DomainUnload += new EventHandler(this.UnloadEventHandler);
- AppDomain.CurrentDomain.ProcessExit += new EventHandler(this.ExitEventHandler);
- AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(this.ExceptionEventHandler);
-
- string instanceName = null;
- if (!ADP.IsEmpty(categoryName)) {
- if (ADP.IsPlatformNT5) {
- instanceName = GetInstanceName();
- }
- }
-
- // level 0-3: hard connects/disconnects, plus basic pool/pool entry statistics
- string basicCategoryName = categoryName;
- HardConnectsPerSecond = new Counter(basicCategoryName, instanceName, CreationData.HardConnectsPerSecond.CounterName, CreationData.HardConnectsPerSecond.CounterType);
- HardDisconnectsPerSecond = new Counter(basicCategoryName, instanceName, CreationData.HardDisconnectsPerSecond.CounterName, CreationData.HardDisconnectsPerSecond.CounterType);
- NumberOfNonPooledConnections = new Counter(basicCategoryName, instanceName, CreationData.NumberOfNonPooledConnections.CounterName, CreationData.NumberOfNonPooledConnections.CounterType);
- NumberOfPooledConnections = new Counter(basicCategoryName, instanceName, CreationData.NumberOfPooledConnections.CounterName, CreationData.NumberOfPooledConnections.CounterType);
- NumberOfActiveConnectionPoolGroups = new Counter(basicCategoryName, instanceName, CreationData.NumberOfActiveConnectionPoolGroups.CounterName, CreationData.NumberOfActiveConnectionPoolGroups.CounterType);
- NumberOfInactiveConnectionPoolGroups = new Counter(basicCategoryName, instanceName, CreationData.NumberOfInactiveConnectionPoolGroups.CounterName, CreationData.NumberOfInactiveConnectionPoolGroups.CounterType);
- NumberOfActiveConnectionPools = new Counter(basicCategoryName, instanceName, CreationData.NumberOfActiveConnectionPools.CounterName, CreationData.NumberOfActiveConnectionPools.CounterType);
- NumberOfInactiveConnectionPools = new Counter(basicCategoryName, instanceName, CreationData.NumberOfInactiveConnectionPools.CounterName, CreationData.NumberOfInactiveConnectionPools.CounterType);
- NumberOfStasisConnections = new Counter(basicCategoryName, instanceName, CreationData.NumberOfStasisConnections.CounterName, CreationData.NumberOfStasisConnections.CounterType);
- NumberOfReclaimedConnections = new Counter(basicCategoryName, instanceName, CreationData.NumberOfReclaimedConnections.CounterName, CreationData.NumberOfReclaimedConnections.CounterType);
-
- // level 4: expensive stuff
- string verboseCategoryName = null;
- if (!ADP.IsEmpty(categoryName)) {
- // don't load TraceSwitch if no categoryName so that Odbc/OleDb have a chance of not loading TraceSwitch
- // which are also used by System.Diagnostics.PerformanceCounter.ctor & System.Transactions.get_Current
- TraceSwitch perfCtrSwitch = new TraceSwitch("ConnectionPoolPerformanceCounterDetail", "level of detail to track with connection pool performance counters");
- if (TraceLevel.Verbose == perfCtrSwitch.Level) {
- verboseCategoryName = categoryName;
- }
- }
- SoftConnectsPerSecond = new Counter(verboseCategoryName, instanceName, CreationData.SoftConnectsPerSecond.CounterName, CreationData.SoftConnectsPerSecond.CounterType);
- SoftDisconnectsPerSecond = new Counter(verboseCategoryName, instanceName, CreationData.SoftDisconnectsPerSecond.CounterName, CreationData.SoftDisconnectsPerSecond.CounterType);
- NumberOfActiveConnections = new Counter(verboseCategoryName, instanceName, CreationData.NumberOfActiveConnections.CounterName, CreationData.NumberOfActiveConnections.CounterType);
- NumberOfFreeConnections = new Counter(verboseCategoryName, instanceName, CreationData.NumberOfFreeConnections.CounterName, CreationData.NumberOfFreeConnections.CounterType);
- }
- [FileIOPermission(SecurityAction.Assert, Unrestricted=true)]
- private string GetAssemblyName() {
- string result = null;
- // First try GetEntryAssembly name, then AppDomain.FriendlyName.
- Assembly assembly = Assembly.GetEntryAssembly();
- if (null != assembly) {
- AssemblyName name = assembly.GetName();
- if (name != null) {
- result = name.Name; // MDAC 73469
- }
- }
- return result;
- }
- // SxS: this method uses GetCurrentProcessId to construct the instance name.
- //
- [ResourceExposure(ResourceScope.None)]
- [ResourceConsumption(ResourceScope.Process, ResourceScope.Process)]
- private string GetInstanceName() {
- string result = null;
- string instanceName = GetAssemblyName(); // instance perfcounter name
- if (ADP.IsEmpty(instanceName)) {
- AppDomain appDomain = AppDomain.CurrentDomain;
- if (null != appDomain) {
- instanceName = appDomain.FriendlyName;
- }
- }
- //
- int pid = SafeNativeMethods.GetCurrentProcessId();
- // SQLBUDT #366157 -there are several characters which have special meaning
- // to PERFMON. They recommend that we translate them as shown below, to
- // prevent problems.
- result = String.Format((IFormatProvider)null, "{0}[{1}]", instanceName, pid);
- result = result.Replace('(','[').Replace(')',']').Replace('#','_').Replace('/','_').Replace('\\','_');
- // SQLBUVSTS #94625 - counter instance name cannot be greater than 127
- if (result.Length > CounterInstanceNameMaxLength) {
- // Replacing the middle part with "[...]"
- // For example: if path is c:\long_path\very_(Ax200)_long__path\perftest.exe and process ID is 1234 than the resulted instance name will be:
- // c:\long_path\very_(AxM)[...](AxN)_long__path\perftest.exe[1234]
- // while M and N are adjusted to make each part before and after the [...] = 61 (making the total = 61 + 5 + 61 = 127)
- const string insertString = "[...]";
- int firstPartLength = (CounterInstanceNameMaxLength - insertString.Length) / 2;
- int lastPartLength = CounterInstanceNameMaxLength - firstPartLength - insertString.Length;
- result = string.Format((IFormatProvider)null, "{0}{1}{2}",
- result.Substring(0, firstPartLength),
- insertString,
- result.Substring(result.Length - lastPartLength, lastPartLength));
- Debug.Assert(result.Length == CounterInstanceNameMaxLength,
- string.Format((IFormatProvider)null, "wrong calculation of the instance name: expected {0}, actual: {1}", CounterInstanceNameMaxLength, result.Length));
- }
- return result;
- }
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
- public void Dispose() {
- // ExceptionEventHandler with IsTerminiating may be called before
- // the Connection Close is called or the variables are initialized
- SafeDispose(HardConnectsPerSecond);
- SafeDispose(HardDisconnectsPerSecond);
- SafeDispose(SoftConnectsPerSecond);
- SafeDispose(SoftDisconnectsPerSecond);
- SafeDispose(NumberOfNonPooledConnections);
- SafeDispose(NumberOfPooledConnections);
- SafeDispose(NumberOfActiveConnectionPoolGroups);
- SafeDispose(NumberOfInactiveConnectionPoolGroups);
- SafeDispose(NumberOfActiveConnectionPools);
- SafeDispose(NumberOfActiveConnections);
- SafeDispose(NumberOfFreeConnections);
- SafeDispose(NumberOfStasisConnections);
- SafeDispose(NumberOfReclaimedConnections);
- }
- [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
- private void SafeDispose(Counter counter) { // WebData 103603
- if (null != counter) {
- counter.Dispose();
- }
- }
- [PrePrepareMethod]
- void ExceptionEventHandler (object sender, UnhandledExceptionEventArgs e) {
- if ((null != e) && e.IsTerminating) {
- Dispose();
- }
- }
- [PrePrepareMethod]
- void ExitEventHandler (object sender, EventArgs e) {
- Dispose();
- }
- [PrePrepareMethod]
- void UnloadEventHandler (object sender, EventArgs e) {
- Dispose();
- }
- }
-
- sealed internal class DbConnectionPoolCountersNoCounters : DbConnectionPoolCounters {
- public static readonly DbConnectionPoolCountersNoCounters SingletonInstance = new DbConnectionPoolCountersNoCounters();
- private DbConnectionPoolCountersNoCounters() : base () {
- }
- }
- }
|