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

Metrics Support - alpha #2949

Merged
merged 60 commits into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
5794a6c
Added basic metric types
jamescrosswell Dec 4, 2023
3752fd5
Moved Metric classes
jamescrosswell Dec 5, 2023
0d6587b
Added Increment aggregator
jamescrosswell Dec 6, 2023
088e4fd
Implemented Gauge metric
jamescrosswell Dec 6, 2023
9fac649
Implemented Distribution and Set aggregations
jamescrosswell Dec 6, 2023
c65355d
Added Metrics to ISentryClient API
jamescrosswell Dec 6, 2023
b77c04d
Update Hub.cs
jamescrosswell Dec 6, 2023
c0233db
Verify tests
jamescrosswell Dec 6, 2023
3b74b80
Basic flush loop (no tests yet)
jamescrosswell Dec 6, 2023
c83e9c9
Implemented statsd serialization
jamescrosswell Dec 7, 2023
9150098
Update CHANGELOG.md
jamescrosswell Dec 7, 2023
19dc74a
Split tests for Aggregagtor and BucketHelper
jamescrosswell Dec 7, 2023
cac0d79
Update MetricBucketHelperTests.cs
jamescrosswell Dec 7, 2023
721e6b3
Integrated review feedback
jamescrosswell Dec 10, 2023
a7ba47e
Create MetricTests.verify.cs
jamescrosswell Dec 11, 2023
90be220
Updated verify tests
jamescrosswell Dec 11, 2023
73be790
Merge branch 'main' into metrics
jamescrosswell Dec 11, 2023
94790d7
Added Timing
jamescrosswell Dec 11, 2023
e05f8ee
Merge branch 'metrics' of github.com:getsentry/sentry-dotnet into met…
jamescrosswell Dec 11, 2023
54af5c2
Added a (commented out) test to check if the aggregator is threadsafe
jamescrosswell Dec 11, 2023
9344f38
Fixed concurrency issue (could still make this more performant)
jamescrosswell Dec 12, 2023
5827608
Reduced the scope of the lock for updating metrics
jamescrosswell Dec 12, 2023
f3275ac
Fixed unit tests
jamescrosswell Dec 12, 2023
0f86158
Update MetricAggregator.cs
jamescrosswell Dec 12, 2023
7a75155
Initial implementation of Code Locations
jamescrosswell Dec 14, 2023
a116f56
Merge branch 'main' into metrics
jamescrosswell Dec 14, 2023
7f47f1a
Update Program.cs
jamescrosswell Dec 14, 2023
cd83a4e
Updated solution filters
jamescrosswell Dec 14, 2023
826a413
Update CHANGELOG.md
jamescrosswell Dec 14, 2023
994b8ba
Changed Flush to FlushAsync
jamescrosswell Dec 14, 2023
8e7f0ce
Metrics now get flushed properly when disposing of the Hub
jamescrosswell Dec 14, 2023
aa3682f
Fixed serialization for code locations
jamescrosswell Dec 14, 2023
d9918d8
Update Timing.cs
jamescrosswell Dec 14, 2023
6de5909
Clear stale seen periods at the end of each day
jamescrosswell Dec 15, 2023
d180a9d
Update CodeLocations.cs
jamescrosswell Dec 15, 2023
2a6f344
Fixed stacklevel when calling one of the two Timing constructors
jamescrosswell Dec 15, 2023
052c7a9
Removed IAsyncDisposable from MetricAggregator
jamescrosswell Dec 18, 2023
82469ba
Merge branch 'main' into metrics
jamescrosswell Dec 18, 2023
2eedd9c
Cherry picked https://github.com/getsentry/Ben.Demystifier/pull/4
jamescrosswell Dec 18, 2023
18a08bd
Merge branch 'metrics' of github.com:getsentry/sentry-dotnet into met…
jamescrosswell Dec 18, 2023
c72c7e1
Update Ben.Demystifier
jamescrosswell Dec 18, 2023
2a323c5
Get line numbers with stack traces without enhanced stack traces
jamescrosswell Dec 19, 2023
57e2b12
Update Ben.Demystifier
jamescrosswell Dec 19, 2023
d2c6cb5
Reversed changes to AspNetCore.Basic sample (unrelated to this PR)
jamescrosswell Dec 19, 2023
a9c5d6b
Update Program.cs
jamescrosswell Dec 19, 2023
30ef3b4
Improved the lock when incrementing/adding to existing metrics
jamescrosswell Dec 19, 2023
34a5c3e
Tweaking docs
jamescrosswell Dec 19, 2023
7faa57c
Update CHANGELOG.md
jamescrosswell Dec 20, 2023
d956b5d
Integrating review feedback
jamescrosswell Dec 20, 2023
3efab8a
Source generated RegEx in metric helper
jamescrosswell Dec 20, 2023
62a7001
Merge branch 'metrics' of github.com:getsentry/sentry-dotnet into met…
jamescrosswell Dec 20, 2023
c68c25c
Update Envelope.cs
jamescrosswell Dec 20, 2023
1c3b275
Merge branch 'main' into metrics
jamescrosswell Dec 21, 2023
4cb9ef7
Review feedback
jamescrosswell Dec 27, 2023
36fe029
Merge branch 'main' into metrics
jamescrosswell Dec 27, 2023
8cc439c
Integrating review feedback
jamescrosswell Jan 3, 2024
705d131
More performant string delimited tags used in the bucket key
jamescrosswell Jan 4, 2024
353a928
Integrating review feedback
jamescrosswell Jan 4, 2024
589c3b2
Integrated review feedback
jamescrosswell Jan 6, 2024
bce6e50
Removed unused private field
jamescrosswell Jan 6, 2024
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: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Features

- Experimental pre-release availability of Delightful Developer Metrics. We're exploring the use of Metrics in Sentry. The API will very likely change and we don't yet have any documentation. ([#2949](https://github.com/getsentry/sentry-dotnet/pull/2949))
jamescrosswell marked this conversation as resolved.
Show resolved Hide resolved

### Dependencies

- Bump Cocoa SDK from v8.17.0 to v8.17.1 ([#2936](https://github.com/getsentry/sentry-dotnet/pull/2936))
Expand Down
8 changes: 7 additions & 1 deletion samples/Sentry.Samples.AspNetCore.Basic/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ public static IWebHost BuildWebHost(string[] args) =>
.UseSentry(o =>
{
// A DSN is required. You can set it here, or in configuration, or in an environment variable.
o.Dsn = "https://eb18e953812b41c3aeb042e666fd3b5c@o447951.ingest.sentry.io/5428537";
o.Dsn = "https://b887218a80114d26a9b1a51c5f88e0b4@o447951.ingest.sentry.io/6601807";

// Enable Sentry performance monitoring
o.EnableTracing = true;

o.ExperimentalMetrics = new ExperimentalMetricsOptions(){ MetricSampleRate = 1.0 };
#if DEBUG
// Log debug information about the Sentry SDK
o.Debug = true;
Expand All @@ -35,6 +36,11 @@ public static IWebHost BuildWebHost(string[] args) =>
// exception when serving a request to path: /throw
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/hello", () =>
{
SentrySdk.Metrics.Increment("hello.world");
return "Hello World!";
});
// Reported events will be grouped by route pattern
endpoints.MapGet("/throw/{message?}", context =>
{
Expand Down
16 changes: 16 additions & 0 deletions src/Sentry/DelegatingMetricAggregator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
namespace Sentry;

internal class DelegatingMetricAggregator(IMetricAggregator innerAggregator) : IMetricAggregator
jamescrosswell marked this conversation as resolved.
Show resolved Hide resolved
{
public void Increment(string key, double value = 1, MeasurementUnit? unit = null, IDictionary<string, string>? tags = null,
jamescrosswell marked this conversation as resolved.
Show resolved Hide resolved
DateTime? timestamp = null) => innerAggregator.Increment(key, value, unit, tags, timestamp);

public void Gauge(string key, double value = 1, MeasurementUnit? unit = null, IDictionary<string, string>? tags = null,
DateTime? timestamp = null) => innerAggregator.Gauge(key, value, unit, tags, timestamp);

public void Distribution(string key, double value = 1, MeasurementUnit? unit = null, IDictionary<string, string>? tags = null,
DateTime? timestamp = null) => innerAggregator.Distribution(key, value, unit, tags, timestamp);

public void Set(string key, double value = 1, MeasurementUnit? unit = null, IDictionary<string, string>? tags = null,
DateTime? timestamp = null) => innerAggregator.Set(key, value, unit, tags, timestamp);
}
28 changes: 28 additions & 0 deletions src/Sentry/DisabledMetricAggregator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace Sentry;

internal class DisabledMetricAggregator : IMetricAggregator
{
public void Increment(string key, double value = 1, MeasurementUnit? unit = null, IDictionary<string, string>? tags = null,
jamescrosswell marked this conversation as resolved.
Show resolved Hide resolved
DateTime? timestamp = null)
{
// No Op
}

public void Gauge(string key, double value = 1, MeasurementUnit? unit = null, IDictionary<string, string>? tags = null,
DateTime? timestamp = null)
{
// No Op
}

public void Distribution(string key, double value = 1, MeasurementUnit? unit = null, IDictionary<string, string>? tags = null,
DateTime? timestamp = null)
{
// No Op
}

public void Set(string key, double value = 1, MeasurementUnit? unit = null, IDictionary<string, string>? tags = null,
DateTime? timestamp = null)
{
// No Op
}
}
5 changes: 5 additions & 0 deletions src/Sentry/Extensibility/DisabledHub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,11 @@ public void CaptureSession(SessionUpdate sessionUpdate)
/// </summary>
public Task FlushAsync(TimeSpan timeout) => Task.CompletedTask;

/// <summary>
/// Disabled Metrics Aggregator (all methods are no-op).
/// </summary>
public IMetricAggregator Metrics { get; } = new DisabledMetricAggregator();

/// <summary>
/// No-Op.
/// </summary>
Expand Down
4 changes: 4 additions & 0 deletions src/Sentry/Extensibility/HubAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,10 @@ public void CaptureSession(SessionUpdate sessionUpdate)
public Task FlushAsync(TimeSpan timeout)
=> SentrySdk.FlushAsync(timeout);

/// <inheritdoc cref="IMetricAggregator"/>
public IMetricAggregator Metrics
=> SentrySdk.Metrics;

/// <summary>
/// Forwards the call to <see cref="SentrySdk"/>
/// </summary>
Expand Down
76 changes: 76 additions & 0 deletions src/Sentry/IMetricAggregator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
namespace Sentry;

/// <summary>
/// Exposes EXPERIMENTAL capability to emit metrics. This API is subject to change without major version bumps so use
/// with caution. We advise disabling in production at the moment.
/// </summary>
public interface IMetricAggregator
{
/// <summary>
/// Emits a Counter metric
/// </summary>
/// <param name="key">A unique key identifying the metric</param>
/// <param name="value">The value to be added</param>
/// <param name="unit">An optional <see cref="MeasurementUnit"/></param>
/// <param name="tags">Optional Tags to associate with the metric</param>
/// <param name="timestamp">The time when the metric was emitted</param>
void Increment(
string key,
double value = 1.0,
MeasurementUnit? unit = null,
IDictionary<string, string>? tags = null,
DateTime? timestamp = null
// , int stacklevel = 0 // Used for code locations
);

/// <summary>
/// Emits a Gauge metric
/// </summary>
/// <param name="key">A unique key identifying the metric</param>
/// <param name="value">The value to be added</param>
/// <param name="unit">An optional <see cref="MeasurementUnit"/></param>
/// <param name="tags">Optional Tags to associate with the metric</param>
/// <param name="timestamp">The time when the metric was emitted</param>
void Gauge(
string key,
double value = 1.0,
MeasurementUnit? unit = null,
IDictionary<string, string>? tags = null,
DateTime? timestamp = null
// , int stacklevel = 0 // Used for code locations
);

/// <summary>
/// Emits a Distribution metric
/// </summary>
/// <param name="key">A unique key identifying the metric</param>
/// <param name="value">The value to be added</param>
/// <param name="unit">An optional <see cref="MeasurementUnit"/></param>
/// <param name="tags">Optional Tags to associate with the metric</param>
/// <param name="timestamp">The time when the metric was emitted</param>
jamescrosswell marked this conversation as resolved.
Show resolved Hide resolved
void Distribution(
string key,
double value = 1.0,
MeasurementUnit? unit = null,
IDictionary<string, string>? tags = null,
DateTime? timestamp = null
// , int stacklevel = 0 // Used for code locations
);

/// <summary>
/// Emits a Set metric
/// </summary>
/// <param name="key">A unique key identifying the metric</param>
/// <param name="value">The value to be added</param>
/// <param name="unit">An optional <see cref="MeasurementUnit"/></param>
/// <param name="tags">Optional Tags to associate with the metric</param>
/// <param name="timestamp">The time when the metric was emitted</param>
void Set(
string key,
double value = 1.0,
jamescrosswell marked this conversation as resolved.
Show resolved Hide resolved
MeasurementUnit? unit = null,
IDictionary<string, string>? tags = null,
DateTime? timestamp = null
// , int stacklevel = 0 // Used for code locations
);
}
5 changes: 5 additions & 0 deletions src/Sentry/ISentryClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,9 @@ public interface ISentryClient
/// <param name="timeout">The amount of time allowed for flushing.</param>
/// <returns>A task to await for the flush operation.</returns>
Task FlushAsync(TimeSpan timeout);

/// <summary>
/// <inheritdoc cref="IMetricAggregator"/>
/// </summary>
IMetricAggregator Metrics { get; }
}
6 changes: 6 additions & 0 deletions src/Sentry/Internal/Hub.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Sentry.Infrastructure;
using Sentry.Integrations;
using Sentry.Internal.ScopeStack;
using Sentry.Protocol.Metrics;

namespace Sentry.Internal;

Expand All @@ -22,6 +23,9 @@ internal class Hub : IHub, IDisposable

internal IInternalScopeManager ScopeManager { get; }

/// <inheritdoc cref="IMetricAggregator"/>
public IMetricAggregator Metrics { get; }
jamescrosswell marked this conversation as resolved.
Show resolved Hide resolved

private int _isEnabled = 1;
public bool IsEnabled => _isEnabled == 1;

Expand Down Expand Up @@ -58,6 +62,8 @@ internal Hub(
PushScope();
}

Metrics = new DelegatingMetricAggregator(_ownedClient.Metrics);
jamescrosswell marked this conversation as resolved.
Show resolved Hide resolved
jamescrosswell marked this conversation as resolved.
Show resolved Hide resolved

foreach (var integration in options.Integrations)
{
options.LogDebug("Registering integration: '{0}'.", integration.GetType().Name);
Expand Down
Loading
Loading