From ee01d8deac31a386457c3e0764786f9592d7c73f Mon Sep 17 00:00:00 2001 From: Nathan Coad Date: Wed, 28 Jan 2026 08:49:04 +1100 Subject: [PATCH] improve lifecycle data --- internal/report/snapshots.go | 2 +- internal/tasks/dailyAggregate.go | 10 -- internal/tasks/monthlyAggregate.go | 15 --- server/router/docs/docs.go | 131 ++++++++++++++++++++++ server/router/docs/swagger.json | 170 ++++++++++++++-------------- server/router/docs/swagger.yaml | 173 +++++++++++++++-------------- 6 files changed, 304 insertions(+), 197 deletions(-) diff --git a/internal/report/snapshots.go b/internal/report/snapshots.go index 7e4d354..6e22d37 100644 --- a/internal/report/snapshots.go +++ b/internal/report/snapshots.go @@ -1199,7 +1199,7 @@ agg_presence AS ( agg."VcpuCount", agg."RamGB", agg.pool, - COALESCE(agg.creation_time, lifecycle.first_seen) AS creation_time, + agg.creation_time AS creation_time, COALESCE(lifecycle.deleted_at, agg.deletion_time) AS deletion_time, %s AS presence FROM agg diff --git a/internal/tasks/dailyAggregate.go b/internal/tasks/dailyAggregate.go index 6aac1c8..738c705 100644 --- a/internal/tasks/dailyAggregate.go +++ b/internal/tasks/dailyAggregate.go @@ -155,11 +155,6 @@ func (c *CronTask) aggregateDailySummary(ctx context.Context, targetTime time.Ti } else { c.Logger.Info("Daily aggregation deletion times", "source_lifecycle_cache", applied) } - if applied, err := db.ApplyLifecycleCreationToSummary(ctx, dbConn, summaryTable); err != nil { - c.Logger.Warn("failed to apply lifecycle creations to daily summary", "error", err, "table", summaryTable) - } else if applied > 0 { - c.Logger.Info("Daily aggregation creation times", "source_lifecycle_cache", applied) - } if err := db.RefineCreationDeletionFromUnion(ctx, dbConn, summaryTable, unionQuery); err != nil { c.Logger.Warn("failed to refine creation/deletion times", "error", err, "table", summaryTable) } @@ -411,11 +406,6 @@ LIMIT 1 } else { c.Logger.Debug("refined creation/deletion times", "table", summaryTable) } - if applied, err := db.ApplyLifecycleCreationToSummary(ctx, dbConn, summaryTable); err != nil { - c.Logger.Warn("failed to apply lifecycle creations to daily summary (Go path)", "error", err, "table", summaryTable) - } else if applied > 0 { - c.Logger.Info("Daily aggregation creation times (Go path)", "source_lifecycle_cache", applied) - } if err := db.UpdateSummaryPresenceByWindow(ctx, dbConn, summaryTable, dayStart.Unix(), dayEnd.Unix()); err != nil { c.Logger.Warn("failed to update daily AvgIsPresent from lifecycle window (Go path)", "error", err, "table", summaryTable) } diff --git a/internal/tasks/monthlyAggregate.go b/internal/tasks/monthlyAggregate.go index 1f0571e..302bee7 100644 --- a/internal/tasks/monthlyAggregate.go +++ b/internal/tasks/monthlyAggregate.go @@ -171,11 +171,6 @@ func (c *CronTask) aggregateMonthlySummary(ctx context.Context, targetMonth time } else { c.Logger.Info("Monthly aggregation deletion times", "source_lifecycle_cache", applied) } - if applied, err := db.ApplyLifecycleCreationToSummary(ctx, dbConn, monthlyTable); err != nil { - c.Logger.Warn("failed to apply lifecycle creations to monthly summary", "error", err, "table", monthlyTable) - } else if applied > 0 { - c.Logger.Info("Monthly aggregation creation times", "source_lifecycle_cache", applied) - } if err := db.UpdateSummaryPresenceByWindow(ctx, dbConn, monthlyTable, monthStart.Unix(), monthEnd.Unix()); err != nil { c.Logger.Warn("failed to update monthly AvgIsPresent from lifecycle window", "error", err, "table", monthlyTable) } @@ -298,11 +293,6 @@ func (c *CronTask) aggregateMonthlySummaryGoHourly(ctx context.Context, monthSta if err := c.insertDailyAggregates(ctx, summaryTable, aggMap, totalSamples, totalSamplesByVcenter); err != nil { return err } - if applied, err := db.ApplyLifecycleCreationToSummary(ctx, dbConn, summaryTable); err != nil { - c.Logger.Warn("failed to apply lifecycle creations to monthly summary (Go hourly)", "error", err, "table", summaryTable) - } else if applied > 0 { - c.Logger.Info("Monthly aggregation creation times (Go hourly)", "source_lifecycle_cache", applied) - } if err := db.UpdateSummaryPresenceByWindow(ctx, dbConn, summaryTable, monthStart.Unix(), monthEnd.Unix()); err != nil { c.Logger.Warn("failed to update monthly AvgIsPresent from lifecycle window (Go hourly)", "error", err, "table", summaryTable) } @@ -375,11 +365,6 @@ func (c *CronTask) aggregateMonthlySummaryGo(ctx context.Context, monthStart, mo } else { c.Logger.Info("Monthly aggregation deletion times", "source_lifecycle_cache", applied) } - if applied, err := db.ApplyLifecycleCreationToSummary(ctx, dbConn, summaryTable); err != nil { - c.Logger.Warn("failed to apply lifecycle creations to monthly summary (Go)", "error", err, "table", summaryTable) - } else if applied > 0 { - c.Logger.Info("Monthly aggregation creation times (Go)", "source_lifecycle_cache", applied) - } if err := db.RefineCreationDeletionFromUnion(ctx, dbConn, summaryTable, unionQuery); err != nil { c.Logger.Warn("failed to refine creation/deletion times (monthly Go)", "error", err, "table", summaryTable) diff --git a/server/router/docs/docs.go b/server/router/docs/docs.go index b159efd..e6fd2a1 100644 --- a/server/router/docs/docs.go +++ b/server/router/docs/docs.go @@ -104,6 +104,53 @@ const docTemplate = `{ } } }, + "/api/diagnostics/daily-creation": { + "get": { + "description": "Returns counts of daily summary rows missing CreationTime and sample rows for the given date.", + "produces": [ + "application/json" + ], + "tags": [ + "diagnostics" + ], + "summary": "Daily summary CreationTime diagnostics", + "parameters": [ + { + "type": "string", + "description": "Daily date (YYYY-MM-DD)", + "name": "date", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "Diagnostics result", + "schema": { + "$ref": "#/definitions/models.DailyCreationDiagnosticsResponse" + } + }, + "400": { + "description": "Invalid request", + "schema": { + "$ref": "#/definitions/models.ErrorResponse" + } + }, + "404": { + "description": "Summary not found", + "schema": { + "$ref": "#/definitions/models.ErrorResponse" + } + }, + "500": { + "description": "Server error", + "schema": { + "$ref": "#/definitions/models.ErrorResponse" + } + } + } + } + }, "/api/encrypt": { "post": { "description": "Encrypts a plaintext value and returns the ciphertext.", @@ -1134,6 +1181,90 @@ const docTemplate = `{ } } }, + "models.DailyCreationDiagnosticsResponse": { + "type": "object", + "properties": { + "avg_is_present_lt_one_count": { + "type": "integer" + }, + "date": { + "type": "string" + }, + "missing_by_vcenter": { + "type": "array", + "items": { + "$ref": "#/definitions/models.DailyCreationMissingByVcenter" + } + }, + "missing_creation_count": { + "type": "integer" + }, + "missing_creation_partial_count": { + "type": "integer" + }, + "missing_creation_partial_samples": { + "type": "array", + "items": { + "$ref": "#/definitions/models.DailyCreationMissingSample" + } + }, + "missing_creation_pct": { + "type": "number" + }, + "samples": { + "type": "array", + "items": { + "$ref": "#/definitions/models.DailyCreationMissingSample" + } + }, + "status": { + "type": "string" + }, + "table": { + "type": "string" + }, + "total_rows": { + "type": "integer" + } + } + }, + "models.DailyCreationMissingByVcenter": { + "type": "object", + "properties": { + "missing_count": { + "type": "integer" + }, + "vcenter": { + "type": "string" + } + } + }, + "models.DailyCreationMissingSample": { + "type": "object", + "properties": { + "avg_is_present": { + "type": "number" + }, + "name": { + "type": "string" + }, + "samples_present": { + "type": "integer" + }, + "snapshot_time": { + "type": "integer" + }, + "vcenter": { + "type": "string" + }, + "vm_id": { + "type": "string" + }, + "vm_uuid": { + "type": "string" + } + } + }, "models.ErrorResponse": { "type": "object", "properties": { diff --git a/server/router/docs/swagger.json b/server/router/docs/swagger.json index fc78561..0650a21 100644 --- a/server/router/docs/swagger.json +++ b/server/router/docs/swagger.json @@ -1170,6 +1170,90 @@ } } }, + "models.DailyCreationDiagnosticsResponse": { + "type": "object", + "properties": { + "avg_is_present_lt_one_count": { + "type": "integer" + }, + "date": { + "type": "string" + }, + "missing_by_vcenter": { + "type": "array", + "items": { + "$ref": "#/definitions/models.DailyCreationMissingByVcenter" + } + }, + "missing_creation_count": { + "type": "integer" + }, + "missing_creation_partial_count": { + "type": "integer" + }, + "missing_creation_partial_samples": { + "type": "array", + "items": { + "$ref": "#/definitions/models.DailyCreationMissingSample" + } + }, + "missing_creation_pct": { + "type": "number" + }, + "samples": { + "type": "array", + "items": { + "$ref": "#/definitions/models.DailyCreationMissingSample" + } + }, + "status": { + "type": "string" + }, + "table": { + "type": "string" + }, + "total_rows": { + "type": "integer" + } + } + }, + "models.DailyCreationMissingByVcenter": { + "type": "object", + "properties": { + "missing_count": { + "type": "integer" + }, + "vcenter": { + "type": "string" + } + } + }, + "models.DailyCreationMissingSample": { + "type": "object", + "properties": { + "avg_is_present": { + "type": "number" + }, + "name": { + "type": "string" + }, + "samples_present": { + "type": "integer" + }, + "snapshot_time": { + "type": "integer" + }, + "vcenter": { + "type": "string" + }, + "vm_id": { + "type": "string" + }, + "vm_uuid": { + "type": "string" + } + } + }, "models.ErrorResponse": { "type": "object", "properties": { @@ -1334,90 +1418,6 @@ "type": "string" } } - }, - "models.DailyCreationDiagnosticsResponse": { - "type": "object", - "properties": { - "status": { - "type": "string" - }, - "date": { - "type": "string" - }, - "table": { - "type": "string" - }, - "total_rows": { - "type": "integer" - }, - "missing_creation_count": { - "type": "integer" - }, - "missing_creation_pct": { - "type": "number" - }, - "avg_is_present_lt_one_count": { - "type": "integer" - }, - "missing_creation_partial_count": { - "type": "integer" - }, - "missing_by_vcenter": { - "type": "array", - "items": { - "$ref": "#/definitions/models.DailyCreationMissingByVcenter" - } - }, - "samples": { - "type": "array", - "items": { - "$ref": "#/definitions/models.DailyCreationMissingSample" - } - }, - "missing_creation_partial_samples": { - "type": "array", - "items": { - "$ref": "#/definitions/models.DailyCreationMissingSample" - } - } - } - }, - "models.DailyCreationMissingByVcenter": { - "type": "object", - "properties": { - "vcenter": { - "type": "string" - }, - "missing_count": { - "type": "integer" - } - } - }, - "models.DailyCreationMissingSample": { - "type": "object", - "properties": { - "vcenter": { - "type": "string" - }, - "vm_id": { - "type": "string" - }, - "vm_uuid": { - "type": "string" - }, - "name": { - "type": "string" - }, - "samples_present": { - "type": "integer" - }, - "avg_is_present": { - "type": "number" - }, - "snapshot_time": { - "type": "integer" - } - } } } -} +} \ No newline at end of file diff --git a/server/router/docs/swagger.yaml b/server/router/docs/swagger.yaml index 6b5390f..a5509fa 100644 --- a/server/router/docs/swagger.yaml +++ b/server/router/docs/swagger.yaml @@ -126,6 +126,61 @@ definitions: modified: type: string type: object + models.DailyCreationDiagnosticsResponse: + properties: + avg_is_present_lt_one_count: + type: integer + date: + type: string + missing_by_vcenter: + items: + $ref: '#/definitions/models.DailyCreationMissingByVcenter' + type: array + missing_creation_count: + type: integer + missing_creation_partial_count: + type: integer + missing_creation_partial_samples: + items: + $ref: '#/definitions/models.DailyCreationMissingSample' + type: array + missing_creation_pct: + type: number + samples: + items: + $ref: '#/definitions/models.DailyCreationMissingSample' + type: array + status: + type: string + table: + type: string + total_rows: + type: integer + type: object + models.DailyCreationMissingByVcenter: + properties: + missing_count: + type: integer + vcenter: + type: string + type: object + models.DailyCreationMissingSample: + properties: + avg_is_present: + type: number + name: + type: string + samples_present: + type: integer + snapshot_time: + type: integer + vcenter: + type: string + vm_id: + type: string + vm_uuid: + type: string + type: object models.ErrorResponse: properties: message: @@ -233,95 +288,9 @@ definitions: status: type: string type: object - models.DailyCreationDiagnosticsResponse: - properties: - status: - type: string - date: - type: string - table: - type: string - total_rows: - type: integer - missing_creation_count: - type: integer - missing_creation_pct: - type: number - avg_is_present_lt_one_count: - type: integer - missing_creation_partial_count: - type: integer - missing_by_vcenter: - items: - $ref: '#/definitions/models.DailyCreationMissingByVcenter' - type: array - samples: - items: - $ref: '#/definitions/models.DailyCreationMissingSample' - type: array - missing_creation_partial_samples: - items: - $ref: '#/definitions/models.DailyCreationMissingSample' - type: array - type: object - models.DailyCreationMissingByVcenter: - properties: - vcenter: - type: string - missing_count: - type: integer - type: object - models.DailyCreationMissingSample: - properties: - vcenter: - type: string - vm_id: - type: string - vm_uuid: - type: string - name: - type: string - samples_present: - type: integer - avg_is_present: - type: number - snapshot_time: - type: integer - type: object info: contact: {} paths: - /api/diagnostics/daily-creation: - get: - description: Returns counts of daily summary rows missing CreationTime and sample rows for the given date. - parameters: - - description: Daily date (YYYY-MM-DD) - in: query - name: date - required: true - type: string - produces: - - application/json - responses: - "200": - description: Diagnostics result - schema: - $ref: '#/definitions/models.DailyCreationDiagnosticsResponse' - "400": - description: Invalid request - schema: - $ref: '#/definitions/models.ErrorResponse' - "404": - description: Summary not found - schema: - $ref: '#/definitions/models.ErrorResponse' - "500": - description: Server error - schema: - $ref: '#/definitions/models.ErrorResponse' - summary: Daily summary CreationTime diagnostics - tags: - - diagnostics /: get: description: Renders the main UI page. @@ -383,6 +352,38 @@ paths: summary: Cleanup vCenter inventory (deprecated) tags: - maintenance + /api/diagnostics/daily-creation: + get: + description: Returns counts of daily summary rows missing CreationTime and sample + rows for the given date. + parameters: + - description: Daily date (YYYY-MM-DD) + in: query + name: date + required: true + type: string + produces: + - application/json + responses: + "200": + description: Diagnostics result + schema: + $ref: '#/definitions/models.DailyCreationDiagnosticsResponse' + "400": + description: Invalid request + schema: + $ref: '#/definitions/models.ErrorResponse' + "404": + description: Summary not found + schema: + $ref: '#/definitions/models.ErrorResponse' + "500": + description: Server error + schema: + $ref: '#/definitions/models.ErrorResponse' + summary: Daily summary CreationTime diagnostics + tags: + - diagnostics /api/encrypt: post: consumes: