Add Support For Multiplexing `System.Diagnostics.Metrics` for `Dotnet Monitor` and...
authorkkeirstead <85592574+kkeirstead@users.noreply.github.com>
Thu, 3 Aug 2023 00:28:44 +0000 (19:28 -0500)
committerGitHub <noreply@github.com>
Thu, 3 Aug 2023 00:28:44 +0000 (17:28 -0700)
This PR corresponds to https://github.com/dotnet/runtime/pull/86504 from
the runtime repo to support multiplexing for
`System.Diagnostics.Metrics`. This change converts `dotnet monitor` and
`dotnet counters` to use a shared session, assuming the `MaxHistograms`,
`MaxTimeSeries`, and `IntervalSeconds` are all the same.

src/Microsoft.Diagnostics.Monitoring.EventPipe/Configuration/MetricSourceConfiguration.cs
src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/MetricsPipeline.cs
src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/MetricsPipelineSettings.cs
src/Microsoft.Diagnostics.Monitoring.EventPipe/Counters/TraceEventExtensions.cs
src/Microsoft.Diagnostics.Monitoring.EventPipe/Microsoft.Diagnostics.Monitoring.EventPipe.csproj
src/Microsoft.Diagnostics.Monitoring.EventPipe/Triggers/EventCounter/EventCounterTrigger.cs
src/Microsoft.Diagnostics.Monitoring.EventPipe/Triggers/SystemDiagnosticsMetricsTrigger/SystemDiagnosticsMetricsTrigger.cs
src/Microsoft.Diagnostics.Monitoring.EventPipe/Triggers/SystemDiagnosticsMetricsTrigger/SystemDiagnosticsMetricsTriggerSettings.cs
src/Microsoft.Diagnostics.NETCore.Client/DiagnosticsIpc/ProcessInfo.cs
src/Tools/dotnet-counters/CounterMonitor.cs
src/Tools/dotnet-counters/dotnet-counters.csproj

index effbdba9261284cf9bad4e19f0ab5ff6786a3980..3becf63e73ab33bfae52b54b935e3b3d92707be9 100644 (file)
@@ -30,7 +30,10 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe
 
     public sealed class MetricSourceConfiguration : MonitoringSourceConfiguration
     {
+        private const string SharedSessionId = "SHARED";
+
         private readonly IList<EventPipeProvider> _eventPipeProviders;
+        public string ClientId { get; private set; }
         public string SessionId { get; private set; }
 
         public MetricSourceConfiguration(float metricIntervalSeconds, IEnumerable<string> eventCounterProviderNames)
@@ -38,7 +41,7 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe
         {
         }
 
-        public MetricSourceConfiguration(float metricIntervalSeconds, IEnumerable<MetricEventPipeProvider> providers, int maxHistograms = 20, int maxTimeSeries = 1000)
+        public MetricSourceConfiguration(float metricIntervalSeconds, IEnumerable<MetricEventPipeProvider> providers, int maxHistograms = 20, int maxTimeSeries = 1000, bool useSharedSession = false)
         {
             if (providers == null)
             {
@@ -65,7 +68,10 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe
                 const long TimeSeriesValuesEventKeyword = 0x2;
                 string metrics = string.Join(',', meterProviders.Select(p => p.Provider));
 
-                SessionId = Guid.NewGuid().ToString();
+                ClientId = Guid.NewGuid().ToString();
+
+                // Shared Session Id was added in 8.0 - older runtimes will not properly support it.
+                SessionId = useSharedSession ? SharedSessionId : Guid.NewGuid().ToString();
 
                 EventPipeProvider metricsEventSourceProvider =
                     new(MonitoringSourceConfiguration.SystemDiagnosticsMetricsProviderName, EventLevel.Informational, TimeSeriesValuesEventKeyword,
@@ -75,7 +81,8 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe
                             { "Metrics", metrics },
                             { "RefreshInterval", metricIntervalSeconds.ToString(CultureInfo.InvariantCulture) },
                             { "MaxTimeSeries", maxTimeSeries.ToString(CultureInfo.InvariantCulture) },
-                            { "MaxHistograms", maxHistograms.ToString(CultureInfo.InvariantCulture) }
+                            { "MaxHistograms", maxHistograms.ToString(CultureInfo.InvariantCulture) },
+                            { "ClientId", ClientId  }
                         }
                     );
 
index 45b7e7fb0550c249ab569b580fea3d08ac353843..1c3a29ab8a5e39d789eb9e768c7a9d597f91384c 100644 (file)
@@ -15,6 +15,7 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe
     {
         private readonly IEnumerable<ICountersLogger> _loggers;
         private readonly CounterFilter _filter;
+        private string _clientId;
         private string _sessionId;
 
         public MetricsPipeline(DiagnosticsClient client,
@@ -45,8 +46,9 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe
                 IntervalSeconds = counterGroup.IntervalSeconds,
                 Type = (MetricType)counterGroup.Type
             }),
-                Settings.MaxHistograms, Settings.MaxTimeSeries);
+                Settings.MaxHistograms, Settings.MaxTimeSeries, useSharedSession: Settings.UseSharedSession);
 
+            _clientId = config.ClientId;
             _sessionId = config.SessionId;
 
             return config;
@@ -59,7 +61,7 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe
             eventSource.Dynamic.All += traceEvent => {
                 try
                 {
-                    if (traceEvent.TryGetCounterPayload(_filter, _sessionId, out ICounterPayload counterPayload))
+                    if (traceEvent.TryGetCounterPayload(_filter, _sessionId, _clientId, out ICounterPayload counterPayload))
                     {
                         ExecuteCounterLoggerAction((metricLogger) => metricLogger.Log(counterPayload));
                     }
index 48d705dd5aa9f19ddeaf622d64b031ee0f1c0a15..4e9c4f83f4b834218f82c569c1229ebb76f1ee90 100644 (file)
@@ -16,6 +16,8 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe
         public int MaxHistograms { get; set; }
 
         public int MaxTimeSeries { get; set; }
+
+        public bool UseSharedSession { get; set; }
     }
 
     [Flags]
index 347a4e11f2c281f8484350a88d42fa1e535259e8..942a7ebddf89f9e84e87d71b52cec6d085d4568a 100644 (file)
@@ -4,13 +4,16 @@
 using System;
 using System.Collections.Generic;
 using System.Globalization;
+using System.Text;
 using Microsoft.Diagnostics.Tracing;
 
 namespace Microsoft.Diagnostics.Monitoring.EventPipe
 {
     internal static class TraceEventExtensions
     {
-        public static bool TryGetCounterPayload(this TraceEvent traceEvent, CounterFilter filter, string sessionId, out ICounterPayload payload)
+        private static HashSet<string> inactiveSharedSessions = new(StringComparer.OrdinalIgnoreCase);
+
+        public static bool TryGetCounterPayload(this TraceEvent traceEvent, CounterFilter filter, string sessionId, string clientId, out ICounterPayload payload)
         {
             payload = null;
 
@@ -71,7 +74,7 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe
                 return true;
             }
 
-            if (sessionId != null && MonitoringSourceConfiguration.SystemDiagnosticsMetricsProviderName.Equals(traceEvent.ProviderName))
+            if (clientId != null && !inactiveSharedSessions.Contains(clientId) && MonitoringSourceConfiguration.SystemDiagnosticsMetricsProviderName.Equals(traceEvent.ProviderName))
             {
                 if (traceEvent.EventName == "BeginInstrumentReporting")
                 {
@@ -114,6 +117,10 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe
                 {
                     HandleMultipleSessionsNotSupportedError(traceEvent, sessionId, out payload);
                 }
+                else if (traceEvent.EventName == "MultipleSessionsConfiguredIncorrectlyError")
+                {
+                    HandleMultipleSessionsConfiguredIncorrectlyError(traceEvent, clientId, out payload);
+                }
 
                 return payload != null;
             }
@@ -299,7 +306,7 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe
 
             string payloadSessionId = (string)obj.PayloadValue(0);
             string error = (string)obj.PayloadValue(1);
-            if (sessionId != payloadSessionId)
+            if (payloadSessionId != sessionId)
             {
                 return;
             }
@@ -322,13 +329,66 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe
             }
             else
             {
-                string errorMessage = "Error: Another metrics collection session is already in progress for the target process, perhaps from another tool? " + Environment.NewLine +
+                string errorMessage = "Error: Another metrics collection session is already in progress for the target process." + Environment.NewLine +
                 "Concurrent sessions are not supported.";
 
                 payload = new ErrorPayload(errorMessage, obj.TimeStamp);
             }
         }
 
+        internal static bool TryCreateSharedSessionConfiguredIncorrectlyMessage(TraceEvent obj, string clientId, out string message)
+        {
+            message = string.Empty;
+
+            string payloadSessionId = (string)obj.PayloadValue(0);
+
+            if (payloadSessionId != clientId)
+            {
+                // If our session is not the one that is running then the error is not for us,
+                // it is for some other session that came later
+                return false;
+            }
+
+            string expectedMaxHistograms = (string)obj.PayloadValue(1);
+            string actualMaxHistograms = (string)obj.PayloadValue(2);
+            string expectedMaxTimeSeries = (string)obj.PayloadValue(3);
+            string actualMaxTimeSeries = (string)obj.PayloadValue(4);
+            string expectedRefreshInterval = (string)obj.PayloadValue(5);
+            string actualRefreshInterval = (string)obj.PayloadValue(6);
+
+            StringBuilder errorMessage = new("Error: Another shared metrics collection session is already in progress for the target process." + Environment.NewLine +
+            "To enable this metrics session alongside the existing session, update the following values:" + Environment.NewLine);
+
+            if (expectedMaxHistograms != actualMaxHistograms)
+            {
+                errorMessage.Append($"MaxHistograms: {expectedMaxHistograms}" + Environment.NewLine);
+            }
+            if (expectedMaxTimeSeries != actualMaxTimeSeries)
+            {
+                errorMessage.Append($"MaxTimeSeries: {expectedMaxTimeSeries}" + Environment.NewLine);
+            }
+            if (expectedRefreshInterval != actualRefreshInterval)
+            {
+                errorMessage.Append($"IntervalSeconds: {expectedRefreshInterval}" + Environment.NewLine);
+            }
+
+            message = errorMessage.ToString();
+
+            return true;
+        }
+
+        private static void HandleMultipleSessionsConfiguredIncorrectlyError(TraceEvent obj, string clientId, out ICounterPayload payload)
+        {
+            payload = null;
+
+            if (TryCreateSharedSessionConfiguredIncorrectlyMessage(obj, clientId, out string message))
+            {
+                payload = new ErrorPayload(message.ToString(), obj.TimeStamp);
+
+                inactiveSharedSessions.Add(clientId);
+            }
+        }
+
         private static void HandleObservableInstrumentCallbackError(TraceEvent obj, string sessionId, out ICounterPayload payload)
         {
             payload = null;
index aef58a9d4f9b229d673ff738552ac1a048e7ae34..0682848f12adeca53e4ba842ef25d21cbaa707c5 100644 (file)
@@ -39,6 +39,7 @@
 
   <ItemGroup>
     <InternalsVisibleTo Include="dotnet-monitor" />
+    <InternalsVisibleTo Include="dotnet-counters" />
     <InternalsVisibleTo Include="Microsoft.Diagnostics.Monitoring.EventPipe.UnitTests" />
     <InternalsVisibleTo Include="Microsoft.Diagnostics.Monitoring.WebApi" />
     <InternalsVisibleTo Include="Microsoft.Diagnostics.Monitoring.Tool.UnitTests" />
index a41580f7a1547e0ffbcab73f2881e189dfe06eb6..6350d430386c90fdffc7258925ed2a991b28b4dc 100644 (file)
@@ -58,7 +58,7 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe.Triggers.EventCounter
         public bool HasSatisfiedCondition(TraceEvent traceEvent)
         {
             // Filter to the counter of interest before forwarding to the implementation
-            if (traceEvent.TryGetCounterPayload(_filter, null, out ICounterPayload payload))
+            if (traceEvent.TryGetCounterPayload(_filter, null, null, out ICounterPayload payload))
             {
                 return _impl.HasSatisfiedCondition(payload);
             }
index 20331b09d4c8a1b16b03d67c9708d7b4979102c6..378e38906565cfc632d3fd276b73b0958013769e 100644 (file)
@@ -27,6 +27,7 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe.Triggers.SystemDiagnosticsM
         private readonly CounterFilter _filter;
         private readonly SystemDiagnosticsMetricsTriggerImpl _impl;
         private readonly string _meterName;
+        private readonly string _clientId;
         private readonly string _sessionId;
 
         public SystemDiagnosticsMetricsTrigger(SystemDiagnosticsMetricsTriggerSettings settings)
@@ -45,6 +46,8 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe.Triggers.SystemDiagnosticsM
 
             _meterName = settings.MeterName;
 
+            _clientId = settings.ClientId;
+
             _sessionId = settings.SessionId;
         }
 
@@ -56,7 +59,7 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe.Triggers.SystemDiagnosticsM
         public bool HasSatisfiedCondition(TraceEvent traceEvent)
         {
             // Filter to the counter of interest before forwarding to the implementation
-            if (traceEvent.TryGetCounterPayload(_filter, _sessionId, out ICounterPayload payload))
+            if (traceEvent.TryGetCounterPayload(_filter, _sessionId, _clientId, out ICounterPayload payload))
             {
                 return _impl.HasSatisfiedCondition(payload);
             }
@@ -71,7 +74,9 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe.Triggers.SystemDiagnosticsM
                 settings.CounterIntervalSeconds,
                 MetricSourceConfiguration.CreateProviders(new string[] { settings.MeterName }, MetricType.Meter),
                 settings.MaxHistograms,
-                settings.MaxTimeSeries);
+                settings.MaxTimeSeries,
+                useSharedSession: settings.UseSharedSession);
+            settings.ClientId = config.ClientId;
             settings.SessionId = config.SessionId;
 
             return config;
index 405059a736dfb7538760ce4019fabefe42735025..08c0dc2b7d4dc6f9aab440ca7948551ea3b55e5c 100644 (file)
@@ -62,8 +62,12 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe.Triggers.SystemDiagnosticsM
 
         public int MaxTimeSeries { get; set; }
 
+        public string ClientId { get; set; }
+
         public string SessionId { get; set; }
 
+        public bool UseSharedSession { get; set; }
+
         IEnumerable<ValidationResult> IValidatableObject.Validate(ValidationContext validationContext)
         {
             return SharedTriggerSettingsValidation.Validate(GreaterThan, LessThan);
index 2d84a4b2546a9ae7ef5f6de189577cb33d269c26..4a5c75a61cdf15bf5f468e9cdef9780741524b4b 100644 (file)
@@ -98,6 +98,34 @@ namespace Microsoft.Diagnostics.NETCore.Client
             return processInfo;
         }
 
+        internal bool TryGetProcessClrVersion(out Version version)
+        {
+            version = null;
+            if (string.IsNullOrEmpty(ClrProductVersionString))
+            {
+                return false;
+            }
+
+            // The version is of the SemVer2 form: <major>.<minor>.<patch>[-<prerelease>][+<metadata>]
+            // Remove the prerelease and metadata version information before parsing.
+
+            ReadOnlySpan<char> versionSpan = ClrProductVersionString.AsSpan();
+            int metadataIndex = versionSpan.IndexOf('+');
+            if (-1 == metadataIndex)
+            {
+                metadataIndex = versionSpan.Length;
+            }
+
+            ReadOnlySpan<char> noMetadataVersion = versionSpan.Slice(0, metadataIndex);
+            int prereleaseIndex = noMetadataVersion.IndexOf('-');
+            if (-1 == prereleaseIndex)
+            {
+                prereleaseIndex = metadataIndex;
+            }
+
+            return Version.TryParse(noMetadataVersion.Slice(0, prereleaseIndex).ToString(), out version);
+        }
+
         private static ProcessInfo ParseCommon2(byte[] payload, ref int index)
         {
             ProcessInfo processInfo = ParseCommon(payload, ref index);
index a01707438607b7e098d869623d64f1b7e7198bb2..5ec240d0523ddfa5c4e06a60e897cbfa1c9050c5 100644 (file)
@@ -14,6 +14,7 @@ using System.Linq;
 using System.Text;
 using System.Threading;
 using System.Threading.Tasks;
+using Microsoft.Diagnostics.Monitoring.EventPipe;
 using Microsoft.Diagnostics.NETCore.Client;
 using Microsoft.Diagnostics.Tools.Counters.Exporters;
 using Microsoft.Diagnostics.Tracing;
@@ -24,7 +25,10 @@ namespace Microsoft.Diagnostics.Tools.Counters
     public class CounterMonitor
     {
         private const int BufferDelaySecs = 1;
+        private const string SharedSessionId = "SHARED"; // This should be identical to the one used by dotnet-monitor in MetricSourceConfiguration.cs
+        private static HashSet<string> inactiveSharedSessions = new(StringComparer.OrdinalIgnoreCase);
 
+        private string _sessionId;
         private int _processId;
         private int _interval;
         private CounterSet _counterList;
@@ -37,7 +41,7 @@ namespace Microsoft.Diagnostics.Tools.Counters
         private bool _resumeRuntime;
         private DiagnosticsClient _diagnosticsClient;
         private EventPipeSession _session;
-        private readonly string _metricsEventSourceSessionId;
+        private readonly string _clientId;
         private int _maxTimeSeries;
         private int _maxHistograms;
         private TimeSpan _duration;
@@ -53,7 +57,8 @@ namespace Microsoft.Diagnostics.Tools.Counters
         public CounterMonitor()
         {
             _pauseCmdSet = false;
-            _metricsEventSourceSessionId = Guid.NewGuid().ToString();
+            _clientId = Guid.NewGuid().ToString();
+
             _shouldExit = new TaskCompletionSource<int>();
         }
 
@@ -70,7 +75,8 @@ namespace Microsoft.Diagnostics.Tools.Counters
                 // There's a potential race here between the two tasks but not a huge deal if we miss by one event.
                 _renderer.ToggleStatus(_pauseCmdSet);
 
-                if (obj.ProviderName == "System.Diagnostics.Metrics")
+                // If a session received a MultipleSessionsConfiguredIncorrectlyError, ignore future shared events
+                if (obj.ProviderName == "System.Diagnostics.Metrics" && !inactiveSharedSessions.Contains(_clientId))
                 {
                     if (obj.EventName == "BeginInstrumentReporting")
                     {
@@ -112,6 +118,10 @@ namespace Microsoft.Diagnostics.Tools.Counters
                     {
                         HandleMultipleSessionsNotSupportedError(obj);
                     }
+                    else if (obj.EventName == "MultipleSessionsConfiguredIncorrectlyError")
+                    {
+                        HandleMultipleSessionsConfiguredIncorrectlyError(obj);
+                    }
                 }
                 else if (obj.EventName == "EventCounters")
                 {
@@ -142,7 +152,7 @@ namespace Microsoft.Diagnostics.Tools.Counters
             string sessionId = (string)obj.PayloadValue(0);
             string meterName = (string)obj.PayloadValue(1);
             // string instrumentName = (string)obj.PayloadValue(3);
-            if (sessionId != _metricsEventSourceSessionId)
+            if (sessionId != _sessionId)
             {
                 return;
             }
@@ -158,7 +168,7 @@ namespace Microsoft.Diagnostics.Tools.Counters
             string unit = (string)obj.PayloadValue(4);
             string tags = (string)obj.PayloadValue(5);
             string rateText = (string)obj.PayloadValue(6);
-            if (sessionId != _metricsEventSourceSessionId)
+            if (sessionId != _sessionId || !Filter(meterName, instrumentName))
             {
                 return;
             }
@@ -182,7 +192,7 @@ namespace Microsoft.Diagnostics.Tools.Counters
             string unit = (string)obj.PayloadValue(4);
             string tags = (string)obj.PayloadValue(5);
             string lastValueText = (string)obj.PayloadValue(6);
-            if (sessionId != _metricsEventSourceSessionId)
+            if (sessionId != _sessionId || !Filter(meterName, instrumentName))
             {
                 return;
             }
@@ -217,7 +227,7 @@ namespace Microsoft.Diagnostics.Tools.Counters
             string tags = (string)obj.PayloadValue(5);
             //string rateText = (string)obj.PayloadValue(6); // Not currently using rate for UpDownCounters.
             string valueText = (string)obj.PayloadValue(7);
-            if (sessionId != _metricsEventSourceSessionId)
+            if (sessionId != _sessionId || !Filter(meterName, instrumentName))
             {
                 return;
             }
@@ -247,7 +257,7 @@ namespace Microsoft.Diagnostics.Tools.Counters
             string unit = (string)obj.PayloadValue(4);
             string tags = (string)obj.PayloadValue(5);
             string quantilesText = (string)obj.PayloadValue(6);
-            if (sessionId != _metricsEventSourceSessionId)
+            if (sessionId != _sessionId || !Filter(meterName, instrumentName))
             {
                 return;
             }
@@ -263,7 +273,7 @@ namespace Microsoft.Diagnostics.Tools.Counters
         private void HandleHistogramLimitReached(TraceEvent obj)
         {
             string sessionId = (string)obj.PayloadValue(0);
-            if (sessionId != _metricsEventSourceSessionId)
+            if (sessionId != _clientId)
             {
                 return;
             }
@@ -276,7 +286,7 @@ namespace Microsoft.Diagnostics.Tools.Counters
         private void HandleTimeSeriesLimitReached(TraceEvent obj)
         {
             string sessionId = (string)obj.PayloadValue(0);
-            if (sessionId != _metricsEventSourceSessionId)
+            if (sessionId != _sessionId)
             {
                 return;
             }
@@ -290,7 +300,7 @@ namespace Microsoft.Diagnostics.Tools.Counters
         {
             string sessionId = (string)obj.PayloadValue(0);
             string error = (string)obj.PayloadValue(1);
-            if (sessionId != _metricsEventSourceSessionId)
+            if (sessionId != _sessionId)
             {
                 return;
             }
@@ -305,7 +315,7 @@ namespace Microsoft.Diagnostics.Tools.Counters
         {
             string sessionId = (string)obj.PayloadValue(0);
             string error = (string)obj.PayloadValue(1);
-            if (sessionId != _metricsEventSourceSessionId)
+            if (sessionId != _sessionId)
             {
                 return;
             }
@@ -318,18 +328,28 @@ namespace Microsoft.Diagnostics.Tools.Counters
         private void HandleMultipleSessionsNotSupportedError(TraceEvent obj)
         {
             string runningSessionId = (string)obj.PayloadValue(0);
-            if (runningSessionId == _metricsEventSourceSessionId)
+            if (runningSessionId == _sessionId)
             {
                 // If our session is the one that is running then the error is not for us,
                 // it is for some other session that came later
                 return;
             }
             _renderer.SetErrorText(
-                "Error: Another metrics collection session is already in progress for the target process, perhaps from another tool?" + Environment.NewLine +
+                "Error: Another metrics collection session is already in progress for the target process." + Environment.NewLine +
                 "Concurrent sessions are not supported.");
             _shouldExit.TrySetResult((int)ReturnCode.SessionCreationError);
         }
 
+        private void HandleMultipleSessionsConfiguredIncorrectlyError(TraceEvent obj)
+        {
+            if (TraceEventExtensions.TryCreateSharedSessionConfiguredIncorrectlyMessage(obj, _clientId, out string message))
+            {
+                _renderer.SetErrorText(message);
+                inactiveSharedSessions.Add(_clientId);
+                _shouldExit.TrySetResult((int)ReturnCode.SessionCreationError);
+            }
+        }
+
         private static KeyValuePair<double, double>[] ParseQuantiles(string quantileList)
         {
             string[] quantileParts = quantileList.Split(';', StringSplitOptions.RemoveEmptyEntries);
@@ -840,21 +860,35 @@ namespace Microsoft.Diagnostics.Tools.Counters
                     metrics.Append(string.Join(',', providerCounters));
                 }
             }
+
+            // Shared Session Id was added in 8.0 - older runtimes will not properly support it.
+            _sessionId = Guid.NewGuid().ToString();
+            if (_diagnosticsClient.GetProcessInfo().TryGetProcessClrVersion(out Version version))
+            {
+                _sessionId = version.Major >= 8 ? SharedSessionId : _sessionId;
+            }
+
             EventPipeProvider metricsEventSourceProvider =
                 new("System.Diagnostics.Metrics", EventLevel.Informational, TimeSeriesValues,
                     new Dictionary<string, string>()
                     {
-                        { "SessionId", _metricsEventSourceSessionId },
+                        { "SessionId", _sessionId },
                         { "Metrics", metrics.ToString() },
                         { "RefreshInterval", _interval.ToString() },
                         { "MaxTimeSeries", _maxTimeSeries.ToString() },
-                        { "MaxHistograms", _maxHistograms.ToString() }
+                        { "MaxHistograms", _maxHistograms.ToString() },
+                        { "ClientId", _clientId  }
                     }
                 );
 
             return eventCounterProviders.Append(metricsEventSourceProvider).ToArray();
         }
 
+        private bool Filter(string meterName, string instrumentName)
+        {
+            return _counterList.GetCounters(meterName).Contains(instrumentName) || _counterList.IncludesAllCounters(meterName);
+        }
+
         private Task<int> Start()
         {
             EventPipeProvider[] providers = GetEventPipeProviders();
index 777b8b96472dac6cfdab7ebc685e346fb6dc18b3..790b04b95dcd81b97f5e897beb22129440b8f009 100644 (file)
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
@@ -23,6 +23,7 @@
 
   <ItemGroup>
     <ProjectReference Include="$(MSBuildThisFileDirectory)..\..\Microsoft.Diagnostics.NETCore.Client\Microsoft.Diagnostics.NETCore.Client.csproj" />
+    <ProjectReference Include="$(MSBuildThisFileDirectory)..\..\Microsoft.Diagnostics.Monitoring.EventPipe\Microsoft.Diagnostics.Monitoring.EventPipe.csproj" />
   </ItemGroup>
 
   <ItemGroup>