cb60f10320bafcba23a342e6462e8d54e2cae2c3
[platform/core/dotnet/diagnostics.git] /
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3
4 using System;
5 using System.Collections.Generic;
6 using System.Linq;
7 using Microsoft.Diagnostics.Monitoring.EventPipe.Triggers.Shared;
8
9 namespace Microsoft.Diagnostics.Monitoring.EventPipe.Triggers.SystemDiagnosticsMetrics
10 {
11     // The core implementation of the SystemDiagnosticsMetrics trigger that processes
12     // the trigger settings and evaluates the counter payload. Primary motivation
13     // for the implementation is for unit testability separate from TraceEvent.
14     internal sealed class SystemDiagnosticsMetricsTriggerImpl
15     {
16         private readonly long _intervalTicks;
17         private readonly Func<double, bool> _valueFilterDefault;
18         private readonly Func<Dictionary<int, double>, bool> _valueFilterHistogram;
19         private readonly long _windowTicks;
20
21         private long? _latestTicks;
22         private long? _targetTicks;
23
24         public SystemDiagnosticsMetricsTriggerImpl(SystemDiagnosticsMetricsTriggerSettings settings)
25         {
26             if (null == settings)
27             {
28                 throw new ArgumentNullException(nameof(settings));
29             }
30
31             if (settings.HistogramPercentile.HasValue)
32             {
33                 Func<double, bool> evalFunc = null;
34                 SharedTriggerImplHelper.SetDefaultValueFilter(ref evalFunc, settings.GreaterThan, settings.LessThan);
35
36                 _valueFilterHistogram = histogramValues =>
37                 {
38                     if (!histogramValues.TryGetValue(settings.HistogramPercentile.Value, out double value) || !evalFunc(value))
39                     {
40                         return false;
41                     }
42
43                     return true;
44                 };
45             }
46             else
47             {
48                 SharedTriggerImplHelper.SetDefaultValueFilter(ref _valueFilterDefault, settings.GreaterThan, settings.LessThan);
49             }
50
51             SharedTriggerImplHelper.SetIntervalAndWindowTicks(ref _intervalTicks, ref _windowTicks, settings.CounterIntervalSeconds, settings.SlidingWindowDuration.Ticks);
52         }
53
54         public bool HasSatisfiedCondition(ICounterPayload payload)
55         {
56             EventType eventType = payload.EventType;
57
58             if (eventType == EventType.Error || eventType == EventType.CounterEnded)
59             {
60                 // not currently logging the error messages
61
62                 return false;
63             }
64             else
65             {
66                 bool passesValueFilter = (payload is PercentilePayload percentilePayload) ?
67                     _valueFilterHistogram(CreatePayloadDictionary(percentilePayload)) :
68                     _valueFilterDefault(payload.Value);
69
70                 return SharedTriggerImplHelper.HasSatisfiedCondition(ref _latestTicks, ref _targetTicks, _windowTicks, _intervalTicks, payload, passesValueFilter);
71             }
72         }
73
74         private static Dictionary<int, double> CreatePayloadDictionary(PercentilePayload percentilePayload)
75         {
76             return percentilePayload.Quantiles.ToDictionary(keySelector: p => CounterUtilities.CreatePercentile(p.Percentage), elementSelector: p => p.Value);
77         }
78     }
79 }