//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------ namespace System.ServiceModel.Diagnostics { using System.Diagnostics; using System.Runtime; using System.ServiceModel; using System.ServiceModel.Activation; using System.ServiceModel.Administration; using System.Diagnostics.PerformanceData; abstract class ServicePerformanceCountersBase : PerformanceCountersBase { string instanceName; internal enum PerfCounters : int { Calls = 0, CallsPerSecond, CallsOutstanding, CallsFailed, CallsFailedPerSecond, CallsFaulted, CallsFaultedPerSecond, CallDuration, CallDurationBase, SecurityValidationAuthenticationFailures, SecurityValidationAuthenticationFailuresPerSecond, CallsNotAuthorized, CallsNotAuthorizedPerSecond, Instances, InstancesRate, RMSessionsFaulted, RMSessionsFaultedPerSecond, RMMessagesDropped, RMMessagesDroppedPerSecond, TxFlowed, TxFlowedPerSecond, TxCommitted, TxCommittedPerSecond, TxAborted, TxAbortedPerSecond, TxInDoubt, TxInDoubtPerSecond, MsmqPoisonMessages, MsmqPoisonMessagesPerSecond, MsmqRejectedMessages, MsmqRejectedMessagesPerSecond, MsmqDroppedMessages, MsmqDroppedMessagesPerSecond, CallsPercentMaxCalls, CallsPercentMaxCallsBase, InstancesPercentMaxInstances, InstancesPercentMaxInstancesBase, SessionsPercentMaxSessions, SessionsPercentMaxSessionsBase, TotalCounters = SessionsPercentMaxSessionsBase + 1 } protected static readonly string[] perfCounterNames = { PerformanceCounterStrings.SERVICEMODELSERVICE.SCalls, PerformanceCounterStrings.SERVICEMODELSERVICE.SCallsPerSecond, PerformanceCounterStrings.SERVICEMODELSERVICE.SCallsOutstanding, PerformanceCounterStrings.SERVICEMODELSERVICE.SCallsFailed, PerformanceCounterStrings.SERVICEMODELSERVICE.SCallsFailedPerSecond, PerformanceCounterStrings.SERVICEMODELSERVICE.SCallsFaulted, PerformanceCounterStrings.SERVICEMODELSERVICE.SCallsFaultedPerSecond, PerformanceCounterStrings.SERVICEMODELSERVICE.SCallDuration, PerformanceCounterStrings.SERVICEMODELSERVICE.SCallDurationBase, PerformanceCounterStrings.SERVICEMODELSERVICE.SSecurityValidationAuthenticationFailures, PerformanceCounterStrings.SERVICEMODELSERVICE.SSecurityValidationAuthenticationFailuresPerSecond, PerformanceCounterStrings.SERVICEMODELSERVICE.SSecurityCallsNotAuthorized, PerformanceCounterStrings.SERVICEMODELSERVICE.SSecurityCallsNotAuthorizedPerSecond, PerformanceCounterStrings.SERVICEMODELSERVICE.SInstances, PerformanceCounterStrings.SERVICEMODELSERVICE.SInstancesPerSecond, PerformanceCounterStrings.SERVICEMODELSERVICE.SRMSessionsFaulted, PerformanceCounterStrings.SERVICEMODELSERVICE.SRMSessionsFaultedPerSecond, PerformanceCounterStrings.SERVICEMODELSERVICE.SRMMessagesDropped, PerformanceCounterStrings.SERVICEMODELSERVICE.SRMMessagesDroppedPerSecond, PerformanceCounterStrings.SERVICEMODELSERVICE.STxFlowed, PerformanceCounterStrings.SERVICEMODELSERVICE.STxFlowedPerSecond, PerformanceCounterStrings.SERVICEMODELSERVICE.STxCommitted, PerformanceCounterStrings.SERVICEMODELSERVICE.STxCommittedPerSecond, PerformanceCounterStrings.SERVICEMODELSERVICE.STxAborted, PerformanceCounterStrings.SERVICEMODELSERVICE.STxAbortedPerSecond, PerformanceCounterStrings.SERVICEMODELSERVICE.STxInDoubt, PerformanceCounterStrings.SERVICEMODELSERVICE.STxInDoubtPerSecond, PerformanceCounterStrings.SERVICEMODELSERVICE.MsmqPoisonMessages, PerformanceCounterStrings.SERVICEMODELSERVICE.MsmqPoisonMessagesPerSecond, PerformanceCounterStrings.SERVICEMODELSERVICE.MsmqRejectedMessages, PerformanceCounterStrings.SERVICEMODELSERVICE.MsmqRejectedMessagesPerSecond, PerformanceCounterStrings.SERVICEMODELSERVICE.MsmqDroppedMessages, PerformanceCounterStrings.SERVICEMODELSERVICE.MsmqDroppedMessagesPerSecond, PerformanceCounterStrings.SERVICEMODELSERVICE.CallsPercentMaxConcurrentCalls, PerformanceCounterStrings.SERVICEMODELSERVICE.CallsPercentMaxConcurrentCallsBase, PerformanceCounterStrings.SERVICEMODELSERVICE.InstancesPercentMaxConcurrentInstances, PerformanceCounterStrings.SERVICEMODELSERVICE.InstancesPercentMaxConcurrentInstancesBase, PerformanceCounterStrings.SERVICEMODELSERVICE.SessionsPercentMaxConcurrentSessions, PerformanceCounterStrings.SERVICEMODELSERVICE.SessionsPercentMaxConcurrentSessionsBase, }; const int maxCounterLength = 64; const int hashLength = 2; [Flags] enum truncOptions : uint { NoBits = 0, service32 = 0x01, uri31 = 0x04 } internal ServicePerformanceCountersBase(ServiceHostBase serviceHost) { this.instanceName = CreateFriendlyInstanceName(serviceHost); } internal override string InstanceName { get { return this.instanceName; } } internal override string[] CounterNames { get { return perfCounterNames; } } internal override int PerfCounterStart { get { return (int)PerfCounters.Calls; } } internal override int PerfCounterEnd { get { return (int)PerfCounters.TotalCounters; } } private static string GetServiceUri(ServiceHostBase serviceHost, ServiceInfo serviceInfo) { string uri; if (!TryGetFullVirtualPath(serviceHost, out uri)) { uri = serviceInfo.FirstAddress; } return uri; } private static string GetFullInstanceName(ServiceHostBase serviceHost) { // instance name is: serviceName@uri ServiceInfo serviceInfo = new ServiceInfo(serviceHost); string serviceName = serviceInfo.ServiceName; string uri = GetServiceUri(serviceHost, serviceInfo); return String.Format("{0}@{1}", serviceName, uri); } private static string GetShortInstanceName(ServiceHostBase serviceHost) { ServiceInfo serviceInfo = new ServiceInfo(serviceHost); string serviceName = serviceInfo.ServiceName; string uri = GetServiceUri(serviceHost, serviceInfo); int length = serviceName.Length + uri.Length + 2; if (length > maxCounterLength) { int count = 0; truncOptions tasks = ServicePerformanceCountersBase.GetCompressionTasks( length, serviceName.Length, uri.Length); //if necessary, compress service name to 8 chars with a 2 char hash code if ((tasks & truncOptions.service32) > 0) { count = 32; serviceName = GetHashedString(serviceName, count - hashLength, serviceName.Length - count + hashLength, true); } //if necessary, compress uri to 36 chars with a 2 char hash code if ((tasks & truncOptions.uri31) > 0) { count = 31; uri = GetHashedString(uri, 0, uri.Length - count + hashLength, false); } } // replace '/' with '|' because perfmon fails when '/' is in perfcounter instance name return serviceName + "@" + uri.Replace('/', '|'); } internal static string CreateFriendlyInstanceName(ServiceHostBase serviceHost) { string shortInstanceName = GetShortInstanceName(serviceHost); if (!ServiceModelAppSettings.EnsureUniquePerformanceCounterInstanceNames) { return shortInstanceName; } string fullInstanceName = GetFullInstanceName(serviceHost); return EnsureUniqueInstanceName(PerformanceCounterStrings.SERVICEMODELSERVICE.ServicePerfCounters, shortInstanceName, fullInstanceName); } internal static string GetFriendlyInstanceName(ServiceHostBase serviceHost) { string shortInstanceName = GetShortInstanceName(serviceHost); if (!ServiceModelAppSettings.EnsureUniquePerformanceCounterInstanceNames) { return shortInstanceName; } string fullInstanceName = GetFullInstanceName(serviceHost); return GetUniqueInstanceName(PerformanceCounterStrings.SERVICEMODELSERVICE.ServicePerfCounters, shortInstanceName, fullInstanceName); } static bool TryGetFullVirtualPath(ServiceHostBase serviceHost, out string uri) { VirtualPathExtension pathExtension = serviceHost.Extensions.Find(); if (pathExtension == null) { uri = null; return false; } uri = pathExtension.ApplicationVirtualPath + pathExtension.VirtualPath.ToString().Replace("~", ""); return uri != null; } static truncOptions GetCompressionTasks(int totalLen, int serviceLen, int uriLen) { truncOptions bitmask = 0; if (totalLen > maxCounterLength) { int workingLen = totalLen; //note: order of if statements important (see spec)! if (workingLen > maxCounterLength && serviceLen > 32) { bitmask |= truncOptions.service32; //compress service name to 16 chars workingLen -= serviceLen - 32; } if (workingLen > maxCounterLength && uriLen > 31) { bitmask |= truncOptions.uri31; //compress uri to 31 chars } } return bitmask; } internal abstract void MethodCalled(); internal abstract void MethodReturnedSuccess(); internal abstract void MethodReturnedError(); internal abstract void MethodReturnedFault(); internal abstract void SaveCallDuration(long time); internal abstract void AuthenticationFailed(); internal abstract void AuthorizationFailed(); internal abstract void ServiceInstanceCreated(); internal abstract void ServiceInstanceRemoved(); internal abstract void SessionFaulted(); internal abstract void MessageDropped(); internal abstract void TxCommitted(long count); internal abstract void TxInDoubt(long count); internal abstract void TxAborted(long count); internal abstract void TxFlowed(); internal abstract void MsmqDroppedMessage(); internal abstract void MsmqPoisonMessage(); internal abstract void MsmqRejectedMessage(); internal abstract void IncrementThrottlePercent(int counterIndex); internal abstract void SetThrottleBase(int counterIndex, long denominator); internal abstract void DecrementThrottlePercent(int counterIndex); } }