[HUDI-571] Add 'commits show archived' command to CLI
This commit is contained in:
@@ -28,9 +28,12 @@ import org.apache.hudi.common.model.HoodieWriteStat;
|
||||
import org.apache.hudi.common.table.HoodieTableMetaClient;
|
||||
import org.apache.hudi.common.table.HoodieTimeline;
|
||||
import org.apache.hudi.common.table.timeline.HoodieActiveTimeline;
|
||||
import org.apache.hudi.common.table.timeline.HoodieArchivedTimeline;
|
||||
import org.apache.hudi.common.table.timeline.HoodieDefaultTimeline;
|
||||
import org.apache.hudi.common.table.timeline.HoodieInstant;
|
||||
import org.apache.hudi.common.util.NumericUtils;
|
||||
|
||||
import org.apache.hudi.common.util.StringUtils;
|
||||
import org.apache.spark.launcher.SparkLauncher;
|
||||
import org.springframework.shell.core.CommandMarker;
|
||||
import org.springframework.shell.core.annotation.CliCommand;
|
||||
@@ -38,7 +41,10 @@ import org.springframework.shell.core.annotation.CliOption;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -51,6 +57,49 @@ import java.util.stream.Collectors;
|
||||
@Component
|
||||
public class CommitsCommand implements CommandMarker {
|
||||
|
||||
private String printCommits(HoodieDefaultTimeline timeline,
|
||||
final Integer limit, final String sortByField,
|
||||
final boolean descending,
|
||||
final boolean headerOnly) throws IOException {
|
||||
final List<Comparable[]> rows = new ArrayList<>();
|
||||
|
||||
final List<HoodieInstant> commits = timeline.getCommitsTimeline().filterCompletedInstants()
|
||||
.getInstants().collect(Collectors.toList());
|
||||
// timeline can be read from multiple files. So sort is needed instead of reversing the collection
|
||||
Collections.sort(commits, HoodieInstant.COMPARATOR.reversed());
|
||||
|
||||
for (int i = 0; i < commits.size(); i++) {
|
||||
final HoodieInstant commit = commits.get(i);
|
||||
final HoodieCommitMetadata commitMetadata = HoodieCommitMetadata.fromBytes(
|
||||
timeline.getInstantDetails(commit).get(),
|
||||
HoodieCommitMetadata.class);
|
||||
rows.add(new Comparable[]{commit.getTimestamp(),
|
||||
commitMetadata.fetchTotalBytesWritten(),
|
||||
commitMetadata.fetchTotalFilesInsert(),
|
||||
commitMetadata.fetchTotalFilesUpdated(),
|
||||
commitMetadata.fetchTotalPartitionsWritten(),
|
||||
commitMetadata.fetchTotalRecordsWritten(),
|
||||
commitMetadata.fetchTotalUpdateRecordsWritten(),
|
||||
commitMetadata.fetchTotalWriteErrors()});
|
||||
}
|
||||
|
||||
final Map<String, Function<Object, String>> fieldNameToConverterMap = new HashMap<>();
|
||||
fieldNameToConverterMap.put("Total Bytes Written", entry -> {
|
||||
return NumericUtils.humanReadableByteCount((Double.valueOf(entry.toString())));
|
||||
});
|
||||
|
||||
final TableHeader header = new TableHeader()
|
||||
.addTableHeaderField("CommitTime")
|
||||
.addTableHeaderField("Total Bytes Written")
|
||||
.addTableHeaderField("Total Files Added")
|
||||
.addTableHeaderField("Total Files Updated")
|
||||
.addTableHeaderField("Total Partitions Written")
|
||||
.addTableHeaderField("Total Records Written")
|
||||
.addTableHeaderField("Total Update Records Written")
|
||||
.addTableHeaderField("Total Errors");
|
||||
return HoodiePrintHelper.print(header, fieldNameToConverterMap, sortByField, descending, limit, headerOnly, rows);
|
||||
}
|
||||
|
||||
@CliCommand(value = "commits show", help = "Show the commits")
|
||||
public String showCommits(
|
||||
@CliOption(key = {"limit"}, help = "Limit commits",
|
||||
@@ -62,26 +111,39 @@ public class CommitsCommand implements CommandMarker {
|
||||
throws IOException {
|
||||
|
||||
HoodieActiveTimeline activeTimeline = HoodieCLI.getTableMetaClient().getActiveTimeline();
|
||||
HoodieTimeline timeline = activeTimeline.getCommitsTimeline().filterCompletedInstants();
|
||||
List<HoodieInstant> commits = timeline.getReverseOrderedInstants().collect(Collectors.toList());
|
||||
List<Comparable[]> rows = new ArrayList<>();
|
||||
for (HoodieInstant commit : commits) {
|
||||
HoodieCommitMetadata commitMetadata =
|
||||
HoodieCommitMetadata.fromBytes(timeline.getInstantDetails(commit).get(), HoodieCommitMetadata.class);
|
||||
rows.add(new Comparable[] {commit.getTimestamp(), commitMetadata.fetchTotalBytesWritten(),
|
||||
commitMetadata.fetchTotalFilesInsert(), commitMetadata.fetchTotalFilesUpdated(),
|
||||
commitMetadata.fetchTotalPartitionsWritten(), commitMetadata.fetchTotalRecordsWritten(),
|
||||
commitMetadata.fetchTotalUpdateRecordsWritten(), commitMetadata.fetchTotalWriteErrors()});
|
||||
return printCommits(activeTimeline, limit, sortByField, descending, headerOnly);
|
||||
}
|
||||
|
||||
@CliCommand(value = "commits show archived", help = "Show the archived commits")
|
||||
public String showArchivedCommits(
|
||||
@CliOption(key = {"startTs"}, mandatory = false, help = "start time for commits, default: now - 10 days")
|
||||
String startTs,
|
||||
@CliOption(key = {"endTs"}, mandatory = false, help = "end time for commits, default: now - 1 day")
|
||||
String endTs,
|
||||
@CliOption(key = {"limit"}, mandatory = false, help = "Limit commits", unspecifiedDefaultValue = "-1")
|
||||
final Integer limit,
|
||||
@CliOption(key = {"sortBy"}, help = "Sorting Field", unspecifiedDefaultValue = "")
|
||||
final String sortByField,
|
||||
@CliOption(key = {"desc"}, help = "Ordering", unspecifiedDefaultValue = "false")
|
||||
final boolean descending,
|
||||
@CliOption(key = {"headeronly"}, help = "Print Header Only", unspecifiedDefaultValue = "false")
|
||||
final boolean headerOnly)
|
||||
throws IOException {
|
||||
if (StringUtils.isNullOrEmpty(startTs)) {
|
||||
startTs = getTimeDaysAgo(10);
|
||||
}
|
||||
if (StringUtils.isNullOrEmpty(endTs)) {
|
||||
endTs = getTimeDaysAgo(1);
|
||||
}
|
||||
HoodieArchivedTimeline archivedTimeline = HoodieCLI.getTableMetaClient().getArchivedTimeline();
|
||||
try {
|
||||
archivedTimeline.loadInstantDetailsInMemory(startTs, endTs);
|
||||
return printCommits(archivedTimeline.findInstantsInRange(startTs, endTs),
|
||||
limit, sortByField, descending, headerOnly);
|
||||
} finally {
|
||||
// clear the instant details from memory after printing to reduce usage
|
||||
archivedTimeline.clearInstantDetailsFromMemory(startTs, endTs);
|
||||
}
|
||||
|
||||
Map<String, Function<Object, String>> fieldNameToConverterMap = new HashMap<>();
|
||||
fieldNameToConverterMap.put("Total Bytes Written", entry -> NumericUtils.humanReadableByteCount((Double.parseDouble(entry.toString()))));
|
||||
|
||||
TableHeader header = new TableHeader().addTableHeaderField("CommitTime").addTableHeaderField("Total Bytes Written")
|
||||
.addTableHeaderField("Total Files Added").addTableHeaderField("Total Files Updated")
|
||||
.addTableHeaderField("Total Partitions Written").addTableHeaderField("Total Records Written")
|
||||
.addTableHeaderField("Total Update Records Written").addTableHeaderField("Total Errors");
|
||||
return HoodiePrintHelper.print(header, fieldNameToConverterMap, sortByField, descending, limit, headerOnly, rows);
|
||||
}
|
||||
|
||||
@CliCommand(value = "commits refresh", help = "Refresh the commits")
|
||||
@@ -241,4 +303,9 @@ public class CommitsCommand implements CommandMarker {
|
||||
+ HoodieCLI.syncTableMetadata.getTableConfig().getTableName();
|
||||
}
|
||||
|
||||
private String getTimeDaysAgo(int numberOfDays) {
|
||||
Date date = Date.from(ZonedDateTime.now().minusDays(numberOfDays).toInstant());
|
||||
return HoodieActiveTimeline.COMMIT_FORMATTER.format(date);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user