e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
469 lines
23 KiB
C#
469 lines
23 KiB
C#
// ****************************************************************************
|
|
// Copyright (C) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// CONTENTS
|
|
// Performance counters used by default host
|
|
//
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Xml;
|
|
using System.Reflection;
|
|
using System.Threading;
|
|
using System.Diagnostics;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Transactions;
|
|
|
|
using System.Workflow.Runtime.Hosting;
|
|
|
|
namespace System.Workflow.Runtime
|
|
{
|
|
internal enum PerformanceCounterOperation
|
|
{
|
|
Increment,
|
|
Decrement
|
|
}
|
|
|
|
internal enum PerformanceCounterAction
|
|
{
|
|
Aborted,
|
|
Completion,
|
|
Creation,
|
|
Unloading,
|
|
Executing,
|
|
Idle,
|
|
NotExecuting,
|
|
Persisted,
|
|
Loading,
|
|
Runnable,
|
|
Suspension,
|
|
Resumption,
|
|
Termination,
|
|
Starting,
|
|
}
|
|
|
|
internal sealed class PerformanceCounterManager
|
|
{
|
|
private static String c_PerformanceCounterCategoryName = ExecutionStringManager.PerformanceCounterCategory;
|
|
|
|
// Create a declarative model for specifying performance counter behavior.
|
|
|
|
private static PerformanceCounterData[] s_DefaultPerformanceCounters = new PerformanceCounterData[]
|
|
{
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesCreatedName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesCreatedDescription,
|
|
PerformanceCounterType.NumberOfItems64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Creation, PerformanceCounterOperation.Increment ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesCreatedRateName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesCreatedRateDescription,
|
|
PerformanceCounterType.RateOfCountsPerSecond64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Creation, PerformanceCounterOperation.Increment ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesUnloadedName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesUnloadedDescription,
|
|
PerformanceCounterType.NumberOfItems64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Unloading, PerformanceCounterOperation.Increment ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesUnloadedRateName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesUnloadedRateDescription,
|
|
PerformanceCounterType.RateOfCountsPerSecond64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Unloading, PerformanceCounterOperation.Increment ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesLoadedName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesLoadedDescription,
|
|
PerformanceCounterType.NumberOfItems64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Loading, PerformanceCounterOperation.Increment ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesLoadedRateName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesLoadedRateDescription,
|
|
PerformanceCounterType.RateOfCountsPerSecond64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Loading, PerformanceCounterOperation.Increment ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesCompletedName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesCompletedDescription,
|
|
PerformanceCounterType.NumberOfItems64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Completion, PerformanceCounterOperation.Increment ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesCompletedRateName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesCompletedRateDescription,
|
|
PerformanceCounterType.RateOfCountsPerSecond64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Completion, PerformanceCounterOperation.Increment ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesSuspendedName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesSuspendedDescription,
|
|
PerformanceCounterType.NumberOfItems64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Suspension, PerformanceCounterOperation.Increment ),
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Resumption, PerformanceCounterOperation.Decrement ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesSuspendedRateName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesSuspendedRateDescription,
|
|
PerformanceCounterType.RateOfCountsPerSecond64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Suspension, PerformanceCounterOperation.Increment ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesTerminatedName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesTerminatedDescription,
|
|
PerformanceCounterType.NumberOfItems64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Termination, PerformanceCounterOperation.Increment ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesTerminatedRateName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesTerminatedRateDescription,
|
|
PerformanceCounterType.RateOfCountsPerSecond64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Termination, PerformanceCounterOperation.Increment ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesInMemoryName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesInMemoryDescription,
|
|
PerformanceCounterType.NumberOfItems64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Creation, PerformanceCounterOperation.Increment ),
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Loading, PerformanceCounterOperation.Increment ),
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Unloading, PerformanceCounterOperation.Decrement ),
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Completion, PerformanceCounterOperation.Decrement ),
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Termination, PerformanceCounterOperation.Decrement ),
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Aborted, PerformanceCounterOperation.Decrement ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesExecutingName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesExecutingDescription,
|
|
PerformanceCounterType.NumberOfItems64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Executing, PerformanceCounterOperation.Increment ),
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.NotExecuting, PerformanceCounterOperation.Decrement ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesIdleRateName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesIdleRateDescription,
|
|
PerformanceCounterType.RateOfCountsPerSecond64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Idle, PerformanceCounterOperation.Increment ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesRunnableName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesRunnableDescription,
|
|
PerformanceCounterType.NumberOfItems64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Runnable, PerformanceCounterOperation.Increment ),
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.NotExecuting, PerformanceCounterOperation.Decrement ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesAbortedName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesAbortedDescription,
|
|
PerformanceCounterType.NumberOfItems64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Aborted, PerformanceCounterOperation.Increment ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesAbortedRateName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesAbortedRateDescription,
|
|
PerformanceCounterType.RateOfCountsPerSecond64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Aborted, PerformanceCounterOperation.Increment ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesPersistedName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesPersistedDescription,
|
|
PerformanceCounterType.NumberOfItems64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Persisted, PerformanceCounterOperation.Increment ),
|
|
}),
|
|
new PerformanceCounterData( ExecutionStringManager.PerformanceCounterSchedulesPersistedRateName,
|
|
ExecutionStringManager.PerformanceCounterSchedulesPersistedRateDescription,
|
|
PerformanceCounterType.RateOfCountsPerSecond64,
|
|
new PerformanceCounterActionMapping[]
|
|
{
|
|
new PerformanceCounterActionMapping( PerformanceCounterAction.Persisted, PerformanceCounterOperation.Increment ),
|
|
}),
|
|
};
|
|
|
|
private String m_instanceName;
|
|
private Dictionary<PerformanceCounterAction, List<PerformanceCounterStatement>> m_actionStatements;
|
|
|
|
internal PerformanceCounterManager()
|
|
{
|
|
}
|
|
|
|
internal void Initialize(WorkflowRuntime runtime)
|
|
{
|
|
runtime.WorkflowExecutorInitializing += WorkflowExecutorInitializing;
|
|
}
|
|
|
|
internal void Uninitialize(WorkflowRuntime runtime)
|
|
{
|
|
runtime.WorkflowExecutorInitializing -= WorkflowExecutorInitializing;
|
|
}
|
|
|
|
[SuppressMessage("Microsoft.Security", "CA2106:SecureAsserts",
|
|
Justification = "Design has been approved.")]
|
|
internal void SetInstanceName(String instanceName)
|
|
{
|
|
PerformanceCounterData[] data = s_DefaultPerformanceCounters;
|
|
|
|
if (String.IsNullOrEmpty(instanceName))
|
|
{
|
|
try
|
|
{
|
|
// The assert is safe here as we never give out the instance name.
|
|
new System.Security.Permissions.SecurityPermission(System.Security.Permissions.PermissionState.Unrestricted).Assert();
|
|
Process process = Process.GetCurrentProcess();
|
|
ProcessModule mainModule = process.MainModule;
|
|
instanceName = mainModule.ModuleName;
|
|
}
|
|
finally
|
|
{
|
|
System.Security.CodeAccessPermission.RevertAssert();
|
|
}
|
|
}
|
|
|
|
this.m_instanceName = instanceName;
|
|
|
|
// Build a mapping of PerformanceCounterActions to the actual actions that need
|
|
// to be performed. If this become a perf issue, we could build the default mapping
|
|
// at build time.
|
|
|
|
Dictionary<PerformanceCounterAction, List<PerformanceCounterStatement>> actionStatements = new Dictionary<PerformanceCounterAction, List<PerformanceCounterStatement>>();
|
|
|
|
if (PerformanceCounterCategory.Exists(c_PerformanceCounterCategoryName))
|
|
{
|
|
for (int i = 0; i < data.Length; ++i)
|
|
{
|
|
PerformanceCounterData currentData = data[i];
|
|
for (int j = 0; j < currentData.Mappings.Length; ++j)
|
|
{
|
|
PerformanceCounterActionMapping currentMapping = currentData.Mappings[j];
|
|
if (!actionStatements.ContainsKey(currentMapping.Action))
|
|
{
|
|
actionStatements.Add(currentMapping.Action, new List<PerformanceCounterStatement>());
|
|
}
|
|
List<PerformanceCounterStatement> lStatements = actionStatements[currentMapping.Action];
|
|
PerformanceCounterStatement newStatement = new PerformanceCounterStatement(CreateCounters(currentData.Name), currentMapping.Operation);
|
|
lStatements.Add(newStatement);
|
|
}
|
|
}
|
|
}
|
|
|
|
this.m_actionStatements = actionStatements;
|
|
}
|
|
|
|
private void Notify(PerformanceCounterAction action, WorkflowExecutor executor)
|
|
{
|
|
System.Diagnostics.Debug.Assert(this.m_actionStatements != null);
|
|
|
|
List<PerformanceCounterStatement> lStatements;
|
|
|
|
if (this.m_actionStatements.TryGetValue(action, out lStatements))
|
|
{
|
|
foreach (PerformanceCounterStatement statement in lStatements)
|
|
{
|
|
NotifyCounter(action, statement, executor);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal List<PerformanceCounter> CreateCounters(String name)
|
|
{
|
|
List<PerformanceCounter> counters = new List<PerformanceCounter>();
|
|
|
|
counters.Add(
|
|
new PerformanceCounter(
|
|
c_PerformanceCounterCategoryName,
|
|
name,
|
|
"_Global_",
|
|
false));
|
|
|
|
if (!String.IsNullOrEmpty(this.m_instanceName))
|
|
{
|
|
counters.Add(
|
|
new PerformanceCounter(
|
|
c_PerformanceCounterCategoryName,
|
|
name,
|
|
this.m_instanceName,
|
|
false));
|
|
}
|
|
|
|
return counters;
|
|
}
|
|
|
|
private void NotifyCounter(PerformanceCounterAction action, PerformanceCounterStatement statement, WorkflowExecutor executor)
|
|
{
|
|
foreach (PerformanceCounter counter in statement.Counters)
|
|
{
|
|
switch (statement.Operation)
|
|
{
|
|
case PerformanceCounterOperation.Increment:
|
|
counter.Increment();
|
|
break;
|
|
|
|
case PerformanceCounterOperation.Decrement:
|
|
counter.Decrement();
|
|
break;
|
|
|
|
default:
|
|
System.Diagnostics.Debug.Assert(false, "Unknown performance counter operation.");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void WorkflowExecutorInitializing(object sender, WorkflowRuntime.WorkflowExecutorInitializingEventArgs e)
|
|
{
|
|
if (null == sender)
|
|
throw new ArgumentNullException("sender");
|
|
|
|
if (null == e)
|
|
throw new ArgumentNullException("e");
|
|
|
|
if (!typeof(WorkflowExecutor).IsInstanceOfType(sender))
|
|
throw new ArgumentException("sender");
|
|
|
|
WorkflowExecutor exec = (WorkflowExecutor)sender;
|
|
|
|
exec.WorkflowExecutionEvent += new EventHandler<WorkflowExecutor.WorkflowExecutionEventArgs>(WorkflowExecutionEvent);
|
|
}
|
|
|
|
private void WorkflowExecutionEvent(object sender, WorkflowExecutor.WorkflowExecutionEventArgs e)
|
|
{
|
|
if (null == sender)
|
|
throw new ArgumentNullException("sender");
|
|
|
|
if (!typeof(WorkflowExecutor).IsInstanceOfType(sender))
|
|
throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, ExecutionStringManager.InvalidArgumentType, "sender", typeof(WorkflowExecutor).ToString()));
|
|
|
|
WorkflowExecutor exec = (WorkflowExecutor)sender;
|
|
|
|
PerformanceCounterAction action;
|
|
|
|
switch (e.EventType)
|
|
{
|
|
case WorkflowEventInternal.Created:
|
|
action = PerformanceCounterAction.Creation;
|
|
break;
|
|
case WorkflowEventInternal.Started:
|
|
action = PerformanceCounterAction.Starting;
|
|
break;
|
|
case WorkflowEventInternal.Runnable:
|
|
action = PerformanceCounterAction.Runnable;
|
|
break;
|
|
case WorkflowEventInternal.Executing:
|
|
action = PerformanceCounterAction.Executing;
|
|
break;
|
|
case WorkflowEventInternal.NotExecuting:
|
|
action = PerformanceCounterAction.NotExecuting;
|
|
break;
|
|
case WorkflowEventInternal.Resumed:
|
|
action = PerformanceCounterAction.Resumption;
|
|
break;
|
|
case WorkflowEventInternal.SchedulerEmpty:
|
|
//
|
|
// SchedulerEmpty signals that are about to persist
|
|
// after which we will be idle. We need to do the idle
|
|
// work now so that it is included in the state for the idle persist.
|
|
action = PerformanceCounterAction.Idle;
|
|
break;
|
|
case WorkflowEventInternal.Completed:
|
|
action = PerformanceCounterAction.Completion;
|
|
break;
|
|
case WorkflowEventInternal.Suspended:
|
|
action = PerformanceCounterAction.Suspension;
|
|
break;
|
|
case WorkflowEventInternal.Terminated:
|
|
action = PerformanceCounterAction.Termination;
|
|
break;
|
|
case WorkflowEventInternal.Loaded:
|
|
action = PerformanceCounterAction.Loading;
|
|
break;
|
|
case WorkflowEventInternal.Aborted:
|
|
action = PerformanceCounterAction.Aborted;
|
|
break;
|
|
case WorkflowEventInternal.Unloaded:
|
|
action = PerformanceCounterAction.Unloading;
|
|
break;
|
|
case WorkflowEventInternal.Persisted:
|
|
action = PerformanceCounterAction.Persisted;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
Notify(action, exec);
|
|
}
|
|
}
|
|
|
|
internal struct PerformanceCounterData
|
|
{
|
|
internal String Name;
|
|
internal String Description;
|
|
internal PerformanceCounterType CounterType;
|
|
internal PerformanceCounterActionMapping[] Mappings;
|
|
|
|
internal PerformanceCounterData(
|
|
String name,
|
|
String description,
|
|
PerformanceCounterType counterType,
|
|
PerformanceCounterActionMapping[] mappings)
|
|
{
|
|
System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(name));
|
|
System.Diagnostics.Debug.Assert(!String.IsNullOrEmpty(description));
|
|
System.Diagnostics.Debug.Assert(mappings != null && mappings.Length != 0);
|
|
|
|
this.Name = name;
|
|
this.Description = description;
|
|
this.CounterType = counterType;
|
|
this.Mappings = mappings;
|
|
}
|
|
};
|
|
|
|
internal struct PerformanceCounterActionMapping
|
|
{
|
|
internal PerformanceCounterOperation Operation;
|
|
internal PerformanceCounterAction Action;
|
|
|
|
internal PerformanceCounterActionMapping(PerformanceCounterAction action, PerformanceCounterOperation operation)
|
|
{
|
|
this.Operation = operation;
|
|
this.Action = action;
|
|
}
|
|
}
|
|
|
|
internal struct PerformanceCounterStatement
|
|
{
|
|
internal List<PerformanceCounter> Counters;
|
|
internal PerformanceCounterOperation Operation;
|
|
|
|
|
|
internal PerformanceCounterStatement(List<PerformanceCounter> counters,
|
|
PerformanceCounterOperation operation)
|
|
{
|
|
System.Diagnostics.Debug.Assert(counters != null);
|
|
|
|
this.Counters = counters;
|
|
this.Operation = operation;
|
|
}
|
|
}
|
|
}
|