[hermes] soteria: go:S3776 #46

Open
opened 2026-09-24 21:34:09 +00:00 by hermes-automation · 0 comments

SonarQube reports go:S3776 in internal/server/metrics.go. The build is green; this is a standing finding, not a failure.

What is wrong

RecordInventory (internal/server/metrics.go:133) has cognitive complexity 16 because the per-PVC metric logic — the reason-defaulting if, the healthy/unhealthy if/else, the empty-LastBackupAt guard, and the parseBackupTime if — is all written inline inside a doubly-nested for loop (namespace -> pvc), so every branch inside picks up two extra nesting increments.

Ariadne opened no pull request for it: no automated patch was possible for this finding.

Facts

  • gitea — Refactor this method to reduce its Cognitive Complexity from 16 to the 15 allowed. (CRITICAL, 6min estimated) (internal/server/metrics.go:133)

Suggested fix (not applied)

Hermes could not open a pull request for this, so the change below was not written, validated, or pushed anywhere. It is a starting point for whoever picks this up, not a reviewed patch.

internal/server/metrics.go — Extract the per-PVC branch logic into its own method, recordPVCMetric. This doesn't change any behavior (same maps, same labels, same values, same order of operations) but moves the four conditional branches out of the doubly-nested loop into a top-level method with nesting depth 0, dropping RecordInventory's cognitive complexity to just the two for loops (well under 15) and keeping the extracted method's own complexity low too. Adjust the parameter type to whatever the actual element type of namespace.PVCs is in this codebase (shown here as api.PVCInventory to match the api.InventoryResponse/
... (truncated)

// RecordInventory updates PVC backup metrics from the latest inventory snapshot.
func (t *telemetry) RecordInventory(inv api.InventoryResponse) {
	t.mu.Lock()
	defer t.mu.Unlock()

	t.pvcBackupAgeHours = map[string]metricSample{}
	t.pvcBackupHealth = map[string]metricSample{}
	t.pvcBackupHealthReason = map[string]metricSample{}
	t.pvcBackupLastSuccess = map[string]metricSample{}
	t.pvcBackupCount = map[string]metricSample{}
	t.pvcBackupCompletedCount = map[string]metricSample{}
	t.pvcBackupLastSizeBytes = map[string]metricSample{}
	t.pvcBackupTotalSizeBytes = map[string]metricSample{}

	for _, namespace := range inv.Namespaces {
		for _, pvc := range namespace.PVCs {
			t.recordPVCMetric(pvc)
		}
	}

	t.inventoryRefreshTime = float64(time.Now().Unix())
}

// recordPVCMetric records the backup metrics for a single PVC. Callers must hold t.mu.
func (t *telemetry) recordPVCMetric(pvc api.PVCInventory) {
	labels := map[string]string{
		"namespace": pvc.Namespace,
		"pvc":       pvc.PVC,
		"volume":    pvc.Volume,
		"driver":    pvc.Driver,
	}
	setMetric(t.pvcBackupCount, labels, float64(pvc.BackupCount))
	setMetric(t.pvcBackupCompletedCount, labels, float64(pvc.CompletedBackups))
	setMetric(t.pvcBackupLastSizeBytes, labels, pvc.LastBackupSizeBytes)
	setMetric(t.pvcBackupTotalSizeBytes, labels, pvc.TotalBackupSizeBytes)

	reasonLabels := cloneLabels(labels)
	reason := strings.TrimSpace(pvc.HealthReason)
	if reason == "" {
		reason = "unknown"
	}
	reasonLabels["reason"] = reason
	setMetric(t.pvcBackupHealthReason, reasonLabels, 1)

	if pvc.Healthy {
		setMetric(t.pvcBackupHealth
... (truncated)

Filed automatically by Ariadne from a Hermes Agent diagnosis (run run_ef3fd691f4da4ffcbf1f40c3e3f15f06). Hermes has no write access to this repository; no files or infrastructure were changed.

SonarQube reports **go:S3776** in `internal/server/metrics.go`. The build is green; this is a standing finding, not a failure. ## What is wrong RecordInventory (internal/server/metrics.go:133) has cognitive complexity 16 because the per-PVC metric logic — the reason-defaulting if, the healthy/unhealthy if/else, the empty-LastBackupAt guard, and the parseBackupTime if — is all written inline inside a doubly-nested for loop (namespace -> pvc), so every branch inside picks up two extra nesting increments. Ariadne opened no pull request for it: no automated patch was possible for this finding. ## Facts - **gitea** — Refactor this method to reduce its Cognitive Complexity from 16 to the 15 allowed. (CRITICAL, 6min estimated) (`internal/server/metrics.go:133`) ## Suggested fix (not applied) Hermes could not open a pull request for this, so the change below was not written, validated, or pushed anywhere. It is a starting point for whoever picks this up, not a reviewed patch. **`internal/server/metrics.go`** — Extract the per-PVC branch logic into its own method, recordPVCMetric. This doesn't change any behavior (same maps, same labels, same values, same order of operations) but moves the four conditional branches out of the doubly-nested loop into a top-level method with nesting depth 0, dropping RecordInventory's cognitive complexity to just the two for loops (well under 15) and keeping the extracted method's own complexity low too. Adjust the parameter type to whatever the actual element type of namespace.PVCs is in this codebase (shown here as api.PVCInventory to match the api.InventoryResponse/ ... (truncated) ``` // RecordInventory updates PVC backup metrics from the latest inventory snapshot. func (t *telemetry) RecordInventory(inv api.InventoryResponse) { t.mu.Lock() defer t.mu.Unlock() t.pvcBackupAgeHours = map[string]metricSample{} t.pvcBackupHealth = map[string]metricSample{} t.pvcBackupHealthReason = map[string]metricSample{} t.pvcBackupLastSuccess = map[string]metricSample{} t.pvcBackupCount = map[string]metricSample{} t.pvcBackupCompletedCount = map[string]metricSample{} t.pvcBackupLastSizeBytes = map[string]metricSample{} t.pvcBackupTotalSizeBytes = map[string]metricSample{} for _, namespace := range inv.Namespaces { for _, pvc := range namespace.PVCs { t.recordPVCMetric(pvc) } } t.inventoryRefreshTime = float64(time.Now().Unix()) } // recordPVCMetric records the backup metrics for a single PVC. Callers must hold t.mu. func (t *telemetry) recordPVCMetric(pvc api.PVCInventory) { labels := map[string]string{ "namespace": pvc.Namespace, "pvc": pvc.PVC, "volume": pvc.Volume, "driver": pvc.Driver, } setMetric(t.pvcBackupCount, labels, float64(pvc.BackupCount)) setMetric(t.pvcBackupCompletedCount, labels, float64(pvc.CompletedBackups)) setMetric(t.pvcBackupLastSizeBytes, labels, pvc.LastBackupSizeBytes) setMetric(t.pvcBackupTotalSizeBytes, labels, pvc.TotalBackupSizeBytes) reasonLabels := cloneLabels(labels) reason := strings.TrimSpace(pvc.HealthReason) if reason == "" { reason = "unknown" } reasonLabels["reason"] = reason setMetric(t.pvcBackupHealthReason, reasonLabels, 1) if pvc.Healthy { setMetric(t.pvcBackupHealth ... (truncated) ``` ## Links - SonarQube finding: https://quality.bstein.dev/project/issues?resolved=false&id=soteria&open=AZ4WREVmqCRMjDT4bXbu - Full evidence bundle and audit trail live in Ariadne at `/api/admin/audit/events`, event types `hermes_autotriage_incident` and `hermes_autotriage_diagnosis`. Filed automatically by Ariadne from a Hermes Agent diagnosis (run [run_ef3fd691f4da4ffcbf1f40c3e3f15f06](https://triage.bstein.dev/chat?resume=run_ef3fd691f4da4ffcbf1f40c3e3f15f06)). Hermes has no write access to this repository; no files or infrastructure were changed. <!-- hermes-triage job=soteria classification=go:S3776 incident=sonar/soteria/go:S3776/AZ4WREVmqCRMjDT4bXbu -->
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: titan/soteria#46
No description provided.