|
12 | 12 | package com.automq.stream.s3.metrics;
|
13 | 13 |
|
14 | 14 | import com.automq.stream.s3.ByteBufAlloc;
|
| 15 | +import com.automq.stream.s3.backpressure.LoadLevel; |
15 | 16 | import com.automq.stream.s3.metrics.operations.S3ObjectStage;
|
16 | 17 | import com.automq.stream.s3.metrics.operations.S3Stage;
|
17 | 18 | import com.automq.stream.s3.metrics.wrapper.ConfigListener;
|
|
34 | 35 | import io.opentelemetry.api.common.Attributes;
|
35 | 36 | import io.opentelemetry.api.metrics.LongCounter;
|
36 | 37 | import io.opentelemetry.api.metrics.Meter;
|
| 38 | +import io.opentelemetry.api.metrics.ObservableDoubleGauge; |
37 | 39 | import io.opentelemetry.api.metrics.ObservableLongGauge;
|
38 | 40 |
|
39 | 41 | import static com.automq.stream.s3.metrics.S3StreamMetricsConstant.LABEL_CACHE_NAME;
|
@@ -139,10 +141,23 @@ public class S3StreamMetricsManager {
|
139 | 141 | private static final MultiAttributes<String> OPERATOR_INDEX_ATTRIBUTES = new MultiAttributes<>(Attributes.empty(),
|
140 | 142 | S3StreamMetricsConstant.LABEL_INDEX);
|
141 | 143 |
|
| 144 | + // Back Pressure |
| 145 | + private static final MultiAttributes<String> BACK_PRESSURE_STATE_ATTRIBUTES = new MultiAttributes<>(Attributes.empty(), |
| 146 | + S3StreamMetricsConstant.LABEL_BACK_PRESSURE_STATE); |
| 147 | + private static ObservableLongGauge backPressureState = new NoopObservableLongGauge(); |
| 148 | + private static Supplier<LoadLevel> backPressureStateSupplier = () -> LoadLevel.NORMAL; |
| 149 | + |
| 150 | + // Broker Quota |
| 151 | + private static final MultiAttributes<String> BROKER_QUOTA_TYPE_ATTRIBUTES = new MultiAttributes<>(Attributes.empty(), |
| 152 | + S3StreamMetricsConstant.LABEL_BROKER_QUOTA_TYPE); |
| 153 | + private static ObservableDoubleGauge brokerQuotaLimit = new NoopObservableDoubleGauge(); |
| 154 | + private static Supplier<Map<String, Double>> brokerQuotaLimitSupplier = () -> new ConcurrentHashMap<>(); |
142 | 155 |
|
143 | 156 | static {
|
144 | 157 | BASE_ATTRIBUTES_LISTENERS.add(ALLOC_TYPE_ATTRIBUTES);
|
145 | 158 | BASE_ATTRIBUTES_LISTENERS.add(OPERATOR_INDEX_ATTRIBUTES);
|
| 159 | + BASE_ATTRIBUTES_LISTENERS.add(BACK_PRESSURE_STATE_ATTRIBUTES); |
| 160 | + BASE_ATTRIBUTES_LISTENERS.add(BROKER_QUOTA_TYPE_ATTRIBUTES); |
146 | 161 | }
|
147 | 162 |
|
148 | 163 | public static void configure(MetricsConfig metricsConfig) {
|
@@ -400,6 +415,8 @@ public static void initMetrics(Meter meter, String prefix) {
|
400 | 415 | });
|
401 | 416 |
|
402 | 417 | initAsyncCacheMetrics(meter, prefix);
|
| 418 | + initBackPressureMetrics(meter, prefix); |
| 419 | + initBrokerQuotaMetrics(meter, prefix); |
403 | 420 | }
|
404 | 421 |
|
405 | 422 | private static void initAsyncCacheMetrics(Meter meter, String prefix) {
|
@@ -475,6 +492,43 @@ private static void initAsyncCacheMetrics(Meter meter, String prefix) {
|
475 | 492 | });
|
476 | 493 | }
|
477 | 494 |
|
| 495 | + private static void initBackPressureMetrics(Meter meter, String prefix) { |
| 496 | + backPressureState = meter.gaugeBuilder(prefix + S3StreamMetricsConstant.BACK_PRESSURE_STATE_METRIC_NAME) |
| 497 | + .setDescription("Back pressure state") |
| 498 | + .ofLongs() |
| 499 | + .buildWithCallback(result -> { |
| 500 | + if (MetricsLevel.INFO.isWithin(metricsConfig.getMetricsLevel())) { |
| 501 | + LoadLevel state = backPressureStateSupplier.get(); |
| 502 | + result.record(state.ordinal(), BACK_PRESSURE_STATE_ATTRIBUTES.get(state.name())); |
| 503 | + // To beautify Grafana dashboard, we record -1 for other states |
| 504 | + for (LoadLevel l : LoadLevel.values()) { |
| 505 | + if (l != state) { |
| 506 | + result.record(-1, BACK_PRESSURE_STATE_ATTRIBUTES.get(l.name())); |
| 507 | + } |
| 508 | + } |
| 509 | + } |
| 510 | + }); |
| 511 | + } |
| 512 | + |
| 513 | + private static void initBrokerQuotaMetrics(Meter meter, String prefix) { |
| 514 | + brokerQuotaLimit = meter.gaugeBuilder(prefix + S3StreamMetricsConstant.BROKER_QUOTA_LIMIT_METRIC_NAME) |
| 515 | + .setDescription("Broker quota limit") |
| 516 | + .buildWithCallback(result -> { |
| 517 | + if (MetricsLevel.INFO.isWithin(metricsConfig.getMetricsLevel())) { |
| 518 | + Map<String, Double> brokerQuotaLimitMap = brokerQuotaLimitSupplier.get(); |
| 519 | + for (Map.Entry<String, Double> entry : brokerQuotaLimitMap.entrySet()) { |
| 520 | + String quotaType = entry.getKey(); |
| 521 | + Double quotaLimit = entry.getValue(); |
| 522 | + // drop too large values |
| 523 | + if (quotaLimit > 1e15) { |
| 524 | + continue; |
| 525 | + } |
| 526 | + result.record(quotaLimit, BROKER_QUOTA_TYPE_ATTRIBUTES.get(quotaType)); |
| 527 | + } |
| 528 | + } |
| 529 | + }); |
| 530 | + } |
| 531 | + |
478 | 532 | public static void registerNetworkLimiterQueueSizeSupplier(AsyncNetworkBandwidthLimiter.Type type,
|
479 | 533 | Supplier<Integer> networkLimiterQueueSizeSupplier) {
|
480 | 534 | switch (type) {
|
@@ -907,4 +961,12 @@ public static void registerLocalStreamRangeIndexCacheSizeSupplier(Supplier<Integ
|
907 | 961 | public static void registerLocalStreamRangeIndexCacheStreamNumSupplier(Supplier<Integer> localStreamRangeIndexCacheStreamNum) {
|
908 | 962 | S3StreamMetricsManager.localStreamRangeIndexCacheStreamNum = localStreamRangeIndexCacheStreamNum;
|
909 | 963 | }
|
| 964 | + |
| 965 | + public static void registerBackPressureStateSupplier(Supplier<LoadLevel> backPressureStateSupplier) { |
| 966 | + S3StreamMetricsManager.backPressureStateSupplier = backPressureStateSupplier; |
| 967 | + } |
| 968 | + |
| 969 | + public static void registerBrokerQuotaLimitSupplier(Supplier<Map<String, Double>> brokerQuotaLimitSupplier) { |
| 970 | + S3StreamMetricsManager.brokerQuotaLimitSupplier = brokerQuotaLimitSupplier; |
| 971 | + } |
910 | 972 | }
|
0 commit comments