Skip to main content

risingwave_stream/executor/monitor/
streaming_stats.rs

1// Copyright 2022 RisingWave Labs
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::sync::OnceLock;
16
17use prometheus::{
18    Histogram, IntCounter, IntGauge, Registry, exponential_buckets, histogram_opts,
19    register_histogram_with_registry, register_int_counter_with_registry,
20    register_int_gauge_with_registry,
21};
22use risingwave_common::catalog::TableId;
23use risingwave_common::config::MetricLevel;
24use risingwave_common::metrics::{
25    GaugeAggregation, IntGaugeVecRelabelExt, LabelGuardedHistogramVec, LabelGuardedIntCounter,
26    LabelGuardedIntCounterVec, LabelGuardedIntGaugeVec, MetricVecRelabelExt,
27    RelabeledAggregatedIntGauge, RelabeledAggregatedIntGaugeVec, RelabeledGuardedHistogramVec,
28    RelabeledGuardedIntCounterVec,
29};
30use risingwave_common::monitor::GLOBAL_METRICS_REGISTRY;
31use risingwave_common::monitor::in_mem::CountMap;
32use risingwave_common::{
33    register_guarded_histogram_vec_with_registry, register_guarded_int_counter_vec_with_registry,
34    register_guarded_int_gauge_vec_with_registry,
35};
36use risingwave_connector::sink::catalog::SinkId;
37use risingwave_pb::id::ExecutorId;
38
39use crate::common::log_store_impl::kv_log_store::{
40    REWIND_BACKOFF_MULTIPLIER, REWIND_INITIAL_DELAY, REWIND_MAX_DELAY,
41};
42use crate::executor::prelude::ActorId;
43use crate::task::FragmentId;
44
45#[derive(Clone)]
46pub struct StreamingMetrics {
47    pub level: MetricLevel,
48
49    // Executor metrics (disabled by default)
50    pub executor_row_count: RelabeledGuardedIntCounterVec,
51
52    // Profiling Metrics:
53    // Aggregated per operator rather than per actor.
54    // These are purely in-memory, never collected by prometheus.
55    pub mem_stream_node_output_row_count: CountMap<ExecutorId>,
56    pub mem_stream_node_output_blocking_duration_ns: CountMap<ExecutorId>,
57
58    // Streaming actor metrics from tokio (disabled by default)
59    actor_scheduled_duration: RelabeledGuardedIntCounterVec,
60    actor_scheduled_cnt: RelabeledGuardedIntCounterVec,
61    actor_poll_duration: RelabeledGuardedIntCounterVec,
62    actor_poll_cnt: RelabeledGuardedIntCounterVec,
63    actor_idle_duration: RelabeledGuardedIntCounterVec,
64    actor_idle_cnt: RelabeledGuardedIntCounterVec,
65
66    // Streaming actor
67    pub actor_count: LabelGuardedIntGaugeVec,
68    pub actor_in_record_cnt: RelabeledGuardedIntCounterVec,
69    pub actor_out_record_cnt: RelabeledGuardedIntCounterVec,
70    pub fragment_channel_buffered_bytes: LabelGuardedIntGaugeVec,
71    pub actor_current_epoch: RelabeledAggregatedIntGaugeVec,
72    pub project_expr_inflight_window_size: RelabeledAggregatedIntGaugeVec,
73
74    // Source
75    pub source_output_row_count: RelabeledGuardedIntCounterVec,
76    pub source_split_change_count: RelabeledGuardedIntCounterVec,
77    pub source_backfill_row_count: RelabeledGuardedIntCounterVec,
78
79    // Sink
80    sink_input_row_count: RelabeledGuardedIntCounterVec,
81    sink_input_bytes: RelabeledGuardedIntCounterVec,
82    sink_chunk_buffer_size: RelabeledAggregatedIntGaugeVec,
83
84    // Exchange (see also `compute::ExchangeServiceMetrics`)
85    pub exchange_frag_recv_size: LabelGuardedIntCounterVec,
86
87    // Streaming Merge (We breakout this metric from `barrier_align_duration` because
88    // the alignment happens on different levels)
89    pub merge_barrier_align_duration: RelabeledGuardedIntCounterVec,
90
91    // Backpressure
92    pub actor_output_buffer_blocking_duration_ns: RelabeledGuardedIntCounterVec,
93    actor_input_buffer_blocking_duration_ns: RelabeledGuardedIntCounterVec,
94
95    // Streaming Join
96    pub join_lookup_miss_count: RelabeledGuardedIntCounterVec,
97    pub join_lookup_total_count: RelabeledGuardedIntCounterVec,
98    pub join_insert_cache_miss_count: RelabeledGuardedIntCounterVec,
99    pub join_actor_input_waiting_duration_ns: RelabeledGuardedIntCounterVec,
100    pub join_match_duration_ns: RelabeledGuardedIntCounterVec,
101    pub join_cached_entry_count: RelabeledAggregatedIntGaugeVec,
102    pub join_matched_join_keys: RelabeledGuardedHistogramVec,
103
104    // Streaming Join, Streaming Dynamic Filter and Streaming Union
105    pub barrier_align_duration: RelabeledGuardedIntCounterVec,
106
107    // Streaming Aggregation
108    agg_lookup_miss_count: RelabeledGuardedIntCounterVec,
109    agg_total_lookup_count: RelabeledGuardedIntCounterVec,
110    agg_cached_entry_count: RelabeledAggregatedIntGaugeVec,
111    agg_chunk_lookup_miss_count: RelabeledGuardedIntCounterVec,
112    agg_chunk_total_lookup_count: RelabeledGuardedIntCounterVec,
113    agg_dirty_groups_count: RelabeledAggregatedIntGaugeVec,
114    agg_dirty_groups_heap_size: RelabeledAggregatedIntGaugeVec,
115    agg_distinct_cache_miss_count: RelabeledGuardedIntCounterVec,
116    agg_distinct_total_cache_count: RelabeledGuardedIntCounterVec,
117    agg_distinct_cached_entry_count: RelabeledAggregatedIntGaugeVec,
118    agg_state_cache_lookup_count: RelabeledGuardedIntCounterVec,
119    agg_state_cache_miss_count: RelabeledGuardedIntCounterVec,
120
121    // Streaming TopN
122    group_top_n_cache_miss_count: RelabeledGuardedIntCounterVec,
123    group_top_n_total_query_cache_count: RelabeledGuardedIntCounterVec,
124    group_top_n_cached_entry_count: RelabeledAggregatedIntGaugeVec,
125    // TODO(rc): why not just use the above three?
126    group_top_n_appendonly_cache_miss_count: RelabeledGuardedIntCounterVec,
127    group_top_n_appendonly_total_query_cache_count: RelabeledGuardedIntCounterVec,
128    group_top_n_appendonly_cached_entry_count: RelabeledAggregatedIntGaugeVec,
129
130    // Lookup executor
131    lookup_cache_miss_count: RelabeledGuardedIntCounterVec,
132    lookup_total_query_cache_count: RelabeledGuardedIntCounterVec,
133    lookup_cached_entry_count: RelabeledAggregatedIntGaugeVec,
134
135    // temporal join
136    temporal_join_cache_miss_count: RelabeledGuardedIntCounterVec,
137    temporal_join_total_query_cache_count: RelabeledGuardedIntCounterVec,
138    temporal_join_cached_entry_count: RelabeledAggregatedIntGaugeVec,
139
140    // Backfill
141    backfill_snapshot_read_row_count: RelabeledGuardedIntCounterVec,
142    backfill_upstream_output_row_count: RelabeledGuardedIntCounterVec,
143
144    // CDC Backfill
145    cdc_backfill_snapshot_read_row_count: RelabeledGuardedIntCounterVec,
146    cdc_backfill_upstream_output_row_count: RelabeledGuardedIntCounterVec,
147
148    // Snapshot Backfill
149    pub(crate) snapshot_backfill_consume_row_count: RelabeledGuardedIntCounterVec,
150
151    // Over Window
152    over_window_cached_entry_count: RelabeledAggregatedIntGaugeVec,
153    over_window_cache_lookup_count: RelabeledGuardedIntCounterVec,
154    over_window_cache_miss_count: RelabeledGuardedIntCounterVec,
155    over_window_range_cache_entry_count: RelabeledAggregatedIntGaugeVec,
156    over_window_range_cache_lookup_count: RelabeledGuardedIntCounterVec,
157    over_window_range_cache_left_miss_count: RelabeledGuardedIntCounterVec,
158    over_window_range_cache_right_miss_count: RelabeledGuardedIntCounterVec,
159    over_window_accessed_entry_count: RelabeledGuardedIntCounterVec,
160    over_window_compute_count: RelabeledGuardedIntCounterVec,
161    over_window_same_output_count: RelabeledGuardedIntCounterVec,
162    over_window_state_cleaned_row_count: RelabeledGuardedIntCounterVec,
163
164    // Match recognize
165    match_recognize_matches_emitted_count: RelabeledGuardedIntCounterVec,
166    match_recognize_evicted_rows_count: RelabeledGuardedIntCounterVec,
167    match_recognize_scan_budget_exhausted_count: RelabeledGuardedIntCounterVec,
168    match_recognize_within_deadline_overflow_count: RelabeledGuardedIntCounterVec,
169    match_recognize_retained_rows: RelabeledAggregatedIntGaugeVec,
170
171    /// The duration from receipt of barrier to all actors collection.
172    /// The max of all nodes' `barrier_inflight_latency` for a partial graph is the latency for a
173    /// barrier to flow through that partial graph.
174    pub barrier_inflight_latency: LabelGuardedHistogramVec,
175    /// The duration of sync to storage.
176    pub barrier_sync_latency: LabelGuardedHistogramVec,
177    pub barrier_batch_size: Histogram,
178    /// The progress made by the earliest in-flight barriers in the local barrier manager.
179    pub barrier_manager_progress: LabelGuardedIntCounterVec,
180
181    pub kv_log_store_storage_write_count: RelabeledGuardedIntCounterVec,
182    pub kv_log_store_storage_write_size: RelabeledGuardedIntCounterVec,
183    pub kv_log_store_rewind_count: RelabeledGuardedIntCounterVec,
184    pub kv_log_store_rewind_delay: RelabeledGuardedHistogramVec,
185    pub kv_log_store_storage_read_count: RelabeledGuardedIntCounterVec,
186    pub kv_log_store_storage_read_size: RelabeledGuardedIntCounterVec,
187    pub kv_log_store_buffer_unconsumed_item_count: RelabeledAggregatedIntGaugeVec,
188    pub kv_log_store_buffer_unconsumed_row_count: RelabeledAggregatedIntGaugeVec,
189    pub kv_log_store_buffer_unconsumed_epoch_count: RelabeledAggregatedIntGaugeVec,
190    pub kv_log_store_buffer_unconsumed_min_epoch: RelabeledAggregatedIntGaugeVec,
191    pub kv_log_store_buffer_memory_bytes: RelabeledAggregatedIntGaugeVec,
192
193    pub crossdb_last_consumed_min_epoch: RelabeledAggregatedIntGaugeVec,
194
195    pub sync_kv_log_store_read_count: RelabeledGuardedIntCounterVec,
196    pub sync_kv_log_store_read_size: RelabeledGuardedIntCounterVec,
197    pub sync_kv_log_store_write_pause_duration_ns: RelabeledGuardedIntCounterVec,
198    pub sync_kv_log_store_state: RelabeledGuardedIntCounterVec,
199    pub sync_kv_log_store_wait_next_poll_ns: RelabeledGuardedIntCounterVec,
200    pub sync_kv_log_store_storage_write_count: RelabeledGuardedIntCounterVec,
201    pub sync_kv_log_store_storage_write_size: RelabeledGuardedIntCounterVec,
202    pub sync_kv_log_store_buffer_unconsumed_item_count: RelabeledAggregatedIntGaugeVec,
203    pub sync_kv_log_store_buffer_unconsumed_row_count: RelabeledAggregatedIntGaugeVec,
204    pub sync_kv_log_store_buffer_unconsumed_epoch_count: RelabeledAggregatedIntGaugeVec,
205    pub sync_kv_log_store_buffer_unconsumed_min_epoch: RelabeledAggregatedIntGaugeVec,
206    pub sync_kv_log_store_buffer_memory_bytes: RelabeledAggregatedIntGaugeVec,
207
208    // Memory management
209    pub lru_runtime_loop_count: IntCounter,
210    pub lru_latest_sequence: IntGauge,
211    pub lru_watermark_sequence: IntGauge,
212    pub lru_eviction_policy: IntGauge,
213    pub jemalloc_allocated_bytes: IntGauge,
214    pub jemalloc_active_bytes: IntGauge,
215    pub jemalloc_resident_bytes: IntGauge,
216    pub jemalloc_metadata_bytes: IntGauge,
217    pub jvm_allocated_bytes: IntGauge,
218    pub jvm_active_bytes: IntGauge,
219    pub stream_memory_usage: RelabeledAggregatedIntGaugeVec,
220
221    // Materialized view
222    materialize_cache_hit_count: RelabeledGuardedIntCounterVec,
223    materialize_data_exist_count: RelabeledGuardedIntCounterVec,
224    materialize_cache_total_count: RelabeledGuardedIntCounterVec,
225    materialize_input_row_count: RelabeledGuardedIntCounterVec,
226    pub materialize_current_epoch: RelabeledAggregatedIntGaugeVec,
227
228    // PostgreSQL CDC LSN monitoring
229    pub pg_cdc_state_table_lsn: LabelGuardedIntGaugeVec,
230    pub pg_cdc_jni_commit_offset_lsn: LabelGuardedIntGaugeVec,
231
232    // MySQL CDC binlog monitoring
233    pub mysql_cdc_state_binlog_file_seq: LabelGuardedIntGaugeVec,
234    pub mysql_cdc_state_binlog_position: LabelGuardedIntGaugeVec,
235
236    // SQL Server CDC LSN monitoring
237    pub sqlserver_cdc_state_change_lsn: LabelGuardedIntGaugeVec,
238    pub sqlserver_cdc_state_commit_lsn: LabelGuardedIntGaugeVec,
239    pub sqlserver_cdc_jni_commit_offset_lsn: LabelGuardedIntGaugeVec,
240
241    // Gap Fill
242    pub gap_fill_generated_rows_count: RelabeledGuardedIntCounterVec,
243
244    // Now (temporal filter clock)
245    pub now_streaming_clock_ms: LabelGuardedIntGaugeVec,
246    pub now_wall_clock_drift_ms: LabelGuardedIntGaugeVec,
247
248    // State Table
249    pub state_table_iter_count: RelabeledGuardedIntCounterVec,
250    pub state_table_get_count: RelabeledGuardedIntCounterVec,
251    pub state_table_iter_vnode_pruned_count: RelabeledGuardedIntCounterVec,
252    pub state_table_get_vnode_pruned_count: RelabeledGuardedIntCounterVec,
253}
254
255pub static GLOBAL_STREAMING_METRICS: OnceLock<StreamingMetrics> = OnceLock::new();
256
257fn latency_buckets(max: f64, count: usize) -> Vec<f64> {
258    const MIN: f64 = 0.1;
259
260    assert!(count > 1);
261    let factor = (max / MIN).powf(1.0 / (count - 1) as f64);
262    let mut buckets = exponential_buckets(MIN, factor, count).unwrap();
263    *buckets.last_mut().unwrap() = max;
264    buckets
265}
266
267pub fn global_streaming_metrics(metric_level: MetricLevel) -> StreamingMetrics {
268    GLOBAL_STREAMING_METRICS
269        .get_or_init(|| StreamingMetrics::new(&GLOBAL_METRICS_REGISTRY, metric_level))
270        .clone()
271}
272
273impl StreamingMetrics {
274    pub fn new(registry: &Registry, level: MetricLevel) -> Self {
275        let executor_row_count = register_guarded_int_counter_vec_with_registry!(
276            "stream_executor_row_count",
277            "Total number of rows that have been output from each executor",
278            &["actor_id", "fragment_id", "executor_identity"],
279            registry
280        )
281        .unwrap()
282        .relabel_debug_1(level);
283
284        let stream_node_output_row_count = CountMap::new();
285        let stream_node_output_blocking_duration_ns = CountMap::new();
286
287        let source_output_row_count = register_guarded_int_counter_vec_with_registry!(
288            "stream_source_output_rows_counts",
289            "Total number of rows that have been output from source",
290            &["actor_id", "source_id", "source_name", "fragment_id"],
291            registry
292        )
293        .unwrap()
294        .relabel_debug_1(level);
295
296        let source_split_change_count = register_guarded_int_counter_vec_with_registry!(
297            "stream_source_split_change_event_count",
298            "Total number of split change events that have been operated by source",
299            &["actor_id", "source_id", "source_name", "fragment_id"],
300            registry
301        )
302        .unwrap()
303        .relabel_debug_1(level);
304
305        let source_backfill_row_count = register_guarded_int_counter_vec_with_registry!(
306            "stream_source_backfill_rows_counts",
307            "Total number of rows that have been backfilled for source",
308            &["actor_id", "source_id", "source_name", "fragment_id"],
309            registry
310        )
311        .unwrap()
312        .relabel_debug_1(level);
313
314        let sink_input_row_count = register_guarded_int_counter_vec_with_registry!(
315            "stream_sink_input_row_count",
316            "Total number of rows streamed into sink executors",
317            &["actor_id", "sink_id", "fragment_id"],
318            registry
319        )
320        .unwrap()
321        .relabel_debug_1(level);
322
323        let sink_input_bytes = register_guarded_int_counter_vec_with_registry!(
324            "stream_sink_input_bytes",
325            "Total size of chunks streamed into sink executors",
326            &["actor_id", "sink_id", "fragment_id"],
327            registry
328        )
329        .unwrap()
330        .relabel_debug_1(level);
331
332        let materialize_input_row_count = register_guarded_int_counter_vec_with_registry!(
333            "stream_mview_input_row_count",
334            "Total number of rows streamed into materialize executors",
335            &["actor_id", "table_id", "fragment_id"],
336            registry
337        )
338        .unwrap()
339        .relabel_debug_1(level);
340
341        let materialize_current_epoch = register_guarded_int_gauge_vec_with_registry!(
342            "stream_mview_current_epoch",
343            "The current epoch of the materialized executor",
344            &["actor_id", "table_id", "fragment_id"],
345            registry
346        )
347        .unwrap()
348        .relabel_debug_1_with_aggregation(level, GaugeAggregation::Min);
349
350        let pg_cdc_state_table_lsn = register_guarded_int_gauge_vec_with_registry!(
351            "stream_pg_cdc_state_table_lsn",
352            "Current LSN value stored in PostgreSQL CDC state table",
353            &["source_id"],
354            registry,
355        )
356        .unwrap();
357
358        let pg_cdc_jni_commit_offset_lsn = register_guarded_int_gauge_vec_with_registry!(
359            "stream_pg_cdc_jni_commit_offset_lsn",
360            "LSN value when JNI commit offset is called for PostgreSQL CDC",
361            &["source_id"],
362            registry,
363        )
364        .unwrap();
365
366        let mysql_cdc_state_binlog_file_seq = register_guarded_int_gauge_vec_with_registry!(
367            "stream_mysql_cdc_state_binlog_file_seq",
368            "Current binlog file sequence number stored in MySQL CDC state table",
369            &["source_id"],
370            registry,
371        )
372        .unwrap();
373
374        let mysql_cdc_state_binlog_position = register_guarded_int_gauge_vec_with_registry!(
375            "stream_mysql_cdc_state_binlog_position",
376            "Current binlog position stored in MySQL CDC state table",
377            &["source_id"],
378            registry,
379        )
380        .unwrap();
381
382        let sqlserver_cdc_state_change_lsn = register_guarded_int_gauge_vec_with_registry!(
383            "stream_sqlserver_cdc_state_change_lsn",
384            "Current change_lsn value stored in SQL Server CDC state table",
385            &["source_id"],
386            registry,
387        )
388        .unwrap();
389
390        let sqlserver_cdc_state_commit_lsn = register_guarded_int_gauge_vec_with_registry!(
391            "stream_sqlserver_cdc_state_commit_lsn",
392            "Current commit_lsn value stored in SQL Server CDC state table",
393            &["source_id"],
394            registry,
395        )
396        .unwrap();
397
398        let sqlserver_cdc_jni_commit_offset_lsn = register_guarded_int_gauge_vec_with_registry!(
399            "stream_sqlserver_cdc_jni_commit_offset_lsn",
400            "LSN value when JNI commit offset is called for SQL Server CDC",
401            &["source_id"],
402            registry,
403        )
404        .unwrap();
405
406        let sink_chunk_buffer_size = register_guarded_int_gauge_vec_with_registry!(
407            "stream_sink_chunk_buffer_size",
408            "Total size of chunks buffered in a barrier",
409            &["actor_id", "sink_id", "fragment_id"],
410            registry
411        )
412        .unwrap()
413        .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
414        let actor_output_buffer_blocking_duration_ns =
415            register_guarded_int_counter_vec_with_registry!(
416                "stream_actor_output_buffer_blocking_duration_ns",
417                "Total blocking duration (ns) of output buffer",
418                &["actor_id", "fragment_id", "downstream_fragment_id"],
419                registry
420            )
421            .unwrap()
422            // mask the first label `actor_id` if the level is less verbose than `Debug`
423            .relabel_debug_1(level);
424
425        let actor_input_buffer_blocking_duration_ns =
426            register_guarded_int_counter_vec_with_registry!(
427                "stream_actor_input_buffer_blocking_duration_ns",
428                "Total blocking duration (ns) of input buffer",
429                &["actor_id", "fragment_id", "upstream_fragment_id"],
430                registry
431            )
432            .unwrap()
433            // mask the first label `actor_id` if the level is less verbose than `Debug`
434            .relabel_debug_1(level);
435
436        let fragment_channel_buffered_bytes = register_guarded_int_gauge_vec_with_registry!(
437            "stream_fragment_channel_buffered_bytes",
438            "Estimated buffered bytes for actor channels by fragment",
439            &["fragment_id"],
440            registry
441        )
442        .unwrap();
443
444        let exchange_frag_recv_size = register_guarded_int_counter_vec_with_registry!(
445            "stream_exchange_frag_recv_size",
446            "Total size of messages that have been received from upstream Fragment",
447            &["up_fragment_id", "down_fragment_id"],
448            registry
449        )
450        .unwrap();
451
452        let actor_poll_duration = register_guarded_int_counter_vec_with_registry!(
453            "stream_actor_poll_duration",
454            "tokio's metrics",
455            &["actor_id", "fragment_id"],
456            registry
457        )
458        .unwrap()
459        .relabel_debug_1(level);
460
461        let actor_poll_cnt = register_guarded_int_counter_vec_with_registry!(
462            "stream_actor_poll_cnt",
463            "tokio's metrics",
464            &["actor_id", "fragment_id"],
465            registry
466        )
467        .unwrap()
468        .relabel_debug_1(level);
469
470        let actor_scheduled_duration = register_guarded_int_counter_vec_with_registry!(
471            "stream_actor_scheduled_duration",
472            "tokio's metrics",
473            &["actor_id", "fragment_id"],
474            registry
475        )
476        .unwrap()
477        .relabel_debug_1(level);
478
479        let actor_scheduled_cnt = register_guarded_int_counter_vec_with_registry!(
480            "stream_actor_scheduled_cnt",
481            "tokio's metrics",
482            &["actor_id", "fragment_id"],
483            registry
484        )
485        .unwrap()
486        .relabel_debug_1(level);
487
488        let actor_idle_duration = register_guarded_int_counter_vec_with_registry!(
489            "stream_actor_idle_duration",
490            "tokio's metrics",
491            &["actor_id", "fragment_id"],
492            registry
493        )
494        .unwrap()
495        .relabel_debug_1(level);
496
497        let actor_idle_cnt = register_guarded_int_counter_vec_with_registry!(
498            "stream_actor_idle_cnt",
499            "tokio's metrics",
500            &["actor_id", "fragment_id"],
501            registry
502        )
503        .unwrap()
504        .relabel_debug_1(level);
505
506        let actor_in_record_cnt = register_guarded_int_counter_vec_with_registry!(
507            "stream_actor_in_record_cnt",
508            "Total number of rows actor received",
509            &["actor_id", "fragment_id", "upstream_fragment_id"],
510            registry
511        )
512        .unwrap()
513        .relabel_debug_1(level);
514
515        let actor_out_record_cnt = register_guarded_int_counter_vec_with_registry!(
516            "stream_actor_out_record_cnt",
517            "Total number of rows actor sent",
518            &["actor_id", "fragment_id"],
519            registry
520        )
521        .unwrap()
522        .relabel_debug_1(level);
523
524        let actor_current_epoch = register_guarded_int_gauge_vec_with_registry!(
525            "stream_actor_current_epoch",
526            "Current epoch of actor",
527            &["actor_id", "fragment_id"],
528            registry
529        )
530        .unwrap()
531        .relabel_debug_1_with_aggregation(level, GaugeAggregation::Min);
532
533        let project_expr_inflight_window_size = register_guarded_int_gauge_vec_with_registry!(
534            "stream_project_expr_inflight_window_size",
535            "Number of messages waiting in ProjectExecutor's ordered projection window",
536            &["actor_id", "fragment_id"],
537            registry
538        )
539        .unwrap()
540        .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
541
542        let actor_count = register_guarded_int_gauge_vec_with_registry!(
543            "stream_actor_count",
544            "Total number of actors (parallelism)",
545            &["fragment_id"],
546            registry
547        )
548        .unwrap();
549
550        let merge_barrier_align_duration = register_guarded_int_counter_vec_with_registry!(
551            "stream_merge_barrier_align_duration_ns",
552            "Total merge barrier alignment duration (ns)",
553            &["actor_id", "fragment_id"],
554            registry
555        )
556        .unwrap()
557        .relabel_debug_1(level);
558
559        let join_lookup_miss_count = register_guarded_int_counter_vec_with_registry!(
560            "stream_join_lookup_miss_count",
561            "Join executor lookup miss duration",
562            &["actor_id", "side", "join_table_id", "fragment_id"],
563            registry
564        )
565        .unwrap()
566        .relabel_debug_1(level);
567
568        let join_lookup_total_count = register_guarded_int_counter_vec_with_registry!(
569            "stream_join_lookup_total_count",
570            "Join executor lookup total operation",
571            &["actor_id", "side", "join_table_id", "fragment_id"],
572            registry
573        )
574        .unwrap()
575        .relabel_debug_1(level);
576
577        let join_insert_cache_miss_count = register_guarded_int_counter_vec_with_registry!(
578            "stream_join_insert_cache_miss_count",
579            "Join executor cache miss when insert operation",
580            &["actor_id", "side", "join_table_id", "fragment_id"],
581            registry
582        )
583        .unwrap()
584        .relabel_debug_1(level);
585
586        let join_actor_input_waiting_duration_ns = register_guarded_int_counter_vec_with_registry!(
587            "stream_join_actor_input_waiting_duration_ns",
588            "Total waiting duration (ns) of input buffer of join actor",
589            &["actor_id", "fragment_id"],
590            registry
591        )
592        .unwrap()
593        .relabel_debug_1(level);
594
595        let join_match_duration_ns = register_guarded_int_counter_vec_with_registry!(
596            "stream_join_match_duration_ns",
597            "Matching duration for each side",
598            &["actor_id", "fragment_id", "side"],
599            registry
600        )
601        .unwrap()
602        .relabel_debug_1(level);
603
604        let barrier_align_duration = register_guarded_int_counter_vec_with_registry!(
605            "stream_barrier_align_duration_ns",
606            "Duration of join align barrier",
607            &["actor_id", "fragment_id", "wait_side", "executor"],
608            registry
609        )
610        .unwrap()
611        .relabel_debug_1(level);
612
613        let join_cached_entry_count = register_guarded_int_gauge_vec_with_registry!(
614            "stream_join_cached_entry_count",
615            "Number of cached entries in streaming join operators",
616            &["actor_id", "fragment_id", "side"],
617            registry
618        )
619        .unwrap()
620        .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
621
622        let join_matched_join_keys_opts = histogram_opts!(
623            "stream_join_matched_join_keys",
624            "The number of keys matched in the opposite side",
625            exponential_buckets(16.0, 2.0, 28).unwrap() // max 2^31
626        );
627
628        let join_matched_join_keys = register_guarded_histogram_vec_with_registry!(
629            join_matched_join_keys_opts,
630            &["actor_id", "fragment_id", "table_id"],
631            registry
632        )
633        .unwrap()
634        .relabel_debug_1(level);
635
636        let agg_lookup_miss_count = register_guarded_int_counter_vec_with_registry!(
637            "stream_agg_lookup_miss_count",
638            "Aggregation executor lookup miss duration",
639            &["actor_id", "table_id", "fragment_id"],
640            registry
641        )
642        .unwrap()
643        .relabel_debug_1(level);
644
645        let agg_total_lookup_count = register_guarded_int_counter_vec_with_registry!(
646            "stream_agg_lookup_total_count",
647            "Aggregation executor lookup total operation",
648            &["actor_id", "table_id", "fragment_id"],
649            registry
650        )
651        .unwrap()
652        .relabel_debug_1(level);
653
654        let agg_distinct_cache_miss_count = register_guarded_int_counter_vec_with_registry!(
655            "stream_agg_distinct_cache_miss_count",
656            "Aggregation executor dinsinct miss duration",
657            &["actor_id", "table_id", "fragment_id"],
658            registry
659        )
660        .unwrap()
661        .relabel_debug_1(level);
662
663        let agg_distinct_total_cache_count = register_guarded_int_counter_vec_with_registry!(
664            "stream_agg_distinct_total_cache_count",
665            "Aggregation executor distinct total operation",
666            &["actor_id", "table_id", "fragment_id"],
667            registry
668        )
669        .unwrap()
670        .relabel_debug_1(level);
671
672        let agg_distinct_cached_entry_count = register_guarded_int_gauge_vec_with_registry!(
673            "stream_agg_distinct_cached_entry_count",
674            "Total entry counts in distinct aggregation executor cache",
675            &["actor_id", "table_id", "fragment_id"],
676            registry
677        )
678        .unwrap()
679        .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
680
681        let agg_dirty_groups_count = register_guarded_int_gauge_vec_with_registry!(
682            "stream_agg_dirty_groups_count",
683            "Total dirty group counts in aggregation executor",
684            &["actor_id", "table_id", "fragment_id"],
685            registry
686        )
687        .unwrap()
688        .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
689
690        let agg_dirty_groups_heap_size = register_guarded_int_gauge_vec_with_registry!(
691            "stream_agg_dirty_groups_heap_size",
692            "Total dirty group heap size in aggregation executor",
693            &["actor_id", "table_id", "fragment_id"],
694            registry
695        )
696        .unwrap()
697        .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
698
699        let agg_state_cache_lookup_count = register_guarded_int_counter_vec_with_registry!(
700            "stream_agg_state_cache_lookup_count",
701            "Aggregation executor state cache lookup count",
702            &["actor_id", "table_id", "fragment_id"],
703            registry
704        )
705        .unwrap()
706        .relabel_debug_1(level);
707
708        let agg_state_cache_miss_count = register_guarded_int_counter_vec_with_registry!(
709            "stream_agg_state_cache_miss_count",
710            "Aggregation executor state cache miss count",
711            &["actor_id", "table_id", "fragment_id"],
712            registry
713        )
714        .unwrap()
715        .relabel_debug_1(level);
716
717        let group_top_n_cache_miss_count = register_guarded_int_counter_vec_with_registry!(
718            "stream_group_top_n_cache_miss_count",
719            "Group top n executor cache miss count",
720            &["actor_id", "table_id", "fragment_id"],
721            registry
722        )
723        .unwrap()
724        .relabel_debug_1(level);
725
726        let group_top_n_total_query_cache_count = register_guarded_int_counter_vec_with_registry!(
727            "stream_group_top_n_total_query_cache_count",
728            "Group top n executor query cache total count",
729            &["actor_id", "table_id", "fragment_id"],
730            registry
731        )
732        .unwrap()
733        .relabel_debug_1(level);
734
735        let group_top_n_cached_entry_count = register_guarded_int_gauge_vec_with_registry!(
736            "stream_group_top_n_cached_entry_count",
737            "Total entry counts in group top n executor cache",
738            &["actor_id", "table_id", "fragment_id"],
739            registry
740        )
741        .unwrap()
742        .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
743
744        let group_top_n_appendonly_cache_miss_count =
745            register_guarded_int_counter_vec_with_registry!(
746                "stream_group_top_n_appendonly_cache_miss_count",
747                "Group top n appendonly executor cache miss count",
748                &["actor_id", "table_id", "fragment_id"],
749                registry
750            )
751            .unwrap()
752            .relabel_debug_1(level);
753
754        let group_top_n_appendonly_total_query_cache_count =
755            register_guarded_int_counter_vec_with_registry!(
756                "stream_group_top_n_appendonly_total_query_cache_count",
757                "Group top n appendonly executor total cache count",
758                &["actor_id", "table_id", "fragment_id"],
759                registry
760            )
761            .unwrap()
762            .relabel_debug_1(level);
763
764        let group_top_n_appendonly_cached_entry_count =
765            register_guarded_int_gauge_vec_with_registry!(
766                "stream_group_top_n_appendonly_cached_entry_count",
767                "Total entry counts in group top n appendonly executor cache",
768                &["actor_id", "table_id", "fragment_id"],
769                registry
770            )
771            .unwrap()
772            .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
773
774        let lookup_cache_miss_count = register_guarded_int_counter_vec_with_registry!(
775            "stream_lookup_cache_miss_count",
776            "Lookup executor cache miss count",
777            &["actor_id", "table_id", "fragment_id"],
778            registry
779        )
780        .unwrap()
781        .relabel_debug_1(level);
782
783        let lookup_total_query_cache_count = register_guarded_int_counter_vec_with_registry!(
784            "stream_lookup_total_query_cache_count",
785            "Lookup executor query cache total count",
786            &["actor_id", "table_id", "fragment_id"],
787            registry
788        )
789        .unwrap()
790        .relabel_debug_1(level);
791
792        let lookup_cached_entry_count = register_guarded_int_gauge_vec_with_registry!(
793            "stream_lookup_cached_entry_count",
794            "Total entry counts in lookup executor cache",
795            &["actor_id", "table_id", "fragment_id"],
796            registry
797        )
798        .unwrap()
799        .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
800
801        let temporal_join_cache_miss_count = register_guarded_int_counter_vec_with_registry!(
802            "stream_temporal_join_cache_miss_count",
803            "Temporal join executor cache miss count",
804            &["actor_id", "table_id", "fragment_id"],
805            registry
806        )
807        .unwrap()
808        .relabel_debug_1(level);
809
810        let temporal_join_total_query_cache_count =
811            register_guarded_int_counter_vec_with_registry!(
812                "stream_temporal_join_total_query_cache_count",
813                "Temporal join executor query cache total count",
814                &["actor_id", "table_id", "fragment_id"],
815                registry
816            )
817            .unwrap()
818            .relabel_debug_1(level);
819
820        let temporal_join_cached_entry_count = register_guarded_int_gauge_vec_with_registry!(
821            "stream_temporal_join_cached_entry_count",
822            "Total entry count in temporal join executor cache",
823            &["actor_id", "table_id", "fragment_id"],
824            registry
825        )
826        .unwrap()
827        .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
828
829        let agg_cached_entry_count = register_guarded_int_gauge_vec_with_registry!(
830            "stream_agg_cached_entry_count",
831            "Number of cached keys in streaming aggregation operators",
832            &["actor_id", "table_id", "fragment_id"],
833            registry
834        )
835        .unwrap()
836        .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
837
838        let agg_chunk_lookup_miss_count = register_guarded_int_counter_vec_with_registry!(
839            "stream_agg_chunk_lookup_miss_count",
840            "Aggregation executor chunk-level lookup miss duration",
841            &["actor_id", "table_id", "fragment_id"],
842            registry
843        )
844        .unwrap()
845        .relabel_debug_1(level);
846
847        let agg_chunk_total_lookup_count = register_guarded_int_counter_vec_with_registry!(
848            "stream_agg_chunk_lookup_total_count",
849            "Aggregation executor chunk-level lookup total operation",
850            &["actor_id", "table_id", "fragment_id"],
851            registry
852        )
853        .unwrap()
854        .relabel_debug_1(level);
855
856        let backfill_snapshot_read_row_count = register_guarded_int_counter_vec_with_registry!(
857            "stream_backfill_snapshot_read_row_count",
858            "Total number of rows that have been read from the backfill snapshot",
859            &["actor_id", "table_id"],
860            registry
861        )
862        .unwrap()
863        .relabel_debug_1(level);
864
865        let backfill_upstream_output_row_count = register_guarded_int_counter_vec_with_registry!(
866            "stream_backfill_upstream_output_row_count",
867            "Total number of rows that have been output from the backfill upstream",
868            &["actor_id", "table_id"],
869            registry
870        )
871        .unwrap()
872        .relabel_debug_1(level);
873
874        let cdc_backfill_snapshot_read_row_count = register_guarded_int_counter_vec_with_registry!(
875            "stream_cdc_backfill_snapshot_read_row_count",
876            "Total number of rows that have been read from the cdc_backfill snapshot",
877            &["actor_id", "table_id"],
878            registry
879        )
880        .unwrap()
881        .relabel_debug_1(level);
882
883        let cdc_backfill_upstream_output_row_count =
884            register_guarded_int_counter_vec_with_registry!(
885                "stream_cdc_backfill_upstream_output_row_count",
886                "Total number of rows that have been output from the cdc_backfill upstream",
887                &["actor_id", "table_id"],
888                registry
889            )
890            .unwrap()
891            .relabel_debug_1(level);
892
893        let snapshot_backfill_consume_row_count = register_guarded_int_counter_vec_with_registry!(
894            "stream_snapshot_backfill_consume_snapshot_row_count",
895            "Total number of rows that have been output from snapshot backfill",
896            &["actor_id", "table_id", "stage"],
897            registry
898        )
899        .unwrap()
900        .relabel_debug_1(level);
901
902        let over_window_cached_entry_count = register_guarded_int_gauge_vec_with_registry!(
903            "stream_over_window_cached_entry_count",
904            "Total entry (partition) count in over window executor cache",
905            &["actor_id", "table_id", "fragment_id"],
906            registry
907        )
908        .unwrap()
909        .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
910
911        let over_window_cache_lookup_count = register_guarded_int_counter_vec_with_registry!(
912            "stream_over_window_cache_lookup_count",
913            "Over window executor cache lookup count",
914            &["actor_id", "table_id", "fragment_id"],
915            registry
916        )
917        .unwrap()
918        .relabel_debug_1(level);
919
920        let over_window_cache_miss_count = register_guarded_int_counter_vec_with_registry!(
921            "stream_over_window_cache_miss_count",
922            "Over window executor cache miss count",
923            &["actor_id", "table_id", "fragment_id"],
924            registry
925        )
926        .unwrap()
927        .relabel_debug_1(level);
928
929        let over_window_range_cache_entry_count = register_guarded_int_gauge_vec_with_registry!(
930            "stream_over_window_range_cache_entry_count",
931            "Over window partition range cache entry count",
932            &["actor_id", "table_id", "fragment_id"],
933            registry,
934        )
935        .unwrap()
936        .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
937
938        let over_window_range_cache_lookup_count = register_guarded_int_counter_vec_with_registry!(
939            "stream_over_window_range_cache_lookup_count",
940            "Over window partition range cache lookup count",
941            &["actor_id", "table_id", "fragment_id"],
942            registry
943        )
944        .unwrap()
945        .relabel_debug_1(level);
946
947        let over_window_range_cache_left_miss_count =
948            register_guarded_int_counter_vec_with_registry!(
949                "stream_over_window_range_cache_left_miss_count",
950                "Over window partition range cache left miss count",
951                &["actor_id", "table_id", "fragment_id"],
952                registry
953            )
954            .unwrap()
955            .relabel_debug_1(level);
956
957        let over_window_range_cache_right_miss_count =
958            register_guarded_int_counter_vec_with_registry!(
959                "stream_over_window_range_cache_right_miss_count",
960                "Over window partition range cache right miss count",
961                &["actor_id", "table_id", "fragment_id"],
962                registry
963            )
964            .unwrap()
965            .relabel_debug_1(level);
966
967        let over_window_accessed_entry_count = register_guarded_int_counter_vec_with_registry!(
968            "stream_over_window_accessed_entry_count",
969            "Over window accessed entry count",
970            &["actor_id", "table_id", "fragment_id"],
971            registry
972        )
973        .unwrap()
974        .relabel_debug_1(level);
975
976        let over_window_compute_count = register_guarded_int_counter_vec_with_registry!(
977            "stream_over_window_compute_count",
978            "Over window compute count",
979            &["actor_id", "table_id", "fragment_id"],
980            registry
981        )
982        .unwrap()
983        .relabel_debug_1(level);
984
985        let over_window_same_output_count = register_guarded_int_counter_vec_with_registry!(
986            "stream_over_window_same_output_count",
987            "Over window same output count",
988            &["actor_id", "table_id", "fragment_id"],
989            registry
990        )
991        .unwrap()
992        .relabel_debug_1(level);
993
994        let over_window_state_cleaned_row_count = register_guarded_int_counter_vec_with_registry!(
995            "stream_over_window_state_cleaned_row_count",
996            "Over window number of stale state rows deleted by watermark-driven state cleaning",
997            &["actor_id", "table_id", "fragment_id"],
998            registry
999        )
1000        .unwrap()
1001        .relabel_debug_1(level);
1002
1003        let match_recognize_matches_emitted_count =
1004            register_guarded_int_counter_vec_with_registry!(
1005                "stream_match_recognize_matches_emitted_count",
1006                "Matches emitted by the match recognize executor",
1007                &["actor_id", "table_id", "fragment_id"],
1008                registry
1009            )
1010            .unwrap()
1011            .relabel_debug_1(level);
1012
1013        let match_recognize_evicted_rows_count = register_guarded_int_counter_vec_with_registry!(
1014            "stream_match_recognize_evicted_rows_count",
1015            "Buffered rows evicted by the match recognize executor",
1016            &["actor_id", "table_id", "fragment_id"],
1017            registry
1018        )
1019        .unwrap()
1020        .relabel_debug_1(level);
1021
1022        let match_recognize_scan_budget_exhausted_count = register_guarded_int_counter_vec_with_registry!(
1023            "stream_match_recognize_scan_budget_exhausted_count",
1024            "Partition visits that exhausted the match recognize scan budget and degraded conservatively",
1025            &["actor_id", "table_id", "fragment_id"],
1026            registry
1027        )
1028        .unwrap()
1029        .relabel_debug_1(level);
1030
1031        let match_recognize_within_deadline_overflow_count = register_guarded_int_counter_vec_with_registry!(
1032            "stream_match_recognize_within_deadline_overflow_count",
1033            "Buffered rows whose WITHIN deadline lies past the ORDER BY type's range, so their window never closes",
1034            &["actor_id", "table_id", "fragment_id"],
1035            registry
1036        )
1037        .unwrap()
1038        .relabel_debug_1(level);
1039
1040        let match_recognize_retained_rows = register_guarded_int_gauge_vec_with_registry!(
1041            "stream_match_recognize_retained_rows",
1042            "Rows currently retained in memory by the match recognize executor, summed over the actor's partitions",
1043            &["actor_id", "table_id", "fragment_id"],
1044            registry
1045        )
1046        .unwrap()
1047        .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
1048
1049        let barrier_inflight_latency = register_guarded_histogram_vec_with_registry!(
1050            "stream_barrier_inflight_duration_seconds",
1051            "barrier_inflight_latency",
1052            &["partial_graph"],
1053            latency_buckets(600.0, 20),
1054            registry
1055        )
1056        .unwrap();
1057
1058        let barrier_sync_latency = register_guarded_histogram_vec_with_registry!(
1059            "stream_barrier_sync_storage_duration_seconds",
1060            "barrier_sync_latency",
1061            &["partial_graph"],
1062            latency_buckets(600.0, 20),
1063            registry
1064        )
1065        .unwrap();
1066
1067        let opts = histogram_opts!(
1068            "stream_barrier_batch_size",
1069            "barrier_batch_size",
1070            exponential_buckets(1.0, 2.0, 8).unwrap()
1071        );
1072        let barrier_batch_size = register_histogram_with_registry!(opts, registry).unwrap();
1073
1074        let barrier_manager_progress = register_guarded_int_counter_vec_with_registry!(
1075            "stream_barrier_manager_progress",
1076            "The number of actors that have processed the earliest in-flight barriers",
1077            &["partial_graph"],
1078            registry
1079        )
1080        .unwrap();
1081
1082        let sync_kv_log_store_wait_next_poll_ns = register_guarded_int_counter_vec_with_registry!(
1083            "sync_kv_log_store_wait_next_poll_ns",
1084            "Total duration (ns) of waiting for next poll",
1085            &["actor_id", "target", "fragment_id", "relation"],
1086            registry
1087        )
1088        .unwrap()
1089        .relabel_debug_1(level);
1090
1091        let sync_kv_log_store_read_count = register_guarded_int_counter_vec_with_registry!(
1092            "sync_kv_log_store_read_count",
1093            "read row count throughput of sync_kv log store",
1094            &["actor_id", "type", "target", "fragment_id", "relation"],
1095            registry
1096        )
1097        .unwrap()
1098        .relabel_debug_1(level);
1099
1100        let sync_kv_log_store_read_size = register_guarded_int_counter_vec_with_registry!(
1101            "sync_kv_log_store_read_size",
1102            "read size throughput of sync_kv log store",
1103            &["actor_id", "type", "target", "fragment_id", "relation"],
1104            registry
1105        )
1106        .unwrap()
1107        .relabel_debug_1(level);
1108
1109        let sync_kv_log_store_write_pause_duration_ns =
1110            register_guarded_int_counter_vec_with_registry!(
1111                "sync_kv_log_store_write_pause_duration_ns",
1112                "Duration (ns) of sync_kv log store write pause",
1113                &["actor_id", "target", "fragment_id", "relation"],
1114                registry
1115            )
1116            .unwrap()
1117            .relabel_debug_1(level);
1118
1119        let sync_kv_log_store_state = register_guarded_int_counter_vec_with_registry!(
1120            "sync_kv_log_store_state",
1121            "clean/unclean state transition for sync_kv log store",
1122            &["actor_id", "state", "target", "fragment_id", "relation"],
1123            registry
1124        )
1125        .unwrap()
1126        .relabel_debug_1(level);
1127
1128        let sync_kv_log_store_storage_write_count =
1129            register_guarded_int_counter_vec_with_registry!(
1130                "sync_kv_log_store_storage_write_count",
1131                "Write row count throughput of sync_kv log store",
1132                &["actor_id", "target", "fragment_id", "relation"],
1133                registry
1134            )
1135            .unwrap()
1136            .relabel_debug_1(level);
1137
1138        let sync_kv_log_store_storage_write_size = register_guarded_int_counter_vec_with_registry!(
1139            "sync_kv_log_store_storage_write_size",
1140            "Write size throughput of sync_kv log store",
1141            &["actor_id", "target", "fragment_id", "relation"],
1142            registry
1143        )
1144        .unwrap()
1145        .relabel_debug_1(level);
1146
1147        let sync_kv_log_store_buffer_unconsumed_item_count =
1148            register_guarded_int_gauge_vec_with_registry!(
1149                "sync_kv_log_store_buffer_unconsumed_item_count",
1150                "Number of Unconsumed Item in buffer",
1151                &["actor_id", "target", "fragment_id", "relation"],
1152                registry
1153            )
1154            .unwrap()
1155            .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
1156
1157        let sync_kv_log_store_buffer_unconsumed_row_count =
1158            register_guarded_int_gauge_vec_with_registry!(
1159                "sync_kv_log_store_buffer_unconsumed_row_count",
1160                "Number of Unconsumed Row in buffer",
1161                &["actor_id", "target", "fragment_id", "relation"],
1162                registry
1163            )
1164            .unwrap()
1165            .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
1166
1167        let sync_kv_log_store_buffer_unconsumed_epoch_count =
1168            register_guarded_int_gauge_vec_with_registry!(
1169                "sync_kv_log_store_buffer_unconsumed_epoch_count",
1170                "Number of Unconsumed Epoch in buffer",
1171                &["actor_id", "target", "fragment_id", "relation"],
1172                registry
1173            )
1174            .unwrap()
1175            .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
1176
1177        let sync_kv_log_store_buffer_unconsumed_min_epoch =
1178            register_guarded_int_gauge_vec_with_registry!(
1179                "sync_kv_log_store_buffer_unconsumed_min_epoch",
1180                "Number of Unconsumed Epoch in buffer",
1181                &["actor_id", "target", "fragment_id", "relation"],
1182                registry
1183            )
1184            .unwrap()
1185            .relabel_debug_1_with_aggregation(level, GaugeAggregation::Min);
1186        let sync_kv_log_store_buffer_memory_bytes =
1187            register_guarded_int_gauge_vec_with_registry!(
1188                "sync_kv_log_store_buffer_memory_bytes",
1189                "Estimated heap bytes used by synced kv log store buffer (unconsumed + consumed but not truncated)",
1190                &["actor_id", "target", "fragment_id", "relation"],
1191                registry
1192            )
1193            .unwrap()
1194            .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
1195
1196        let kv_log_store_storage_write_count = register_guarded_int_counter_vec_with_registry!(
1197            "kv_log_store_storage_write_count",
1198            "Write row count throughput of kv log store",
1199            &["actor_id", "connector", "sink_id", "sink_name"],
1200            registry
1201        )
1202        .unwrap()
1203        .relabel_debug_1(level);
1204
1205        let kv_log_store_storage_write_size = register_guarded_int_counter_vec_with_registry!(
1206            "kv_log_store_storage_write_size",
1207            "Write size throughput of kv log store",
1208            &["actor_id", "connector", "sink_id", "sink_name"],
1209            registry
1210        )
1211        .unwrap()
1212        .relabel_debug_1(level);
1213
1214        let kv_log_store_storage_read_count = register_guarded_int_counter_vec_with_registry!(
1215            "kv_log_store_storage_read_count",
1216            "Write row count throughput of kv log store",
1217            &["actor_id", "connector", "sink_id", "sink_name", "read_type"],
1218            registry
1219        )
1220        .unwrap()
1221        .relabel_debug_1(level);
1222
1223        let kv_log_store_storage_read_size = register_guarded_int_counter_vec_with_registry!(
1224            "kv_log_store_storage_read_size",
1225            "Write size throughput of kv log store",
1226            &["actor_id", "connector", "sink_id", "sink_name", "read_type"],
1227            registry
1228        )
1229        .unwrap()
1230        .relabel_debug_1(level);
1231
1232        let kv_log_store_rewind_count = register_guarded_int_counter_vec_with_registry!(
1233            "kv_log_store_rewind_count",
1234            "Kv log store rewind rate",
1235            &["actor_id", "connector", "sink_id", "sink_name"],
1236            registry
1237        )
1238        .unwrap()
1239        .relabel_debug_1(level);
1240
1241        let kv_log_store_rewind_delay_opts = {
1242            let first_delay_secs = REWIND_INITIAL_DELAY.as_secs_f64();
1243            let base = REWIND_BACKOFF_MULTIPLIER as f64;
1244            let bucket_count = (REWIND_MAX_DELAY.as_secs_f64() / first_delay_secs)
1245                .log(base)
1246                .ceil() as usize;
1247            let buckets = exponential_buckets(first_delay_secs, base, bucket_count).unwrap();
1248            histogram_opts!(
1249                "kv_log_store_rewind_delay",
1250                "Kv log store rewind delay",
1251                buckets,
1252            )
1253        };
1254
1255        let kv_log_store_rewind_delay = register_guarded_histogram_vec_with_registry!(
1256            kv_log_store_rewind_delay_opts,
1257            &["actor_id", "connector", "sink_id", "sink_name"],
1258            registry
1259        )
1260        .unwrap()
1261        .relabel_debug_1(level);
1262
1263        let kv_log_store_buffer_unconsumed_item_count =
1264            register_guarded_int_gauge_vec_with_registry!(
1265                "kv_log_store_buffer_unconsumed_item_count",
1266                "Number of Unconsumed Item in buffer",
1267                &["actor_id", "connector", "sink_id", "sink_name"],
1268                registry
1269            )
1270            .unwrap()
1271            .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
1272
1273        let kv_log_store_buffer_unconsumed_row_count =
1274            register_guarded_int_gauge_vec_with_registry!(
1275                "kv_log_store_buffer_unconsumed_row_count",
1276                "Number of Unconsumed Row in buffer",
1277                &["actor_id", "connector", "sink_id", "sink_name"],
1278                registry
1279            )
1280            .unwrap()
1281            .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
1282
1283        let kv_log_store_buffer_unconsumed_epoch_count =
1284            register_guarded_int_gauge_vec_with_registry!(
1285                "kv_log_store_buffer_unconsumed_epoch_count",
1286                "Number of Unconsumed Epoch in buffer",
1287                &["actor_id", "connector", "sink_id", "sink_name"],
1288                registry
1289            )
1290            .unwrap()
1291            .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
1292
1293        let kv_log_store_buffer_unconsumed_min_epoch =
1294            register_guarded_int_gauge_vec_with_registry!(
1295                "kv_log_store_buffer_unconsumed_min_epoch",
1296                "Number of Unconsumed Epoch in buffer",
1297                &["actor_id", "connector", "sink_id", "sink_name"],
1298                registry
1299            )
1300            .unwrap()
1301            .relabel_debug_1_with_aggregation(level, GaugeAggregation::Min);
1302
1303        let crossdb_last_consumed_min_epoch = register_guarded_int_gauge_vec_with_registry!(
1304            "crossdb_last_consumed_min_epoch",
1305            "Last consumed min epoch for cross-database changelog stream scan",
1306            &["actor_id", "table_id", "fragment_id"],
1307            registry
1308        )
1309        .unwrap()
1310        .relabel_debug_1_with_aggregation(level, GaugeAggregation::Min);
1311
1312        let kv_log_store_buffer_memory_bytes =
1313            register_guarded_int_gauge_vec_with_registry!(
1314                "kv_log_store_buffer_memory_bytes",
1315                "Estimated heap bytes used by kv log store buffer (unconsumed + consumed but not truncated)",
1316                &[
1317                    "actor_id",
1318                    "fragment_id",
1319                    "connector",
1320                    "sink_id",
1321                    "sink_name",
1322                ],
1323                registry
1324            )
1325            .unwrap()
1326            .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
1327
1328        let lru_runtime_loop_count = register_int_counter_with_registry!(
1329            "lru_runtime_loop_count",
1330            "The counts of the eviction loop in LRU manager per second",
1331            registry
1332        )
1333        .unwrap();
1334
1335        let lru_latest_sequence = register_int_gauge_with_registry!(
1336            "lru_latest_sequence",
1337            "Current LRU global sequence",
1338            registry,
1339        )
1340        .unwrap();
1341
1342        let lru_watermark_sequence = register_int_gauge_with_registry!(
1343            "lru_watermark_sequence",
1344            "Current LRU watermark sequence",
1345            registry,
1346        )
1347        .unwrap();
1348
1349        let lru_eviction_policy = register_int_gauge_with_registry!(
1350            "lru_eviction_policy",
1351            "Current LRU eviction policy",
1352            registry,
1353        )
1354        .unwrap();
1355
1356        let jemalloc_allocated_bytes = register_int_gauge_with_registry!(
1357            "jemalloc_allocated_bytes",
1358            "The allocated memory jemalloc, got from jemalloc_ctl",
1359            registry
1360        )
1361        .unwrap();
1362
1363        let jemalloc_active_bytes = register_int_gauge_with_registry!(
1364            "jemalloc_active_bytes",
1365            "The active memory jemalloc, got from jemalloc_ctl",
1366            registry
1367        )
1368        .unwrap();
1369
1370        let jemalloc_resident_bytes = register_int_gauge_with_registry!(
1371            "jemalloc_resident_bytes",
1372            "The active memory jemalloc, got from jemalloc_ctl",
1373            registry
1374        )
1375        .unwrap();
1376
1377        let jemalloc_metadata_bytes = register_int_gauge_with_registry!(
1378            "jemalloc_metadata_bytes",
1379            "The active memory jemalloc, got from jemalloc_ctl",
1380            registry
1381        )
1382        .unwrap();
1383
1384        let jvm_allocated_bytes = register_int_gauge_with_registry!(
1385            "jvm_allocated_bytes",
1386            "The allocated jvm memory",
1387            registry
1388        )
1389        .unwrap();
1390
1391        let jvm_active_bytes = register_int_gauge_with_registry!(
1392            "jvm_active_bytes",
1393            "The active jvm memory",
1394            registry
1395        )
1396        .unwrap();
1397
1398        let materialize_cache_hit_count = register_guarded_int_counter_vec_with_registry!(
1399            "stream_materialize_cache_hit_count",
1400            "Materialize executor cache hit count",
1401            &["actor_id", "table_id", "fragment_id"],
1402            registry
1403        )
1404        .unwrap()
1405        .relabel_debug_1(level);
1406
1407        let materialize_data_exist_count = register_guarded_int_counter_vec_with_registry!(
1408            "stream_materialize_data_exist_count",
1409            "Materialize executor data exist count",
1410            &["actor_id", "table_id", "fragment_id"],
1411            registry
1412        )
1413        .unwrap()
1414        .relabel_debug_1(level);
1415
1416        let materialize_cache_total_count = register_guarded_int_counter_vec_with_registry!(
1417            "stream_materialize_cache_total_count",
1418            "Materialize executor cache total operation",
1419            &["actor_id", "table_id", "fragment_id"],
1420            registry
1421        )
1422        .unwrap()
1423        .relabel_debug_1(level);
1424
1425        let stream_memory_usage = register_guarded_int_gauge_vec_with_registry!(
1426            "stream_memory_usage",
1427            "Memory usage for stream executors",
1428            &["actor_id", "table_id", "desc"],
1429            registry
1430        )
1431        .unwrap()
1432        .relabel_debug_1_with_aggregation(level, GaugeAggregation::Sum);
1433
1434        let gap_fill_generated_rows_count = register_guarded_int_counter_vec_with_registry!(
1435            "gap_fill_generated_rows_count",
1436            "Total number of rows generated by gap fill executor",
1437            &["actor_id", "fragment_id"],
1438            registry
1439        )
1440        .unwrap()
1441        .relabel_debug_1(level);
1442
1443        let state_table_iter_count = register_guarded_int_counter_vec_with_registry!(
1444            "state_table_iter_count",
1445            "Total number of state table iter operations",
1446            &["actor_id", "fragment_id", "table_id"],
1447            registry
1448        )
1449        .unwrap()
1450        .relabel_debug_1(level);
1451
1452        let state_table_get_count = register_guarded_int_counter_vec_with_registry!(
1453            "state_table_get_count",
1454            "Total number of state table get operations",
1455            &["actor_id", "fragment_id", "table_id"],
1456            registry
1457        )
1458        .unwrap()
1459        .relabel_debug_1(level);
1460
1461        let state_table_iter_vnode_pruned_count = register_guarded_int_counter_vec_with_registry!(
1462            "state_table_iter_vnode_pruned_count",
1463            "Total number of state table iter operations pruned by vnode statistics",
1464            &["actor_id", "fragment_id", "table_id"],
1465            registry
1466        )
1467        .unwrap()
1468        .relabel_debug_1(level);
1469
1470        let state_table_get_vnode_pruned_count = register_guarded_int_counter_vec_with_registry!(
1471            "state_table_get_vnode_pruned_count",
1472            "Total number of state table get operations pruned by vnode statistics",
1473            &["actor_id", "fragment_id", "table_id"],
1474            registry
1475        )
1476        .unwrap()
1477        .relabel_debug_1(level);
1478
1479        let now_streaming_clock_ms = register_guarded_int_gauge_vec_with_registry!(
1480            "stream_now_streaming_clock_ms",
1481            "Latest streaming NOW() timestamp (milliseconds since Unix epoch) \
1482             emitted as a watermark by this fragment on this compute node.",
1483            &["fragment_id"],
1484            registry,
1485        )
1486        .unwrap();
1487        let now_wall_clock_drift_ms = register_guarded_int_gauge_vec_with_registry!(
1488            "stream_now_wall_clock_drift_ms",
1489            "Latest processed barrier epoch minus the latest streaming NOW() timestamp \
1490             emitted as a watermark by this fragment on this compute node, \
1491             in milliseconds. This is relative to processed barriers, not scrape-time wall clock.",
1492            &["fragment_id"],
1493            registry,
1494        )
1495        .unwrap();
1496
1497        Self {
1498            level,
1499            executor_row_count,
1500            mem_stream_node_output_row_count: stream_node_output_row_count,
1501            mem_stream_node_output_blocking_duration_ns: stream_node_output_blocking_duration_ns,
1502            actor_scheduled_duration,
1503            actor_scheduled_cnt,
1504            actor_poll_duration,
1505            actor_poll_cnt,
1506            actor_idle_duration,
1507            actor_idle_cnt,
1508            actor_count,
1509            actor_in_record_cnt,
1510            actor_out_record_cnt,
1511            fragment_channel_buffered_bytes,
1512            actor_current_epoch,
1513            project_expr_inflight_window_size,
1514            source_output_row_count,
1515            source_split_change_count,
1516            source_backfill_row_count,
1517            sink_input_row_count,
1518            sink_input_bytes,
1519            sink_chunk_buffer_size,
1520            exchange_frag_recv_size,
1521            merge_barrier_align_duration,
1522            actor_output_buffer_blocking_duration_ns,
1523            actor_input_buffer_blocking_duration_ns,
1524            join_lookup_miss_count,
1525            join_lookup_total_count,
1526            join_insert_cache_miss_count,
1527            join_actor_input_waiting_duration_ns,
1528            join_match_duration_ns,
1529            join_cached_entry_count,
1530            join_matched_join_keys,
1531            barrier_align_duration,
1532            agg_lookup_miss_count,
1533            agg_total_lookup_count,
1534            agg_cached_entry_count,
1535            agg_chunk_lookup_miss_count,
1536            agg_chunk_total_lookup_count,
1537            agg_dirty_groups_count,
1538            agg_dirty_groups_heap_size,
1539            agg_distinct_cache_miss_count,
1540            agg_distinct_total_cache_count,
1541            agg_distinct_cached_entry_count,
1542            agg_state_cache_lookup_count,
1543            agg_state_cache_miss_count,
1544            group_top_n_cache_miss_count,
1545            group_top_n_total_query_cache_count,
1546            group_top_n_cached_entry_count,
1547            group_top_n_appendonly_cache_miss_count,
1548            group_top_n_appendonly_total_query_cache_count,
1549            group_top_n_appendonly_cached_entry_count,
1550            lookup_cache_miss_count,
1551            lookup_total_query_cache_count,
1552            lookup_cached_entry_count,
1553            temporal_join_cache_miss_count,
1554            temporal_join_total_query_cache_count,
1555            temporal_join_cached_entry_count,
1556            backfill_snapshot_read_row_count,
1557            backfill_upstream_output_row_count,
1558            cdc_backfill_snapshot_read_row_count,
1559            cdc_backfill_upstream_output_row_count,
1560            snapshot_backfill_consume_row_count,
1561            over_window_cached_entry_count,
1562            over_window_cache_lookup_count,
1563            over_window_cache_miss_count,
1564            over_window_range_cache_entry_count,
1565            over_window_range_cache_lookup_count,
1566            over_window_range_cache_left_miss_count,
1567            over_window_range_cache_right_miss_count,
1568            over_window_accessed_entry_count,
1569            over_window_compute_count,
1570            over_window_same_output_count,
1571            over_window_state_cleaned_row_count,
1572            match_recognize_matches_emitted_count,
1573            match_recognize_evicted_rows_count,
1574            match_recognize_scan_budget_exhausted_count,
1575            match_recognize_within_deadline_overflow_count,
1576            match_recognize_retained_rows,
1577            barrier_inflight_latency,
1578            barrier_sync_latency,
1579            barrier_batch_size,
1580            barrier_manager_progress,
1581            kv_log_store_storage_write_count,
1582            kv_log_store_storage_write_size,
1583            kv_log_store_rewind_count,
1584            kv_log_store_rewind_delay,
1585            kv_log_store_storage_read_count,
1586            kv_log_store_storage_read_size,
1587            kv_log_store_buffer_unconsumed_item_count,
1588            kv_log_store_buffer_unconsumed_row_count,
1589            kv_log_store_buffer_unconsumed_epoch_count,
1590            kv_log_store_buffer_unconsumed_min_epoch,
1591            kv_log_store_buffer_memory_bytes,
1592            crossdb_last_consumed_min_epoch,
1593            sync_kv_log_store_read_count,
1594            sync_kv_log_store_read_size,
1595            sync_kv_log_store_write_pause_duration_ns,
1596            sync_kv_log_store_state,
1597            sync_kv_log_store_wait_next_poll_ns,
1598            sync_kv_log_store_storage_write_count,
1599            sync_kv_log_store_storage_write_size,
1600            sync_kv_log_store_buffer_unconsumed_item_count,
1601            sync_kv_log_store_buffer_unconsumed_row_count,
1602            sync_kv_log_store_buffer_unconsumed_epoch_count,
1603            sync_kv_log_store_buffer_unconsumed_min_epoch,
1604            sync_kv_log_store_buffer_memory_bytes,
1605            lru_runtime_loop_count,
1606            lru_latest_sequence,
1607            lru_watermark_sequence,
1608            lru_eviction_policy,
1609            jemalloc_allocated_bytes,
1610            jemalloc_active_bytes,
1611            jemalloc_resident_bytes,
1612            jemalloc_metadata_bytes,
1613            jvm_allocated_bytes,
1614            jvm_active_bytes,
1615            stream_memory_usage,
1616            materialize_cache_hit_count,
1617            materialize_data_exist_count,
1618            materialize_cache_total_count,
1619            materialize_input_row_count,
1620            materialize_current_epoch,
1621            pg_cdc_state_table_lsn,
1622            pg_cdc_jni_commit_offset_lsn,
1623            mysql_cdc_state_binlog_file_seq,
1624            mysql_cdc_state_binlog_position,
1625            sqlserver_cdc_state_change_lsn,
1626            sqlserver_cdc_state_commit_lsn,
1627            sqlserver_cdc_jni_commit_offset_lsn,
1628            gap_fill_generated_rows_count,
1629            now_streaming_clock_ms,
1630            now_wall_clock_drift_ms,
1631            state_table_iter_count,
1632            state_table_get_count,
1633            state_table_iter_vnode_pruned_count,
1634            state_table_get_vnode_pruned_count,
1635        }
1636    }
1637
1638    /// Create a new `StreamingMetrics` instance used in tests or other places.
1639    pub fn unused() -> Self {
1640        global_streaming_metrics(MetricLevel::Disabled)
1641    }
1642
1643    pub fn new_actor_metrics(&self, actor_id: ActorId, fragment_id: FragmentId) -> ActorMetrics {
1644        let label_list: &[&str; 2] = &[&actor_id.to_string(), &fragment_id.to_string()];
1645        let actor_scheduled_duration = self
1646            .actor_scheduled_duration
1647            .with_guarded_label_values(label_list);
1648        let actor_scheduled_cnt = self
1649            .actor_scheduled_cnt
1650            .with_guarded_label_values(label_list);
1651        let actor_poll_duration = self
1652            .actor_poll_duration
1653            .with_guarded_label_values(label_list);
1654        let actor_poll_cnt = self.actor_poll_cnt.with_guarded_label_values(label_list);
1655        let actor_idle_duration = self
1656            .actor_idle_duration
1657            .with_guarded_label_values(label_list);
1658        let actor_idle_cnt = self.actor_idle_cnt.with_guarded_label_values(label_list);
1659        ActorMetrics {
1660            actor_scheduled_duration,
1661            actor_scheduled_cnt,
1662            actor_poll_duration,
1663            actor_poll_cnt,
1664            actor_idle_duration,
1665            actor_idle_cnt,
1666        }
1667    }
1668
1669    pub(crate) fn new_actor_input_metrics(
1670        &self,
1671        actor_id: ActorId,
1672        fragment_id: FragmentId,
1673        upstream_fragment_id: FragmentId,
1674    ) -> ActorInputMetrics {
1675        let actor_id_str = actor_id.to_string();
1676        let fragment_id_str = fragment_id.to_string();
1677        let upstream_fragment_id_str = upstream_fragment_id.to_string();
1678        ActorInputMetrics {
1679            actor_in_record_cnt: self.actor_in_record_cnt.with_guarded_label_values(&[
1680                &actor_id_str,
1681                &fragment_id_str,
1682                &upstream_fragment_id_str,
1683            ]),
1684            actor_input_buffer_blocking_duration_ns: self
1685                .actor_input_buffer_blocking_duration_ns
1686                .with_guarded_label_values(&[
1687                    &actor_id_str,
1688                    &fragment_id_str,
1689                    &upstream_fragment_id_str,
1690                ]),
1691        }
1692    }
1693
1694    pub fn new_sink_exec_metrics(
1695        &self,
1696        id: SinkId,
1697        actor_id: ActorId,
1698        fragment_id: FragmentId,
1699    ) -> SinkExecutorMetrics {
1700        let label_list: &[&str; 3] = &[
1701            &actor_id.to_string(),
1702            &id.to_string(),
1703            &fragment_id.to_string(),
1704        ];
1705        SinkExecutorMetrics {
1706            sink_input_row_count: self
1707                .sink_input_row_count
1708                .with_guarded_label_values(label_list),
1709            sink_input_bytes: self.sink_input_bytes.with_guarded_label_values(label_list),
1710            sink_chunk_buffer_size: self
1711                .sink_chunk_buffer_size
1712                .with_guarded_label_values(label_list),
1713        }
1714    }
1715
1716    pub fn new_group_top_n_metrics(
1717        &self,
1718        table_id: TableId,
1719        actor_id: ActorId,
1720        fragment_id: FragmentId,
1721    ) -> GroupTopNMetrics {
1722        let label_list: &[&str; 3] = &[
1723            &actor_id.to_string(),
1724            &table_id.to_string(),
1725            &fragment_id.to_string(),
1726        ];
1727
1728        GroupTopNMetrics {
1729            group_top_n_cache_miss_count: self
1730                .group_top_n_cache_miss_count
1731                .with_guarded_label_values(label_list),
1732            group_top_n_total_query_cache_count: self
1733                .group_top_n_total_query_cache_count
1734                .with_guarded_label_values(label_list),
1735            group_top_n_cached_entry_count: self
1736                .group_top_n_cached_entry_count
1737                .with_guarded_label_values(label_list),
1738        }
1739    }
1740
1741    pub fn new_append_only_group_top_n_metrics(
1742        &self,
1743        table_id: TableId,
1744        actor_id: ActorId,
1745        fragment_id: FragmentId,
1746    ) -> GroupTopNMetrics {
1747        let label_list: &[&str; 3] = &[
1748            &actor_id.to_string(),
1749            &table_id.to_string(),
1750            &fragment_id.to_string(),
1751        ];
1752
1753        GroupTopNMetrics {
1754            group_top_n_cache_miss_count: self
1755                .group_top_n_appendonly_cache_miss_count
1756                .with_guarded_label_values(label_list),
1757            group_top_n_total_query_cache_count: self
1758                .group_top_n_appendonly_total_query_cache_count
1759                .with_guarded_label_values(label_list),
1760            group_top_n_cached_entry_count: self
1761                .group_top_n_appendonly_cached_entry_count
1762                .with_guarded_label_values(label_list),
1763        }
1764    }
1765
1766    pub fn new_lookup_executor_metrics(
1767        &self,
1768        table_id: TableId,
1769        actor_id: ActorId,
1770        fragment_id: FragmentId,
1771    ) -> LookupExecutorMetrics {
1772        let label_list: &[&str; 3] = &[
1773            &actor_id.to_string(),
1774            &table_id.to_string(),
1775            &fragment_id.to_string(),
1776        ];
1777
1778        LookupExecutorMetrics {
1779            lookup_cache_miss_count: self
1780                .lookup_cache_miss_count
1781                .with_guarded_label_values(label_list),
1782            lookup_total_query_cache_count: self
1783                .lookup_total_query_cache_count
1784                .with_guarded_label_values(label_list),
1785            lookup_cached_entry_count: self
1786                .lookup_cached_entry_count
1787                .with_guarded_label_values(label_list),
1788        }
1789    }
1790
1791    pub fn new_hash_agg_metrics(
1792        &self,
1793        table_id: TableId,
1794        actor_id: ActorId,
1795        fragment_id: FragmentId,
1796    ) -> HashAggMetrics {
1797        let label_list: &[&str; 3] = &[
1798            &actor_id.to_string(),
1799            &table_id.to_string(),
1800            &fragment_id.to_string(),
1801        ];
1802        HashAggMetrics {
1803            agg_lookup_miss_count: self
1804                .agg_lookup_miss_count
1805                .with_guarded_label_values(label_list),
1806            agg_total_lookup_count: self
1807                .agg_total_lookup_count
1808                .with_guarded_label_values(label_list),
1809            agg_cached_entry_count: self
1810                .agg_cached_entry_count
1811                .with_guarded_label_values(label_list),
1812            agg_chunk_lookup_miss_count: self
1813                .agg_chunk_lookup_miss_count
1814                .with_guarded_label_values(label_list),
1815            agg_chunk_total_lookup_count: self
1816                .agg_chunk_total_lookup_count
1817                .with_guarded_label_values(label_list),
1818            agg_dirty_groups_count: self
1819                .agg_dirty_groups_count
1820                .with_guarded_label_values(label_list),
1821            agg_dirty_groups_heap_size: self
1822                .agg_dirty_groups_heap_size
1823                .with_guarded_label_values(label_list),
1824            agg_state_cache_lookup_count: self
1825                .agg_state_cache_lookup_count
1826                .with_guarded_label_values(label_list),
1827            agg_state_cache_miss_count: self
1828                .agg_state_cache_miss_count
1829                .with_guarded_label_values(label_list),
1830        }
1831    }
1832
1833    pub fn new_agg_distinct_dedup_metrics(
1834        &self,
1835        table_id: TableId,
1836        actor_id: ActorId,
1837        fragment_id: FragmentId,
1838    ) -> AggDistinctDedupMetrics {
1839        let label_list: &[&str; 3] = &[
1840            &actor_id.to_string(),
1841            &table_id.to_string(),
1842            &fragment_id.to_string(),
1843        ];
1844        AggDistinctDedupMetrics {
1845            agg_distinct_cache_miss_count: self
1846                .agg_distinct_cache_miss_count
1847                .with_guarded_label_values(label_list),
1848            agg_distinct_total_cache_count: self
1849                .agg_distinct_total_cache_count
1850                .with_guarded_label_values(label_list),
1851            agg_distinct_cached_entry_count: self
1852                .agg_distinct_cached_entry_count
1853                .with_guarded_label_values(label_list),
1854        }
1855    }
1856
1857    pub fn new_temporal_join_metrics(
1858        &self,
1859        table_id: TableId,
1860        actor_id: ActorId,
1861        fragment_id: FragmentId,
1862    ) -> TemporalJoinMetrics {
1863        let label_list: &[&str; 3] = &[
1864            &actor_id.to_string(),
1865            &table_id.to_string(),
1866            &fragment_id.to_string(),
1867        ];
1868        TemporalJoinMetrics {
1869            temporal_join_cache_miss_count: self
1870                .temporal_join_cache_miss_count
1871                .with_guarded_label_values(label_list),
1872            temporal_join_total_query_cache_count: self
1873                .temporal_join_total_query_cache_count
1874                .with_guarded_label_values(label_list),
1875            temporal_join_cached_entry_count: self
1876                .temporal_join_cached_entry_count
1877                .with_guarded_label_values(label_list),
1878        }
1879    }
1880
1881    pub fn new_backfill_metrics(&self, table_id: TableId, actor_id: ActorId) -> BackfillMetrics {
1882        let label_list: &[&str; 2] = &[&actor_id.to_string(), &table_id.to_string()];
1883        BackfillMetrics {
1884            backfill_snapshot_read_row_count: self
1885                .backfill_snapshot_read_row_count
1886                .with_guarded_label_values(label_list),
1887            backfill_upstream_output_row_count: self
1888                .backfill_upstream_output_row_count
1889                .with_guarded_label_values(label_list),
1890        }
1891    }
1892
1893    pub fn new_cdc_backfill_metrics(
1894        &self,
1895        table_id: TableId,
1896        actor_id: ActorId,
1897    ) -> CdcBackfillMetrics {
1898        let label_list: &[&str; 2] = &[&actor_id.to_string(), &table_id.to_string()];
1899        CdcBackfillMetrics {
1900            cdc_backfill_snapshot_read_row_count: self
1901                .cdc_backfill_snapshot_read_row_count
1902                .with_guarded_label_values(label_list),
1903            cdc_backfill_upstream_output_row_count: self
1904                .cdc_backfill_upstream_output_row_count
1905                .with_guarded_label_values(label_list),
1906        }
1907    }
1908
1909    pub fn new_over_window_metrics(
1910        &self,
1911        table_id: TableId,
1912        actor_id: ActorId,
1913        fragment_id: FragmentId,
1914    ) -> OverWindowMetrics {
1915        let label_list: &[&str; 3] = &[
1916            &actor_id.to_string(),
1917            &table_id.to_string(),
1918            &fragment_id.to_string(),
1919        ];
1920        OverWindowMetrics {
1921            over_window_cached_entry_count: self
1922                .over_window_cached_entry_count
1923                .with_guarded_label_values(label_list),
1924            over_window_cache_lookup_count: self
1925                .over_window_cache_lookup_count
1926                .with_guarded_label_values(label_list),
1927            over_window_cache_miss_count: self
1928                .over_window_cache_miss_count
1929                .with_guarded_label_values(label_list),
1930            over_window_range_cache_entry_count: self
1931                .over_window_range_cache_entry_count
1932                .with_guarded_label_values(label_list),
1933            over_window_range_cache_lookup_count: self
1934                .over_window_range_cache_lookup_count
1935                .with_guarded_label_values(label_list),
1936            over_window_range_cache_left_miss_count: self
1937                .over_window_range_cache_left_miss_count
1938                .with_guarded_label_values(label_list),
1939            over_window_range_cache_right_miss_count: self
1940                .over_window_range_cache_right_miss_count
1941                .with_guarded_label_values(label_list),
1942            over_window_accessed_entry_count: self
1943                .over_window_accessed_entry_count
1944                .with_guarded_label_values(label_list),
1945            over_window_compute_count: self
1946                .over_window_compute_count
1947                .with_guarded_label_values(label_list),
1948            over_window_same_output_count: self
1949                .over_window_same_output_count
1950                .with_guarded_label_values(label_list),
1951            over_window_state_cleaned_row_count: self
1952                .over_window_state_cleaned_row_count
1953                .with_guarded_label_values(label_list),
1954        }
1955    }
1956
1957    pub fn new_match_recognize_metrics(
1958        &self,
1959        table_id: TableId,
1960        actor_id: ActorId,
1961        fragment_id: FragmentId,
1962    ) -> MatchRecognizeMetrics {
1963        let label_list: &[&str; 3] = &[
1964            &actor_id.to_string(),
1965            &table_id.to_string(),
1966            &fragment_id.to_string(),
1967        ];
1968        MatchRecognizeMetrics {
1969            match_recognize_matches_emitted_count: self
1970                .match_recognize_matches_emitted_count
1971                .with_guarded_label_values(label_list),
1972            match_recognize_evicted_rows_count: self
1973                .match_recognize_evicted_rows_count
1974                .with_guarded_label_values(label_list),
1975            match_recognize_scan_budget_exhausted_count: self
1976                .match_recognize_scan_budget_exhausted_count
1977                .with_guarded_label_values(label_list),
1978            match_recognize_within_deadline_overflow_count: self
1979                .match_recognize_within_deadline_overflow_count
1980                .with_guarded_label_values(label_list),
1981            match_recognize_retained_rows: self
1982                .match_recognize_retained_rows
1983                .with_guarded_label_values(label_list),
1984        }
1985    }
1986
1987    pub fn new_materialize_cache_metrics(
1988        &self,
1989        table_id: TableId,
1990        actor_id: ActorId,
1991        fragment_id: FragmentId,
1992    ) -> MaterializeCacheMetrics {
1993        let label_list: &[&str; 3] = &[
1994            &actor_id.to_string(),
1995            &table_id.to_string(),
1996            &fragment_id.to_string(),
1997        ];
1998        MaterializeCacheMetrics {
1999            materialize_cache_hit_count: self
2000                .materialize_cache_hit_count
2001                .with_guarded_label_values(label_list),
2002            materialize_data_exist_count: self
2003                .materialize_data_exist_count
2004                .with_guarded_label_values(label_list),
2005            materialize_cache_total_count: self
2006                .materialize_cache_total_count
2007                .with_guarded_label_values(label_list),
2008        }
2009    }
2010
2011    pub fn new_materialize_metrics(
2012        &self,
2013        table_id: TableId,
2014        actor_id: ActorId,
2015        fragment_id: FragmentId,
2016    ) -> MaterializeMetrics {
2017        let label_list: &[&str; 3] = &[
2018            &actor_id.to_string(),
2019            &table_id.to_string(),
2020            &fragment_id.to_string(),
2021        ];
2022        MaterializeMetrics {
2023            materialize_input_row_count: self
2024                .materialize_input_row_count
2025                .with_guarded_label_values(label_list),
2026            materialize_current_epoch: self
2027                .materialize_current_epoch
2028                .with_guarded_label_values(label_list),
2029        }
2030    }
2031
2032    pub fn new_state_table_metrics(
2033        &self,
2034        table_id: TableId,
2035        actor_id: ActorId,
2036        fragment_id: FragmentId,
2037    ) -> StateTableMetrics {
2038        let label_list: &[&str; 3] = &[
2039            &actor_id.to_string(),
2040            &fragment_id.to_string(),
2041            &table_id.to_string(),
2042        ];
2043        StateTableMetrics {
2044            iter_count: self
2045                .state_table_iter_count
2046                .with_guarded_label_values(label_list),
2047            get_count: self
2048                .state_table_get_count
2049                .with_guarded_label_values(label_list),
2050            iter_vnode_pruned_count: self
2051                .state_table_iter_vnode_pruned_count
2052                .with_guarded_label_values(label_list),
2053            get_vnode_pruned_count: self
2054                .state_table_get_vnode_pruned_count
2055                .with_guarded_label_values(label_list),
2056        }
2057    }
2058}
2059
2060pub(crate) struct ActorInputMetrics {
2061    pub(crate) actor_in_record_cnt: LabelGuardedIntCounter,
2062    pub(crate) actor_input_buffer_blocking_duration_ns: LabelGuardedIntCounter,
2063}
2064
2065/// Tokio metrics for actors
2066pub struct ActorMetrics {
2067    pub actor_scheduled_duration: LabelGuardedIntCounter,
2068    pub actor_scheduled_cnt: LabelGuardedIntCounter,
2069    pub actor_poll_duration: LabelGuardedIntCounter,
2070    pub actor_poll_cnt: LabelGuardedIntCounter,
2071    pub actor_idle_duration: LabelGuardedIntCounter,
2072    pub actor_idle_cnt: LabelGuardedIntCounter,
2073}
2074
2075pub struct SinkExecutorMetrics {
2076    pub sink_input_row_count: LabelGuardedIntCounter,
2077    pub sink_input_bytes: LabelGuardedIntCounter,
2078    pub sink_chunk_buffer_size: RelabeledAggregatedIntGauge,
2079}
2080
2081pub struct MaterializeCacheMetrics {
2082    pub materialize_cache_hit_count: LabelGuardedIntCounter,
2083    pub materialize_data_exist_count: LabelGuardedIntCounter,
2084    pub materialize_cache_total_count: LabelGuardedIntCounter,
2085}
2086
2087pub struct MaterializeMetrics {
2088    pub materialize_input_row_count: LabelGuardedIntCounter,
2089    pub materialize_current_epoch: RelabeledAggregatedIntGauge,
2090}
2091
2092pub struct GroupTopNMetrics {
2093    pub group_top_n_cache_miss_count: LabelGuardedIntCounter,
2094    pub group_top_n_total_query_cache_count: LabelGuardedIntCounter,
2095    pub group_top_n_cached_entry_count: RelabeledAggregatedIntGauge,
2096}
2097
2098pub struct LookupExecutorMetrics {
2099    pub lookup_cache_miss_count: LabelGuardedIntCounter,
2100    pub lookup_total_query_cache_count: LabelGuardedIntCounter,
2101    pub lookup_cached_entry_count: RelabeledAggregatedIntGauge,
2102}
2103
2104pub struct HashAggMetrics {
2105    pub agg_lookup_miss_count: LabelGuardedIntCounter,
2106    pub agg_total_lookup_count: LabelGuardedIntCounter,
2107    pub agg_cached_entry_count: RelabeledAggregatedIntGauge,
2108    pub agg_chunk_lookup_miss_count: LabelGuardedIntCounter,
2109    pub agg_chunk_total_lookup_count: LabelGuardedIntCounter,
2110    pub agg_dirty_groups_count: RelabeledAggregatedIntGauge,
2111    pub agg_dirty_groups_heap_size: RelabeledAggregatedIntGauge,
2112    pub agg_state_cache_lookup_count: LabelGuardedIntCounter,
2113    pub agg_state_cache_miss_count: LabelGuardedIntCounter,
2114}
2115
2116pub struct AggDistinctDedupMetrics {
2117    pub agg_distinct_cache_miss_count: LabelGuardedIntCounter,
2118    pub agg_distinct_total_cache_count: LabelGuardedIntCounter,
2119    pub agg_distinct_cached_entry_count: RelabeledAggregatedIntGauge,
2120}
2121
2122pub struct TemporalJoinMetrics {
2123    pub temporal_join_cache_miss_count: LabelGuardedIntCounter,
2124    pub temporal_join_total_query_cache_count: LabelGuardedIntCounter,
2125    pub temporal_join_cached_entry_count: RelabeledAggregatedIntGauge,
2126}
2127
2128pub struct BackfillMetrics {
2129    pub backfill_snapshot_read_row_count: LabelGuardedIntCounter,
2130    pub backfill_upstream_output_row_count: LabelGuardedIntCounter,
2131}
2132
2133#[derive(Clone)]
2134pub struct CdcBackfillMetrics {
2135    pub cdc_backfill_snapshot_read_row_count: LabelGuardedIntCounter,
2136    pub cdc_backfill_upstream_output_row_count: LabelGuardedIntCounter,
2137}
2138
2139pub struct OverWindowMetrics {
2140    pub over_window_cached_entry_count: RelabeledAggregatedIntGauge,
2141    pub over_window_cache_lookup_count: LabelGuardedIntCounter,
2142    pub over_window_cache_miss_count: LabelGuardedIntCounter,
2143    pub over_window_range_cache_entry_count: RelabeledAggregatedIntGauge,
2144    pub over_window_range_cache_lookup_count: LabelGuardedIntCounter,
2145    pub over_window_range_cache_left_miss_count: LabelGuardedIntCounter,
2146    pub over_window_range_cache_right_miss_count: LabelGuardedIntCounter,
2147    pub over_window_accessed_entry_count: LabelGuardedIntCounter,
2148    pub over_window_compute_count: LabelGuardedIntCounter,
2149    pub over_window_same_output_count: LabelGuardedIntCounter,
2150    pub over_window_state_cleaned_row_count: LabelGuardedIntCounter,
2151}
2152
2153pub struct MatchRecognizeMetrics {
2154    pub match_recognize_matches_emitted_count: LabelGuardedIntCounter,
2155    pub match_recognize_evicted_rows_count: LabelGuardedIntCounter,
2156    pub match_recognize_scan_budget_exhausted_count: LabelGuardedIntCounter,
2157    pub match_recognize_within_deadline_overflow_count: LabelGuardedIntCounter,
2158    /// Rows currently retained in memory across the actor's partitions. Retention is bounded only
2159    /// by match liveness and `WITHIN`, so this gauge is the one signal of a partition set growing
2160    /// toward memory exhaustion (a pattern whose closer never arrives retains its rows forever).
2161    pub match_recognize_retained_rows: RelabeledAggregatedIntGauge,
2162}
2163
2164#[derive(Clone)]
2165pub struct StateTableMetrics {
2166    pub iter_count: LabelGuardedIntCounter,
2167    pub get_count: LabelGuardedIntCounter,
2168    pub iter_vnode_pruned_count: LabelGuardedIntCounter,
2169    pub get_vnode_pruned_count: LabelGuardedIntCounter,
2170}
2171
2172#[cfg(test)]
2173mod tests {
2174    use risingwave_common::metrics::get_label;
2175
2176    use super::*;
2177
2178    fn assert_aggregation(
2179        gauge_vec: &RelabeledAggregatedIntGaugeVec,
2180        first_labels: &[&str],
2181        second_labels: &[&str],
2182        expected: i64,
2183    ) {
2184        let first = gauge_vec.with_guarded_label_values(first_labels);
2185        let second = gauge_vec.with_guarded_label_values(second_labels);
2186        first.set(5);
2187        second.set(7);
2188        assert_eq!(first.get(), expected);
2189        assert_eq!(second.get(), expected);
2190    }
2191
2192    fn assert_min_ignores_absent(
2193        gauge_vec: &RelabeledAggregatedIntGaugeVec,
2194        empty_labels: &[&str],
2195        pending_labels: &[&str],
2196    ) {
2197        let empty = gauge_vec.with_guarded_label_values(empty_labels);
2198        let pending = gauge_vec.with_guarded_label_values(pending_labels);
2199        empty.set_optional(None);
2200        pending.set_optional(Some(100));
2201        assert_eq!(empty.get(), 100);
2202        assert_eq!(pending.get(), 100);
2203    }
2204
2205    fn assert_metric_labels(registry: &Registry, metric_name: &str, expected: &[(&str, &str)]) {
2206        let metric_family = registry
2207            .gather()
2208            .into_iter()
2209            .find(|family| family.name() == metric_name)
2210            .unwrap();
2211        let metric = metric_family.get_metric().first().unwrap();
2212        for (name, value) in expected {
2213            assert_eq!(get_label::<String>(metric, name).as_deref(), Some(*value));
2214        }
2215    }
2216
2217    fn record_reordered_metrics(
2218        metrics: &StreamingMetrics,
2219    ) -> (
2220        LabelGuardedIntCounter,
2221        SinkExecutorMetrics,
2222        HashAggMetrics,
2223        OverWindowMetrics,
2224        MatchRecognizeMetrics,
2225    ) {
2226        let source_output_row_count = metrics
2227            .source_output_row_count
2228            .with_guarded_label_values(&["11", "22", "source", "33"]);
2229        source_output_row_count.inc();
2230        let sink_metrics =
2231            metrics.new_sink_exec_metrics(SinkId::new(44), ActorId::new(11), FragmentId::new(33));
2232        sink_metrics.sink_input_row_count.inc();
2233        let agg_metrics =
2234            metrics.new_hash_agg_metrics(TableId::new(55), ActorId::new(11), FragmentId::new(33));
2235        agg_metrics.agg_lookup_miss_count.inc();
2236        let over_window_metrics = metrics.new_over_window_metrics(
2237            TableId::new(66),
2238            ActorId::new(11),
2239            FragmentId::new(33),
2240        );
2241        over_window_metrics
2242            .over_window_state_cleaned_row_count
2243            .inc();
2244        let match_recognize_metrics = metrics.new_match_recognize_metrics(
2245            TableId::new(77),
2246            ActorId::new(11),
2247            FragmentId::new(33),
2248        );
2249        match_recognize_metrics
2250            .match_recognize_matches_emitted_count
2251            .inc();
2252        match_recognize_metrics.match_recognize_retained_rows.set(1);
2253        (
2254            source_output_row_count,
2255            sink_metrics,
2256            agg_metrics,
2257            over_window_metrics,
2258            match_recognize_metrics,
2259        )
2260    }
2261
2262    #[test]
2263    fn info_and_critical_metrics_blank_actor_id_without_shifting_other_labels() {
2264        for level in [MetricLevel::Critical, MetricLevel::Info] {
2265            let registry = Registry::new();
2266            let metrics = StreamingMetrics::new(&registry, level);
2267            let _recorded_metrics = record_reordered_metrics(&metrics);
2268
2269            assert_metric_labels(
2270                &registry,
2271                "stream_source_output_rows_counts",
2272                &[
2273                    ("actor_id", ""),
2274                    ("source_id", "22"),
2275                    ("source_name", "source"),
2276                    ("fragment_id", "33"),
2277                ],
2278            );
2279            assert_metric_labels(
2280                &registry,
2281                "stream_sink_input_row_count",
2282                &[("actor_id", ""), ("sink_id", "44"), ("fragment_id", "33")],
2283            );
2284            assert_metric_labels(
2285                &registry,
2286                "stream_agg_lookup_miss_count",
2287                &[("actor_id", ""), ("table_id", "55"), ("fragment_id", "33")],
2288            );
2289            assert_metric_labels(
2290                &registry,
2291                "stream_over_window_state_cleaned_row_count",
2292                &[("actor_id", ""), ("table_id", "66"), ("fragment_id", "33")],
2293            );
2294            assert_metric_labels(
2295                &registry,
2296                "stream_match_recognize_matches_emitted_count",
2297                &[("actor_id", ""), ("table_id", "77"), ("fragment_id", "33")],
2298            );
2299            assert_metric_labels(
2300                &registry,
2301                "stream_match_recognize_retained_rows",
2302                &[("actor_id", ""), ("table_id", "77"), ("fragment_id", "33")],
2303            );
2304        }
2305    }
2306
2307    #[test]
2308    fn debug_metrics_retain_actor_id() {
2309        let registry = Registry::new();
2310        let metrics = StreamingMetrics::new(&registry, MetricLevel::Debug);
2311        let _recorded_metrics = record_reordered_metrics(&metrics);
2312
2313        assert_metric_labels(
2314            &registry,
2315            "stream_sink_input_row_count",
2316            &[("actor_id", "11"), ("sink_id", "44"), ("fragment_id", "33")],
2317        );
2318    }
2319
2320    #[test]
2321    fn actor_relabeled_gauges_use_the_assigned_reducers() {
2322        for level in [MetricLevel::Critical, MetricLevel::Info] {
2323            let registry = Registry::new();
2324            let metrics = StreamingMetrics::new(&registry, level);
2325
2326            assert_aggregation(
2327                &metrics.actor_current_epoch,
2328                &["1", "fragment"],
2329                &["2", "fragment"],
2330                5,
2331            );
2332            for gauge_vec in [
2333                &metrics.materialize_current_epoch,
2334                &metrics.crossdb_last_consumed_min_epoch,
2335            ] {
2336                assert_aggregation(
2337                    gauge_vec,
2338                    &["1", "table", "fragment"],
2339                    &["2", "table", "fragment"],
2340                    5,
2341                );
2342            }
2343            assert_aggregation(
2344                &metrics.kv_log_store_buffer_unconsumed_min_epoch,
2345                &["1", "connector", "sink", "name"],
2346                &["2", "connector", "sink", "name"],
2347                5,
2348            );
2349            assert_aggregation(
2350                &metrics.sync_kv_log_store_buffer_unconsumed_min_epoch,
2351                &["1", "target", "fragment", "relation"],
2352                &["2", "target", "fragment", "relation"],
2353                5,
2354            );
2355
2356            assert_aggregation(
2357                &metrics.project_expr_inflight_window_size,
2358                &["1", "fragment"],
2359                &["2", "fragment"],
2360                12,
2361            );
2362            assert_aggregation(
2363                &metrics.sink_chunk_buffer_size,
2364                &["1", "sink", "fragment"],
2365                &["2", "sink", "fragment"],
2366                12,
2367            );
2368            assert_aggregation(
2369                &metrics.join_cached_entry_count,
2370                &["1", "fragment", "side"],
2371                &["2", "fragment", "side"],
2372                12,
2373            );
2374            for gauge_vec in [
2375                &metrics.agg_cached_entry_count,
2376                &metrics.agg_dirty_groups_count,
2377                &metrics.agg_dirty_groups_heap_size,
2378                &metrics.agg_distinct_cached_entry_count,
2379                &metrics.group_top_n_appendonly_cached_entry_count,
2380                &metrics.group_top_n_cached_entry_count,
2381                &metrics.lookup_cached_entry_count,
2382                &metrics.match_recognize_retained_rows,
2383                &metrics.over_window_cached_entry_count,
2384                &metrics.over_window_range_cache_entry_count,
2385                &metrics.temporal_join_cached_entry_count,
2386            ] {
2387                assert_aggregation(
2388                    gauge_vec,
2389                    &["1", "table", "fragment"],
2390                    &["2", "table", "fragment"],
2391                    12,
2392                );
2393            }
2394            assert_aggregation(
2395                &metrics.stream_memory_usage,
2396                &["1", "table", "description"],
2397                &["2", "table", "description"],
2398                12,
2399            );
2400            assert_aggregation(
2401                &metrics.kv_log_store_buffer_memory_bytes,
2402                &["1", "fragment", "connector", "sink", "name"],
2403                &["2", "fragment", "connector", "sink", "name"],
2404                12,
2405            );
2406            for gauge_vec in [
2407                &metrics.kv_log_store_buffer_unconsumed_epoch_count,
2408                &metrics.kv_log_store_buffer_unconsumed_item_count,
2409                &metrics.kv_log_store_buffer_unconsumed_row_count,
2410            ] {
2411                assert_aggregation(
2412                    gauge_vec,
2413                    &["1", "connector", "sink", "name"],
2414                    &["2", "connector", "sink", "name"],
2415                    12,
2416                );
2417            }
2418            for gauge_vec in [
2419                &metrics.sync_kv_log_store_buffer_memory_bytes,
2420                &metrics.sync_kv_log_store_buffer_unconsumed_epoch_count,
2421                &metrics.sync_kv_log_store_buffer_unconsumed_item_count,
2422                &metrics.sync_kv_log_store_buffer_unconsumed_row_count,
2423            ] {
2424                assert_aggregation(
2425                    gauge_vec,
2426                    &["1", "target", "fragment", "relation"],
2427                    &["2", "target", "fragment", "relation"],
2428                    12,
2429                );
2430            }
2431        }
2432    }
2433
2434    #[test]
2435    fn empty_log_store_buffers_do_not_mask_pending_epochs() {
2436        for level in [MetricLevel::Critical, MetricLevel::Info] {
2437            let registry = Registry::new();
2438            let metrics = StreamingMetrics::new(&registry, level);
2439
2440            assert_min_ignores_absent(
2441                &metrics.kv_log_store_buffer_unconsumed_min_epoch,
2442                &["1", "connector", "sink", "name"],
2443                &["2", "connector", "sink", "name"],
2444            );
2445            assert_min_ignores_absent(
2446                &metrics.sync_kv_log_store_buffer_unconsumed_min_epoch,
2447                &["1", "target", "fragment", "relation"],
2448                &["2", "target", "fragment", "relation"],
2449            );
2450        }
2451    }
2452}