Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HDDS-11206. Statistics storage usage indicators include min, max, median, stdev #6977

Merged
merged 4 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import org.apache.hadoop.hdds.annotation.InterfaceAudience;

import java.util.HashMap;
import java.util.Map;

/**
Expand Down Expand Up @@ -48,4 +49,8 @@ public interface NodeManagerMXBean {
*/
Map<String, Map<String, String>> getNodeStatusInfo();

default Map<String, String> getNodeStatics() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: Statics -> Statistics.

Also applies to other instances of Statics in the patch.

return new HashMap<>();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.Arrays;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
Expand Down Expand Up @@ -1217,6 +1218,47 @@ public static String[] calculateStoragePercentage(
return storagePercentage;
}

@Override
public Map<String, String> getNodeStatics() {
if (nodeStateManager.getAllNodes().size() < 1) {
return new HashMap<>();
}
Map<String, String> nodeStatics = new HashMap<>();
float[] usages = new float[nodeStateManager.getAllNodes().size()];
float totalOzoneUsed = 0;
int i = 0;
for (DatanodeInfo dni : nodeStateManager.getAllNodes()) {
String[] storagePercentage = calculateStoragePercentage(
dni.getStorageReports());
if (storagePercentage[0].equals("N/A")) {
usages[i++] = 0;
} else {
float storagePerc = Float.parseFloat(storagePercentage[0]);
usages[i++] = storagePerc;
totalOzoneUsed = totalOzoneUsed + storagePerc;
}
}

totalOzoneUsed /= nodeStateManager.getAllNodes().size();
Arrays.sort(usages);
float median = usages[usages.length / 2];
nodeStatics.put(UsageStatics.MEDINNA.getLabel(), String.valueOf(median));
float max = usages[usages.length - 1];
nodeStatics.put(UsageStatics.MAX.getLabel(), String.valueOf(max));
float min = usages[0];
nodeStatics.put(UsageStatics.MIN.getLabel(), String.valueOf(min));

float dev = 0;
for (i = 0; i < usages.length; i++) {
dev += (usages[i] - totalOzoneUsed) * (usages[i] - totalOzoneUsed);
}
dev = (float) Math.sqrt(dev / usages.length);
DecimalFormat decimalFormat = new DecimalFormat("#0.00");
decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
nodeStatics.put(UsageStatics.STDEV.getLabel(), decimalFormat.format(dev));
return nodeStatics;
}

/**
* Based on the current time and the last heartbeat, calculate the time difference
* and get a string of the relative value. E.g. "2s ago", "1m 2s ago", etc.
Expand Down Expand Up @@ -1284,6 +1326,20 @@ public String getLabel() {
}
}

private enum UsageStatics {
MIN("Min"),
MAX("Max"),
MEDINNA("Medina"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: MEDINA -> MEDIAN. Also applies to similar typos.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your comment and review, @ivandika3 .
I'll update later.

STDEV("Stdev");
private String label;
public String getLabel() {
return label;
}
UsageStatics(String label) {
this.label = label;
}
}

/**
* Returns the min of no healthy volumes reported out of the set
* of datanodes constituting the pipeline.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,16 @@ <h2>SCM Information</h2>
</tbody>
</table>

<h2>Statistical</h2>
<table class="table table-bordered table-striped">
<tbody>
<tr>
<td>DataNodes usages% (Min/Median/Max/stdDev)</td>
<td>{{statistical.usages.min}}%/{{statistical.usages.medina}}%/{{statistical.usages.max}}%/{{statistical.usages.stdev}}%</td>
</tr>
</tbody>
ivandika3 marked this conversation as resolved.
Show resolved Hide resolved
</table>

<h2>Node Status</h2>
<div class="row">
<div class="col-md-6 text-left">
Expand Down
19 changes: 19 additions & 0 deletions hadoop-hdds/server-scm/src/main/resources/webapps/scm/scm.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@
$scope.RecordsToDisplay = "10";
$scope.currentPage = 1;
$scope.lastIndex = 0;
$scope.statistical = {
usages : {}
}
$scope.statistical.usages.min = "";
$scope.statistical.usages.max = "";
$scope.statistical.usages.medina = "";
$scope.statistical.usages.stdev = "";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: statistical -> statistics.

I think it's also better to be more specific that it is the statistics for DNs (since technically we can have statistics for SCM in the future). Maybe scope.statistics.nodes.usages. prefix is better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have updated it.


function get_protocol(URLScheme, value, baseProto, fallbackProto) {
let protocol = "unknown"
Expand Down Expand Up @@ -81,6 +88,18 @@
$scope.totalItems = nodeStatusCopy.length;
$scope.lastIndex = Math.ceil(nodeStatusCopy.length / $scope.RecordsToDisplay);
$scope.nodeStatus = nodeStatusCopy.slice(0, $scope.RecordsToDisplay);

ctrl.nodemanagermetrics.NodeStatics.map(({ key, value }) => {
if(key == "Min") {
$scope.statistical.usages.min = value;
} else if(key == "Max") {
$scope.statistical.usages.max = value;
} else if(key == "Medina") {
$scope.statistical.usages.medina = value;
} else if(key == "Stdev") {
$scope.statistical.usages.stdev = value;
}
});
});
/*if option is 'All' display all records else display specified record on page*/
$scope.UpdateRecordsToShow = () => {
Expand Down