Restructure solution layout by module

This commit is contained in:
master
2025-10-28 15:10:40 +02:00
parent 95daa159c4
commit d870da18ce
4103 changed files with 192899 additions and 187024 deletions

View File

@@ -0,0 +1,107 @@
using System.Diagnostics;
using System.Diagnostics.Metrics;
using System.Net;
namespace StellaOps.Concelier.Connector.Common.Telemetry;
/// <summary>
/// Central telemetry instrumentation for connector HTTP operations.
/// </summary>
public static class SourceDiagnostics
{
public const string ActivitySourceName = "StellaOps.Concelier.Connector";
public const string MeterName = "StellaOps.Concelier.Connector";
private static readonly ActivitySource ActivitySource = new(ActivitySourceName);
private static readonly Meter Meter = new(MeterName);
private static readonly Counter<long> HttpRequestCounter = Meter.CreateCounter<long>("concelier.source.http.requests");
private static readonly Counter<long> HttpRetryCounter = Meter.CreateCounter<long>("concelier.source.http.retries");
private static readonly Counter<long> HttpFailureCounter = Meter.CreateCounter<long>("concelier.source.http.failures");
private static readonly Counter<long> HttpNotModifiedCounter = Meter.CreateCounter<long>("concelier.source.http.not_modified");
private static readonly Histogram<double> HttpDuration = Meter.CreateHistogram<double>("concelier.source.http.duration", unit: "ms");
private static readonly Histogram<long> HttpPayloadBytes = Meter.CreateHistogram<long>("concelier.source.http.payload_bytes", unit: "byte");
public static Activity? StartFetch(string sourceName, Uri requestUri, string httpMethod, string? clientName)
{
var tags = new ActivityTagsCollection
{
{ "concelier.source", sourceName },
{ "http.method", httpMethod },
{ "http.url", requestUri.ToString() },
};
if (!string.IsNullOrWhiteSpace(clientName))
{
tags.Add("http.client_name", clientName!);
}
return ActivitySource.StartActivity("SourceFetch", ActivityKind.Client, parentContext: default, tags: tags);
}
public static void RecordHttpRequest(string sourceName, string? clientName, HttpStatusCode statusCode, int attemptCount, TimeSpan duration, long? contentLength, string? rateLimitRemaining)
{
var tags = BuildDefaultTags(sourceName, clientName, statusCode, attemptCount);
HttpRequestCounter.Add(1, tags);
HttpDuration.Record(duration.TotalMilliseconds, tags);
if (contentLength.HasValue && contentLength.Value >= 0)
{
HttpPayloadBytes.Record(contentLength.Value, tags);
}
if (statusCode == HttpStatusCode.NotModified)
{
HttpNotModifiedCounter.Add(1, tags);
}
if ((int)statusCode >= 500 || statusCode == HttpStatusCode.TooManyRequests)
{
HttpFailureCounter.Add(1, tags);
}
if (!string.IsNullOrWhiteSpace(rateLimitRemaining) && long.TryParse(rateLimitRemaining, out var remaining))
{
tags.Add("http.rate_limit.remaining", remaining);
}
}
public static void RecordRetry(string sourceName, string? clientName, HttpStatusCode? statusCode, int attempt, TimeSpan delay)
{
var tags = new TagList
{
{ "concelier.source", sourceName },
{ "http.retry_attempt", attempt },
{ "http.retry_delay_ms", delay.TotalMilliseconds },
};
if (clientName is not null)
{
tags.Add("http.client_name", clientName);
}
if (statusCode.HasValue)
{
tags.Add("http.status_code", (int)statusCode.Value);
}
HttpRetryCounter.Add(1, tags);
}
private static TagList BuildDefaultTags(string sourceName, string? clientName, HttpStatusCode statusCode, int attemptCount)
{
var tags = new TagList
{
{ "concelier.source", sourceName },
{ "http.status_code", (int)statusCode },
{ "http.attempts", attemptCount },
};
if (clientName is not null)
{
tags.Add("http.client_name", clientName);
}
return tags;
}
}