Skip to content

Commit 4a080e7

Browse files
committed
feat!: make public Metrics type non-generic
1 parent 7faa682 commit 4a080e7

25 files changed

+308
-418
lines changed

samples/Sentry.Samples.Console.Basic/Program.cs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,21 @@
5555
});
5656

5757
// Sentry (trace-connected) Metrics via SentrySdk.Experimental.Metrics are enabled by default.
58-
options.Experimental.SetBeforeSendMetric<int>(static metric =>
58+
options.Experimental.SetBeforeSendMetric(static metric =>
5959
{
60+
if (metric.TryGetValue(out int integer) && integer < 0)
61+
{
62+
// Return null to drop the metric
63+
return null;
64+
}
65+
6066
// A demonstration of how you can modify the metric object before sending it to Sentry
61-
metric.SetAttribute("operating_system.platform", Environment.OSVersion.Platform.ToString());
62-
metric.SetAttribute("operating_system.version", Environment.OSVersion.Version.ToString());
67+
if (metric.Type is SentryMetricType.Counter)
68+
{
69+
metric.SetAttribute("operating_system.platform", Environment.OSVersion.Platform.ToString());
70+
metric.SetAttribute("operating_system.version", Environment.OSVersion.Version.ToString());
71+
}
6372

64-
// Return null to drop the metric
6573
return metric;
6674
});
6775
});
@@ -95,10 +103,13 @@ async Task FirstFunction()
95103
// Info-Log filtered via "BeforeSendLog" callback
96104
SentrySdk.Logger.LogInfo("HTTP Request completed.");
97105

98-
// Metric modified via "BeforeSendMetric" callback for type "int" before sending it to Sentry
106+
// Counter-Metric prevented from being sent to Sentry via "BeforeSendMetric" callback
107+
SentrySdk.Experimental.Metrics.EmitCounter("sentry.samples.console.basic.ignore", -1);
108+
109+
// Counter-Metric modified before sending it to Sentry via "BeforeSendMetric" callback
99110
SentrySdk.Experimental.Metrics.EmitCounter("sentry.samples.console.basic.http_requests_completed", 1);
100111

101-
// Metric sent as is because no "BeforeSendMetric" is set for type "double"
112+
// Distribution-Metric sent as is (see "BeforeSendMetric" callback)
102113
SentrySdk.Experimental.Metrics.EmitDistribution("sentry.samples.console.basic.http_request_duration", stopwatch.Elapsed.TotalSeconds, SentryUnits.Duration.Second,
103114
[new KeyValuePair<string, object>("http.request.method", HttpMethod.Get.Method), new KeyValuePair<string, object>("http.response.status_code", (int)HttpStatusCode.OK)]);
104115
}

src/Sentry/IHub.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public interface IHub : ISentryClient, ISentryScopeManager
3636
/// Available options:
3737
/// <list type="bullet">
3838
/// <item><see cref="Sentry.SentryOptions.ExperimentalSentryOptions.EnableMetrics"/></item>
39-
/// <item><see cref="Sentry.SentryOptions.ExperimentalSentryOptions.SetBeforeSendMetric{T}(System.Func{SentryMetric{T}, SentryMetric{T}})"/></item>
39+
/// <item><see cref="Sentry.SentryOptions.ExperimentalSentryOptions.SetBeforeSendMetric(System.Func{SentryMetric, SentryMetric})"/></item>
4040
/// </list>
4141
/// </remarks>
4242
[Experimental("SENTRYTRACECONNECTEDMETRICS", UrlFormat = "https://github.com/getsentry/sentry-dotnet/discussions/4838")]

src/Sentry/Internal/DefaultSentryTraceMetrics.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ internal sealed class DefaultSentryTraceMetrics : SentryTraceMetrics, IDisposabl
1010
private readonly SentryOptions _options;
1111
private readonly ISystemClock _clock;
1212

13-
private readonly BatchProcessor<ISentryMetric> _batchProcessor;
13+
private readonly BatchProcessor<SentryMetric> _batchProcessor;
1414

1515
internal DefaultSentryTraceMetrics(IHub hub, SentryOptions options, ISystemClock clock, int batchCount, TimeSpan batchInterval)
1616
{
@@ -21,7 +21,7 @@ internal DefaultSentryTraceMetrics(IHub hub, SentryOptions options, ISystemClock
2121
_options = options;
2222
_clock = clock;
2323

24-
_batchProcessor = new BatchProcessor<ISentryMetric>(hub, batchCount, batchInterval, TraceMetric.Capture, _options.ClientReportRecorder, _options.DiagnosticLogger);
24+
_batchProcessor = new BatchProcessor<SentryMetric>(hub, batchCount, batchInterval, TraceMetric.Capture, _options.ClientReportRecorder, _options.DiagnosticLogger);
2525
}
2626

2727
/// <inheritdoc />
@@ -63,12 +63,12 @@ private protected override void CaptureMetric<T>(SentryMetricType type, string n
6363
}
6464

6565
/// <inheritdoc />
66-
protected internal override void CaptureMetric<T>(SentryMetric<T> metric) where T : struct
66+
private protected override void CaptureMetric<T>(SentryMetric<T> metric) where T : struct
6767
{
6868
Debug.Assert(SentryMetric.IsSupported(typeof(T)));
6969
Debug.Assert(!string.IsNullOrEmpty(metric.Name));
7070

71-
var configuredMetric = metric;
71+
SentryMetric? configuredMetric = metric;
7272

7373
if (_options.Experimental.BeforeSendMetricInternal is { } beforeSendMetric)
7474
{

src/Sentry/Internal/DisabledSentryTraceMetrics.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ private protected override void CaptureMetric<T>(SentryMetricType type, string n
2121
}
2222

2323
/// <inheritdoc />
24-
protected internal override void CaptureMetric<T>(SentryMetric<T> metric) where T : struct
24+
private protected override void CaptureMetric<T>(SentryMetric<T> metric) where T : struct
2525
{
2626
// disabled
2727
}

src/Sentry/Internal/Polyfills.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,32 @@ public static void WriteRawValue(this Utf8JsonWriter writer, byte[] utf8Json)
6262
}
6363
}
6464
#endif
65+
66+
// TODO: remove when updating Polyfill: https://github.com/getsentry/sentry-dotnet/pull/4879
67+
#if !NET6_0_OR_GREATER
68+
internal static class EnumerableExtensions
69+
{
70+
internal static bool TryGetNonEnumeratedCount<TSource>(this IEnumerable<TSource> source, out int count)
71+
{
72+
if (source is null)
73+
{
74+
throw new ArgumentNullException(nameof(source));
75+
}
76+
77+
if (source is ICollection<TSource> genericCollection)
78+
{
79+
count = genericCollection.Count;
80+
return true;
81+
}
82+
83+
if (source is ICollection collection)
84+
{
85+
count = collection.Count;
86+
return true;
87+
}
88+
89+
count = 0;
90+
return false;
91+
}
92+
}
93+
#endif

src/Sentry/Protocol/TraceMetric.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ namespace Sentry.Protocol;
1212
/// </remarks>
1313
internal sealed class TraceMetric : ISentryJsonSerializable
1414
{
15-
private readonly ISentryMetric[] _items;
15+
private readonly SentryMetric[] _items;
1616

17-
public TraceMetric(ISentryMetric[] metrics)
17+
public TraceMetric(SentryMetric[] metrics)
1818
{
1919
_items = metrics;
2020
}
2121

2222
public int Length => _items.Length;
23-
public ReadOnlySpan<ISentryMetric> Items => _items;
23+
public ReadOnlySpan<SentryMetric> Items => _items;
2424

2525
public void WriteTo(Utf8JsonWriter writer, IDiagnosticLogger? logger)
2626
{
@@ -36,7 +36,7 @@ public void WriteTo(Utf8JsonWriter writer, IDiagnosticLogger? logger)
3636
writer.WriteEndObject();
3737
}
3838

39-
internal static void Capture(IHub hub, ISentryMetric[] metrics)
39+
internal static void Capture(IHub hub, SentryMetric[] metrics)
4040
{
4141
_ = hub.CaptureEnvelope(Envelope.FromMetric(new TraceMetric(metrics)));
4242
}

src/Sentry/SentryLog.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ internal void SetOrigin(string origin)
189189
SetAttribute("sentry.origin", origin);
190190
}
191191

192+
/// <inheritdoc cref="ISentryJsonSerializable.WriteTo(Utf8JsonWriter, IDiagnosticLogger)" />
192193
internal void WriteTo(Utf8JsonWriter writer, IDiagnosticLogger? logger)
193194
{
194195
writer.WriteStartObject();

src/Sentry/SentryMetric.Factory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
namespace Sentry;
55

6-
internal static class SentryMetric
6+
public abstract partial class SentryMetric
77
{
88
internal static SentryMetric<T> Create<T>(IHub hub, SentryOptions options, ISystemClock clock, SentryMetricType type, string name, T value, string? unit, IEnumerable<KeyValuePair<string, object>>? attributes, Scope? scope) where T : struct
99
{

src/Sentry/SentryMetric.Generic.cs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
using Sentry.Extensibility;
2+
3+
namespace Sentry;
4+
5+
/// <summary>
6+
/// Internal generic representation of <see cref="SentryMetric"/>.
7+
/// </summary>
8+
/// <typeparam name="T">The numeric type of the metric.</typeparam>
9+
/// <remarks>
10+
/// We hide some of the generic implementation details from user code.
11+
/// </remarks>
12+
internal sealed class SentryMetric<T> : SentryMetric where T : struct
13+
{
14+
private readonly T _value;
15+
16+
[SetsRequiredMembers]
17+
internal SentryMetric(DateTimeOffset timestamp, SentryId traceId, SentryMetricType type, string name, T value)
18+
: base(timestamp, traceId, type, name)
19+
{
20+
_value = value;
21+
}
22+
23+
internal override object Value => _value;
24+
25+
/// <inheritdoc />
26+
public override bool TryGetValue<TValue>(out TValue value) where TValue : struct
27+
{
28+
if (_value is TValue match)
29+
{
30+
value = match;
31+
return true;
32+
}
33+
34+
value = default;
35+
return false;
36+
}
37+
38+
private protected override void WriteMetricValueTo(Utf8JsonWriter writer, IDiagnosticLogger? logger)
39+
{
40+
const string propertyName = "value";
41+
var type = typeof(T);
42+
43+
if (type == typeof(long))
44+
{
45+
writer.WriteNumber(propertyName, (long)(object)_value);
46+
}
47+
else if (type == typeof(double))
48+
{
49+
writer.WriteNumber(propertyName, (double)(object)_value);
50+
}
51+
else if (type == typeof(int))
52+
{
53+
writer.WriteNumber(propertyName, (int)(object)_value);
54+
}
55+
else if (type == typeof(float))
56+
{
57+
writer.WriteNumber(propertyName, (float)(object)_value);
58+
}
59+
else if (type == typeof(short))
60+
{
61+
writer.WriteNumber(propertyName, (short)(object)_value);
62+
}
63+
else if (type == typeof(byte))
64+
{
65+
writer.WriteNumber(propertyName, (byte)(object)_value);
66+
}
67+
else
68+
{
69+
Debug.Fail($"Unhandled Metric Type {typeof(T)}.", "This instruction should be unreachable.");
70+
}
71+
}
72+
}

src/Sentry/SentryMetric.Interface.cs

Lines changed: 0 additions & 12 deletions
This file was deleted.

0 commit comments

Comments
 (0)