@@ -107,6 +107,7 @@ enum class EGroupFields : ui8 {
107
107
PDiskId,
108
108
VDisk, // VDisk information
109
109
PDisk, // PDisk information
110
+ Latency,
110
111
COUNT
111
112
};
112
113
@@ -235,7 +236,7 @@ class TStorageGroups : public TViewerPipeClient {
235
236
ui64 AllocatedSize = 0 ;
236
237
ui64 AvailableSize = 0 ;
237
238
TString Status;
238
- NKikimrBlobStorage::EVDiskStatus VDiskStatus = NKikimrBlobStorage::EVDiskStatus::ERROR ;
239
+ std::optional< NKikimrBlobStorage::EVDiskStatus> VDiskStatus ;
239
240
ui64 Read = 0 ;
240
241
ui64 Write = 0 ;
241
242
NKikimrViewer::EFlag DiskSpace = NKikimrViewer::EFlag::Grey;
@@ -317,6 +318,27 @@ class TStorageGroups : public TViewerPipeClient {
317
318
return MissingDisks == 0 ? TString (" 0" ) : TStringBuilder () << " -" << MissingDisks;
318
319
}
319
320
321
+ static int RoundUpTime (int v) {
322
+ static const int roundUp[] = {1 , 5 , 10 , 50 , 100 , 200 , 500 , 1000 };
323
+ auto it = std::lower_bound (std::begin (roundUp), std::end (roundUp), v);
324
+ if (it == std::end (roundUp)) {
325
+ return 1000 ;
326
+ }
327
+ return *it;
328
+ }
329
+
330
+ TString GetLatencyForGroup () const {
331
+ if (PutTabletLogLatency == 0 ) {
332
+ return " -" ;
333
+ } else if (PutTabletLogLatency < 1000 ) {
334
+ return TStringBuilder () << RoundUpTime (PutTabletLogLatency) << " us" ;
335
+ } else if (PutTabletLogLatency < 1000000 ) {
336
+ return TStringBuilder () << RoundUpTime (PutTabletLogLatency / 1000 ) << " ms" ;
337
+ } else {
338
+ return TStringBuilder () << RoundUpTime (PutTabletLogLatency / 1000000 ) << " s" ;
339
+ }
340
+ }
341
+
320
342
// none: ok, dead:1
321
343
// block-4-2: ok, replicating:1 starting:1, degraded:1, degraded:2, dead:3
322
344
// mirror-3-dc: ok, degraded:1(1), degraded:1(2), degraded:1(3), degraded:2(3,1), dead:3(3,1,1)
@@ -331,18 +353,18 @@ class TStorageGroups : public TViewerPipeClient {
331
353
static_assert (sizeof (TVDiskID::FailRealm) == 1 , " expecting byte" );
332
354
std::vector<ui8> failedDomainsPerRealm;
333
355
for (const TVDisk& vdisk : VDisks) {
334
- if (vdisk.VDiskStatus != NKikimrBlobStorage::EVDiskStatus::READY) {
356
+ if (vdisk.VDiskStatus && *vdisk. VDiskStatus != NKikimrBlobStorage::EVDiskStatus::READY) {
335
357
if (ErasureSpecies == TErasureType::ErasureMirror3dc) {
336
358
if (failedDomainsPerRealm.size () <= vdisk.VDiskId .FailRealm ) {
337
359
failedDomainsPerRealm.resize (vdisk.VDiskId .FailRealm + 1 );
338
360
}
339
361
failedDomainsPerRealm[vdisk.VDiskId .FailRealm ]++;
340
362
}
341
363
++MissingDisks;
342
- if (vdisk.VDiskStatus == NKikimrBlobStorage::EVDiskStatus::INIT_PENDING) {
364
+ if (* vdisk.VDiskStatus == NKikimrBlobStorage::EVDiskStatus::INIT_PENDING) {
343
365
++startingDisks;
344
366
}
345
- if (vdisk.VDiskStatus == NKikimrBlobStorage::EVDiskStatus::REPLICATING) {
367
+ if (* vdisk.VDiskStatus == NKikimrBlobStorage::EVDiskStatus::REPLICATING) {
346
368
++replicatingDisks;
347
369
}
348
370
}
@@ -452,6 +474,10 @@ class TStorageGroups : public TViewerPipeClient {
452
474
Read = read;
453
475
Write = write;
454
476
}
477
+
478
+ ui64 GetLatencyForSort () const {
479
+ return PutTabletLogLatency;
480
+ }
455
481
};
456
482
457
483
using TGroupData = std::vector<TGroup>;
@@ -478,7 +504,8 @@ class TStorageGroups : public TViewerPipeClient {
478
504
.set(+EGroupFields::Erasure)
479
505
.set(+EGroupFields::Usage)
480
506
.set(+EGroupFields::Used)
481
- .set(+EGroupFields::Limit);
507
+ .set(+EGroupFields::Limit)
508
+ .set(+EGroupFields::Latency);
482
509
const TFieldsType FieldsBsPools = TFieldsType().set(+EGroupFields::PoolName)
483
510
.set(+EGroupFields::Kind)
484
511
.set(+EGroupFields::MediaType)
@@ -569,6 +596,12 @@ class TStorageGroups : public TViewerPipeClient {
569
596
result = EGroupFields::PDisk;
570
597
} else if (field == " DiskSpaceUsage" ) {
571
598
result = EGroupFields::DiskSpaceUsage;
599
+ } else if (field == " NodeId" ) {
600
+ result = EGroupFields::NodeId;
601
+ } else if (field == " PDiskId" ) {
602
+ result = EGroupFields::PDiskId;
603
+ } else if (field == " Latency" ) {
604
+ result = EGroupFields::Latency;
572
605
}
573
606
return result;
574
607
}
@@ -931,6 +964,10 @@ class TStorageGroups : public TViewerPipeClient {
931
964
GroupCollection ([](const TGroup* group) { return group->State ; });
932
965
SortCollection (GroupGroups, [](const TGroupGroup& groupGroup) { return groupGroup.Name ; });
933
966
break ;
967
+ case EGroupFields::Latency:
968
+ GroupCollection ([](const TGroup* group) { return group->GetLatencyForGroup (); });
969
+ SortCollection (GroupGroups, [](const TGroupGroup& groupGroup) { return groupGroup.Name ; }, true );
970
+ break ;
934
971
case EGroupFields::Read:
935
972
case EGroupFields::Write:
936
973
case EGroupFields::NodeId:
@@ -999,6 +1036,9 @@ class TStorageGroups : public TViewerPipeClient {
999
1036
case EGroupFields::State:
1000
1037
SortCollection (GroupView, [](const TGroup* group) { return group->State ; }, ReverseSort);
1001
1038
break ;
1039
+ case EGroupFields::Latency:
1040
+ SortCollection (GroupView, [](const TGroup* group) { return group->GetLatencyForSort (); }, ReverseSort);
1041
+ break ;
1002
1042
case EGroupFields::PDiskId:
1003
1043
case EGroupFields::NodeId:
1004
1044
case EGroupFields::PDisk:
@@ -1147,7 +1187,10 @@ class TStorageGroups : public TViewerPipeClient {
1147
1187
vDisk.AvailableSize = info.GetAvailableSize ();
1148
1188
// vDisk.Kind = info.GetKind();
1149
1189
vDisk.Status = info.GetStatusV2 ();
1150
- NKikimrBlobStorage::EVDiskStatus_Parse (info.GetStatusV2 (), &vDisk.VDiskStatus );
1190
+ NKikimrBlobStorage::EVDiskStatus vDiskStatus;
1191
+ if (vDisk.Status && NKikimrBlobStorage::EVDiskStatus_Parse (vDisk.Status , &vDiskStatus)) {
1192
+ vDisk.VDiskStatus = vDiskStatus;
1193
+ }
1151
1194
}
1152
1195
1153
1196
bool AreBSControllerRequestsDone () const {
@@ -1432,7 +1475,6 @@ class TStorageGroups : public TViewerPipeClient {
1432
1475
for (auto & vDiskId : info->GetVDiskIds ()) {
1433
1476
TVDisk& vDisk = group.VDisks .emplace_back ();
1434
1477
vDisk.VDiskId = VDiskIDFromVDiskID (vDiskId);
1435
- vDisk.VDiskStatus = NKikimrBlobStorage::EVDiskStatus::ERROR;
1436
1478
}
1437
1479
if (capacity != GroupData.capacity ()) {
1438
1480
// we expect to never do this
@@ -1493,7 +1535,9 @@ class TStorageGroups : public TViewerPipeClient {
1493
1535
vDisk.VDiskStatus = info.GetReplicated () ? NKikimrBlobStorage::EVDiskStatus::READY : NKikimrBlobStorage::EVDiskStatus::REPLICATING;
1494
1536
break ;
1495
1537
}
1496
- vDisk.Status = NKikimrBlobStorage::EVDiskStatus_Name (vDisk.VDiskStatus );
1538
+ if (vDisk.VDiskStatus ) {
1539
+ vDisk.Status = NKikimrBlobStorage::EVDiskStatus_Name (*vDisk.VDiskStatus );
1540
+ }
1497
1541
vDisk.DiskSpace = static_cast <NKikimrViewer::EFlag>(info.GetDiskSpace ());
1498
1542
vDisk.Donor = info.GetDonorMode ();
1499
1543
for (auto & donor : info.GetDonors ()) {
@@ -1829,9 +1873,9 @@ class TStorageGroups : public TViewerPipeClient {
1829
1873
void ReplyAndPassAway () override {
1830
1874
ApplyEverything ();
1831
1875
NKikimrViewer::TStorageGroupsInfo json;
1832
- json.SetVersion (2 );
1833
- json.SetFieldsAvailable (FieldsAvailable.to_ulong ());
1834
- json.SetFieldsRequired (FieldsRequired.to_ulong ());
1876
+ json.SetVersion (Viewer-> GetCapabilityVersion ( " /storage/groups " ) );
1877
+ json.SetFieldsAvailable (FieldsAvailable.to_string ());
1878
+ json.SetFieldsRequired (FieldsRequired.to_string ());
1835
1879
if (NeedFilter) {
1836
1880
json.SetNeedFilter (true );
1837
1881
}
@@ -1907,6 +1951,11 @@ class TStorageGroups : public TViewerPipeClient {
1907
1951
if (FieldsAvailable.test (+EGroupFields::Available)) {
1908
1952
jsonGroup.SetAvailable (group->Available );
1909
1953
}
1954
+ if (FieldsAvailable.test (+EGroupFields::Latency)) {
1955
+ jsonGroup.SetLatencyPutTabletLog (group->PutTabletLogLatency );
1956
+ jsonGroup.SetLatencyPutUserData (group->PutUserDataLatency );
1957
+ jsonGroup.SetLatencyGetFast (group->GetFastLatency );
1958
+ }
1910
1959
}
1911
1960
} else {
1912
1961
for (const TGroupGroup& groupGroup : GroupGroups) {
@@ -2002,6 +2051,7 @@ class TStorageGroups : public TViewerPipeClient {
2002
2051
* `AllocationUnits`
2003
2052
* `Read`
2004
2053
* `Write`
2054
+ * `Latency`
2005
2055
required: false
2006
2056
type: string
2007
2057
- name: group
@@ -2018,6 +2068,7 @@ class TStorageGroups : public TViewerPipeClient {
2018
2068
* `MediaType`
2019
2069
* `MissingDisks`
2020
2070
* `State`
2071
+ * `Latency`
2021
2072
required: false
2022
2073
type: string
2023
2074
- name: fields_required
@@ -2043,6 +2094,7 @@ class TStorageGroups : public TViewerPipeClient {
2043
2094
* `Write`
2044
2095
* `PDisk`
2045
2096
* `VDisk`
2097
+ * `Latency`
2046
2098
required: false
2047
2099
type: string
2048
2100
- name: offset
0 commit comments