Skip to content

Commit 934af54

Browse files
authored
Add additional fields to the model for the FDB database status. (#2267)
1 parent fb0f42c commit 934af54

File tree

5 files changed

+326
-25
lines changed

5 files changed

+326
-25
lines changed

api/v1beta2/foundationdb_status.go

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,21 @@ type FoundationDBStatusClusterInfo struct {
140140

141141
// BounceImpact represents the bounce_impact part of the machine-readable status.
142142
BounceImpact FoundationDBBounceImpact `json:"bounce_impact,omitempty"`
143+
144+
// DatabaseAvailable indicates whether the database is currently available.
145+
DatabaseAvailable *bool `json:"database_available,omitempty"`
146+
147+
// ActivePrimaryDC indicates which data center is currently the primary.
148+
ActivePrimaryDC *string `json:"active_primary_dc,omitempty"`
149+
150+
// DatabaseLockState provides information about the database's locking.
151+
DatabaseLockState FoundationDBStatusLockState `json:"database_lock_state,omitempty"`
152+
}
153+
154+
// FoundationDBStatusLockState provides information about the database's locking.
155+
type FoundationDBStatusLockState struct {
156+
// Locked indicates whether the database is currently locked.
157+
Locked *bool `json:"locked,omitempty"`
143158
}
144159

145160
// FoundationDBBounceImpact represents the bounce_impact part of the machine-readable status.
@@ -209,6 +224,51 @@ type FoundationDBStatusProcessRoleInfo struct {
209224
StoredBytes int `json:"stored_bytes,omitempty"`
210225
// ID represent the role ID.
211226
ID string `json:"id,omitempty"`
227+
228+
// DataLag indicates whether this process is lagging in its writes.
229+
DataLag FoundationDBStatusLagInfo `json:"data_lag,omitempty"`
230+
231+
// KVStoreUsedBytes indicates how much space this process is using on its disk.
232+
KVStoreUsedBytes *int64 `json:"kvstore_used_bytes"`
233+
234+
// KVStoreTotalBytes indicates how much space this process's disk has in total.
235+
KVStoreTotalBytes *int64 `json:"kvstore_total_bytes"`
236+
237+
// KVStoreFreeBytes indicates how much free space this process's disk has.
238+
KVStoreFreeBytes *int64 `json:"kvstore_free_bytes"`
239+
240+
// KVStoreAvailableBytes indicates how much space this process can still use on its disk, inclusive of both free space and unused written space.
241+
KVStoreAvailableBytes *int64 `json:"kvstore_available_bytes"`
242+
243+
// ReadLatencyStatistics provides statistics about this process's read latencies.
244+
ReadLatencyStatistics FoundationDBStatusPerfStatistics `json:"read_latency_statistics"`
245+
246+
// ReadLatencyStatistics provides statistics about this process's commit latencies.
247+
CommitLatencyStatistics FoundationDBStatusPerfStatistics `json:"commit_latency_statistics"`
248+
249+
// ReadLatencyStatistics provides statistics about this process's GRV latencies.
250+
GRVLatencyStatistics FoundationDBStatusGRVStatistics `json:"grv_latency_statistics"`
251+
}
252+
253+
// FoundationDBStatusPerfStatistics models information about one dimension of a process's performance.
254+
type FoundationDBStatusPerfStatistics struct {
255+
// Count provides the number of observations for this stat.
256+
Count *int `json:"count"`
257+
258+
// Median provides the median value for this stat.
259+
Median *float64 `json:"median"`
260+
261+
// P99 provides the 99th percentile value for this stat.
262+
P99 *float64 `json:"p99"`
263+
}
264+
265+
// FoundationDBStatusGRVStatistics models information about a process's GRV latencies.
266+
type FoundationDBStatusGRVStatistics struct {
267+
// Batch provides the GRV latencies at batch priority.
268+
Batch FoundationDBStatusPerfStatistics `json:"batch"`
269+
270+
// Default provides the GRV latencies at default priority.
271+
Default FoundationDBStatusPerfStatistics `json:"default"`
212272
}
213273

214274
// FoundationDBStatusDataStatistics provides information about the data in
@@ -225,6 +285,9 @@ type FoundationDBStatusDataStatistics struct {
225285

226286
// TeamTrackers provides information about (highest priority) teams.
227287
TeamTrackers []FoundationDBStatusTeamTracker `json:"team_trackers,omitempty"`
288+
289+
// TotalDiskUsedBytes provides the total bytes used on disk by the database.
290+
TotalDiskUsedBytes *int64 `json:"total_disk_used_bytes,omitempty"`
228291
}
229292

230293
// FoundationDBStatusDataState provides information about the state of data
@@ -268,6 +331,9 @@ type FoundationDBStatusTeamTracker struct {
268331
// FoundationDBStatusDataState provides information about the state of the
269332
// highest priority team.
270333
State FoundationDBStatusDataState `json:"state,omitempty"`
334+
335+
// UnhealthyServers defines how many unhealthy servers this team has.
336+
UnhealthyServers *int64 `json:"unhealthy_servers,omitempty"`
271337
}
272338

273339
// FoundationDBStatusClientDBStatus represents the databaseStatus field in the
@@ -335,6 +401,9 @@ func (client FoundationDBStatusConnectedClient) Description() string {
335401
// FoundationDBStatusLayerInfo provides information about layers that are
336402
// running against the cluster.
337403
type FoundationDBStatusLayerInfo struct {
404+
// Valid indicates whether the layer info is valid, meaning that it can be trusted as a full set of information.
405+
Valid *bool `json:"_valid,omitempty"`
406+
338407
// Backup provides information about backups that have been started.
339408
Backup FoundationDBStatusBackupInfo `json:"backup,omitempty"`
340409

@@ -354,9 +423,20 @@ type FoundationDBStatusBackupInfo struct {
354423
// FoundationDBStatusBackupTag provides information about a backup under a tag
355424
// in the cluster status.
356425
type FoundationDBStatusBackupTag struct {
426+
// CurrentContainer identifies the container for this backup.
357427
CurrentContainer string `json:"current_container,omitempty"`
358-
RunningBackup bool `json:"running_backup,omitempty"`
359-
Restorable bool `json:"running_backup_is_restorable,omitempty"`
428+
429+
// RunningBackup indicates whether the backup is currently running.
430+
RunningBackup *bool `json:"running_backup,omitempty"`
431+
432+
// Restorable indicates whether the current backup is restorable.
433+
Restorable *bool `json:"running_backup_is_restorable,omitempty"`
434+
435+
// LastRestorableSecondsBehind indicates how long ago the last restorable point-in-time for the backup is.
436+
LastRestorableSecondsBehind *float64 `json:"last_restorable_seconds_behind,omitempty"`
437+
438+
// LastRestorableSecondsBehind indicates how many versions behind the last restorable point-in-time for the backup is.
439+
LastRestorableVersion *int64 `json:"last_restorable_version,omitempty"`
360440
}
361441

362442
// FoundationDBStatusLogInfo provides information about the fault tolerance metrics

api/v1beta2/foundationdb_status_test.go

Lines changed: 94 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,26 @@ package v1beta2
2222

2323
import (
2424
"encoding/json"
25+
"maps"
2526
"net"
2627
"os"
2728
"path/filepath"
28-
29-
"k8s.io/utils/pointer"
29+
"slices"
3030

3131
. "github.com/onsi/ginkgo/v2"
3232
. "github.com/onsi/gomega"
33+
"github.com/onsi/gomega/format"
34+
"k8s.io/utils/pointer"
3335
)
3436

3537
var _ = Describe("FoundationDBStatus", func() {
38+
BeforeEach(func() {
39+
format.MaxLength = 10000000
40+
})
41+
3642
When("parsing the status json with a 7.1.0-rc1 cluster", func() {
3743
migrationType := StorageMigrationTypeDisabled
38-
status := FoundationDBStatusClusterInfo{
44+
clusterInfo := FoundationDBStatusClusterInfo{
3945
Messages: []FoundationDBStatusMessage{},
4046
IncompatibleConnections: []string{},
4147
ConnectionString: "test_cluster:[email protected]:4501,10.1.18.254:4501,10.1.19.0:4501",
@@ -73,10 +79,23 @@ var _ = Describe("FoundationDBStatus", func() {
7379
{
7480
Role: string(ProcessRoleGrvProxy),
7581
ID: "0de7f5c5e549cad1",
82+
GRVLatencyStatistics: FoundationDBStatusGRVStatistics{
83+
Batch: FoundationDBStatusPerfStatistics{Count: pointer.Int(6), Median: pointer.Float64(0.000531435), P99: pointer.Float64(0.00130677)},
84+
Default: FoundationDBStatusPerfStatistics{Count: pointer.Int(225), Median: pointer.Float64(0.00062561), P99: pointer.Float64(0.010715200000000001)},
85+
},
7686
},
7787
{
7888
Role: string(ProcessRoleStorage),
7989
ID: "9941616400759d37",
90+
DataLag: FoundationDBStatusLagInfo{
91+
Seconds: 0.19625800000000002,
92+
Versions: 196258,
93+
},
94+
KVStoreUsedBytes: pointer.Int64(104878232),
95+
KVStoreTotalBytes: pointer.Int64(135012552704),
96+
KVStoreFreeBytes: pointer.Int64(84178223104),
97+
KVStoreAvailableBytes: pointer.Int64(84178223104),
98+
ReadLatencyStatistics: FoundationDBStatusPerfStatistics{Count: pointer.Int(297), Median: pointer.Float64(0.000116825), P99: pointer.Float64(0.000711441)},
8099
},
81100
},
82101
Messages: []FoundationDBStatusProcessMessage{},
@@ -100,8 +119,14 @@ var _ = Describe("FoundationDBStatus", func() {
100119
Roles: []FoundationDBStatusProcessRoleInfo{
101120
{Role: string(ProcessRoleCoordinator)},
102121
{
103-
Role: string(ProcessClassStorage),
104-
ID: "389c23d59a646e52",
122+
Role: string(ProcessClassStorage),
123+
ID: "389c23d59a646e52",
124+
DataLag: FoundationDBStatusLagInfo{Seconds: 2.1227, Versions: 2122697},
125+
KVStoreUsedBytes: pointer.Int64(104878232),
126+
KVStoreTotalBytes: pointer.Int64(135012552704),
127+
KVStoreFreeBytes: pointer.Int64(84178239488),
128+
KVStoreAvailableBytes: pointer.Int64(84178239488),
129+
ReadLatencyStatistics: FoundationDBStatusPerfStatistics{Count: pointer.Int(334), Median: pointer.Float64(0.000102282), P99: pointer.Float64(0.000386477)},
105130
},
106131
{
107132
Role: string(ProcessRoleResolver),
@@ -131,10 +156,24 @@ var _ = Describe("FoundationDBStatus", func() {
131156
{
132157
Role: string(ProcessRoleCommitProxy),
133158
ID: "0eb90e4a0ece85b3",
159+
CommitLatencyStatistics: FoundationDBStatusPerfStatistics{
160+
Count: pointer.Int(31),
161+
Median: pointer.Float64(0.00794888),
162+
P99: pointer.Float64(0.09054090000000001),
163+
},
134164
},
135165
{
136166
Role: string(ProcessRoleStorage),
137167
ID: "b5e42e100018bf11",
168+
DataLag: FoundationDBStatusLagInfo{
169+
Seconds: 0.19625800000000002,
170+
Versions: 196258,
171+
},
172+
KVStoreUsedBytes: pointer.Int64(104861752),
173+
KVStoreTotalBytes: pointer.Int64(135012552704),
174+
KVStoreFreeBytes: pointer.Int64(84178112512),
175+
KVStoreAvailableBytes: pointer.Int64(84178112512),
176+
ReadLatencyStatistics: FoundationDBStatusPerfStatistics{Count: pointer.Int(0), Median: pointer.Float64(0), P99: pointer.Float64(0)},
138177
},
139178
},
140179
Messages: []FoundationDBStatusProcessMessage{},
@@ -213,8 +252,12 @@ var _ = Describe("FoundationDBStatus", func() {
213252
UptimeSeconds: 85.0029,
214253
Roles: []FoundationDBStatusProcessRoleInfo{
215254
{
216-
Role: string(ProcessRoleLog),
217-
ID: "2c66a861b33b2697",
255+
Role: string(ProcessRoleLog),
256+
ID: "2c66a861b33b2697",
257+
KVStoreUsedBytes: pointer.Int64(104861752),
258+
KVStoreTotalBytes: pointer.Int64(135012552704),
259+
KVStoreFreeBytes: pointer.Int64(84178214912),
260+
KVStoreAvailableBytes: pointer.Int64(84178214912),
218261
},
219262
},
220263
Messages: []FoundationDBStatusProcessMessage{},
@@ -237,8 +280,12 @@ var _ = Describe("FoundationDBStatus", func() {
237280
UptimeSeconds: 85.003,
238281
Roles: []FoundationDBStatusProcessRoleInfo{
239282
{
240-
Role: string(ProcessRoleLog),
241-
ID: "56cf105980ec2b07",
283+
Role: string(ProcessRoleLog),
284+
ID: "56cf105980ec2b07",
285+
KVStoreUsedBytes: pointer.Int64(104861752),
286+
KVStoreTotalBytes: pointer.Int64(135012552704),
287+
KVStoreFreeBytes: pointer.Int64(84178214912),
288+
KVStoreAvailableBytes: pointer.Int64(84178214912),
242289
},
243290
},
244291
Messages: []FoundationDBStatusProcessMessage{},
@@ -261,8 +308,12 @@ var _ = Describe("FoundationDBStatus", func() {
261308
UptimeSeconds: 85.0027,
262309
Roles: []FoundationDBStatusProcessRoleInfo{
263310
{
264-
Role: string(ProcessRoleLog),
265-
ID: "31754d1d7d8d6f05",
311+
Role: string(ProcessRoleLog),
312+
ID: "31754d1d7d8d6f05",
313+
KVStoreUsedBytes: pointer.Int64(104861752),
314+
KVStoreTotalBytes: pointer.Int64(135012552704),
315+
KVStoreFreeBytes: pointer.Int64(84178202624),
316+
KVStoreAvailableBytes: pointer.Int64(84178202624),
266317
},
267318
},
268319
Messages: []FoundationDBStatusProcessMessage{},
@@ -274,10 +325,12 @@ var _ = Describe("FoundationDBStatus", func() {
274325
State: FoundationDBStatusDataState{Description: "", Healthy: true, Name: "healthy", MinReplicasRemaining: 2},
275326
TeamTrackers: []FoundationDBStatusTeamTracker{
276327
{
277-
Primary: true,
278-
State: FoundationDBStatusDataState{Description: "", Healthy: true, Name: "healthy", MinReplicasRemaining: 2},
328+
Primary: true,
329+
State: FoundationDBStatusDataState{Description: "", Healthy: true, Name: "healthy", MinReplicasRemaining: 2},
330+
UnhealthyServers: pointer.Int64(0),
279331
},
280332
},
333+
TotalDiskUsedBytes: pointer.Int64(629203472),
281334
},
282335
FullReplication: true,
283336
Clients: FoundationDBStatusClusterClientInfo{
@@ -399,6 +452,7 @@ var _ = Describe("FoundationDBStatus", func() {
399452
},
400453
},
401454
Layers: FoundationDBStatusLayerInfo{
455+
Valid: pointer.Bool(true),
402456
Backup: FoundationDBStatusBackupInfo{Paused: false, Tags: nil},
403457
Error: "",
404458
},
@@ -442,6 +496,11 @@ var _ = Describe("FoundationDBStatus", func() {
442496
BounceImpact: FoundationDBBounceImpact{
443497
CanCleanBounce: pointer.Bool(true),
444498
},
499+
DatabaseAvailable: pointer.Bool(true),
500+
ActivePrimaryDC: pointer.String(""),
501+
DatabaseLockState: FoundationDBStatusLockState{
502+
Locked: pointer.Bool(false),
503+
},
445504
}
446505

447506
It("should parse all values correctly", func() {
@@ -452,7 +511,28 @@ var _ = Describe("FoundationDBStatus", func() {
452511
statusParsed := FoundationDBStatus{}
453512
err = statusDecoder.Decode(&statusParsed)
454513
Expect(err).NotTo(HaveOccurred())
455-
Expect(statusParsed.Cluster).To(Equal(status))
514+
515+
// Gomega needs some prodding to effectively format diffs between these status objects, so we compare
516+
// the fields one by one.
517+
clusterInfoParsed := statusParsed.Cluster
518+
Expect(clusterInfoParsed.DatabaseConfiguration).To(Equal(clusterInfo.DatabaseConfiguration))
519+
Expect(clusterInfoParsed.Processes).To(ConsistOf(slices.Collect(maps.Values(clusterInfo.Processes))))
520+
Expect(clusterInfoParsed.Data).To(Equal(clusterInfo.Data))
521+
Expect(clusterInfoParsed.FullReplication).To(Equal(clusterInfo.FullReplication))
522+
Expect(clusterInfoParsed.Generation).To(Equal(clusterInfo.Generation))
523+
Expect(clusterInfoParsed.MaintenanceZone).To(Equal(clusterInfo.MaintenanceZone))
524+
Expect(clusterInfoParsed.Clients.Count).To(Equal(clusterInfo.Clients.Count))
525+
Expect(clusterInfoParsed.Clients.SupportedVersions).To(HaveExactElements(clusterInfoParsed.Clients.SupportedVersions))
526+
Expect(clusterInfoParsed.Layers).To(Equal(clusterInfo.Layers))
527+
Expect(clusterInfoParsed.Logs).To(HaveExactElements(clusterInfo.Logs))
528+
Expect(clusterInfoParsed.Qos).To(Equal(clusterInfo.Qos))
529+
Expect(clusterInfoParsed.FaultTolerance).To(Equal(clusterInfo.FaultTolerance))
530+
Expect(clusterInfoParsed.MaintenanceZone).To(Equal(clusterInfo.MaintenanceZone))
531+
Expect(clusterInfoParsed.IncompatibleConnections).To(HaveExactElements(clusterInfo.IncompatibleConnections))
532+
Expect(clusterInfoParsed.BounceImpact).To(Equal(clusterInfo.BounceImpact))
533+
Expect(clusterInfoParsed.DatabaseAvailable).To(Equal(clusterInfo.DatabaseAvailable))
534+
Expect(clusterInfoParsed.ActivePrimaryDC).To(Equal(clusterInfo.ActivePrimaryDC))
535+
Expect(clusterInfoParsed.DatabaseLockState).To(Equal(clusterInfo.DatabaseLockState))
456536
})
457537
})
458538

0 commit comments

Comments
 (0)