Skip to content

Commit

Permalink
Adding back PrometheusHandler to avoid breaking change (#1534)
Browse files Browse the repository at this point in the history
  • Loading branch information
rwkarg committed Mar 20, 2024
1 parent 52c3c00 commit 6bdc210
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/KubernetesClient/KubernetesClient.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="7.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.1.2" />
<PackageReference Include="IdentityModel.OidcClient" Version="5.2.1" />
<PackageReference Include="Fractions" Version="7.3.0" />
Expand Down
79 changes: 79 additions & 0 deletions src/KubernetesClient/PrometheusHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System.Diagnostics;
using System.Diagnostics.Metrics;
using System.Net.Http;

namespace k8s
{
/// <summary>
/// Implements legacy Prometheus metrics
/// </summary>
/// <remarks>Provided for compatibility for existing usages of PrometheusHandler. It is recommended
/// to transition to using OpenTelemetry and the default HttpClient metrics.
///
/// Note that the tags/labels are not appropriately named for some metrics. This
/// incorrect naming is retained to maintain compatibility and won't be fixed on this implementation.
/// Use OpenTelemetry and the standard HttpClient metrics instead.</remarks>
public class PrometheusHandler : DelegatingHandler
{
private const string Prefix = "k8s_dotnet";
private static readonly Meter Meter = new Meter("k8s.dotnet");

private static readonly Counter<int> RequestsSent = Meter.CreateCounter<int>(
$"{Prefix}_request_total",
description: "Number of requests sent by this client");

private static readonly Histogram<double> RequestLatency = Meter.CreateHistogram<double>(
$"{Prefix}_request_latency_seconds", unit: "milliseconds",
description: "Latency of requests sent by this client");

private static readonly Counter<int> ResponseCodes = Meter.CreateCounter<int>(
$"{Prefix}_response_code_total",
description: "Number of response codes received by the client");

private static readonly UpDownCounter<int> ActiveRequests =
Meter.CreateUpDownCounter<int>(
$"{Prefix}_active_requests",
description: "Number of requests currently in progress");

/// <inheritdoc />
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (request == null)
{
throw new ArgumentNullException(nameof(request));
}

var digest = KubernetesRequestDigest.Parse(request);
var timer = Stopwatch.StartNew();
// Note that this is a tag called "method" but the value is the Verb.
// This is incorrect, but existing behavior.
var methodWithVerbValue = new KeyValuePair<string, object>("method", digest.Verb);
try
{
ActiveRequests.Add(1, methodWithVerbValue);
RequestsSent.Add(1, methodWithVerbValue);

var resp = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
ResponseCodes.Add(
1,
new KeyValuePair<string, object>("method", request.Method.ToString()),
new KeyValuePair<string, object>("code", (int)resp.StatusCode));
return resp;
}
finally
{
timer.Stop();
ActiveRequests.Add(-1, methodWithVerbValue);
var tags = new TagList
{
{ "verb", digest.Verb },
{ "group", digest.ApiGroup },
{ "version", digest.ApiVersion },
{ "kind", digest.Kind },
}
;
RequestLatency.Record(timer.Elapsed.TotalMilliseconds, tags);
}
}
}
}

0 comments on commit 6bdc210

Please sign in to comment.