Merge pull request #2233 from cryptomator/feature/stats-counter-for-metadata

Add to statistics window a counter for metadata

Closes #1511
This commit is contained in:
Armin Schrenk
2022-12-02 13:09:25 +01:00
committed by GitHub
4 changed files with 89 additions and 15 deletions

View File

@@ -41,6 +41,8 @@ public class VaultStats {
private final LongProperty totalBytesDecrypted = new SimpleLongProperty();
private final LongProperty filesRead = new SimpleLongProperty();
private final LongProperty filesWritten = new SimpleLongProperty();
private final LongProperty filesAccessed = new SimpleLongProperty();
private final LongProperty totalFilesAccessed = new SimpleLongProperty();
private final ObjectProperty<Instant> lastActivity = new SimpleObjectProperty<>();
@Inject
@@ -82,6 +84,8 @@ public class VaultStats {
var oldAccessCount = filesRead.get() + filesWritten.get();
filesRead.set(stats.map(CryptoFileSystemStats::pollAmountOfAccessesRead).orElse(0L));
filesWritten.set(stats.map(CryptoFileSystemStats::pollAmountOfAccessesWritten).orElse(0L));
filesAccessed.set(stats.map(CryptoFileSystemStats::pollAmountOfAccesses).orElse(0L));
totalFilesAccessed.set(stats.map(CryptoFileSystemStats::pollTotalAmountOfAccesses).orElse(0L));
var newAccessCount = filesRead.get() + filesWritten.get();
// check for any I/O activity
@@ -188,6 +192,19 @@ public class VaultStats {
public long getFilesWritten() {return filesWritten.get();}
public LongProperty filesAccessed() {
return filesAccessed;}
public long getFilesAccessed() {return filesAccessed.get();}
public LongProperty totalFilesAccessed(){
return totalFilesAccessed;
}
public long getTotalFilesAccessed(){
return totalFilesAccessed.get();
}
public ObjectProperty<Instant> lastActivityProperty() {
return lastActivity;
}

View File

@@ -9,8 +9,10 @@ import javax.inject.Inject;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.beans.binding.Bindings;
import javafx.beans.binding.DoubleBinding;
import javafx.beans.binding.LongBinding;
import javafx.beans.property.LongProperty;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
@@ -21,6 +23,7 @@ import javafx.scene.chart.XYChart.Series;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.util.Arrays;
import java.util.concurrent.Callable;
@VaultStatisticsScoped
public class VaultStatisticsController implements FxController {
@@ -32,6 +35,7 @@ public class VaultStatisticsController implements FxController {
private final VaultStats stats;
private final Series<Number, Number> readData;
private final Series<Number, Number> writeData;
private final Series<Number, Number> accessData;
private final Timeline ioAnimation;
private final LongBinding bpsRead;
private final LongBinding bpsWritten;
@@ -44,15 +48,20 @@ public class VaultStatisticsController implements FxController {
private final LongBinding totalBytesDecrypted;
private final LongBinding filesRead;
private final LongBinding filesWritten;
private final LongBinding filesAccessed;
private final LongBinding totalFilesAccessed;
private final LongBinding bpsEncrypted;
private final LongBinding bpsDecrypted;
public AreaChart<Number, Number> readChart;
public AreaChart<Number, Number> writeChart;
public AreaChart<Number, Number> accessChart;
public NumberAxis readChartXAxis;
public NumberAxis readChartYAxis;
public NumberAxis writeChartXAxis;
public NumberAxis writeChartYAxis;
public NumberAxis accessChartXAxis;
public NumberAxis accessChartYAxis;
@Inject
public VaultStatisticsController(VaultStatisticsComponent component, @VaultStatisticsWindow Stage window, @VaultStatisticsWindow Vault vault) {
@@ -60,6 +69,7 @@ public class VaultStatisticsController implements FxController {
this.stats = vault.getStats();
this.readData = new Series<>();
this.writeData = new Series<>();
this.accessData = new Series<>();
this.bpsRead = WeakBindings.bindLong(stats.bytesPerSecondReadProperty());
this.bpsWritten = WeakBindings.bindLong(stats.bytesPerSecondWrittenProperty());
this.cacheHitRate = WeakBindings.bindDouble(stats.cacheHitRateProperty());
@@ -71,11 +81,13 @@ public class VaultStatisticsController implements FxController {
this.totalBytesEncrypted = WeakBindings.bindLong(stats.totalBytesEncryptedProperty());
this.filesRead = WeakBindings.bindLong(stats.filesRead());
this.filesWritten = WeakBindings.bindLong(stats.filesWritten());
this.filesAccessed = WeakBindings.bindLong(stats.filesAccessed());
this.totalFilesAccessed = WeakBindings.bindLong(stats.totalFilesAccessed());
this.bpsEncrypted = WeakBindings.bindLong(stats.bytesPerSecondEncryptedProperty());
this.bpsDecrypted = WeakBindings.bindLong(stats.bytesPerSecondDecryptedProperty());
this.ioAnimation = new Timeline(); //TODO Research better timer
ioAnimation.getKeyFrames().add(new KeyFrame(Duration.seconds(IO_SAMPLING_INTERVAL), new IoSamplingAnimationHandler(readData, writeData)));
ioAnimation.getKeyFrames().add(new KeyFrame(Duration.seconds(IO_SAMPLING_INTERVAL), new IoSamplingAnimationHandler(readData, writeData, accessData)));
ioAnimation.setCycleCount(Animation.INDEFINITE);
ioAnimation.play();
@@ -89,6 +101,7 @@ public class VaultStatisticsController implements FxController {
public void initialize() {
readChart.getData().addAll(readData);
writeChart.getData().addAll(writeData);
accessChart.getData().addAll(accessData);
}
private class IoSamplingAnimationHandler implements EventHandler<ActionEvent> {
@@ -96,16 +109,21 @@ public class VaultStatisticsController implements FxController {
private long step = IO_SAMPLING_STEPS;
private final Series<Number, Number> decryptedBytesRead;
private final Series<Number, Number> encryptedBytesWrite;
private final Series<Number, Number> accessedFiles;
private final long[] maxBuf = new long[IO_SAMPLING_STEPS];
private final long[] maxAccessBuf = new long[IO_SAMPLING_STEPS];
public IoSamplingAnimationHandler(Series<Number, Number> readData, Series<Number, Number> writeData) {
public IoSamplingAnimationHandler(Series<Number, Number> readData, Series<Number, Number> writeData, Series<Number, Number> accessData) {
this.decryptedBytesRead = readData;
this.encryptedBytesWrite = writeData;
this.accessedFiles = accessData;
// initialize data once and change value of data points later:
for (int i = 0; i < IO_SAMPLING_STEPS; i++) {
decryptedBytesRead.getData().add(new Data<>(i, 0));
encryptedBytesWrite.getData().add(new Data<>(i, 0));
accessedFiles.getData().add(new Data<>(i, 0));
}
}
@@ -114,17 +132,22 @@ public class VaultStatisticsController implements FxController {
final long currentStep = step++;
final long decBytes = stats.bytesPerSecondReadProperty().get();
final long encBytes = stats.bytesPerSecondWrittenProperty().get();
final long accFiles = stats.filesAccessed().get();
maxBuf[(int) currentStep % IO_SAMPLING_STEPS] = Math.max(decBytes, encBytes);
long allTimeMax = Arrays.stream(maxBuf).max().orElse(0l);
long allTimeMax = Arrays.stream(maxBuf).max().orElse(0L);
maxAccessBuf[(int) currentStep % IO_SAMPLING_STEPS] = accFiles;
long allTimeMaxAccessedFiles = Arrays.stream(maxAccessBuf).max().orElse(0L);
// remove oldest value:
decryptedBytesRead.getData().remove(0);
encryptedBytesWrite.getData().remove(0);
accessedFiles.getData().remove(0);
// add latest value:
decryptedBytesRead.getData().add(new Data<>(currentStep, decBytes));
encryptedBytesWrite.getData().add(new Data<>(currentStep, encBytes));
accessedFiles.getData().add(new Data<>(currentStep, accFiles));
// adjust ranges:
readChartXAxis.setLowerBound(currentStep - IO_SAMPLING_STEPS * 1.0);
@@ -133,6 +156,9 @@ public class VaultStatisticsController implements FxController {
writeChartXAxis.setLowerBound(currentStep - IO_SAMPLING_STEPS * 1.0);
writeChartXAxis.setUpperBound(currentStep);
writeChartYAxis.setUpperBound(allTimeMax);
accessChartXAxis.setLowerBound(currentStep - IO_SAMPLING_STEPS * 1.0);
accessChartXAxis.setUpperBound(currentStep);
accessChartYAxis.setUpperBound(allTimeMaxAccessedFiles);
}
}
@@ -207,4 +233,12 @@ public class VaultStatisticsController implements FxController {
public LongBinding filesWrittenProperty() {return filesWritten;}
public long getFilesWritten() {return filesWritten.get();}
public LongBinding filesAccessedProperty() {return filesAccessed;}
public long getFilesAccessed() {return filesAccessed.get();}
public LongBinding totalFilesAccessedProperty() {return totalFilesAccessed;}
public long getTotalFilesAccessed() {return totalFilesAccessed.get();}
}

View File

@@ -13,6 +13,7 @@
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.shape.Arc?>
<?import javafx.scene.shape.Circle?>
<HBox xmlns="http://javafx.com/javafx"
xmlns:fx="http://javafx.com/fxml"
fx:controller="org.cryptomator.ui.stats.VaultStatisticsController"
@@ -22,18 +23,17 @@
</padding>
<!-- Caching -->
<VBox prefWidth="200" prefHeight="200">
<StackPane>
<Group>
<Arc styleClass="cache-arc-background" centerX="100" centerY="100" radiusX="100" radiusY="100" startAngle="225" length="-270"/>
<Arc styleClass="cache-arc-foreground" centerX="100" centerY="100" radiusX="100" radiusY="100" startAngle="225" length="${controller.cacheHitDegrees}"/>
</Group>
<VBox StackPane.alignment="CENTER" alignment="CENTER">
<FormattedLabel styleClass="label-extra-large" format="\%1.0f %%" arg1="${controller.cacheHitPercentage}"/>
<Label text="%stats.cacheHitRate"/>
</VBox>
</StackPane>
</VBox>
<StackPane prefWidth="200" prefHeight="200">
<Group>
<Circle centerX="100" centerY="100" radius="100" opacity="0"/> <!-- for alignment. visible=false does not yield the desired result -->
<Arc styleClass="cache-arc-background" centerX="100" centerY="100" radiusX="100" radiusY="100" startAngle="225" length="-270"/>
<Arc styleClass="cache-arc-foreground" centerX="100" centerY="100" radiusX="100" radiusY="100" startAngle="225" length="${controller.cacheHitDegrees}"/>
</Group>
<VBox StackPane.alignment="CENTER" alignment="CENTER">
<FormattedLabel styleClass="label-extra-large" format="\%1.0f %%" arg1="${controller.cacheHitPercentage}"/>
<Label text="%stats.cacheHitRate"/>
</VBox>
</StackPane>
<!-- Read -->
<VBox prefWidth="300" prefHeight="300" spacing="6" alignment="CENTER">
@@ -72,4 +72,22 @@
<DataLabel byteFormat="%stats.encr.total.data.none" kibFormat="%stats.encr.total.data.kib" mibFormat="%stats.encr.total.data.mib" gibFormat="%stats.encr.total.data.gib" dataInBytes="${controller.totalBytesEncrypted}"/>
<FormattedLabel format="%stats.write.accessCount" arg1="${controller.filesWritten}"/>
</VBox>
<!-- Access -->
<VBox prefWidth="300" prefHeight="300" spacing="6" alignment="CENTER">
<FormattedLabel styleClass="label-large" format="%stats.access.current" arg1="${controller.filesAccessed}"/>
<AreaChart fx:id="accessChart" styleClass="io-stats" createSymbols="false" animated="false">
<xAxis>
<NumberAxis fx:id="accessChartXAxis" styleClass="io-stats" autoRanging="false" forceZeroInRange="false" side="BOTTOM"/>
</xAxis>
<yAxis>
<NumberAxis fx:id="accessChartYAxis" styleClass="io-stats" autoRanging="true" forceZeroInRange="true" side="LEFT" tickUnit="Infinity"/>
</yAxis>
<cursor>
<Cursor fx:constant="DEFAULT"/>
</cursor>
</AreaChart>
<FormattedLabel format="%stats.access.total" arg1="${controller.totalFilesAccessed}"/>
<Label/> <!-- to align with other graphs -->
<Label/> <!-- to align with other graphs -->
</VBox>
</HBox>

View File

@@ -301,6 +301,11 @@ stats.encr.total.data.mib=Data encrypted: %.1f MiB
stats.encr.total.data.gib=Data encrypted: %.1f GiB
stats.write.accessCount=Total writes: %d
## Accesses
stats.access.current=Access: %d
stats.access.total=Total accesses: %d
# Main Window
main.closeBtn.tooltip=Close
main.minimizeBtn.tooltip=Minimize