summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Efimov <[email protected]>2024-09-30 15:42:26 +0200
committerGitHub <[email protected]>2024-09-30 13:42:26 +0000
commit500c5c729df156228582b92fd1bda37d5911496d (patch)
tree94469e1e2c2d94c174aa9cbdf524027a305ebf68
parent463bc9788fc7f832294f3a3eff2208b5a2b68c8e (diff)
Fix group sorting (#9892)
-rw-r--r--ydb/core/viewer/json_handlers_storage.cpp2
-rw-r--r--ydb/core/viewer/json_handlers_viewer.cpp2
-rw-r--r--ydb/core/viewer/protos/viewer.proto10
-rw-r--r--ydb/core/viewer/storage_groups.h101
-rw-r--r--ydb/core/viewer/viewer_nodes.h37
5 files changed, 138 insertions, 14 deletions
diff --git a/ydb/core/viewer/json_handlers_storage.cpp b/ydb/core/viewer/json_handlers_storage.cpp
index fa99923cea3..750da437452 100644
--- a/ydb/core/viewer/json_handlers_storage.cpp
+++ b/ydb/core/viewer/json_handlers_storage.cpp
@@ -4,7 +4,7 @@
namespace NKikimr::NViewer {
void InitStorageGroupsJsonHandler(TJsonHandlers& jsonHandlers) {
- jsonHandlers.AddHandler("/storage/groups", new TJsonHandler<TStorageGroups>(TStorageGroups::GetSwagger()), 5);
+ jsonHandlers.AddHandler("/storage/groups", new TJsonHandler<TStorageGroups>(TStorageGroups::GetSwagger()), 6);
}
void InitStorageJsonHandlers(TJsonHandlers& jsonHandlers) {
diff --git a/ydb/core/viewer/json_handlers_viewer.cpp b/ydb/core/viewer/json_handlers_viewer.cpp
index 9e4ae55f211..3971bfc0345 100644
--- a/ydb/core/viewer/json_handlers_viewer.cpp
+++ b/ydb/core/viewer/json_handlers_viewer.cpp
@@ -243,7 +243,7 @@ void InitViewerHealthCheckJsonHandler(TJsonHandlers& handlers) {
}
void InitViewerNodesJsonHandler(TJsonHandlers& handlers) {
- handlers.AddHandler("/viewer/nodes", new TJsonHandler<TJsonNodes>(TJsonNodes::GetSwagger()), 7);
+ handlers.AddHandler("/viewer/nodes", new TJsonHandler<TJsonNodes>(TJsonNodes::GetSwagger()), 8);
}
void InitViewerACLJsonHandler(TJsonHandlers &jsonHandlers) {
diff --git a/ydb/core/viewer/protos/viewer.proto b/ydb/core/viewer/protos/viewer.proto
index 80a5ddd8ec7..0330e1ef5f8 100644
--- a/ydb/core/viewer/protos/viewer.proto
+++ b/ydb/core/viewer/protos/viewer.proto
@@ -461,6 +461,16 @@ message TStorageGroupInfo {
message TStorageGroupGroup {
string GroupName = 1;
uint64 GroupCount = 2;
+ optional uint64 Used = 13;
+ optional uint64 Limit = 14;
+ optional uint64 Available = 15;
+ optional float Usage = 16;
+ optional uint64 Read = 17;
+ optional uint64 Write = 18;
+ optional float DiskSpaceUsage = 19;
+ optional uint64 LatencyPutTabletLog = 20;
+ optional uint64 LatencyPutUserData = 21;
+ optional uint64 LatencyGetFast = 22;
}
message TStoragePoolInfo {
diff --git a/ydb/core/viewer/storage_groups.h b/ydb/core/viewer/storage_groups.h
index 026ed293805..e18a86a680b 100644
--- a/ydb/core/viewer/storage_groups.h
+++ b/ydb/core/viewer/storage_groups.h
@@ -174,6 +174,8 @@ public:
std::optional<std::size_t> Limit;
ui32 SpaceUsageProblem = 90; // %
+ using TGroupSortKey = std::variant<TString, ui64, float, bool>;
+
struct TPDisk {
ui32 PDiskId = 0;
TNodeId NodeId = 0;
@@ -273,7 +275,7 @@ public:
ui64 Available = 0;
ui64 Read = 0;
ui64 Write = 0;
- ui32 MissingDisks = 0;
+ ui64 MissingDisks = 0;
ui64 PutTabletLogLatency = 0;
ui64 PutUserDataLatency = 0;
ui64 GetFastLatency = 0;
@@ -523,6 +525,30 @@ public:
}
return groupName;
}
+
+ TGroupSortKey GetSortKey(EGroupFields groupBy) const {
+ switch (groupBy) {
+ case EGroupFields::GroupId:
+ case EGroupFields::Erasure:
+ case EGroupFields::PoolName:
+ case EGroupFields::Kind:
+ case EGroupFields::MediaType:
+ case EGroupFields::State:
+ return GetGroupName(groupBy);
+ case EGroupFields::Usage:
+ return Usage;
+ case EGroupFields::DiskSpaceUsage:
+ return DiskSpaceUsage;
+ case EGroupFields::Encryption:
+ return EncryptionMode;
+ case EGroupFields::MissingDisks:
+ return MissingDisks;
+ case EGroupFields::Latency:
+ return PutTabletLogLatency;
+ default:
+ return TString();
+ }
+ }
};
using TGroupData = std::vector<TGroup>;
@@ -530,7 +556,42 @@ public:
struct TGroupGroup {
TString Name;
+ TGroupSortKey SortKey;
TGroupView Groups;
+
+ // stats
+ float Usage = 0; // avg
+ ui64 Used = 0; // sum
+ ui64 Limit = 0; // sum
+ ui64 Available = 0; // sum
+ ui64 Read = 0; // sum
+ ui64 Write = 0; // sum
+ ui64 PutTabletLogLatency = 0; // max
+ ui64 PutUserDataLatency = 0; // max
+ ui64 GetFastLatency = 0; // max
+ float DiskSpaceUsage = 0; // max
+
+ void CalcStats() {
+ for (TGroup* group : Groups) {
+ Usage += group->Usage;
+ Used += group->Used;
+ Limit += group->Limit;
+ Read += group->Read;
+ Write += group->Write;
+ if (Available) {
+ Available = std::min(Available, group->Available);
+ } else {
+ Available = group->Available;
+ }
+ PutTabletLogLatency = std::max(PutTabletLogLatency, group->PutTabletLogLatency);
+ PutUserDataLatency = std::max(PutUserDataLatency, group->PutUserDataLatency);
+ GetFastLatency = std::max(GetFastLatency, group->GetFastLatency);
+ DiskSpaceUsage = std::max(DiskSpaceUsage, group->DiskSpaceUsage);
+ }
+ if (!Groups.empty()) {
+ Usage /= Groups.size();
+ }
+ }
};
TGroupData GroupData;
@@ -547,8 +608,6 @@ public:
const TFieldsType FieldsAll = TFieldsType().set();
const TFieldsType FieldsBsGroups = TFieldsType().set(+EGroupFields::GroupId)
.set(+EGroupFields::Erasure)
- .set(+EGroupFields::Used)
- .set(+EGroupFields::Limit)
.set(+EGroupFields::Latency);
const TFieldsType FieldsBsPools = TFieldsType().set(+EGroupFields::PoolName)
.set(+EGroupFields::Kind)
@@ -655,6 +714,8 @@ public:
result = EGroupFields::PDiskId;
} else if (field == "Latency") {
result = EGroupFields::Latency;
+ } else if (field == "Available") {
+ result = EGroupFields::Available;
}
return result;
}
@@ -1013,6 +1074,7 @@ public:
groupGroups.emplace(gb, GroupGroups.size());
groupGroup = &GroupGroups.emplace_back();
groupGroup->Name = gb;
+ groupGroup->SortKey = group->GetSortKey(GroupBy);
} else {
groupGroup = &GroupGroups[it->second];
}
@@ -1031,7 +1093,7 @@ public:
case EGroupFields::MediaType:
case EGroupFields::State:
GroupCollection();
- SortCollection(GroupGroups, [](const TGroupGroup& groupGroup) { return groupGroup.Name; });
+ SortCollection(GroupGroups, [](const TGroupGroup& groupGroup) { return groupGroup.SortKey; });
NeedGroup = false;
break;
case EGroupFields::Usage:
@@ -1039,7 +1101,7 @@ public:
case EGroupFields::MissingDisks:
case EGroupFields::Latency:
GroupCollection();
- SortCollection(GroupGroups, [](const TGroupGroup& groupGroup) { return groupGroup.Name; }, true);
+ SortCollection(GroupGroups, [](const TGroupGroup& groupGroup) { return groupGroup.SortKey; }, true);
NeedGroup = false;
break;
case EGroupFields::Read:
@@ -2072,10 +2134,37 @@ public:
}
}
} else {
- for (const TGroupGroup& groupGroup : GroupGroups) {
+ for (TGroupGroup& groupGroup : GroupGroups) {
NKikimrViewer::TStorageGroupGroup& jsonGroupGroup = *json.AddStorageGroupGroups();
jsonGroupGroup.SetGroupName(groupGroup.Name);
jsonGroupGroup.SetGroupCount(groupGroup.Groups.size());
+ groupGroup.CalcStats();
+ if (FieldsAvailable.test(+EGroupFields::Used)) {
+ jsonGroupGroup.SetUsed(groupGroup.Used);
+ }
+ if (FieldsAvailable.test(+EGroupFields::Limit)) {
+ jsonGroupGroup.SetLimit(groupGroup.Limit);
+ }
+ if (FieldsAvailable.test(+EGroupFields::Read)) {
+ jsonGroupGroup.SetRead(groupGroup.Read);
+ }
+ if (FieldsAvailable.test(+EGroupFields::Write)) {
+ jsonGroupGroup.SetWrite(groupGroup.Write);
+ }
+ if (FieldsAvailable.test(+EGroupFields::Usage)) {
+ jsonGroupGroup.SetUsage(groupGroup.Usage);
+ }
+ if (FieldsAvailable.test(+EGroupFields::Available)) {
+ jsonGroupGroup.SetAvailable(groupGroup.Available);
+ }
+ if (FieldsAvailable.test(+EGroupFields::DiskSpaceUsage)) {
+ jsonGroupGroup.SetDiskSpaceUsage(groupGroup.DiskSpaceUsage);
+ }
+ if (FieldsAvailable.test(+EGroupFields::Latency)) {
+ jsonGroupGroup.SetLatencyPutTabletLog(groupGroup.PutTabletLogLatency);
+ jsonGroupGroup.SetLatencyPutUserData(groupGroup.PutUserDataLatency);
+ jsonGroupGroup.SetLatencyGetFast(groupGroup.GetFastLatency);
+ }
}
}
AddEvent("RenderingResult");
diff --git a/ydb/core/viewer/viewer_nodes.h b/ydb/core/viewer/viewer_nodes.h
index f51d4f6484a..acbf7bfa26f 100644
--- a/ydb/core/viewer/viewer_nodes.h
+++ b/ydb/core/viewer/viewer_nodes.h
@@ -145,6 +145,8 @@ class TJsonNodes : public TViewerPipeClient {
bool OffloadMerge = true;
size_t OffloadMergeAttempts = 2;
+ using TGroupSortKey = std::variant<TString, ui64, float>;
+
struct TNode {
TEvInterconnect::TNodeInfo NodeInfo;
NKikimrWhiteboard::TSystemStateInfo SystemState;
@@ -470,6 +472,27 @@ class TJsonNodes : public TViewerPipeClient {
return groupName;
}
+ TGroupSortKey GetGroupSortKey(ENodeFields groupBy, TInstant now) const {
+ switch (groupBy) {
+ case ENodeFields::NodeId:
+ case ENodeFields::HostName:
+ case ENodeFields::NodeName:
+ case ENodeFields::Database:
+ case ENodeFields::DC:
+ case ENodeFields::Rack:
+ case ENodeFields::Version:
+ return GetGroupName(groupBy, now);
+ case ENodeFields::DiskSpaceUsage:
+ return DiskSpaceUsage;
+ case ENodeFields::Missing:
+ return MissingDisks;
+ case ENodeFields::Uptime:
+ return static_cast<ui64>(now.Seconds()) - (Disconnected ? SystemState.GetDisconnectTime() : SystemState.GetStartTime());
+ default:
+ return TString();
+ }
+ }
+
void MergeFrom(const NKikimrWhiteboard::TSystemStateInfo& systemState) {
SystemState.MergeFrom(systemState);
Cleanup();
@@ -479,11 +502,6 @@ class TJsonNodes : public TViewerPipeClient {
}
};
- struct TNodeGroup {
- TString Name;
- std::vector<TNode*> Nodes;
- };
-
struct TNodeBatch {
std::vector<TNode*> NodesToAskFor;
std::vector<TNode*> NodesToAskAbout;
@@ -501,6 +519,12 @@ class TJsonNodes : public TViewerPipeClient {
using TNodeData = std::vector<TNode>;
using TNodeView = std::deque<TNode*>;
+ struct TNodeGroup {
+ TString Name;
+ TGroupSortKey SortKey;
+ TNodeView Nodes;
+ };
+
TNodeData NodeData;
TNodeView NodeView;
std::vector<TNodeGroup> NodeGroups;
@@ -1031,6 +1055,7 @@ public:
nodeGroups.emplace(gb, NodeGroups.size());
nodeGroup = &NodeGroups.emplace_back();
nodeGroup->Name = gb;
+ nodeGroup->SortKey = node->GetGroupSortKey(GroupBy, now);
} else {
nodeGroup = &NodeGroups[it->second];
}
@@ -1052,7 +1077,7 @@ public:
case ENodeFields::Uptime:
case ENodeFields::Version:
GroupCollection();
- SortCollection(NodeGroups, [](const TNodeGroup& nodeGroup) { return nodeGroup.Name; });
+ SortCollection(NodeGroups, [](const TNodeGroup& nodeGroup) { return nodeGroup.SortKey; });
NeedGroup = false;
break;
case ENodeFields::NodeInfo: