Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Dotnet Monitor] Ignore - Adding System.Diagnostics.Metrics Support #3529

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions eng/Version.Details.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
<Uri>https://github.com/microsoft/clrmd</Uri>
<Sha>a64d9ac11086f28fbd4b2b2337c19be7826fbfa9</Sha>
</Dependency>
<Dependency Name="Microsoft.SourceBuild.Intermediate.source-build-reference-packages" Version="8.0.0-alpha.1.22578.1">
<Dependency Name="Microsoft.SourceBuild.Intermediate.source-build-reference-packages" Version="8.0.0-alpha.1.22579.1">
<Uri>https://github.com/dotnet/source-build-reference-packages</Uri>
<Sha>7ec4b0aabc55efa11515c987fb0251d39c29f06c</Sha>
<Sha>bed0fd20a5a55843c1f04ef195ef2fd7171ae715</Sha>
<SourceBuild RepoName="source-build-reference-packages" ManagedOnly="true" />
</Dependency>
</ProductDependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace Microsoft.Diagnostics.Monitoring.EventPipe
public sealed class MetricSourceConfiguration : MonitoringSourceConfiguration
{
private readonly IList<EventPipeProvider> _eventPipeProviders;
public string SessionId { get; private set; }

public MetricSourceConfiguration(float metricIntervalSeconds, IEnumerable<string> customProviderNames)
{
Expand Down Expand Up @@ -45,6 +46,37 @@ public MetricSourceConfiguration(float metricIntervalSeconds, IEnumerable<string
})).ToList();
}

public MetricSourceConfiguration(float metricIntervalSeconds, IEnumerable<string> customProviderNames, int maxHistograms, int maxTimeSeries) : this(metricIntervalSeconds, customProviderNames)
{
const long TimeSeriesValues = 0x2;
StringBuilder metrics = new StringBuilder();
foreach (string provider in customProviderNames)
{
if (metrics.Length != 0)
{
metrics.Append(",");
}

metrics.Append(provider);
}

SessionId = Guid.NewGuid().ToString();

EventPipeProvider metricsEventSourceProvider =
new EventPipeProvider("System.Diagnostics.Metrics", EventLevel.Informational, TimeSeriesValues,
new Dictionary<string, string>()
{
{ "SessionId", SessionId },
{ "Metrics", metrics.ToString() },
{ "RefreshInterval", MetricIntervalSeconds.ToString() },
{ "MaxTimeSeries", maxTimeSeries.ToString() },
{ "MaxHistograms", maxHistograms.ToString() }
}
);

_eventPipeProviders = _eventPipeProviders.Append(metricsEventSourceProvider).ToArray();
}

private string MetricIntervalSeconds { get; }

public override IList<EventPipeProvider> GetProviders() => _eventPipeProviders;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ public bool IsIncluded(string providerName, string counterName, int intervalMill
{
return false;
}

return IsIncluded(providerName, counterName);
}

public bool IsIncluded(string providerName, string counterName)
{
if (_enabledCounters.Count == 0)
{
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace Microsoft.Diagnostics.Monitoring.EventPipe
{
internal class CounterPayload : ICounterPayload
public class CounterPayload : ICounterPayload
{
#if NETSTANDARD
private static readonly IReadOnlyDictionary<string, string> Empty = new ReadOnlyDictionary<string, string>(new Dictionary<string, string>(0));
Expand All @@ -35,13 +35,26 @@ public CounterPayload(DateTime timestamp,
Provider = provider;
Interval = interval;
Metadata = metadata ?? Empty;
EventType = EventType.Gauge;
}

// Copied from dotnet-counters
public CounterPayload(string providerName, string name, string displayName, string displayUnits, Dictionary<string, string> metadata, double value, DateTime timestamp, string type, EventType eventType)
{
Provider = providerName;
Name = name;
Metadata = metadata ?? Empty;
Value = value;
Timestamp = timestamp;
CounterType = (CounterType)Enum.Parse(typeof(CounterType), type);
EventType = eventType;
}

public string Namespace { get; }

public string Name { get; }

public string DisplayName { get; }
public string DisplayName { get; protected set; }

public string Unit { get; }

Expand All @@ -56,5 +69,63 @@ public CounterPayload(DateTime timestamp,
public string Provider { get; }

public IReadOnlyDictionary<string, string> Metadata { get; }

public EventType EventType { get; set; }

}

public class GaugePayload : CounterPayload
{
public GaugePayload(string providerName, string name, string displayName, string displayUnits, Dictionary<string, string> metadata, double value, DateTime timestamp) :
base(providerName, name, displayName, displayUnits, metadata, value, timestamp, "Metric", EventType.Gauge)
{
// In case these properties are not provided, set them to appropriate values.
string counterName = string.IsNullOrEmpty(displayName) ? name : displayName;
DisplayName = !string.IsNullOrEmpty(displayUnits) ? $"{counterName} ({displayUnits})" : counterName;
}
}

public class RatePayload : CounterPayload
{
public RatePayload(string providerName, string name, string displayName, string displayUnits, Dictionary<string, string> metadata, double value, double intervalSecs, DateTime timestamp) :
base(providerName, name, displayName, displayUnits, metadata, value, timestamp, "Rate", EventType.Rate)
{
// In case these properties are not provided, set them to appropriate values.
string counterName = string.IsNullOrEmpty(displayName) ? name : displayName;
string unitsName = string.IsNullOrEmpty(displayUnits) ? "Count" : displayUnits;
string intervalName = intervalSecs.ToString() + " sec";
DisplayName = $"{counterName} ({unitsName} / {intervalName})";
}
}

public class PercentilePayload : CounterPayload
{
public PercentilePayload(string providerName, string name, string displayName, string displayUnits, Dictionary<string, string> metadata, double val, DateTime timestamp) :
base(providerName, name, displayName, displayUnits, metadata, val, timestamp, "Metric", EventType.Histogram)
{
// In case these properties are not provided, set them to appropriate values.
string counterName = string.IsNullOrEmpty(displayName) ? name : displayName;
DisplayName = !string.IsNullOrEmpty(displayUnits) ? $"{counterName} ({displayUnits})" : counterName;
}
}

public class ErrorPayload : CounterPayload
{
public ErrorPayload(string providerName, string name, string displayName, string displayUnits, Dictionary<string, string> metadata, double val, DateTime timestamp, string errorMessage) :
base(providerName, name, displayName, displayUnits, metadata, val, timestamp, "Metric", EventType.Error)
{
ErrorMessage = errorMessage;
}

public string ErrorMessage { get; private set; }
}

// If keep this, should probably put it somewhere else
public enum EventType : int
{
Rate,
Gauge,
Histogram,
Error
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ internal class EventCounterPipeline : EventSourcePipeline<EventPipeCounterPipeli
{
private readonly IEnumerable<ICountersLogger> _loggers;
private readonly CounterFilter _filter;
private string _sessionId;

public EventCounterPipeline(DiagnosticsClient client,
EventPipeCounterPipelineSettings settings,
Expand All @@ -38,7 +39,11 @@ public EventCounterPipeline(DiagnosticsClient client,

protected override MonitoringSourceConfiguration CreateConfiguration()
{
return new MetricSourceConfiguration(Settings.CounterIntervalSeconds, _filter.GetProviders());
var config = new MetricSourceConfiguration(Settings.CounterIntervalSeconds, _filter.GetProviders(), Settings.MaxHistograms, Settings.MaxTimeSeries);

_sessionId = config.SessionId;

return config;
}

protected override async Task OnEventSourceAvailable(EventPipeEventSource eventSource, Func<Task> stopSessionAsync, CancellationToken token)
Expand All @@ -49,7 +54,7 @@ protected override async Task OnEventSourceAvailable(EventPipeEventSource eventS
{
try
{
if (traceEvent.TryGetCounterPayload(_filter, out ICounterPayload counterPayload))
if (traceEvent.TryGetCounterPayload(_filter, _sessionId, out List<ICounterPayload> counterPayload))
{
ExecuteCounterLoggerAction((metricLogger) => metricLogger.Log(counterPayload));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ internal class EventPipeCounterPipelineSettings : EventSourcePipelineSettings
//Do not use TimeSpan here since we may need to synchronize this pipeline interval
//with a different session and want to make sure the values are identical.
public float CounterIntervalSeconds { get; set; }

public int MaxHistograms { get; set; }

public int MaxTimeSeries { get; set; }
}

internal class EventPipeCounterGroup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace Microsoft.Diagnostics.Monitoring.EventPipe
{
internal enum CounterType
public enum CounterType
{
//Same as average or mean
Metric,
Expand All @@ -17,7 +17,7 @@ internal enum CounterType
Rate
}

internal interface ICounterPayload
public interface ICounterPayload
{
string Name { get; }

Expand All @@ -36,5 +36,7 @@ internal interface ICounterPayload
float Interval { get; }

IReadOnlyDictionary<string, string> Metadata { get; }

public EventType EventType { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal interface ICountersLogger
{
//TODO Consider making these async.

void Log(ICounterPayload counter);
void Log(List<ICounterPayload> counter);
void PipelineStarted();
void PipelineStopped();
}
Expand Down
Loading