Files
fleet/server/chart/datasets.go
T

63 lines
2.4 KiB
Go

package chart
import (
"context"
"time"
"github.com/fleetdm/fleet/v4/server/chart/api"
)
// UptimeDataset implements api.Dataset for host uptime tracking.
type UptimeDataset struct{}
func (u *UptimeDataset) Name() string { return "uptime" }
func (u *UptimeDataset) DefaultResolutionHours() int { return 3 }
func (u *UptimeDataset) SampleStrategy() api.SampleStrategy { return api.SampleStrategyAccumulate }
func (u *UptimeDataset) DefaultVisualization() string { return "checkerboard" }
func (u *UptimeDataset) Collect(ctx context.Context, store api.DatasetStore, now time.Time, disabledFleetIDs []uint) error {
hostIDs, err := store.FindOnlineHostIDs(ctx, now, disabledFleetIDs)
if err != nil {
return err
}
if len(hostIDs) == 0 {
return nil
}
bucketStart := now.UTC().Truncate(time.Hour)
return store.RecordBucketData(ctx, u.Name(), bucketStart, time.Hour, u.SampleStrategy(),
// The empty string key means "all entities" since uptime isn't tracked per host.
// The value is a bitmap of host IDs that were active in this bucket.
map[string][]byte{"": HostIDsToBlob(hostIDs)})
}
// CVEDataset implements api.Dataset for host CVE tracking.
type CVEDataset struct{}
func (c *CVEDataset) Name() string { return "cve" }
func (c *CVEDataset) DefaultResolutionHours() int { return 3 }
func (c *CVEDataset) SampleStrategy() api.SampleStrategy { return api.SampleStrategySnapshot }
func (c *CVEDataset) DefaultVisualization() string { return "line" }
func (c *CVEDataset) Collect(ctx context.Context, store api.DatasetStore, now time.Time, disabledFleetIDs []uint) error {
// Only track the CVEs that the chart API currently returns.
// TODO: implement bitmap compression so we can track all CVEs.
tracked, err := store.TrackedCriticalCVEs(ctx)
if err != nil {
return err
}
hostIDsByCVE, err := store.AffectedHostIDsByCVE(ctx, disabledFleetIDs, tracked)
if err != nil {
return err
}
bitmaps := make(map[string][]byte, len(hostIDsByCVE))
for cve, hostIDs := range hostIDsByCVE {
bitmaps[cve] = HostIDsToBlob(hostIDs)
}
bucketStart := now.UTC().Truncate(time.Hour)
// Always call RecordBucketData, even when bitmaps is empty: snapshot
// semantics use an empty input to close any open rows for entities no
// longer in the tracked set (recordSnapshot's "absent entities" branch).
return store.RecordBucketData(ctx, c.Name(), bucketStart, time.Hour, c.SampleStrategy(), bitmaps)
}