mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-20 03:31:27 +00:00
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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user