Skip to content

Commit a926218

Browse files
committed
Rename the metrics following OTel naming
- no dashes. - use `db.redis` prefix Implement duration histogram and collapse 4 counters into it.
1 parent 8837b21 commit a926218

File tree

2 files changed

+35
-45
lines changed

2 files changed

+35
-45
lines changed

src/StackExchange.Redis/Message.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ public void Complete()
375375
// set the completion/performance data
376376
performance?.SetCompleted();
377377
#if NET6_0_OR_GREATER
378-
RedisMetrics.Instance.OnMessageComplete(currBox);
378+
RedisMetrics.Instance.OnMessageComplete(this, currBox);
379379
#endif
380380

381381
currBox?.ActivateContinuations();

src/StackExchange.Redis/RedisMetrics.cs

Lines changed: 34 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
#if NET6_0_OR_GREATER
22

3+
using System;
34
using System.Collections.Generic;
5+
using System.Diagnostics;
46
using System.Diagnostics.Metrics;
57

68
namespace StackExchange.Redis;
79

810
internal sealed class RedisMetrics
911
{
12+
private static readonly double s_tickFrequency = (double)TimeSpan.TicksPerSecond / Stopwatch.Frequency;
13+
// cache these boxed boolean values so we don't allocate on each usage.
14+
private static readonly object s_trueBox = true;
15+
private static readonly object s_falseBox = false;
16+
1017
private readonly Meter _meter;
1118
private readonly Counter<long> _operationCount;
12-
private readonly Counter<long> _completedAsynchronously;
13-
private readonly Counter<long> _completedSynchronously;
14-
private readonly Counter<long> _failedAsynchronously;
15-
private readonly Counter<long> _failedSynchronously;
19+
private readonly Histogram<double> _messageDuration;
1620
private readonly Counter<long> _nonPreferredEndpointCount;
1721

1822
public static readonly RedisMetrics Instance = new RedisMetrics();
@@ -22,67 +26,53 @@ private RedisMetrics()
2226
_meter = new Meter("StackExchange.Redis");
2327

2428
_operationCount = _meter.CreateCounter<long>(
25-
"redis-operation-count",
29+
"db.redis.operation.count",
2630
description: "The number of operations performed.");
2731

28-
_completedAsynchronously = _meter.CreateCounter<long>(
29-
"redis-completed-asynchronously",
30-
description: "The number of operations that have been completed asynchronously.");
31-
32-
_completedSynchronously = _meter.CreateCounter<long>(
33-
"redis-completed-synchronously",
34-
description: "The number of operations that have been completed synchronously.");
35-
36-
_failedAsynchronously = _meter.CreateCounter<long>(
37-
"redis-failed-asynchronously",
38-
description: "The number of operations that failed to complete asynchronously.");
39-
40-
_failedSynchronously = _meter.CreateCounter<long>(
41-
"redis-failed-synchronously",
42-
description: "The number of operations that failed to complete synchronously.");
32+
_messageDuration = _meter.CreateHistogram<double>(
33+
"db.redis.duration",
34+
unit: "s",
35+
description: "Measures the duration of outbound message requests.");
4336

4437
_nonPreferredEndpointCount = _meter.CreateCounter<long>(
45-
"redis-non-preferred-endpoint-count",
38+
"db.redis.non_preferred_endpoint.count",
4639
description: "Indicates the total number of messages dispatched to a non-preferred endpoint, for example sent to a primary when the caller stated a preference of replica.");
4740
}
4841

4942
public void IncrementOperationCount(string endpoint)
5043
{
51-
if (_operationCount.Enabled)
52-
{
53-
_operationCount.Add(1,
54-
new KeyValuePair<string, object?>("endpoint", endpoint));
55-
}
44+
_operationCount.Add(1,
45+
new KeyValuePair<string, object?>("endpoint", endpoint));
5646
}
5747

58-
public void OnMessageComplete(IResultBox? result)
48+
public void OnMessageComplete(Message message, IResultBox? result)
5949
{
60-
if (result is not null &&
61-
(_completedAsynchronously.Enabled ||
62-
_completedSynchronously.Enabled ||
63-
_failedAsynchronously.Enabled ||
64-
_failedSynchronously.Enabled))
50+
// The caller ensures we can don't record on the same resultBox from two threads.
51+
// 'result' can be null if this method is called for the same message more than once.
52+
if (result is not null && _messageDuration.Enabled)
6553
{
66-
Counter<long> counter = (result.IsFaulted, result.IsAsync) switch
54+
// Stopwatch.GetElapsedTime is only available in net7.0+
55+
// https://github.com/dotnet/runtime/blob/ae068fec6ede58d2a5b343c5ac41c9ca8715fa47/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Stopwatch.cs#L129-L137
56+
var now = Stopwatch.GetTimestamp();
57+
var duration = new TimeSpan((long)((now - message.CreatedTimestamp) * s_tickFrequency));
58+
59+
var tags = new TagList
6760
{
68-
(false, true) => _completedAsynchronously,
69-
(false, false) => _completedSynchronously,
70-
(true, true) => _failedAsynchronously,
71-
(true, false) => _failedSynchronously,
61+
{ "db.redis.async", result.IsAsync ? s_trueBox : s_falseBox },
62+
{ "db.redis.faulted", result.IsFaulted ? s_trueBox : s_falseBox }
63+
// TODO: can we pass endpoint here?
64+
// should we log the Db?
65+
// { "db.redis.database_index", message.Db },
7266
};
7367

74-
// TODO: can we pass endpoint here?
75-
counter.Add(1);
68+
_messageDuration.Record(duration.TotalSeconds, tags);
7669
}
7770
}
7871

7972
public void IncrementNonPreferredEndpointCount(string endpoint)
8073
{
81-
if (_nonPreferredEndpointCount.Enabled)
82-
{
83-
_nonPreferredEndpointCount.Add(1,
84-
new KeyValuePair<string, object?>("endpoint", endpoint));
85-
}
74+
_nonPreferredEndpointCount.Add(1,
75+
new KeyValuePair<string, object?>("endpoint", endpoint));
8676
}
8777
}
8878

0 commit comments

Comments
 (0)