|
@@ -5,10 +5,10 @@ import org.apache.commons.lang3.exception.ExceptionUtils;
|
|
|
import org.cryptomator.common.Environment;
|
|
|
import org.cryptomator.common.vaults.Vault;
|
|
|
import org.cryptomator.cryptofs.VaultConfig;
|
|
|
+import org.cryptomator.cryptofs.health.api.DiagnosticResult;
|
|
|
|
|
|
import javax.inject.Inject;
|
|
|
import javafx.concurrent.Task;
|
|
|
-import javafx.concurrent.Worker;
|
|
|
import java.io.IOException;
|
|
|
import java.nio.ByteBuffer;
|
|
|
import java.nio.channels.ByteChannel;
|
|
@@ -16,6 +16,9 @@ import java.nio.charset.StandardCharsets;
|
|
|
import java.nio.file.Files;
|
|
|
import java.nio.file.Path;
|
|
|
import java.nio.file.StandardOpenOption;
|
|
|
+import java.time.Instant;
|
|
|
+import java.time.ZoneId;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
import java.util.Collection;
|
|
|
import java.util.Objects;
|
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
@@ -30,12 +33,15 @@ public class HealthReportWriteTask extends Task<Void> {
|
|
|
**************************************
|
|
|
Analyzed vault: %s (Current name \"%s\")
|
|
|
Vault storage path: %s
|
|
|
-
|
|
|
""";
|
|
|
- private static final String REPORT_CHECK_SUCCESS = "\tCheck %s successful. Results:\n";
|
|
|
- private static final String REPORT_CHECK_RESULT = "\t\t %s - %s\n";
|
|
|
- private static final String REPORT_CHECK_CANCELED = "\tCheck %s canceled.\n";
|
|
|
- private static final String REPORT_CHECK_FAILED = "\tCheck %s failed.\n";
|
|
|
+ private static final String REPORT_CHECK_HEADER = """
|
|
|
+
|
|
|
+
|
|
|
+ Check %s
|
|
|
+ ------------------------------
|
|
|
+ """;
|
|
|
+ private static final String REPORT_CHECK_RESULT = "%s - %s";
|
|
|
+ private static final DateTimeFormatter TIME_STAMP = DateTimeFormatter.ofPattern("yyyyMMdd-HHmmss").withZone(ZoneId.systemDefault());
|
|
|
|
|
|
private final Vault vault;
|
|
|
private final VaultConfig vaultConfig;
|
|
@@ -52,25 +58,27 @@ public class HealthReportWriteTask extends Task<Void> {
|
|
|
|
|
|
@Override
|
|
|
protected Void call() throws IOException {
|
|
|
- var path = env.getLogDir().orElse(Path.of(System.getProperty("user.home"))).resolve("healthReport_" + vault.getDisplayName() + "(" + vaultConfig.getId() + ")" + ".log");
|
|
|
+ var path = env.getLogDir().orElse(Path.of(System.getProperty("user.home"))).resolve("healthReport_" + vault.getDisplayName() + "_" + TIME_STAMP.format(Instant.now()) + ".log");
|
|
|
final var tasks = this.tasks.get();
|
|
|
//use file channel, since results can be pretty big
|
|
|
try (var channel = Files.newByteChannel(path, StandardOpenOption.CREATE, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) {
|
|
|
internalWrite(channel, String.format(REPORT_HEADER, vaultConfig.getId(), vault.getDisplayName(), vault.getPath()));
|
|
|
for (var task : tasks) {
|
|
|
+ internalWrite(channel, REPORT_CHECK_HEADER, task.getCheck().identifier());
|
|
|
final var state = task.getEndState();
|
|
|
- if (state == Worker.State.SUCCEEDED) {
|
|
|
- internalWrite(channel, REPORT_CHECK_SUCCESS, task.getCheck().identifier());
|
|
|
- for (var result : task.results()) {
|
|
|
- internalWrite(channel, REPORT_CHECK_RESULT, result.getServerity(), result);
|
|
|
+ switch (state) {
|
|
|
+ case SUCCEEDED -> {
|
|
|
+ internalWrite(channel, "STATUS: SUCCESS\nRESULTS:\n");
|
|
|
+ for (var result : task.results()) {
|
|
|
+ internalWrite(channel, REPORT_CHECK_RESULT, severityToString(result.getServerity()), result);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ case CANCELLED -> internalWrite(channel, "STATUS: CANCELED\n");
|
|
|
+ case FAILED -> {
|
|
|
+ internalWrite(channel, "STATUS: FAILED\nREASON:\n", task.getCheck().identifier());
|
|
|
+ internalWrite(channel, prepareFailureMsg(task));
|
|
|
}
|
|
|
- } else if (state == Worker.State.CANCELLED) {
|
|
|
- internalWrite(channel, REPORT_CHECK_CANCELED, task.getCheck().identifier());
|
|
|
- } else if (state == Worker.State.FAILED) {
|
|
|
- internalWrite(channel, REPORT_CHECK_FAILED, task.getCheck().identifier());
|
|
|
- internalWrite(channel, prepareFailureMsg(task));
|
|
|
- } else {
|
|
|
- throw new IllegalStateException("Cannot export unfinished task");
|
|
|
+ case READY, RUNNING, SCHEDULED -> throw new IllegalStateException("Cannot export unfinished task");
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -81,6 +89,13 @@ public class HealthReportWriteTask extends Task<Void> {
|
|
|
channel.write(ByteBuffer.wrap(s.formatted(formatArguments).getBytes(StandardCharsets.UTF_8)));
|
|
|
}
|
|
|
|
|
|
+ private String severityToString(DiagnosticResult.Severity s) {
|
|
|
+ return switch (s) {
|
|
|
+ case GOOD, INFO, WARN -> s.name();
|
|
|
+ case CRITICAL -> "CRIT";
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
private String prepareFailureMsg(HealthCheckTask task) {
|
|
|
return task.getExceptionOnDone() //
|
|
|
.map(t -> ExceptionUtils.getStackTrace(t)).orElse("Unknown reason of failure.") //
|