|
5 | 5 | import com.linkedin.davinci.storage.DiskHealthCheckService; |
6 | 6 | import com.linkedin.venice.stats.dimensions.VeniceMetricsDimensions; |
7 | 7 | import com.linkedin.venice.stats.metrics.AsyncMetricEntityStateBase; |
| 8 | +import com.linkedin.venice.stats.metrics.TehutiMetricNameEnum; |
8 | 9 | import io.opentelemetry.api.common.Attributes; |
9 | 10 | import io.tehuti.metrics.MetricsRepository; |
10 | 11 | import io.tehuti.metrics.stats.AsyncGauge; |
| 12 | +import java.util.Collections; |
11 | 13 | import java.util.Map; |
12 | 14 | import java.util.function.LongSupplier; |
13 | 15 |
|
|
16 | 18 | * {@code DiskHealthStats} measures the disk health conditions based on the periodic tests ran by |
17 | 19 | * the {@link DiskHealthCheckService}. Reports 1 if healthy, 0 if unhealthy. |
18 | 20 | * |
19 | | - * <p>Tehuti and OTel both poll the same {@link DiskHealthCheckService#isDiskHealthy()} method. |
20 | | - * They cannot share a single registration because Tehuti uses {@link AsyncGauge} (polled by |
21 | | - * Tehuti's async executor) while OTel uses {@link AsyncMetricEntityStateBase} (polled by the |
22 | | - * OTel SDK's PeriodicMetricReader). |
| 21 | + * <p>Uses the joint Tehuti+OTel API: a single {@link AsyncMetricEntityStateBase} registration |
| 22 | + * binds both the Tehuti {@link AsyncGauge} and the OTel ASYNC_GAUGE to the same |
| 23 | + * {@link DiskHealthCheckService#isDiskHealthy()} callback. |
23 | 24 | */ |
24 | 25 | public class DiskHealthStats extends AbstractVeniceStats { |
| 26 | + /** Tehuti metric name for the disk health sensor. */ |
| 27 | + enum TehutiMetricName implements TehutiMetricNameEnum { |
| 28 | + DISK_HEALTHY |
| 29 | + } |
| 30 | + |
25 | 31 | public DiskHealthStats( |
26 | 32 | MetricsRepository metricsRepository, |
27 | 33 | DiskHealthCheckService diskHealthCheckService, |
28 | 34 | String name, |
29 | 35 | String clusterName) { |
30 | 36 | super(metricsRepository, name); |
31 | 37 |
|
32 | | - // Shared callback: 1 = healthy, 0 = unhealthy |
33 | | - LongSupplier healthCallback = () -> diskHealthCheckService.isDiskHealthy() ? 1 : 0; |
34 | | - |
35 | | - // Tehuti: AsyncGauge |
36 | | - registerSensor(new AsyncGauge((ignored, ignored2) -> healthCallback.getAsLong(), "disk_healthy")); |
37 | | - |
38 | | - // OTel: ASYNC_GAUGE with CLUSTER_NAME |
39 | 38 | OpenTelemetryMetricsSetup.OpenTelemetryMetricsSetupInfo otelData = |
40 | 39 | OpenTelemetryMetricsSetup.builder(metricsRepository).setClusterName(clusterName).build(); |
41 | 40 | Map<VeniceMetricsDimensions, String> baseDimensionsMap = otelData.getBaseDimensionsMap(); |
42 | 41 | Attributes baseAttributes = otelData.getBaseAttributes(); |
| 42 | + |
| 43 | + LongSupplier healthCallback = () -> diskHealthCheckService.isDiskHealthy() ? 1 : 0; |
43 | 44 | AsyncMetricEntityStateBase.create( |
44 | 45 | DISK_HEALTH_STATUS.getMetricEntity(), |
45 | 46 | otelData.getOtelRepository(), |
| 47 | + this::registerSensorIfAbsent, |
| 48 | + TehutiMetricName.DISK_HEALTHY, |
| 49 | + Collections.singletonList( |
| 50 | + new AsyncGauge((ig, ig2) -> healthCallback.getAsLong(), TehutiMetricName.DISK_HEALTHY.getMetricName())), |
46 | 51 | baseDimensionsMap, |
47 | 52 | baseAttributes, |
48 | 53 | healthCallback); |
|
0 commit comments