• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

loresoft / HashGate / 25515201519

07 May 2026 06:42PM UTC coverage: 63.517% (-1.3%) from 64.826%
25515201519

push

github

pwelter34
Include client and endpoint in diagnostics

193 of 408 branches covered (47.3%)

Branch coverage included in aggregate %.

48 of 120 new or added lines in 2 files covered. (40.0%)

580 of 809 relevant lines covered (71.69%)

25.69 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

47.41
/src/HashGate.AspNetCore/HashGateDiagnostics.cs
1
// Ignore Spelling: Hmac
2

3
using System.Diagnostics;
4
using System.Diagnostics.Metrics;
5

6
namespace HashGate.AspNetCore;
7

8
/// <summary>
9
/// Provides diagnostic source, meter, metric, and tag names used by HashGate ASP.NET Core instrumentation.
10
/// </summary>
11
public static class HashGateDiagnostics
12
{
13
    /// <summary>
14
    /// The name of the activity source used for HashGate ASP.NET Core tracing.
15
    /// </summary>
16
    public const string SourceName = "HashGate.AspNetCore";
17

18
    /// <summary>
19
    /// The name of the meter used for HashGate ASP.NET Core metrics.
20
    /// </summary>
21
    public const string MeterName = "HashGate.AspNetCore";
22

23
    /// <summary>
24
    /// The metric name for HMAC authentication request attempts.
25
    /// </summary>
26
    public const string AuthenticationRequestsName = "hashgate.auth.requests";
27

28
    /// <summary>
29
    /// The metric name for failed HMAC authentication attempts.
30
    /// </summary>
31
    public const string AuthenticationFailuresName = "hashgate.auth.failures";
32

33
    /// <summary>
34
    /// The metric name for HMAC authentication duration.
35
    /// </summary>
36
    public const string AuthenticationDurationName = "hashgate.auth.duration";
37

38
    /// <summary>
39
    /// The metric name for HMAC replay protection checks.
40
    /// </summary>
41
    public const string ReplayProtectionChecksName = "hashgate.replay_protection.checks";
42

43
    /// <summary>
44
    /// The metric name for rejected replayed HMAC signatures.
45
    /// </summary>
46
    public const string ReplayProtectionReplaysName = "hashgate.replay_protection.replays";
47

48
    /// <summary>
49
    /// The metric name for rate-limited endpoint requests resolved by HashGate.
50
    /// </summary>
51
    public const string EndpointRequestsName = "hashgate.endpoint.requests";
52

53
    /// <summary>
54
    /// The metric name for requests rejected by HashGate rate limiting.
55
    /// </summary>
56
    public const string RateLimitRejectionsName = "hashgate.rate_limit.rejections";
57

58
    /// <summary>
59
    /// The metric name for per-client rate limit provider lookups.
60
    /// </summary>
61
    public const string RateLimitProviderLookupsName = "hashgate.rate_limit.provider.lookup";
62

63
    /// <summary>
64
    /// The metric name for per-client rate limit provider lookups that used default limits.
65
    /// </summary>
66
    public const string RateLimitProviderMissesName = "hashgate.rate_limit.provider.miss";
67

68

69
    /// <summary>
70
    /// The tag name for the authentication scheme used by a request.
71
    /// </summary>
72
    public const string AuthenticationSchemeTagName = "hashgate.auth.scheme";
73

74
    /// <summary>
75
    /// The tag name for the authentication result.
76
    /// </summary>
77
    public const string AuthenticationResultTagName = "hashgate.auth.result";
78

79
    /// <summary>
80
    /// The tag name for the authentication failure reason.
81
    /// </summary>
82
    public const string AuthenticationFailureReasonTagName = "hashgate.auth.failure_reason";
83

84
    /// <summary>
85
    /// The tag name that indicates whether replay protection is enabled.
86
    /// </summary>
87
    public const string ReplayProtectionEnabledTagName = "hashgate.replay_protection.enabled";
88

89
    /// <summary>
90
    /// The tag name for the replay protection result.
91
    /// </summary>
92
    public const string ReplayProtectionResultTagName = "hashgate.replay_protection.result";
93

94
    /// <summary>
95
    /// The tag name for the count of signed HMAC headers.
96
    /// </summary>
97
    public const string HmacSignedHeadersCountTagName = "hashgate.hmac.signed_headers.count";
98

99
    /// <summary>
100
    /// The tag name that indicates whether a request was rejected by rate limiting.
101
    /// </summary>
102
    public const string RateLimitRejectedTagName = "hashgate.rate_limit.rejected";
103

104
    /// <summary>
105
    /// The tag name for the rate limit policy.
106
    /// </summary>
107
    public const string RateLimitPolicyTagName = "hashgate.rate_limit.policy";
108

109
    /// <summary>
110
    /// The tag name for the retry-after duration in milliseconds.
111
    /// </summary>
112
    public const string RateLimitRetryAfterMillisecondsTagName = "hashgate.rate_limit.retry_after_ms";
113

114
    /// <summary>
115
    /// The tag name for the rate limit client identifier.
116
    /// </summary>
117
    public const string RateLimitClientTagName = "hashgate.rate_limit.client";
118

119
    /// <summary>
120
    /// The tag name for the rate-limited endpoint.
121
    /// </summary>
122
    public const string RateLimitEndpointTagName = "hashgate.rate_limit.endpoint";
123

124
    /// <summary>
125
    /// The tag name for the configured requests per rate limit period.
126
    /// </summary>
127
    public const string RateLimitRequestsPerPeriodTagName = "hashgate.rate_limit.requests_per_period";
128

129
    /// <summary>
130
    /// The tag name for the configured rate limit burst factor.
131
    /// </summary>
132
    public const string RateLimitBurstFactorTagName = "hashgate.rate_limit.burst_factor";
133

134
    /// <summary>
135
    /// The tag name for the rate limit partition source.
136
    /// </summary>
137
    public const string RateLimitPartitionSourceTagName = "hashgate.rate_limit.partition_source";
138

139
    /// <summary>
140
    /// The tag name that indicates whether a rate limit provider lookup found client-specific limits.
141
    /// </summary>
142
    public const string RateLimitProviderFoundTagName = "hashgate.rate_limit.provider_found";
143

144
    /// <summary>
145
    /// The tag name for the resolved endpoint.
146
    /// </summary>
147
    public const string EndpointTagName = "hashgate.endpoint";
148

149
    /// <summary>
150
    /// The tag name for the resolved client.
151
    /// </summary>
152
    public const string ClientTagName = "hashgate.client";
153

154

155
    internal static readonly ActivitySource ActivitySource = new(SourceName, ThisAssembly.FileVersion);
1✔
156
    internal static readonly Meter Meter = new(MeterName, ThisAssembly.FileVersion);
1✔
157

158
    internal static readonly Counter<long> AuthenticationRequests = Meter.CreateCounter<long>(
1✔
159
        name: AuthenticationRequestsName,
1✔
160
        unit: "{request}",
1✔
161
        description: "Number of HMAC authentication attempts.");
1✔
162

163
    internal static readonly Counter<long> AuthenticationFailures = Meter.CreateCounter<long>(
1✔
164
        name: AuthenticationFailuresName,
1✔
165
        unit: "{failure}",
1✔
166
        description: "Number of failed HMAC authentication attempts.");
1✔
167

168
    internal static readonly Histogram<double> AuthenticationDuration = Meter.CreateHistogram<double>(
1✔
169
        name: AuthenticationDurationName,
1✔
170
        unit: "ms",
1✔
171
        description: "Duration of HMAC authentication attempts.");
1✔
172

173

174
    internal static readonly Counter<long> ReplayProtectionChecks = Meter.CreateCounter<long>(
1✔
175
        name: ReplayProtectionChecksName,
1✔
176
        unit: "{check}",
1✔
177
        description: "Number of HMAC replay protection checks.");
1✔
178

179
    internal static readonly Counter<long> ReplayProtectionReplays = Meter.CreateCounter<long>(
1✔
180
        name: ReplayProtectionReplaysName,
1✔
181
        unit: "{replay}",
1✔
182
        description: "Number of rejected replayed HMAC signatures.");
1✔
183

184

185
    internal static readonly Counter<long> EndpointRequests = Meter.CreateCounter<long>(
1✔
186
        name: EndpointRequestsName,
1✔
187
        unit: "{request}",
1✔
188
        description: "Number of rate-limited endpoint requests resolved by HashGate.");
1✔
189

190

191
    internal static readonly Counter<long> RateLimitRejections = Meter.CreateCounter<long>(
1✔
192
        name: RateLimitRejectionsName,
1✔
193
        unit: "{rejection}",
1✔
194
        description: "Number of requests rejected by HashGate rate limiting.");
1✔
195

196
    internal static readonly Counter<long> RateLimitProviderLookups = Meter.CreateCounter<long>(
1✔
197
        name: RateLimitProviderLookupsName,
1✔
198
        unit: "{lookup}",
1✔
199
        description: "Number of per-client rate limit provider lookups.");
1✔
200

201
    internal static readonly Counter<long> RateLimitProviderMisses = Meter.CreateCounter<long>(
1✔
202
        name: RateLimitProviderMissesName,
1✔
203
        unit: "{miss}",
1✔
204
        description: "Number of per-client rate limit provider lookups that fell back to default limits.");
1✔
205

206

207
    internal static void RecordAuthentication(
208
        string scheme,
209
        string result,
210
        string? failureReason,
211
        long elapsedTicks,
212
        string? endpoint,
213
        string? client)
214
    {
215
        if (!AuthenticationRequests.Enabled &&
32!
216
            !AuthenticationFailures.Enabled &&
32✔
217
            !AuthenticationDuration.Enabled)
32✔
218
        {
219
            return;
32✔
220
        }
221

NEW
222
        TagList tags =
×
NEW
223
        [
×
NEW
224
            new(AuthenticationSchemeTagName, scheme),
×
NEW
225
            new(AuthenticationResultTagName, result)
×
NEW
226
        ];
×
227

NEW
228
        if (failureReason is not null)
×
NEW
229
            tags.Add(new(AuthenticationFailureReasonTagName, failureReason));
×
230

NEW
231
        if (!string.IsNullOrWhiteSpace(endpoint))
×
NEW
232
            tags.Add(new(EndpointTagName, endpoint));
×
233

NEW
234
        if (!string.IsNullOrWhiteSpace(client))
×
NEW
235
            tags.Add(new(ClientTagName, client));
×
236

NEW
237
        AuthenticationRequests.Add(1, in tags);
×
238

239
        if (failureReason is not null)
×
NEW
240
            AuthenticationFailures.Add(1, in tags);
×
241

242
        var elapsed = GetElapsedMilliseconds(elapsedTicks);
×
NEW
243
        AuthenticationDuration.Record(elapsed, in tags);
×
244
    }
×
245

246
    internal static void RecordReplayProtectionCheck(string result, double ttlMilliseconds)
247
    {
248
        if (!ReplayProtectionChecks.Enabled
21!
249
            && (result != "replay" || !ReplayProtectionReplays.Enabled))
21✔
250
        {
251
            return;
21✔
252
        }
253

NEW
254
        TagList tags =
×
255
        [
×
256
            new(ReplayProtectionResultTagName, result)
×
257
        ];
×
258

NEW
259
        ReplayProtectionChecks.Add(1, in tags);
×
260

261
        if (result == "replay")
×
NEW
262
            ReplayProtectionReplays.Add(1, in tags);
×
263
    }
×
264

265
    internal static void RecordEndpointRequest(string policy, string endpoint, string client)
266
    {
267
        if (!EndpointRequests.Enabled)
23!
268
            return;
23✔
269

NEW
270
        TagList tags =
×
271
        [
×
272
            new(RateLimitPolicyTagName, policy),
×
273
            new(EndpointTagName, endpoint),
×
274
            new(ClientTagName, client)
×
275
        ];
×
276

NEW
277
        EndpointRequests.Add(1, in tags);
×
278
    }
×
279

280
    internal static void RecordRateLimitRejection(string policy, double retryAfterMilliseconds)
281
    {
282
        if (!RateLimitRejections.Enabled)
5!
283
            return;
5✔
284

NEW
285
        TagList tags =
×
286
        [
×
287
            new(RateLimitPolicyTagName, policy)
×
288
        ];
×
289

NEW
290
        RateLimitRejections.Add(1, in tags);
×
291
    }
×
292

293
    internal static void RecordRateLimitProviderLookup(string policy, bool found)
294
    {
295
        if (!RateLimitProviderLookups.Enabled
23!
296
            && (found || !RateLimitProviderMisses.Enabled))
23✔
297
        {
298
            return;
23✔
299
        }
300

NEW
301
        TagList tags =
×
302
        [
×
303
            new(RateLimitPolicyTagName, policy),
×
304
            new(RateLimitProviderFoundTagName, found)
×
305
        ];
×
306

NEW
307
        RateLimitProviderLookups.Add(1, in tags);
×
308

309
        if (!found)
×
NEW
310
            RateLimitProviderMisses.Add(1, in tags);
×
311
    }
×
312

313
    private static double GetElapsedMilliseconds(long startTimestamp)
314
        => Stopwatch.GetElapsedTime(startTimestamp).TotalMilliseconds;
×
315
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc