44using Microsoft . Extensions . DependencyInjection ;
55using Microsoft . Extensions . Diagnostics . HealthChecks ;
66using Microsoft . Extensions . Logging ;
7+ using System . Diagnostics ;
78using OpenTelemetry ;
89using OpenTelemetry . Metrics ;
910using OpenTelemetry . Resources ;
@@ -69,6 +70,8 @@ public static TBuilder ConfigureOpenTelemetry<TBuilder>(this TBuilder builder) w
6970 builder . Logging . SetMinimumLevel ( LogLevel . Information ) ;
7071 builder . Logging . AddFilter ( "Microsoft.EntityFrameworkCore.Database.Command" , LogLevel . Warning ) ;
7172 builder . Logging . AddFilter ( $ "System.Net.Http.HttpClient.{ MinioHealthCheckName } ", LogLevel . Warning ) ;
73+ builder . Logging . AddFilter ( "StackExchange.Redis" , LogLevel . Warning ) ;
74+ builder . Logging . AddFilter ( "Microsoft.Extensions.Caching.StackExchangeRedis" , LogLevel . Warning ) ;
7275 var aiConnectionString = builder . Configuration [ "APPLICATIONINSIGHTS_CONNECTION_STRING" ] ;
7376 var resourceName = builder . Configuration [ "RESOURCE_NAME" ] ?? builder . Environment . ApplicationName ;
7477 var resourceAttributes = new Dictionary < string , object > ( ) ;
@@ -116,6 +119,8 @@ public static TBuilder ConfigureOpenTelemetry<TBuilder>(this TBuilder builder) w
116119 } )
117120 . WithTracing ( tracing =>
118121 {
122+ // Drop noisy Redis PING and Postgres dependency spans.
123+ tracing . SetSampler ( new DependencyFilteringSampler ( ) ) ;
119124 tracing . AddSource ( builder . Environment . ApplicationName )
120125 . AddSource ( "NewsWorker" )
121126 . AddAspNetCoreInstrumentation ( tracing =>
@@ -142,6 +147,76 @@ public static TBuilder ConfigureOpenTelemetry<TBuilder>(this TBuilder builder) w
142147 return builder ;
143148 }
144149
150+ private sealed class DependencyFilteringSampler : Sampler
151+ {
152+ private static readonly Sampler FallbackSampler = new ParentBasedSampler ( new AlwaysOnSampler ( ) ) ;
153+
154+ public override SamplingResult ShouldSample ( in SamplingParameters parameters )
155+ {
156+ if ( IsRedisPing ( parameters ) || IsPostgresDependency ( parameters ) )
157+ {
158+ return new SamplingResult ( SamplingDecision . Drop ) ;
159+ }
160+
161+ return FallbackSampler . ShouldSample ( parameters ) ;
162+ }
163+
164+ private static bool IsRedisPing ( in SamplingParameters parameters )
165+ {
166+ if ( ! string . Equals ( parameters . Name , "PING" , StringComparison . OrdinalIgnoreCase ) )
167+ {
168+ return false ;
169+ }
170+
171+ if ( parameters . Kind != ActivityKind . Client )
172+ {
173+ return false ;
174+ }
175+
176+ foreach ( var tag in parameters . Tags )
177+ {
178+ if ( string . Equals ( tag . Key , "db.system" , StringComparison . OrdinalIgnoreCase )
179+ && string . Equals ( tag . Value ? . ToString ( ) , "redis" , StringComparison . OrdinalIgnoreCase ) )
180+ {
181+ return true ;
182+ }
183+
184+ if ( string . Equals ( tag . Key , "peer.service" , StringComparison . OrdinalIgnoreCase )
185+ && tag . Value ? . ToString ( ) ? . Contains ( "redis" , StringComparison . OrdinalIgnoreCase ) == true )
186+ {
187+ return true ;
188+ }
189+
190+ if ( string . Equals ( tag . Key , "net.peer.name" , StringComparison . OrdinalIgnoreCase )
191+ && tag . Value ? . ToString ( ) ? . Contains ( "redis" , StringComparison . OrdinalIgnoreCase ) == true )
192+ {
193+ return true ;
194+ }
195+ }
196+
197+ return true ;
198+ }
199+
200+ private static bool IsPostgresDependency ( in SamplingParameters parameters )
201+ {
202+ if ( parameters . Kind != ActivityKind . Client )
203+ {
204+ return false ;
205+ }
206+
207+ foreach ( var tag in parameters . Tags )
208+ {
209+ if ( string . Equals ( tag . Key , "db.system" , StringComparison . OrdinalIgnoreCase )
210+ && string . Equals ( tag . Value ? . ToString ( ) , "postgresql" , StringComparison . OrdinalIgnoreCase ) )
211+ {
212+ return true ;
213+ }
214+ }
215+
216+ return false ;
217+ }
218+ }
219+
145220 private static TBuilder AddOpenTelemetryExporters < TBuilder > ( this TBuilder builder ) where TBuilder : IHostApplicationBuilder
146221 {
147222 var useOtlpExporter = ! string . IsNullOrWhiteSpace ( builder . Configuration [ "OTEL_EXPORTER_OTLP_ENDPOINT" ] ) ;
@@ -214,9 +289,13 @@ private static bool IsMinioHealthCheckRequest(HttpRequestMessage request)
214289 {
215290 var uri = request . RequestUri ;
216291
217- return uri is not null
218- && string . Equals ( uri . Host , "wf-infra-minio" , StringComparison . OrdinalIgnoreCase )
219- && uri . AbsolutePath . StartsWith ( MinioHealthEndpointPrefix , StringComparison . OrdinalIgnoreCase ) ;
292+ return uri is not null && IsMinioHealthPath ( uri . AbsolutePath ) ;
293+ }
294+
295+ private static bool IsMinioHealthPath ( string ? path )
296+ {
297+ return ! string . IsNullOrWhiteSpace ( path )
298+ && path . StartsWith ( MinioHealthEndpointPrefix , StringComparison . OrdinalIgnoreCase ) ;
220299 }
221300
222301 private sealed class MinioHealthCheck ( IConfiguration configuration , IHttpClientFactory httpClientFactory ) : IHealthCheck
@@ -240,6 +319,7 @@ public async Task<HealthCheckResult> CheckHealthAsync(
240319 var healthUri = new Uri ( endpoint , path ) ;
241320 try
242321 {
322+ using var suppressScope = SuppressInstrumentationScope . Begin ( ) ;
243323 using var response = await httpClient . GetAsync ( healthUri , cancellationToken ) ;
244324 if ( response . StatusCode != System . Net . HttpStatusCode . OK )
245325 {
0 commit comments