Skip to content

Commit 6bdc210

Browse files
authored
Adding back PrometheusHandler to avoid breaking change (kubernetes-client#1534)
1 parent 52c3c00 commit 6bdc210

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

src/KubernetesClient/KubernetesClient.csproj

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
</PropertyGroup>
1111

1212
<ItemGroup>
13+
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="7.0.0" />
1314
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.1.2" />
1415
<PackageReference Include="IdentityModel.OidcClient" Version="5.2.1" />
1516
<PackageReference Include="Fractions" Version="7.3.0" />
+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
using System.Diagnostics;
2+
using System.Diagnostics.Metrics;
3+
using System.Net.Http;
4+
5+
namespace k8s
6+
{
7+
/// <summary>
8+
/// Implements legacy Prometheus metrics
9+
/// </summary>
10+
/// <remarks>Provided for compatibility for existing usages of PrometheusHandler. It is recommended
11+
/// to transition to using OpenTelemetry and the default HttpClient metrics.
12+
///
13+
/// Note that the tags/labels are not appropriately named for some metrics. This
14+
/// incorrect naming is retained to maintain compatibility and won't be fixed on this implementation.
15+
/// Use OpenTelemetry and the standard HttpClient metrics instead.</remarks>
16+
public class PrometheusHandler : DelegatingHandler
17+
{
18+
private const string Prefix = "k8s_dotnet";
19+
private static readonly Meter Meter = new Meter("k8s.dotnet");
20+
21+
private static readonly Counter<int> RequestsSent = Meter.CreateCounter<int>(
22+
$"{Prefix}_request_total",
23+
description: "Number of requests sent by this client");
24+
25+
private static readonly Histogram<double> RequestLatency = Meter.CreateHistogram<double>(
26+
$"{Prefix}_request_latency_seconds", unit: "milliseconds",
27+
description: "Latency of requests sent by this client");
28+
29+
private static readonly Counter<int> ResponseCodes = Meter.CreateCounter<int>(
30+
$"{Prefix}_response_code_total",
31+
description: "Number of response codes received by the client");
32+
33+
private static readonly UpDownCounter<int> ActiveRequests =
34+
Meter.CreateUpDownCounter<int>(
35+
$"{Prefix}_active_requests",
36+
description: "Number of requests currently in progress");
37+
38+
/// <inheritdoc />
39+
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
40+
{
41+
if (request == null)
42+
{
43+
throw new ArgumentNullException(nameof(request));
44+
}
45+
46+
var digest = KubernetesRequestDigest.Parse(request);
47+
var timer = Stopwatch.StartNew();
48+
// Note that this is a tag called "method" but the value is the Verb.
49+
// This is incorrect, but existing behavior.
50+
var methodWithVerbValue = new KeyValuePair<string, object>("method", digest.Verb);
51+
try
52+
{
53+
ActiveRequests.Add(1, methodWithVerbValue);
54+
RequestsSent.Add(1, methodWithVerbValue);
55+
56+
var resp = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
57+
ResponseCodes.Add(
58+
1,
59+
new KeyValuePair<string, object>("method", request.Method.ToString()),
60+
new KeyValuePair<string, object>("code", (int)resp.StatusCode));
61+
return resp;
62+
}
63+
finally
64+
{
65+
timer.Stop();
66+
ActiveRequests.Add(-1, methodWithVerbValue);
67+
var tags = new TagList
68+
{
69+
{ "verb", digest.Verb },
70+
{ "group", digest.ApiGroup },
71+
{ "version", digest.ApiVersion },
72+
{ "kind", digest.Kind },
73+
}
74+
;
75+
RequestLatency.Record(timer.Elapsed.TotalMilliseconds, tags);
76+
}
77+
}
78+
}
79+
}

0 commit comments

Comments
 (0)