Skip to content

Commit eafdb7d

Browse files
YDB-2101 storage handler added check usage when out-of-space filter (#658)
* YDB-2101 storage handler added check usage when out-of-space filter * remove base64 tests
1 parent 9f1bbc8 commit eafdb7d

File tree

3 files changed

+160
-88
lines changed

3 files changed

+160
-88
lines changed

ydb/core/viewer/json_storage.h

+76-58
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,13 @@ class TJsonStorage : public TJsonStorageBase {
5454
uint64 Read;
5555
uint64 Write;
5656

57-
TGroupRow()
57+
TGroupRow()
5858
: Degraded(0)
5959
, Usage(0)
6060
, Used(0)
6161
, Limit(0)
6262
, Read(0)
63-
, Write(0)
63+
, Write(0)
6464
{}
6565
};
6666
THashMap<TString, TGroupRow> GroupRowsByGroupId;
@@ -245,6 +245,36 @@ class TJsonStorage : public TJsonStorageBase {
245245
}
246246
}
247247

248+
bool CheckGroupFilters(const TString& groupId, const TString& poolName, const TGroupRow& groupRow) {
249+
if (!EffectiveFilterGroupIds.empty() && !EffectiveFilterGroupIds.contains(groupId)) {
250+
return false;
251+
}
252+
switch (With) {
253+
case EWith::MissingDisks:
254+
if (BSGroupWithMissingDisks.count(groupId) == 0) {
255+
return false;
256+
}
257+
break;
258+
case EWith::SpaceProblems:
259+
if (BSGroupWithSpaceProblems.count(groupId) == 0 && groupRow.Usage < 0.8) {
260+
return false;
261+
}
262+
break;
263+
case EWith::Everything:
264+
break;
265+
}
266+
if (Filter) {
267+
if (poolName.Contains(Filter)) {
268+
return true;
269+
}
270+
if (groupId.Contains(Filter)) {
271+
return true;
272+
}
273+
return false;
274+
}
275+
return true;
276+
}
277+
248278
void ReplyAndPassAway() override {
249279
if (CheckAdditionalNodesInfoNeeded()) {
250280
return;
@@ -270,19 +300,62 @@ class TJsonStorage : public TJsonStorageBase {
270300
}
271301
ui64 foundGroups = 0;
272302
ui64 totalGroups = 0;
303+
TVector<TGroupRow> GroupRows;
273304
for (const auto& [poolName, poolInfo] : StoragePoolInfo) {
274305
if ((!FilterTenant.empty() || !FilterStoragePools.empty()) && FilterStoragePools.count(poolName) == 0) {
275306
continue;
276307
}
277308
NKikimrViewer::TStoragePoolInfo* pool = StorageInfo.AddStoragePools();
278309
for (TString groupId : poolInfo.Groups) {
310+
TGroupRow row;
311+
row.PoolName = poolName;
312+
row.GroupId = groupId;
313+
row.Kind = poolInfo.Kind;
314+
auto ib = BSGroupIndex.find(groupId);
315+
if (ib != BSGroupIndex.end()) {
316+
row.Erasure = ib->second.GetErasureSpecies();
317+
const auto& vDiskIds = ib->second.GetVDiskIds();
318+
for (auto iv = vDiskIds.begin(); iv != vDiskIds.end(); ++iv) {
319+
const NKikimrBlobStorage::TVDiskID& vDiskId = *iv;
320+
auto ie = VDisksIndex.find(vDiskId);
321+
bool degraded = false;
322+
if (ie != VDisksIndex.end()) {
323+
ui32 nodeId = ie->second.GetNodeId();
324+
ui32 pDiskId = ie->second.GetPDiskId();
325+
degraded |= !ie->second.GetReplicated() || ie->second.GetVDiskState() != NKikimrWhiteboard::EVDiskState::OK;
326+
row.Used += ie->second.GetAllocatedSize();
327+
row.Limit += ie->second.GetAllocatedSize() + ie->second.GetAvailableSize();
328+
row.Read += ie->second.GetReadThroughput();
329+
row.Write += ie->second.GetWriteThroughput();
330+
331+
auto ip = PDisksIndex.find(std::make_pair(nodeId, pDiskId));
332+
if (ip != PDisksIndex.end()) {
333+
degraded |= ip->second.GetState() != NKikimrBlobStorage::TPDiskState::Normal;
334+
if (!ie->second.HasAvailableSize()) {
335+
row.Limit += ip->second.GetAvailableSize();
336+
}
337+
}
338+
}
339+
if (degraded) {
340+
row.Degraded++;
341+
}
342+
}
343+
}
344+
row.Usage = row.Limit == 0 ? 100 : (float)row.Used / row.Limit;
345+
279346
++totalGroups;
280-
if (!CheckGroupFilters(groupId, poolName)) {
347+
if (!CheckGroupFilters(groupId, poolName, row)) {
281348
continue;
282349
}
283350
++foundGroups;
284351
if (Version == EVersion::v1) {
285352
pool->AddGroups()->SetGroupId(groupId);
353+
} else if (Version == EVersion::v2) {
354+
if (!UsageBuckets.empty() && !BinarySearch(UsageBuckets.begin(), UsageBuckets.end(), (ui32)(row.Usage * 100) / UsagePace)) {
355+
continue;
356+
}
357+
GroupRows.emplace_back(row);
358+
GroupRowsByGroupId[groupId] = row;
286359
}
287360
auto itHiveGroup = BSGroupHiveIndex.find(groupId);
288361
if (itHiveGroup != BSGroupHiveIndex.end()) {
@@ -309,61 +382,6 @@ class TJsonStorage : public TJsonStorageBase {
309382
}
310383

311384
if (Version == EVersion::v2) {
312-
TVector<TGroupRow> GroupRows;
313-
for (const auto& [poolName, poolInfo] : StoragePoolInfo) {
314-
if ((!FilterTenant.empty() || !FilterStoragePools.empty()) && FilterStoragePools.count(poolName) == 0) {
315-
continue;
316-
}
317-
for (TString groupId : poolInfo.Groups) {
318-
if (!CheckGroupFilters(groupId, poolName)) {
319-
continue;
320-
}
321-
322-
TGroupRow row;
323-
row.PoolName = poolName;
324-
row.GroupId = groupId;
325-
row.Kind = poolInfo.Kind;
326-
327-
auto ib = BSGroupIndex.find(groupId);
328-
if (ib != BSGroupIndex.end()) {
329-
row.Erasure = ib->second.GetErasureSpecies();
330-
const auto& vDiskIds = ib->second.GetVDiskIds();
331-
for (auto iv = vDiskIds.begin(); iv != vDiskIds.end(); ++iv) {
332-
const NKikimrBlobStorage::TVDiskID& vDiskId = *iv;
333-
auto ie = VDisksIndex.find(vDiskId);
334-
bool degraded = false;
335-
if (ie != VDisksIndex.end()) {
336-
ui32 nodeId = ie->second.GetNodeId();
337-
ui32 pDiskId = ie->second.GetPDiskId();
338-
degraded |= !ie->second.GetReplicated() || ie->second.GetVDiskState() != NKikimrWhiteboard::EVDiskState::OK;
339-
row.Used += ie->second.GetAllocatedSize();
340-
row.Limit += ie->second.GetAllocatedSize() + ie->second.GetAvailableSize();
341-
row.Read += ie->second.GetReadThroughput();
342-
row.Write += ie->second.GetWriteThroughput();
343-
344-
auto ip = PDisksIndex.find(std::make_pair(nodeId, pDiskId));
345-
if (ip != PDisksIndex.end()) {
346-
degraded |= ip->second.GetState() != NKikimrBlobStorage::TPDiskState::Normal;
347-
if (!ie->second.HasAvailableSize()) {
348-
row.Limit += ip->second.GetAvailableSize();
349-
}
350-
}
351-
}
352-
if (degraded) {
353-
row.Degraded++;
354-
}
355-
}
356-
}
357-
358-
row.Usage = row.Limit == 0 ? 100 : (float)row.Used / row.Limit;
359-
if (!UsageBuckets.empty() && !BinarySearch(UsageBuckets.begin(), UsageBuckets.end(), (ui32)(row.Usage * 100) / UsagePace)) {
360-
continue;
361-
}
362-
GroupRows.emplace_back(row);
363-
GroupRowsByGroupId[groupId] = row;
364-
}
365-
}
366-
367385
switch (GroupSort) {
368386
case EGroupSort::PoolName:
369387
SortCollection(GroupRows, [](const TGroupRow& node) { return node.PoolName;}, ReverseSort);

ydb/core/viewer/json_storage_base.h

-30
Original file line numberDiff line numberDiff line change
@@ -407,36 +407,6 @@ class TJsonStorageBase : public TViewerPipeClient<TJsonStorageBase> {
407407
TList<NKikimrWhiteboard::TPDiskStateInfo> PDisksAppended;
408408
TList<NKikimrWhiteboard::TVDiskStateInfo> VDisksAppended;
409409

410-
bool CheckGroupFilters(const TString& groupId, const TString& poolName) {
411-
if (!EffectiveFilterGroupIds.empty() && !EffectiveFilterGroupIds.contains(groupId)) {
412-
return false;
413-
}
414-
switch (With) {
415-
case EWith::MissingDisks:
416-
if (BSGroupWithMissingDisks.count(groupId) == 0) {
417-
return false;
418-
}
419-
break;
420-
case EWith::SpaceProblems:
421-
if (BSGroupWithSpaceProblems.count(groupId) == 0) {
422-
return false;
423-
}
424-
break;
425-
case EWith::Everything:
426-
break;
427-
}
428-
if (Filter) {
429-
if (poolName.Contains(Filter)) {
430-
return true;
431-
}
432-
if (groupId.Contains(Filter)) {
433-
return true;
434-
}
435-
return false;
436-
}
437-
return true;
438-
}
439-
440410
bool CheckAdditionalNodesInfoNeeded() {
441411
if (NeedAdditionalNodesRequests) {
442412
NeedAdditionalNodesRequests = false;

ydb/core/viewer/viewer_ut.cpp

+84
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <library/cpp/testing/unittest/tests_data.h>
33
#include <ydb/library/actors/interconnect/interconnect.h>
44
#include <ydb/library/actors/helpers/selfping_actor.h>
5+
#include <library/cpp/json/json_value.h>
56
#include <library/cpp/json/json_reader.h>
67
#include <util/stream/null.h>
78
#include <ydb/core/viewer/protos/viewer.pb.h>
@@ -291,6 +292,19 @@ Y_UNIT_TEST_SUITE(Viewer) {
291292
nodeId++;
292293
}
293294

295+
void ChangeVDiskStateResponse(TEvWhiteboard::TEvVDiskStateResponse::TPtr* ev, NKikimrWhiteboard::EFlag diskSpace, ui64 used, ui64 limit) {
296+
auto& pbRecord = (*ev)->Get()->Record;
297+
auto state = pbRecord.add_vdiskstateinfo();
298+
state->mutable_vdiskid()->set_vdisk(0);
299+
state->mutable_vdiskid()->set_groupid(0);
300+
state->mutable_vdiskid()->set_groupgeneration(1);
301+
state->set_diskspace(diskSpace);
302+
state->set_vdiskstate(NKikimrWhiteboard::EVDiskState::OK);
303+
state->set_nodeid(0);
304+
state->set_allocatedsize(used);
305+
state->set_availablesize(limit - used);
306+
}
307+
294308
void ChangeDescribeSchemeResult(TEvSchemeShard::TEvDescribeSchemeResult::TPtr* ev, int tabletsTotal) {
295309
auto record = (*ev)->Get()->MutableRecord();
296310
auto params = record->mutable_pathdescription()->mutable_domaindescription()->mutable_processingparams();
@@ -516,4 +530,74 @@ Y_UNIT_TEST_SUITE(Viewer) {
516530
{
517531
QueryTest("select \"Hello\"", false, "Hello");
518532
}
533+
534+
void StorageSpaceTest(const TString& withValue, const NKikimrWhiteboard::EFlag diskSpace, const ui64 used, const ui64 limit, const bool isExpectingGroup) {
535+
TPortManager tp;
536+
ui16 port = tp.GetPort(2134);
537+
ui16 grpcPort = tp.GetPort(2135);
538+
auto settings = TServerSettings(port);
539+
settings.InitKikimrRunConfig()
540+
.SetNodeCount(1)
541+
.SetUseRealThreads(false)
542+
.SetDomainName("Root");
543+
TServer server(settings);
544+
server.EnableGRpc(grpcPort);
545+
TClient client(settings);
546+
TTestActorRuntime& runtime = *server.GetRuntime();
547+
548+
TActorId sender = runtime.AllocateEdgeActor();
549+
TAutoPtr<IEventHandle> handle;
550+
551+
THttpRequest httpReq(HTTP_METHOD_GET);
552+
httpReq.CgiParameters.emplace("with", withValue);
553+
httpReq.CgiParameters.emplace("version", "v2");
554+
auto page = MakeHolder<TMonPage>("viewer", "title");
555+
TMonService2HttpRequest monReq(nullptr, &httpReq, nullptr, page.Get(), "/json/storage", nullptr);
556+
auto request = MakeHolder<NMon::TEvHttpInfo>(monReq);
557+
558+
auto observerFunc = [&](TAutoPtr<IEventHandle>& ev) {
559+
Y_UNUSED(ev);
560+
if (ev->GetTypeRewrite() == TEvWhiteboard::EvVDiskStateResponse) {
561+
auto *x = reinterpret_cast<TEvWhiteboard::TEvVDiskStateResponse::TPtr*>(&ev);
562+
ChangeVDiskStateResponse(x, diskSpace, used, limit);
563+
}
564+
565+
return TTestActorRuntime::EEventAction::PROCESS;
566+
};
567+
runtime.SetObserverFunc(observerFunc);
568+
569+
runtime.Send(new IEventHandle(NKikimr::NViewer::MakeViewerID(0), sender, request.Release(), 0));
570+
NMon::TEvHttpInfoRes* result = runtime.GrabEdgeEvent<NMon::TEvHttpInfoRes>(handle);
571+
572+
size_t pos = result->Answer.find('{');
573+
TString jsonResult = result->Answer.substr(pos);
574+
Ctest << "json result: " << jsonResult << Endl;
575+
NJson::TJsonValue json;
576+
try {
577+
NJson::ReadJsonTree(jsonResult, &json, true);
578+
}
579+
catch (yexception ex) {
580+
Ctest << ex.what() << Endl;
581+
}
582+
UNIT_ASSERT_VALUES_EQUAL(json.GetMap().contains("StorageGroups"), isExpectingGroup);
583+
}
584+
585+
Y_UNIT_TEST(StorageGroupOutputWithoutFilterNoDepends)
586+
{
587+
StorageSpaceTest("all", NKikimrWhiteboard::EFlag::Green, 10, 100, true);
588+
StorageSpaceTest("all", NKikimrWhiteboard::EFlag::Red, 90, 100, true);
589+
}
590+
591+
Y_UNIT_TEST(StorageGroupOutputWithSpaceCheckDependsOnVDiskSpaceStatus)
592+
{
593+
StorageSpaceTest("space", NKikimrWhiteboard::EFlag::Green, 10, 100, false);
594+
StorageSpaceTest("space", NKikimrWhiteboard::EFlag::Red, 10, 100, true);
595+
}
596+
597+
Y_UNIT_TEST(StorageGroupOutputWithSpaceCheckDependsOnUsage)
598+
{
599+
StorageSpaceTest("space", NKikimrWhiteboard::EFlag::Green, 70, 100, false);
600+
StorageSpaceTest("space", NKikimrWhiteboard::EFlag::Green, 80, 100, true);
601+
StorageSpaceTest("space", NKikimrWhiteboard::EFlag::Green, 90, 100, true);
602+
}
519603
}

0 commit comments

Comments
 (0)