ensure we logout, fix aggregations
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -280,6 +280,11 @@ func (c *CronTask) aggregateDailySummaryGo(ctx context.Context, dayStart, dayEnd
|
||||
return err
|
||||
}
|
||||
|
||||
// Persist rollup cache for monthly aggregation.
|
||||
if err := c.persistDailyRollup(ctx, dayStart.Unix(), aggMap, totalSamples); err != nil {
|
||||
c.Logger.Warn("failed to persist daily rollup cache", "error", err, "date", dayStart.Format("2006-01-02"))
|
||||
}
|
||||
|
||||
// Refine lifecycle with existing SQL helper to pick up first-after deletions.
|
||||
if err := db.RefineCreationDeletionFromUnion(ctx, dbConn, summaryTable, unionQuery); err != nil {
|
||||
c.Logger.Warn("failed to refine creation/deletion times", "error", err, "table", summaryTable)
|
||||
@@ -727,3 +732,44 @@ func btoi(b bool) int64 {
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// persistDailyRollup stores per-day aggregates into vm_daily_rollup to speed monthly aggregation.
|
||||
func (c *CronTask) persistDailyRollup(ctx context.Context, dayUnix int64, agg map[dailyAggKey]*dailyAggVal, totalSamples int) error {
|
||||
dbConn := c.Database.DB()
|
||||
for _, v := range agg {
|
||||
if strings.EqualFold(strings.TrimSpace(v.isTemplate), "true") || v.isTemplate == "1" {
|
||||
continue
|
||||
}
|
||||
row := db.VmDailyRollupRow{
|
||||
Vcenter: v.key.Vcenter,
|
||||
VmId: v.key.VmId,
|
||||
VmUuid: v.key.VmUuid,
|
||||
Name: v.key.Name,
|
||||
CreationTime: v.creation,
|
||||
DeletionTime: v.deletion,
|
||||
SamplesPresent: v.samples,
|
||||
TotalSamples: int64(totalSamples),
|
||||
SumVcpu: float64(v.sumVcpu),
|
||||
SumRam: float64(v.sumRam),
|
||||
SumDisk: v.sumDisk,
|
||||
TinHits: v.tinHits,
|
||||
BronzeHits: v.bronzeHits,
|
||||
SilverHits: v.silverHits,
|
||||
GoldHits: v.goldHits,
|
||||
LastResourcePool: v.resourcePool,
|
||||
LastDatacenter: v.datacenter,
|
||||
LastCluster: v.cluster,
|
||||
LastFolder: v.folder,
|
||||
LastProvisionedDisk: v.lastDisk,
|
||||
LastVcpuCount: v.lastVcpu,
|
||||
LastRamGB: v.lastRam,
|
||||
IsTemplate: v.isTemplate,
|
||||
PoweredOn: v.poweredOn,
|
||||
SrmPlaceholder: v.srmPlaceholder,
|
||||
}
|
||||
if err := db.UpsertVmDailyRollup(ctx, dbConn, dayUnix, row); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ func (c *CronTask) RunVcenterSnapshotHourly(ctx context.Context, logger *slog.Lo
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
minIntervalSeconds := intWithDefault(c.Settings.Values.Settings.VcenterInventorySnapshotSeconds, 3600)
|
||||
minIntervalSeconds := intWithDefault(c.Settings.Values.Settings.VcenterInventorySnapshotSeconds, 3600) / 2
|
||||
if !lastSnapshot.IsZero() && startTime.Sub(lastSnapshot) < time.Duration(minIntervalSeconds)*time.Second {
|
||||
c.Logger.Info("Skipping hourly snapshot, last snapshot too recent",
|
||||
"last_snapshot", lastSnapshot,
|
||||
@@ -882,8 +882,12 @@ func (c *CronTask) captureHourlySnapshotForVcenter(ctx context.Context, startTim
|
||||
return fmt.Errorf("unable to connect to vcenter: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
if err := vc.Logout(); err != nil {
|
||||
logCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
if err := vc.Logout(logCtx); err != nil {
|
||||
c.Logger.Warn("vcenter logout failed", "url", url, "error", err)
|
||||
} else {
|
||||
c.Logger.Debug("vcenter logout succeeded", "url", url)
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ func (c *CronTask) RunVcenterPoll(ctx context.Context, logger *slog.Logger) erro
|
||||
}
|
||||
}
|
||||
c.Logger.Debug("Finished checking vcenter", "url", url)
|
||||
vc.Logout()
|
||||
_ = vc.Logout(ctx)
|
||||
}
|
||||
|
||||
c.Logger.Debug("Finished polling vcenters")
|
||||
|
||||
@@ -173,6 +173,14 @@ func (c *CronTask) aggregateMonthlySummaryGo(ctx context.Context, monthStart, mo
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(aggMap) == 0 {
|
||||
cacheAgg, cacheErr := c.scanDailyRollup(ctx, monthStart, monthEnd)
|
||||
if cacheErr == nil && len(cacheAgg) > 0 {
|
||||
aggMap = cacheAgg
|
||||
} else if cacheErr != nil {
|
||||
c.Logger.Warn("failed to read daily rollup cache; using table scan", "error", cacheErr)
|
||||
}
|
||||
}
|
||||
if len(aggMap) == 0 {
|
||||
return fmt.Errorf("no VM records aggregated for %s", monthStart.Format("2006-01"))
|
||||
}
|
||||
@@ -439,6 +447,89 @@ FROM %s
|
||||
return result, rows.Err()
|
||||
}
|
||||
|
||||
// scanDailyRollup aggregates monthly data from vm_daily_rollup cache.
|
||||
func (c *CronTask) scanDailyRollup(ctx context.Context, start, end time.Time) (map[monthlyAggKey]*monthlyAggVal, error) {
|
||||
dbConn := c.Database.DB()
|
||||
if !db.TableExists(ctx, dbConn, "vm_daily_rollup") {
|
||||
return map[monthlyAggKey]*monthlyAggVal{}, nil
|
||||
}
|
||||
query := `
|
||||
SELECT
|
||||
"Date","Vcenter","VmId","VmUuid","Name","CreationTime","DeletionTime",
|
||||
"SamplesPresent","TotalSamples","SumVcpu","SumRam","SumDisk",
|
||||
"TinHits","BronzeHits","SilverHits","GoldHits",
|
||||
"LastResourcePool","LastDatacenter","LastCluster","LastFolder",
|
||||
"LastProvisionedDisk","LastVcpuCount","LastRamGB","IsTemplate","PoweredOn","SrmPlaceholder"
|
||||
FROM vm_daily_rollup
|
||||
WHERE "Date" >= ? AND "Date" < ?
|
||||
`
|
||||
bind := dbConn.Rebind(query)
|
||||
rows, err := dbConn.QueryxContext(ctx, bind, start.Unix(), end.Unix())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
agg := make(map[monthlyAggKey]*monthlyAggVal, 512)
|
||||
for rows.Next() {
|
||||
var (
|
||||
date sql.NullInt64
|
||||
vcenter, vmId, vmUuid, name string
|
||||
creation, deletion sql.NullInt64
|
||||
samplesPresent, totalSamples sql.NullInt64
|
||||
sumVcpu, sumRam, sumDisk sql.NullFloat64
|
||||
tinHits, bronzeHits, silverHits, goldHits sql.NullInt64
|
||||
lastPool, lastDc, lastCluster, lastFolder sql.NullString
|
||||
lastDisk, lastVcpu, lastRam sql.NullFloat64
|
||||
isTemplate, poweredOn, srmPlaceholder sql.NullString
|
||||
)
|
||||
if err := rows.Scan(
|
||||
&date, &vcenter, &vmId, &vmUuid, &name, &creation, &deletion,
|
||||
&samplesPresent, &totalSamples, &sumVcpu, &sumRam, &sumDisk,
|
||||
&tinHits, &bronzeHits, &silverHits, &goldHits,
|
||||
&lastPool, &lastDc, &lastCluster, &lastFolder,
|
||||
&lastDisk, &lastVcpu, &lastRam, &isTemplate, &poweredOn, &srmPlaceholder,
|
||||
); err != nil {
|
||||
continue
|
||||
}
|
||||
if strings.EqualFold(strings.TrimSpace(isTemplate.String), "true") || isTemplate.String == "1" {
|
||||
continue
|
||||
}
|
||||
key := monthlyAggKey{Vcenter: vcenter, VmId: vmId, VmUuid: vmUuid, Name: name}
|
||||
val := &monthlyAggVal{
|
||||
key: key,
|
||||
resourcePool: lastPool.String,
|
||||
datacenter: lastDc.String,
|
||||
cluster: lastCluster.String,
|
||||
folder: lastFolder.String,
|
||||
isTemplate: isTemplate.String,
|
||||
poweredOn: poweredOn.String,
|
||||
srmPlaceholder: srmPlaceholder.String,
|
||||
provisioned: lastDisk.Float64,
|
||||
vcpuCount: int64(lastVcpu.Float64),
|
||||
ramGB: int64(lastRam.Float64),
|
||||
creation: creation.Int64,
|
||||
deletion: deletion.Int64,
|
||||
lastSnapshot: time.Unix(date.Int64, 0),
|
||||
samplesPresent: samplesPresent.Int64,
|
||||
totalSamples: float64(totalSamples.Int64),
|
||||
sumVcpu: sumVcpu.Float64,
|
||||
sumRam: sumRam.Float64,
|
||||
sumDisk: sumDisk.Float64,
|
||||
tinWeighted: float64(tinHits.Int64),
|
||||
bronzeWeighted: float64(bronzeHits.Int64),
|
||||
silverWeighted: float64(silverHits.Int64),
|
||||
goldWeighted: float64(goldHits.Int64),
|
||||
}
|
||||
if existing, ok := agg[key]; ok {
|
||||
mergeMonthlyAgg(existing, val)
|
||||
} else {
|
||||
agg[key] = val
|
||||
}
|
||||
}
|
||||
return agg, rows.Err()
|
||||
}
|
||||
|
||||
func (c *CronTask) insertMonthlyAggregates(ctx context.Context, summaryTable string, aggMap map[monthlyAggKey]*monthlyAggVal) error {
|
||||
dbConn := c.Database.DB()
|
||||
columns := []string{
|
||||
|
||||
@@ -165,10 +165,7 @@ func (c *CronTask) RunVmCheck(ctx context.Context, logger *slog.Logger) error {
|
||||
poweredOn = "TRUE"
|
||||
}
|
||||
|
||||
err = vc.Logout()
|
||||
if err != nil {
|
||||
c.Logger.Error("unable to logout of vcenter", "error", err)
|
||||
}
|
||||
_ = vc.Logout(ctx)
|
||||
|
||||
if foundVm {
|
||||
c.Logger.Debug("Adding to Inventory table", "vm_name", evt.VmName.String, "vcpus", numVcpus, "ram", numRam, "dc", evt.DatacenterId.String)
|
||||
|
||||
Reference in New Issue
Block a user