-
Notifications
You must be signed in to change notification settings - Fork 740
/
CollectedMeasurement.cs
110 lines (95 loc) · 3.95 KB
/
CollectedMeasurement.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using Microsoft.Shared.Diagnostics;
namespace Microsoft.Extensions.Diagnostics.Metrics.Testing;
/// <summary>
/// Represents a single measurement performed by an instrument.
/// </summary>
/// <typeparam name="T">The type of metric measurement value.</typeparam>
[DebuggerDisplay("{DebuggerToString(),nq}")]
public sealed class CollectedMeasurement<T>
where T : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="CollectedMeasurement{T}"/> class.
/// </summary>
/// <param name="value">The measurement's value.</param>
/// <param name="tags">The dimensions of this measurement.</param>
/// <param name="timestamp">The time that the measurement occurred at.</param>
internal CollectedMeasurement(T value, ReadOnlySpan<KeyValuePair<string, object?>> tags, DateTimeOffset timestamp)
{
var d = new Dictionary<string, object?>();
foreach (var tag in tags)
{
d[tag.Key] = tag.Value;
}
Tags = d;
Timestamp = timestamp;
Value = value;
}
/// <summary>
/// Gets a measurement's value.
/// </summary>
public T Value { get; }
/// <summary>
/// Gets a timestamp indicating when the measurement was recorded.
/// </summary>
public DateTimeOffset Timestamp { get; }
/// <summary>
/// Gets the measurement's dimensions.
/// </summary>
public IReadOnlyDictionary<string, object?> Tags { get; }
/// <summary>
/// Checks that the measurement includes a specific set of tags with specific values.
/// </summary>
/// <param name="tags">The set of tags to check.</param>
/// <returns><see langword="true"/> if all the tags exist in the measurement with matching values, otherwise <see langword="false"/>.</returns>
public bool ContainsTags(params KeyValuePair<string, object?>[] tags)
{
foreach (var kvp in Throw.IfNull(tags))
{
if (!Tags.TryGetValue(kvp.Key, out var value))
{
return false;
}
if (!object.Equals(kvp.Value, value))
{
return false;
}
}
return true;
}
/// <summary>
/// Checks that the measurement includes a specific set of tags with any value.
/// </summary>
/// <param name="tags">The set of tag names to check.</param>
/// <returns><see langword="true"/> if all the tags exist in the measurement, otherwise <see langword="false"/>.</returns>
public bool ContainsTags(params string[] tags)
{
foreach (var key in Throw.IfNull(tags))
{
if (!Tags.ContainsKey(key))
{
return false;
}
}
return true;
}
/// <summary>
/// Checks that the measurement has an exactly matching set of tags with specific values.
/// </summary>
/// <param name="tags">The set of tags to check.</param>
/// <returns><see langword="true"/> if all the tags exist in the measurement with matching values, otherwise <see langword="false"/>.</returns>
public bool MatchesTags(params KeyValuePair<string, object?>[] tags) => ContainsTags(tags) && (Tags.Count == tags.Length);
/// <summary>
/// Checks that the measurement has a exactly matching set of tags with any value.
/// </summary>
/// <param name="tags">The set of tag names to check.</param>
/// <returns><see langword="true"/> if all the tag names exist in the measurement, otherwise <see langword="false"/>.</returns>
public bool MatchesTags(params string[] tags) => ContainsTags(Throw.IfNull(tags)) && (Tags.Count == tags.Length);
internal string DebuggerToString() => $"{Value} @ {Timestamp.ToString("HH:mm:ss.ffff", CultureInfo.InvariantCulture)}";
}