Skip to main content

risingwave_storage/monitor/
compactor_metrics.rs

1// Copyright 2023 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::LazyLock;
16
17use prometheus::core::{AtomicU64, GenericCounter, GenericCounterVec};
18use prometheus::{
19    Histogram, HistogramVec, IntGauge, Registry, exponential_buckets, histogram_opts,
20    register_histogram_vec_with_registry, register_histogram_with_registry,
21    register_int_counter_vec_with_registry, register_int_counter_with_registry,
22    register_int_gauge_with_registry,
23};
24use risingwave_common::monitor::GLOBAL_METRICS_REGISTRY;
25
26#[derive(Debug, Clone)]
27pub struct CompactorMetrics {
28    pub compaction_upload_sst_counts: GenericCounter<AtomicU64>,
29    pub compact_fast_runner_bytes: GenericCounter<AtomicU64>,
30    pub compact_write_bytes: GenericCounterVec<AtomicU64>,
31    pub compact_read_current_level: GenericCounterVec<AtomicU64>,
32    pub compact_read_next_level: GenericCounterVec<AtomicU64>,
33    pub compact_read_sstn_current_level: GenericCounterVec<AtomicU64>,
34    pub compact_read_sstn_next_level: GenericCounterVec<AtomicU64>,
35    pub compact_write_sstn: GenericCounterVec<AtomicU64>,
36    pub compact_sst_duration: Histogram,
37    pub compact_task_duration: HistogramVec,
38    pub compact_task_pending_num: IntGauge,
39    pub compact_task_pending_parallelism: IntGauge,
40    pub write_build_l0_sst_duration: Histogram,
41    pub shared_buffer_to_sstable_size: Histogram,
42    pub get_table_id_total_time_duration: Histogram,
43    pub remote_read_time: Histogram,
44    pub sstable_bloom_filter_size: Histogram,
45    pub sstable_file_size: Histogram,
46    pub sstable_avg_key_size: Histogram,
47    pub sstable_avg_value_size: Histogram,
48    pub iter_scan_key_counts: GenericCounterVec<AtomicU64>,
49    pub write_build_l0_bytes: GenericCounter<AtomicU64>,
50    pub sstable_distinct_epoch_count: Histogram,
51    pub compaction_event_consumed_latency: Histogram,
52    pub compaction_event_loop_iteration_latency: Histogram,
53    pub sstable_block_size: Histogram,
54    pub iceberg_compaction_memory_budget_bytes: IntGauge,
55    pub iceberg_compaction_running_memory_reservation_bytes: IntGauge,
56}
57
58pub static GLOBAL_COMPACTOR_METRICS: LazyLock<CompactorMetrics> =
59    LazyLock::new(|| CompactorMetrics::new(&GLOBAL_METRICS_REGISTRY));
60
61impl CompactorMetrics {
62    fn new(registry: &Registry) -> Self {
63        // 256B - 4GB, finer resolution near 256MB (adds two extra buckets)
64        let size_buckets = exponential_buckets(256.0, 8.0, 9).unwrap();
65        // 10ms - 2.7h
66        let time_buckets = exponential_buckets(0.01, 10.0, 7).unwrap();
67        let opts = histogram_opts!(
68            "compactor_shared_buffer_to_sstable_size",
69            "Histogram of batch size compacted from shared buffer to remote storage",
70            size_buckets.clone()
71        );
72        let shared_buffer_to_sstable_size =
73            register_histogram_with_registry!(opts, registry).unwrap();
74
75        let compaction_upload_sst_counts = register_int_counter_with_registry!(
76            "compactor_compaction_upload_sst_counts",
77            "Total number of sst uploads during compaction",
78            registry
79        )
80        .unwrap();
81
82        let opts = histogram_opts!(
83            "compactor_compact_sst_duration",
84            "Total time of compact_key_range that have been issued to state store",
85            time_buckets.clone()
86        );
87        let compact_sst_duration = register_histogram_with_registry!(opts, registry).unwrap();
88        let opts = histogram_opts!(
89            "compactor_compact_task_duration",
90            "Total time of compact that have been issued to state store",
91            time_buckets.clone()
92        );
93        let compact_task_duration =
94            register_histogram_vec_with_registry!(opts, &["group", "level"], registry).unwrap();
95
96        let opts = histogram_opts!(
97            "compactor_get_table_id_total_time_duration",
98            "Total time of compact that have been issued to state store",
99            time_buckets.clone()
100        );
101        let get_table_id_total_time_duration =
102            register_histogram_with_registry!(opts, registry).unwrap();
103
104        let opts = histogram_opts!(
105            "compactor_remote_read_time",
106            "Total time of operations which read from remote storage when enable prefetch",
107            time_buckets.clone()
108        );
109        let remote_read_time = register_histogram_with_registry!(opts, registry).unwrap();
110
111        let compact_read_current_level = register_int_counter_vec_with_registry!(
112            "storage_level_compact_read_curr",
113            "KBs read from current level during history compactions to next level",
114            &["group", "level_index"],
115            registry
116        )
117        .unwrap();
118
119        let compact_read_next_level = register_int_counter_vec_with_registry!(
120            "storage_level_compact_read_next",
121            "KBs read from next level during history compactions to next level",
122            &["group", "level_index"],
123            registry
124        )
125        .unwrap();
126
127        let compact_write_bytes = register_int_counter_vec_with_registry!(
128            "storage_level_compact_write",
129            "KBs written into next level during history compactions to next level",
130            &["group", "level_index"],
131            registry
132        )
133        .unwrap();
134
135        let compact_read_sstn_current_level = register_int_counter_vec_with_registry!(
136            "storage_level_compact_read_sstn_curr",
137            "num of SSTs read from current level during history compactions to next level",
138            &["group", "level_index"],
139            registry
140        )
141        .unwrap();
142
143        let compact_read_sstn_next_level = register_int_counter_vec_with_registry!(
144            "storage_level_compact_read_sstn_next",
145            "num of SSTs read from next level during history compactions to next level",
146            &["group", "level_index"],
147            registry
148        )
149        .unwrap();
150
151        let compact_write_sstn = register_int_counter_vec_with_registry!(
152            "storage_level_compact_write_sstn",
153            "num of SSTs written into next level during history compactions to next level",
154            &["group", "level_index"],
155            registry
156        )
157        .unwrap();
158
159        let compact_task_pending_num = register_int_gauge_with_registry!(
160            "storage_compact_task_pending_num",
161            "the num of storage compact task",
162            registry
163        )
164        .unwrap();
165
166        let compact_task_pending_parallelism = register_int_gauge_with_registry!(
167            "storage_compact_task_pending_parallelism",
168            "the num of storage compact parallelism",
169            registry
170        )
171        .unwrap();
172
173        let opts = histogram_opts!(
174            "compactor_sstable_bloom_filter_size",
175            "Total bytes gotten from the SST filter payload, for observing filter size",
176            exponential_buckets(16.0, 16.0, 7).unwrap() // max 256MB
177        );
178
179        let sstable_bloom_filter_size = register_histogram_with_registry!(opts, registry).unwrap();
180
181        let opts = histogram_opts!(
182            "compactor_sstable_file_size",
183            "Total bytes gotten from sstable_file_size, for observing sstable_file_size",
184            size_buckets.clone()
185        );
186
187        let sstable_file_size = register_histogram_with_registry!(opts, registry).unwrap();
188
189        let opts = histogram_opts!(
190            "compactor_sstable_avg_key_size",
191            "Total bytes gotten from sstable_avg_key_size, for observing sstable_avg_key_size",
192            size_buckets.clone()
193        );
194
195        let sstable_avg_key_size = register_histogram_with_registry!(opts, registry).unwrap();
196
197        let opts = histogram_opts!(
198            "compactor_sstable_avg_value_size",
199            "Total bytes gotten from sstable_avg_value_size, for observing sstable_avg_value_size",
200            size_buckets.clone()
201        );
202
203        let sstable_avg_value_size = register_histogram_with_registry!(opts, registry).unwrap();
204
205        let opts = histogram_opts!(
206            "state_store_write_build_l0_sst_duration",
207            "Total time of batch_write_build_table that have been issued to state store",
208            time_buckets.clone()
209        );
210        let write_build_l0_sst_duration =
211            register_histogram_with_registry!(opts, registry).unwrap();
212
213        let iter_scan_key_counts = register_int_counter_vec_with_registry!(
214            "compactor_iter_scan_key_counts",
215            "Total number of keys read by iterator",
216            &["type"],
217            registry
218        )
219        .unwrap();
220
221        let write_build_l0_bytes = register_int_counter_with_registry!(
222            "compactor_write_build_l0_bytes",
223            "Total size of compaction files size that have been written to object store from shared buffer",
224            registry
225        ).unwrap();
226        let compact_fast_runner_bytes = register_int_counter_with_registry!(
227            "compactor_fast_compact_bytes",
228            "Total size of compaction files size of fast compactor runner",
229            registry
230        )
231        .unwrap();
232        let opts = histogram_opts!(
233            "compactor_sstable_distinct_epoch_count",
234            "Total number gotten from sstable_distinct_epoch_count, for observing sstable_distinct_epoch_count",
235            exponential_buckets(1.0, 10.0, 6).unwrap()
236        );
237
238        let sstable_distinct_epoch_count =
239            register_histogram_with_registry!(opts, registry).unwrap();
240
241        let opts = histogram_opts!(
242            "compactor_compaction_event_consumed_latency",
243            "The latency of each event being consumed",
244            time_buckets.clone()
245        );
246        let compaction_event_consumed_latency =
247            register_histogram_with_registry!(opts, registry).unwrap();
248
249        let opts = histogram_opts!(
250            "compactor_compaction_event_loop_iteration_latency",
251            "The latency of each iteration of the compaction event loop",
252            time_buckets
253        );
254        let compaction_event_loop_iteration_latency =
255            register_histogram_with_registry!(opts, registry).unwrap();
256
257        let opts = histogram_opts!(
258            "compactor_sstable_block_size",
259            "Total bytes gotten from sstable_block_size, for observing sstable_block_size",
260            size_buckets,
261        );
262
263        let sstable_block_size = register_histogram_with_registry!(opts, registry).unwrap();
264
265        let iceberg_compaction_memory_budget_bytes = register_int_gauge_with_registry!(
266            "storage_iceberg_compaction_memory_budget_bytes",
267            "Heap admission budget for running Iceberg compaction plans on this compactor node",
268            registry
269        )
270        .unwrap();
271        let iceberg_compaction_running_memory_reservation_bytes =
272            register_int_gauge_with_registry!(
273                "storage_iceberg_compaction_running_memory_reservation_bytes",
274                "Estimated heap peak reservations of currently running Iceberg compaction plans",
275                registry
276            )
277            .unwrap();
278        Self {
279            compaction_upload_sst_counts,
280            compact_fast_runner_bytes,
281            compact_write_bytes,
282            compact_read_current_level,
283            compact_read_next_level,
284            compact_read_sstn_current_level,
285            compact_read_sstn_next_level,
286            compact_write_sstn,
287            compact_sst_duration,
288            compact_task_duration,
289            compact_task_pending_num,
290            compact_task_pending_parallelism,
291            write_build_l0_sst_duration,
292            shared_buffer_to_sstable_size,
293            get_table_id_total_time_duration,
294            remote_read_time,
295            sstable_bloom_filter_size,
296            sstable_file_size,
297            sstable_avg_key_size,
298            sstable_avg_value_size,
299            iter_scan_key_counts,
300            write_build_l0_bytes,
301            sstable_distinct_epoch_count,
302            compaction_event_consumed_latency,
303            compaction_event_loop_iteration_latency,
304            sstable_block_size,
305            iceberg_compaction_memory_budget_bytes,
306            iceberg_compaction_running_memory_reservation_bytes,
307        }
308    }
309
310    /// Creates a new `HummockStateStoreMetrics` instance used in tests or other places.
311    pub fn unused() -> Self {
312        GLOBAL_COMPACTOR_METRICS.clone()
313    }
314}