Skip to content

Commit 0a4f4e2

Browse files
support clean metrics of OrphanFilesCleaner (#118)
1 parent e8af7ef commit 0a4f4e2

7 files changed

Lines changed: 119 additions & 11 deletions

File tree

include/paimon/orphan_files_cleaner.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,11 @@ class PAIMON_EXPORT OrphanFilesCleaner {
184184
/// files.
185185
virtual Result<std::set<std::string>> Clean() = 0;
186186

187+
/// Retrieve metrics related to orphan files cleaning operations.
188+
///
189+
/// @return A shared pointer to a `Metrics` object containing cleaning metrics.
190+
virtual std::shared_ptr<Metrics> GetMetrics() const = 0;
191+
187192
protected:
188193
OrphanFilesCleaner() = default;
189194
};

src/paimon/core/operation/file_store_commit_impl.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
#include "paimon/core/schema/schema_manager.h"
6363
#include "paimon/core/schema/table_schema.h"
6464
#include "paimon/core/table/sink/commit_message_impl.h"
65+
#include "paimon/core/utils/duration.h"
6566
#include "paimon/core/utils/file_store_path_factory.h"
6667
#include "paimon/core/utils/snapshot_manager.h"
6768
#include "paimon/fs/file_system.h"
@@ -379,7 +380,7 @@ Status FileStoreCommitImpl::Commit(const std::shared_ptr<ManifestCommittable>& c
379380

380381
int32_t attempt = 0;
381382
int32_t generated_snapshot = 0;
382-
const auto started = std::chrono::high_resolution_clock::now();
383+
Duration duration;
383384
if (!ignore_empty_commit_ || !append_table_files.empty() || !append_table_index_files.empty()) {
384385
PAIMON_ASSIGN_OR_RAISE(int32_t cnt,
385386
TryCommit(append_table_files, append_table_index_files,
@@ -403,10 +404,7 @@ Status FileStoreCommitImpl::Commit(const std::shared_ptr<ManifestCommittable>& c
403404
compaction_input_file_size += entry.File()->file_size;
404405
}
405406
}
406-
metrics_->SetCounter(CommitMetrics::LAST_COMMIT_DURATION,
407-
std::chrono::duration_cast<std::chrono::milliseconds>(
408-
std::chrono::high_resolution_clock::now() - started)
409-
.count());
407+
metrics_->SetCounter(CommitMetrics::LAST_COMMIT_DURATION, duration.Get());
410408
metrics_->SetCounter(CommitMetrics::LAST_COMMIT_ATTEMPTS, attempt);
411409
metrics_->SetCounter(CommitMetrics::LAST_TABLE_FILES_ADDED, table_files_added);
412410
metrics_->SetCounter(CommitMetrics::LAST_TABLE_FILES_DELETED, table_files_deleted);

src/paimon/core/operation/file_store_scan.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "paimon/core/operation/metrics/scan_metrics.h"
4040
#include "paimon/core/partition/partition_info.h"
4141
#include "paimon/core/stats/simple_stats.h"
42+
#include "paimon/core/utils/duration.h"
4243
#include "paimon/core/utils/field_mapping.h"
4344
#include "paimon/core/utils/snapshot_manager.h"
4445
#include "paimon/predicate/literal.h"
@@ -94,7 +95,7 @@ Result<std::vector<PartitionEntry>> FileStoreScan::ReadPartitionEntries() const
9495
}
9596

9697
Result<std::shared_ptr<FileStoreScan::RawPlan>> FileStoreScan::CreatePlan() const {
97-
const auto started = std::chrono::high_resolution_clock::now();
98+
Duration duration;
9899
std::optional<Snapshot> snapshot;
99100
std::vector<ManifestFileMeta> all_manifest_file_metas;
100101
std::vector<ManifestFileMeta> filtered_manifest_file_metas;
@@ -133,10 +134,7 @@ Result<std::shared_ptr<FileStoreScan::RawPlan>> FileStoreScan::CreatePlan() cons
133134
[](const int64_t sum, const ManifestFileMeta& manifest_file_meta) {
134135
return sum + manifest_file_meta.NumAddedFiles() - manifest_file_meta.NumDeletedFiles();
135136
});
136-
metrics_->SetCounter(ScanMetrics::LAST_SCAN_DURATION,
137-
std::chrono::duration_cast<std::chrono::milliseconds>(
138-
std::chrono::high_resolution_clock::now() - started)
139-
.count());
137+
metrics_->SetCounter(ScanMetrics::LAST_SCAN_DURATION, duration.Get());
140138
metrics_->SetCounter(ScanMetrics::LAST_SCANNED_SNAPSHOT_ID,
141139
snapshot.has_value() ? snapshot.value().Id() : int64_t{0});
142140
metrics_->SetCounter(ScanMetrics::LAST_SCANNED_MANIFESTS, filtered_manifest_file_metas.size());
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2026-present Alibaba Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
namespace paimon {
20+
21+
/// Metrics to measure clean operation.
22+
class CleanMetrics {
23+
public:
24+
static constexpr char CLEAN_DURATION[] = "cleanDuration";
25+
static constexpr char CLEAN_LIST_DIRECTORIES_DURATION[] = "listDirectoriesDuration";
26+
static constexpr char CLEAN_LIST_DIRECTORIES[] = "listDirectories";
27+
static constexpr char CLEAN_LIST_FILE_STATUS_DURATION[] = "listFileStatusDuration";
28+
static constexpr char CLEAN_LIST_FILE_STATUS_TASKS[] = "listFileStatusTasks";
29+
static constexpr char CLEAN_LIST_USED_FILES_DURATION[] = "listUsedFilesDuration";
30+
static constexpr char CLEAN_USED_FILES[] = "usedFiles";
31+
static constexpr char CLEAN_SCAN_ORPHAN_FILES_DURATION[] = "scanOrphanFilesDuration";
32+
static constexpr char CLEAN_ORPHAN_FILES[] = "orphanFiles";
33+
};
34+
35+
} // namespace paimon

src/paimon/core/operation/orphan_files_cleaner_impl.cpp

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,17 @@
2525

2626
#include "fmt/format.h"
2727
#include "paimon/common/executor/future.h"
28+
#include "paimon/common/metrics/metrics_impl.h"
2829
#include "paimon/common/utils/path_util.h"
2930
#include "paimon/common/utils/scope_guard.h"
3031
#include "paimon/common/utils/string_utils.h"
3132
#include "paimon/core/manifest/manifest_entry.h"
3233
#include "paimon/core/manifest/manifest_file.h"
3334
#include "paimon/core/manifest/manifest_file_meta.h"
3435
#include "paimon/core/manifest/manifest_list.h"
36+
#include "paimon/core/operation/metrics/clean_metrics.h"
3537
#include "paimon/core/snapshot.h"
38+
#include "paimon/core/utils/duration.h"
3639
#include "paimon/core/utils/file_store_path_factory.h"
3740
#include "paimon/core/utils/snapshot_manager.h"
3841
#include "paimon/status.h"
@@ -61,7 +64,8 @@ OrphanFilesCleanerImpl::OrphanFilesCleanerImpl(
6164
manifest_file_(manifest_file),
6265
manifest_list_(manifest_list),
6366
older_than_ms_(older_than_ms),
64-
should_be_retained_(should_be_retained) {}
67+
should_be_retained_(should_be_retained),
68+
metrics_(std::make_shared<MetricsImpl>()) {}
6569

6670
bool OrphanFilesCleanerImpl::SupportToClean(const std::string& file_name) {
6771
static std::vector<std::pair<std::string, std::string>> supported_pattern = {
@@ -83,6 +87,7 @@ bool OrphanFilesCleanerImpl::SupportToClean(const std::string& file_name) {
8387
}
8488

8589
Result<std::set<std::string>> OrphanFilesCleanerImpl::Clean() {
90+
Duration main_duration;
8691
if (!MinimalTryBestListingDirs(PathUtil::JoinPath(root_path_, "tag")).empty()) {
8792
return Status::NotImplemented("OrphanFilesCleaner do not support cleaning table with tag");
8893
}
@@ -98,9 +103,11 @@ Result<std::set<std::string>> OrphanFilesCleanerImpl::Clean() {
98103
}
99104
PAIMON_ASSIGN_OR_RAISE(std::set<std::string> used_file_names, GetUsedFiles());
100105

106+
Duration duration;
101107
std::set<std::string> need_to_deletes;
102108
std::vector<std::future<void>> futures;
103109
ScopeGuard guard([&futures]() { Wait(futures); });
110+
uint64_t file_statuses_duration = duration.Reset();
104111
for (const auto& file_statuses : CollectAll(file_statuses_futures)) {
105112
for (const auto& file_status : file_statuses) {
106113
if (file_status->IsDir()) {
@@ -129,10 +136,18 @@ Result<std::set<std::string>> OrphanFilesCleanerImpl::Clean() {
129136
}
130137
}
131138
}
139+
metrics_->SetCounter(CleanMetrics::CLEAN_DURATION, main_duration.Get());
140+
metrics_->SetCounter(CleanMetrics::CLEAN_SCAN_ORPHAN_FILES_DURATION, duration.Get());
141+
metrics_->SetCounter(CleanMetrics::CLEAN_LIST_FILE_STATUS_DURATION, file_statuses_duration);
142+
metrics_->SetCounter(CleanMetrics::CLEAN_LIST_FILE_STATUS_TASKS,
143+
static_cast<uint64_t>(file_statuses_futures.size()));
144+
metrics_->SetCounter(CleanMetrics::CLEAN_ORPHAN_FILES,
145+
static_cast<uint64_t>(need_to_deletes.size()));
132146
return need_to_deletes;
133147
}
134148

135149
Result<std::set<std::string>> OrphanFilesCleanerImpl::ListPaimonFileDirs() const {
150+
Duration duration;
136151
std::set<std::string> paimon_file_dirs;
137152
paimon_file_dirs.insert(snapshot_manager_->SnapshotDirectory());
138153
paimon_file_dirs.insert(FileStorePathFactory::ManifestPath(root_path_));
@@ -156,6 +171,9 @@ Result<std::set<std::string>> OrphanFilesCleanerImpl::ListPaimonFileDirs() const
156171
// ListFileDirs(external_path, partition_keys_.size());
157172
// paimon_file_dirs.insert(external_file_dirs.begin(), external_file_dirs.end());
158173
// }
174+
metrics_->SetCounter(CleanMetrics::CLEAN_LIST_DIRECTORIES_DURATION, duration.Get());
175+
metrics_->SetCounter(CleanMetrics::CLEAN_LIST_DIRECTORIES,
176+
static_cast<uint64_t>(paimon_file_dirs.size()));
159177
return paimon_file_dirs;
160178
}
161179

@@ -225,6 +243,7 @@ Result<std::set<std::string>> OrphanFilesCleanerImpl::GetUsedFiles() const {
225243
// TODO(jinli.zjw): consider changelog(add tests), stats
226244
used_files.insert(SnapshotManager::EARLIEST);
227245
used_files.insert(SnapshotManager::LATEST);
246+
Duration duration;
228247
PAIMON_ASSIGN_OR_RAISE(std::vector<Snapshot> snapshots, snapshot_manager_->GetAllSnapshots());
229248
for (const auto& snapshot : snapshots) {
230249
used_files.insert(SnapshotManager::SNAPSHOT_PREFIX + std::to_string(snapshot.Id()));
@@ -257,6 +276,8 @@ Result<std::set<std::string>> OrphanFilesCleanerImpl::GetUsedFiles() const {
257276
}
258277
}
259278
}
279+
metrics_->SetCounter(CleanMetrics::CLEAN_LIST_USED_FILES_DURATION, duration.Get());
280+
metrics_->SetCounter(CleanMetrics::CLEAN_USED_FILES, static_cast<uint64_t>(used_files.size()));
260281
return used_files;
261282
}
262283

src/paimon/core/operation/orphan_files_cleaner_impl.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include "paimon/core/snapshot.h"
2929
#include "paimon/fs/file_system.h"
3030
#include "paimon/memory/memory_pool.h"
31+
#include "paimon/metrics.h"
3132
#include "paimon/orphan_files_cleaner.h"
3233
#include "paimon/result.h"
3334

@@ -62,6 +63,10 @@ class OrphanFilesCleanerImpl : public OrphanFilesCleaner {
6263

6364
Result<std::set<std::string>> Clean() override;
6465

66+
std::shared_ptr<Metrics> GetMetrics() const override {
67+
return metrics_;
68+
}
69+
6570
private:
6671
Result<std::set<std::string>> ListPaimonFileDirs() const;
6772
std::vector<std::unique_ptr<FileStatus>> TryBestListingDirs(const std::string& path) const;
@@ -86,5 +91,7 @@ class OrphanFilesCleanerImpl : public OrphanFilesCleaner {
8691
std::shared_ptr<ManifestList> manifest_list_;
8792
int64_t older_than_ms_;
8893
std::function<bool(const std::string&)> should_be_retained_;
94+
95+
std::shared_ptr<Metrics> metrics_;
8996
};
9097
} // namespace paimon

src/paimon/core/utils/duration.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright 2026-present Alibaba Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#include <chrono>
20+
21+
namespace paimon {
22+
23+
// Calculate operation duration.
24+
class Duration {
25+
public:
26+
Duration() : start_(std::chrono::high_resolution_clock::now()) {}
27+
28+
uint64_t Get() {
29+
return std::chrono::duration_cast<std::chrono::milliseconds>(
30+
std::chrono::high_resolution_clock::now() - start_)
31+
.count();
32+
}
33+
34+
uint64_t Reset() {
35+
uint64_t dura = Get();
36+
start_ = std::chrono::high_resolution_clock::now();
37+
return dura;
38+
}
39+
40+
private:
41+
std::chrono::high_resolution_clock::time_point start_;
42+
};
43+
44+
} // namespace paimon

0 commit comments

Comments
 (0)