diff --git a/src/Benchmarks.ServerJob/ServerJob.cs b/src/Benchmarks.ServerJob/ServerJob.cs
index 81bfca108..62d028463 100644
--- a/src/Benchmarks.ServerJob/ServerJob.cs
+++ b/src/Benchmarks.ServerJob/ServerJob.cs
@@ -137,6 +137,12 @@ public ServerJob ClearServerCounters()
// Other collection options
public bool CollectStartup { get; set; }
public bool CollectCounters { get; set; }
+
+ ///
+ /// The list of performance counter providers to be collected. Defaults to System.Runtime.
+ ///
+ public List CounterProviders { get; set; } = new List();
+
public string BasePath { get; set; }
public int ProcessId { get; set; }
public Dictionary EnvironmentVariables { get; set; } = new Dictionary();
diff --git a/src/BenchmarksDriver2/README.md b/src/BenchmarksDriver2/README.md
index 8c7019f93..79a401eed 100644
--- a/src/BenchmarksDriver2/README.md
+++ b/src/BenchmarksDriver2/README.md
@@ -69,6 +69,7 @@ Options:
--[JOB].dotnetTraceProviders An optional profile name or list of dotnet-trace providers can be passed. Default is 'cpu-sampling'. See https://github.com/dotnet/diagnostics/blob/master/documentation/dotnet-trace-instructions.md for details. e.g., Microsoft-DotNETCore-SampleProfiler, Microsoft-Windows-DotNETRuntime, gc-verbose. Can be used multiple times to set multiple providers.
--[JOB].options.traceOutput The name of the trace file. Can be a file prefix (app will add *.DATE*.zip) , or a specific name and no DATE* will be added e.g., c:\traces\mytrace
--[JOB].collectCounters Whether to collect dotnet counters.
+ --[JOB].counterProviders The name of a performance counter provider from which to collect.
--[JOB].collectStartup Whether to includes the startup phase in the traces, i.e after the application is launched and before it is marked as ready. For a web application it means before it is ready to accept requests.
## Environment
diff --git a/src/BenchmarksServer/Microsoft.Diagnostics.Tools.RuntimeClient/Eventing/SessionConfiguration.cs b/src/BenchmarksServer/Microsoft.Diagnostics.Tools.RuntimeClient/Eventing/SessionConfiguration.cs
index da1ccd0bb..2bcfae531 100644
--- a/src/BenchmarksServer/Microsoft.Diagnostics.Tools.RuntimeClient/Eventing/SessionConfiguration.cs
+++ b/src/BenchmarksServer/Microsoft.Diagnostics.Tools.RuntimeClient/Eventing/SessionConfiguration.cs
@@ -25,7 +25,7 @@ public SessionConfiguration(uint circularBufferSizeMB, EventPipeSerializationFor
throw new ArgumentException("Unrecognized format");
if (providers == null)
throw new ArgumentNullException(nameof(providers));
- if (providers.Count() <= 0)
+ if (providers.Count <= 0)
throw new ArgumentException($"Specified providers collection is empty.");
CircularBufferSizeInMB = circularBufferSizeMB;
@@ -37,7 +37,6 @@ public SessionConfiguration(uint circularBufferSizeMB, EventPipeSerializationFor
public uint CircularBufferSizeInMB { get; }
public EventPipeSerializationFormat Format { get; }
-
public IReadOnlyCollection Providers => _providers.AsReadOnly();
private readonly List _providers;
diff --git a/src/BenchmarksServer/Startup.cs b/src/BenchmarksServer/Startup.cs
index c7baad40e..bf7e90a6c 100644
--- a/src/BenchmarksServer/Startup.cs
+++ b/src/BenchmarksServer/Startup.cs
@@ -3431,41 +3431,78 @@ private static string GetCGroupController(ServerJob job)
return $"benchmarks-{Process.GetCurrentProcess().Id}-{job.Id}";
}
+ private static readonly MeasurementMetadata[] MeasurementMetadatas = new[]
+ {
+ // System.Runtime
+ new MeasurementMetadata { Source = "Counters/System.Runtime", Name = "Counters/System.Runtime/cpu-usage", LongDescription = "Amount of time the process has utilized the CPU (ms)", ShortDescription = "CPU Usage (%)", Format = "n0", Aggregate = Operation.Max, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/System.Runtime", Name = "Counters/System.Runtime/working-set", LongDescription = "Amount of working set used by the process (MB)", ShortDescription = "Working Set (MB)", Format = "n0", Aggregate = Operation.Max, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/System.Runtime", Name = "Counters/System.Runtime/gc-heap-size", LongDescription = "Total heap size reported by the GC (MB)", ShortDescription = "GC Heap Size (MB)", Format = "n0", Aggregate = Operation.Median, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/System.Runtime", Name = "Counters/System.Runtime/gen-0-gc-count", LongDescription = "Number of Gen 0 GCs / sec", ShortDescription = "Gen 0 GC (#/s)", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/System.Runtime", Name = "Counters/System.Runtime/gen-1-gc-count", LongDescription = "Number of Gen 1 GCs / sec", ShortDescription = "Gen 1 GC (#/s)", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/System.Runtime", Name = "Counters/System.Runtime/gen-2-gc-count", LongDescription = "Number of Gen 2 GCs / sec", ShortDescription = "Gen 2 GC (#/s)", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/System.Runtime", Name = "Counters/System.Runtime/time-in-gc", LongDescription = "% time in GC since the last GC", ShortDescription = "Time in GC (%)", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/System.Runtime", Name = "Counters/System.Runtime/gen-0-size", LongDescription = "Gen 0 Heap Size", ShortDescription = "Gen 0 Size (B)", Format = "n0", Aggregate = Operation.Median, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/System.Runtime", Name = "Counters/System.Runtime/gen-1-size", LongDescription = "Gen 1 Heap Size", ShortDescription = "Gen 1 Size (B)", Format = "n0", Aggregate = Operation.Median, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/System.Runtime", Name = "Counters/System.Runtime/gen-2-size", LongDescription = "Gen 2 Heap Size", ShortDescription = "Gen 2 Size (B)", Format = "n0", Aggregate = Operation.Median, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/System.Runtime", Name = "Counters/System.Runtime/loh-size", LongDescription = "LOH Heap Size", ShortDescription = "LOH Size (B)", Format = "n0", Aggregate = Operation.Median, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/System.Runtime", Name = "Counters/System.Runtime/alloc-rate", LongDescription = "Allocation Rate", ShortDescription = "Allocation Rate (B/sec)", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/System.Runtime", Name = "Counters/System.Runtime/assembly-count", LongDescription = "Number of Assemblies Loaded", ShortDescription = "# of Assemblies Loaded", Format = "n0", Aggregate = Operation.Max, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/System.Runtime", Name = "Counters/System.Runtime/exception-count", LongDescription = "Number of Exceptions / sec", ShortDescription = "Exceptions (#/s)", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/System.Runtime", Name = "Counters/System.Runtime/threadpool-thread-count", LongDescription = "Number of ThreadPool Threads", ShortDescription = "ThreadPool Threads Count", Format = "n0", Aggregate = Operation.Median, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/System.Runtime", Name = "Counters/System.Runtime/monitor-lock-contention-count", LongDescription = "Monitor Lock Contention Count", ShortDescription = "Lock Contention (#/s)", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/System.Runtime", Name = "Counters/System.Runtime/threadpool-queue-length", LongDescription = "ThreadPool Work Items Queue Length", ShortDescription = "ThreadPool Queue Length", Format = "n0", Aggregate = Operation.Median, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/System.Runtime", Name = "Counters/System.Runtime/threadpool-completed-items-count", LongDescription = "ThreadPool Completed Work Items Count", ShortDescription = "ThreadPool Items (#/s)", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+
+ // Kestrel
+ new MeasurementMetadata { Source = "Counters/Microsoft-AspNetCore-Server-Kestrel", Name = "Counters/Microsoft-AspNetCore-Server-Kestrel/connections-per-second", LongDescription = "Connection Rate", ShortDescription = "Connection Rate", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Microsoft-AspNetCore-Server-Kestrel", Name = "Counters/Microsoft-AspNetCore-Server-Kestrel/total-connections", LongDescription = "Total Connections", ShortDescription = "Total Connections", Format = "n0", Aggregate = Operation.Max, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Microsoft-AspNetCore-Server-Kestrel", Name = "Counters/Microsoft-AspNetCore-Server-Kestrel/tls-handshakes-per-second", LongDescription = "TLS Handshake Rate", ShortDescription = "TLS Handshake Rate", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Microsoft-AspNetCore-Server-Kestrel", Name = "Counters/Microsoft-AspNetCore-Server-Kestrel/total-tls-handshakes", LongDescription = "Total TLS Handshakes", ShortDescription = "Total TLS Handshakes", Format = "n0", Aggregate = Operation.Max, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Microsoft-AspNetCore-Server-Kestrel", Name = "Counters/Microsoft-AspNetCore-Server-Kestrel/current-tls-handshakes", LongDescription = "Current TLS Handshakes", ShortDescription = "Current TLS Handshakes", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Microsoft-AspNetCore-Server-Kestrel", Name = "Counters/Microsoft-AspNetCore-Server-Kestrel/failed-tls-handshakes", LongDescription = "Failed TLS Handshakes", ShortDescription = "Failed TLS Handshakes", Format = "n0", Aggregate = Operation.Max, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Microsoft-AspNetCore-Server-Kestrel", Name = "Counters/Microsoft-AspNetCore-Server-Kestrel/current-connections", LongDescription = "Current Connections", ShortDescription = "Current Connections", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Microsoft-AspNetCore-Server-Kestrel", Name = "Counters/Microsoft-AspNetCore-Server-Kestrel/connection-queue-length", LongDescription = "Connection Queue Length", ShortDescription = "Connection Queue Length", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Microsoft-AspNetCore-Server-Kestrel", Name = "Counters/Microsoft-AspNetCore-Server-Kestrel/request-queue-length", LongDescription = "Request Queue Length", ShortDescription = "Request Queue Length", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Microsoft-AspNetCore-Server-Kestrel", Name = "Counters/Microsoft-AspNetCore-Server-Kestrel/current-upgraded-requests", LongDescription = "Current Upgraded Requests (WebSockets)", ShortDescription = "Current Upgraded Requests (WebSockets)", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+
+ // Npgsql
+ new MeasurementMetadata { Source = "Counters/Npgsql", Name = "Counters/Npgsql/bytes-written-per-second", LongDescription = "Bytes Written", ShortDescription = "Bytes Written", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Npgsql", Name = "Counters/Npgsql/bytes-read-per-second", LongDescription = "Bytes Read", ShortDescription = "Bytes Read", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Npgsql", Name = "Counters/Npgsql/commands-per-second", LongDescription = "Command Rate", ShortDescription = "Command Rate", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Npgsql", Name = "Counters/Npgsql/total-commands", LongDescription = "Total Commands", ShortDescription = "Total Commands", Format = "n0", Aggregate = Operation.Max, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Npgsql", Name = "Counters/Npgsql/current-commands", LongDescription = "Current Commands", ShortDescription = "Current Commands", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Npgsql", Name = "Counters/Npgsql/failed-commands", LongDescription = "Failed Commands", ShortDescription = "Failed Commands", Format = "n0", Aggregate = Operation.Max, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Npgsql", Name = "Counters/Npgsql/prepared-commands-ratio", LongDescription = "Prepared Commands Ratio", ShortDescription = "Prepared Commands Ratio", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Npgsql", Name = "Counters/Npgsql/connection-pools", LongDescription = "Connection Pools", ShortDescription = "Connection Pools", Format = "n0", Aggregate = Operation.Max, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Npgsql", Name = "Counters/Npgsql/idle-connections", LongDescription = "Idle Connections", ShortDescription = "Idle Connections", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Npgsql", Name = "Counters/Npgsql/busy-connections", LongDescription = "Busy Connections", ShortDescription = "Busy Connections", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Npgsql", Name = "Counters/Npgsql/multiplexing-average-commands-per-batch", LongDescription = "Average commands per multiplexing batch", ShortDescription = "Commands per multiplexing batch", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Npgsql", Name = "Counters/Npgsql/multiplexing-average-waits-per-batch", LongDescription = "Average waits per multiplexing batch", ShortDescription = "Waits per multiplexing batch", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ new MeasurementMetadata { Source = "Counters/Npgsql", Name = "Counters/Npgsql/multiplexing-average-write-time-per-batch", LongDescription = "Average write time per multiplexing batch (us)", ShortDescription = "Time per multiplexing batch (us)", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max },
+ };
+
private static void StartCounters(ServerJob job)
{
- job.Metadata.Enqueue(new MeasurementMetadata { Source = "Counters", Name = "runtime-counter/cpu-usage", LongDescription = "Amount of time the process has utilized the CPU (ms)", ShortDescription = "CPU Usage (%)", Format = "n0", Aggregate = Operation.Max, Reduce = Operation.Max });
- job.Metadata.Enqueue(new MeasurementMetadata { Source = "Counters", Name = "runtime-counter/working-set", LongDescription = "Amount of working set used by the process (MB)", ShortDescription = "Working Set (MB)", Format = "n0", Aggregate = Operation.Max, Reduce = Operation.Max });
- job.Metadata.Enqueue(new MeasurementMetadata { Source = "Counters", Name = "runtime-counter/gc-heap-size", LongDescription = "Total heap size reported by the GC (MB)", ShortDescription = "GC Heap Size (MB)", Format = "n0", Aggregate = Operation.Median, Reduce = Operation.Max });
- job.Metadata.Enqueue(new MeasurementMetadata { Source = "Counters", Name = "runtime-counter/gen-0-gc-count", LongDescription = "Number of Gen 0 GCs / sec", ShortDescription = "Gen 0 GC (#/s)", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max });
- job.Metadata.Enqueue(new MeasurementMetadata { Source = "Counters", Name = "runtime-counter/gen-1-gc-count", LongDescription = "Number of Gen 1 GCs / sec", ShortDescription = "Gen 1 GC (#/s)", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max });
- job.Metadata.Enqueue(new MeasurementMetadata { Source = "Counters", Name = "runtime-counter/gen-2-gc-count", LongDescription = "Number of Gen 2 GCs / sec", ShortDescription = "Gen 2 GC (#/s)", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max });
- job.Metadata.Enqueue(new MeasurementMetadata { Source = "Counters", Name = "runtime-counter/time-in-gc", LongDescription = "% time in GC since the last GC", ShortDescription = "Time in GC (%)", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max });
- job.Metadata.Enqueue(new MeasurementMetadata { Source = "Counters", Name = "runtime-counter/gen-0-size", LongDescription = "Gen 0 Heap Size", ShortDescription = "Gen 0 Size (B)", Format = "n0", Aggregate = Operation.Median, Reduce = Operation.Max });
- job.Metadata.Enqueue(new MeasurementMetadata { Source = "Counters", Name = "runtime-counter/gen-1-size", LongDescription = "Gen 1 Heap Size", ShortDescription = "Gen 1 Size (B)", Format = "n0", Aggregate = Operation.Median, Reduce = Operation.Max });
- job.Metadata.Enqueue(new MeasurementMetadata { Source = "Counters", Name = "runtime-counter/gen-2-size", LongDescription = "Gen 2 Heap Size", ShortDescription = "Gen 2 Size (B)", Format = "n0", Aggregate = Operation.Median, Reduce = Operation.Max });
- job.Metadata.Enqueue(new MeasurementMetadata { Source = "Counters", Name = "runtime-counter/loh-size", LongDescription = "LOH Heap Size", ShortDescription = "LOH Size (B)", Format = "n0", Aggregate = Operation.Median, Reduce = Operation.Max });
- job.Metadata.Enqueue(new MeasurementMetadata { Source = "Counters", Name = "runtime-counter/alloc-rate", LongDescription = "Allocation Rate", ShortDescription = "Allocation Rate (B/sec)", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max });
- job.Metadata.Enqueue(new MeasurementMetadata { Source = "Counters", Name = "runtime-counter/assembly-count", LongDescription = "Number of Assemblies Loaded", ShortDescription = "# of Assemblies Loaded", Format = "n0", Aggregate = Operation.Max, Reduce = Operation.Max });
- job.Metadata.Enqueue(new MeasurementMetadata { Source = "Counters", Name = "runtime-counter/exception-count", LongDescription = "Number of Exceptions / sec", ShortDescription = "Exceptions (#/s)", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max });
- job.Metadata.Enqueue(new MeasurementMetadata { Source = "Counters", Name = "runtime-counter/threadpool-thread-count", LongDescription = "Number of ThreadPool Threads", ShortDescription = "ThreadPool Threads Count", Format = "n0", Aggregate = Operation.Median, Reduce = Operation.Max });
- job.Metadata.Enqueue(new MeasurementMetadata { Source = "Counters", Name = "runtime-counter/monitor-lock-contention-count", LongDescription = "Monitor Lock Contention Count", ShortDescription = "Lock Contention (#/s)", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max });
- job.Metadata.Enqueue(new MeasurementMetadata { Source = "Counters", Name = "runtime-counter/threadpool-queue-length", LongDescription = "ThreadPool Work Items Queue Length", ShortDescription = "ThreadPool Queue Length", Format = "n0", Aggregate = Operation.Median, Reduce = Operation.Max });
- job.Metadata.Enqueue(new MeasurementMetadata { Source = "Counters", Name = "runtime-counter/threadpool-completed-items-count", LongDescription = "ThreadPool Completed Work Items Count", ShortDescription = "ThreadPool Items (#/s)", Format = "n0", Aggregate = Operation.Avg, Reduce = Operation.Max });
+ foreach (var measurementMetadata in MeasurementMetadatas)
+ job.Metadata.Enqueue(measurementMetadata);
eventPipeTerminated = false;
eventPipeTask = new Task(() =>
{
- Log.WriteLine("Listening to event pipes");
+ var providerNames = job.CounterProviders.Count > 0
+ ? job.CounterProviders
+ : new List { "System.Runtime" };
+
+ Log.WriteLine($"Listening to counter event pipes (providers: {string.Join(", ", providerNames)})");
try
{
- var providerList = new List()
- {
- new Provider(
- name: "System.Runtime",
- eventLevel: EventLevel.Informational,
- filterData: "EventCounterIntervalSec=1"),
- };
+ var providerList = providerNames
+ .Select(p => new Provider(
+ name: p,
+ eventLevel: EventLevel.Informational,
+ filterData: "EventCounterIntervalSec=1"))
+ .ToList();
var configuration = new SessionConfiguration(
circularBufferSizeMB: 1000,
@@ -3499,7 +3536,7 @@ private static void StartCounters(ServerJob job)
}
}
- measurement.Name = "runtime-counter/" + counterName;
+ measurement.Name = $"Counters/{eventData.ProviderName}/{counterName}";
switch (payloadFields["CounterType"])
{