chore: align codebase with bible engineering contracts
- identifier-normalization: use strings.EqualFold in h3c/parser.go
- import-export: CSV now uses UTF-8 BOM and semicolon delimiter
- go-code-style: translate all Russian source strings to English (ADL-007)
- go-background-tasks: add Type, Message, Result fields to Job struct
- go-api: wrap list endpoints in {items, total_count, page, per_page, total_pages}
- module-structure: rename helpers.go → context_sleep.go
- build-version-display: htmlError renders version footer on error pages
- go-logging: migrate all log.Printf calls to log/slog with structured attrs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -6,7 +6,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -124,14 +124,14 @@ func (c *RedfishConnector) debugf(format string, args ...interface{}) {
|
||||
if !c.debug {
|
||||
return
|
||||
}
|
||||
log.Printf("redfish-debug: "+format, args...)
|
||||
slog.Debug("redfish-debug: " + fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (c *RedfishConnector) debugSnapshotf(format string, args ...interface{}) {
|
||||
if !c.debugSnapshot {
|
||||
return
|
||||
}
|
||||
log.Printf("redfish-snapshot-debug: "+format, args...)
|
||||
slog.Debug("redfish-snapshot-debug: " + fmt.Sprintf(format, args...))
|
||||
}
|
||||
|
||||
func (c *RedfishConnector) Collect(ctx context.Context, req Request, emit ProgressFn) (*models.AnalysisResult, error) {
|
||||
@@ -149,7 +149,7 @@ func (c *RedfishConnector) Collect(ctx context.Context, req Request, emit Progre
|
||||
hintClient := c.httpClientWithTimeout(req, 4*time.Second)
|
||||
|
||||
if emit != nil {
|
||||
emit(Progress{Status: "running", Progress: 10, Message: "Redfish: подключение к BMC..."})
|
||||
emit(Progress{Status: "running", Progress: 10, Message: "Redfish: connecting to BMC..."})
|
||||
}
|
||||
discoveryCtx := withRedfishTelemetryPhase(ctx, "discovery")
|
||||
serviceRootDoc, err := c.getJSON(discoveryCtx, snapshotClient, req, baseURL, "/redfish/v1")
|
||||
@@ -192,7 +192,7 @@ func (c *RedfishConnector) Collect(ctx context.Context, req Request, emit Progre
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 25,
|
||||
Message: fmt.Sprintf("Redfish: профили mode=%s active=%s", acquisitionPlan.Mode, formatActiveModuleLog(activeModules)),
|
||||
Message: fmt.Sprintf("Redfish: profiles mode=%s active=%s", acquisitionPlan.Mode, formatActiveModuleLog(activeModules)),
|
||||
ActiveModules: activeModules,
|
||||
ModuleScores: moduleScores,
|
||||
DebugInfo: &CollectDebugInfo{
|
||||
@@ -229,33 +229,32 @@ func (c *RedfishConnector) Collect(ctx context.Context, req Request, emit Progre
|
||||
seedPaths := resolvedPlan.SeedPaths
|
||||
criticalPaths := resolvedPlan.CriticalPaths
|
||||
if len(acquisitionPlan.Profiles) > 0 {
|
||||
log.Printf(
|
||||
"redfish-profile-plan: mode=%s profiles=%s notes=%s scores=%s req=%d err=%d p95=%dms avg=%dms throttled=%t",
|
||||
acquisitionPlan.Mode,
|
||||
strings.Join(acquisitionPlan.Profiles, ","),
|
||||
strings.Join(acquisitionPlan.Notes, "; "),
|
||||
formatModuleScoreLog(moduleScores),
|
||||
telemetrySummary.Requests,
|
||||
telemetrySummary.Errors,
|
||||
telemetrySummary.P95.Milliseconds(),
|
||||
telemetrySummary.Avg.Milliseconds(),
|
||||
throttled,
|
||||
slog.Info("redfish-profile-plan",
|
||||
"mode", acquisitionPlan.Mode,
|
||||
"profiles", strings.Join(acquisitionPlan.Profiles, ","),
|
||||
"notes", strings.Join(acquisitionPlan.Notes, "; "),
|
||||
"scores", formatModuleScoreLog(moduleScores),
|
||||
"req", telemetrySummary.Requests,
|
||||
"err", telemetrySummary.Errors,
|
||||
"p95_ms", telemetrySummary.P95.Milliseconds(),
|
||||
"avg_ms", telemetrySummary.Avg.Milliseconds(),
|
||||
"throttled", throttled,
|
||||
)
|
||||
}
|
||||
if emit != nil {
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 30,
|
||||
Message: "Redfish: чтение структуры Redfish...",
|
||||
Message: "Redfish: reading Redfish structure...",
|
||||
CurrentPhase: "snapshot",
|
||||
ETASeconds: acquisitionPlan.Tuning.ETABaseline.SnapshotSeconds,
|
||||
})
|
||||
}
|
||||
|
||||
if emit != nil {
|
||||
emit(Progress{Status: "running", Progress: 55, Message: "Redfish: подготовка snapshot...", CurrentPhase: "snapshot", ETASeconds: acquisitionPlan.Tuning.ETABaseline.SnapshotSeconds})
|
||||
emit(Progress{Status: "running", Progress: 80, Message: "Redfish: подготовка расширенного snapshot...", CurrentPhase: "snapshot", ETASeconds: acquisitionPlan.Tuning.ETABaseline.SnapshotSeconds})
|
||||
emit(Progress{Status: "running", Progress: 90, Message: "Redfish: сбор расширенного snapshot...", CurrentPhase: "snapshot", ETASeconds: acquisitionPlan.Tuning.ETABaseline.SnapshotSeconds})
|
||||
emit(Progress{Status: "running", Progress: 55, Message: "Redfish: preparing snapshot...", CurrentPhase: "snapshot", ETASeconds: acquisitionPlan.Tuning.ETABaseline.SnapshotSeconds})
|
||||
emit(Progress{Status: "running", Progress: 80, Message: "Redfish: preparing extended snapshot...", CurrentPhase: "snapshot", ETASeconds: acquisitionPlan.Tuning.ETABaseline.SnapshotSeconds})
|
||||
emit(Progress{Status: "running", Progress: 90, Message: "Redfish: collecting extended snapshot...", CurrentPhase: "snapshot", ETASeconds: acquisitionPlan.Tuning.ETABaseline.SnapshotSeconds})
|
||||
}
|
||||
// collectCtx covers all data-fetching phases (snapshot, prefetch, plan-B).
|
||||
// Cancelling it via the skip signal aborts only the collection phases while
|
||||
@@ -270,10 +269,10 @@ func (c *RedfishConnector) Collect(ctx context.Context, req Request, emit Progre
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 97,
|
||||
Message: "Redfish: пропуск зависших запросов, анализ уже собранных данных...",
|
||||
Message: "Redfish: skipping stalled requests, analyzing collected data...",
|
||||
})
|
||||
}
|
||||
log.Printf("redfish: skip-hung triggered, cancelling collection phases")
|
||||
slog.Info("redfish: skip-hung triggered, cancelling collection phases")
|
||||
cancelCollect()
|
||||
case <-ctx.Done():
|
||||
}
|
||||
@@ -296,15 +295,14 @@ func (c *RedfishConnector) Collect(ctx context.Context, req Request, emit Progre
|
||||
for p := range prefetchedCritical {
|
||||
delete(fetchErrMap, p)
|
||||
}
|
||||
log.Printf(
|
||||
"redfish-prefetch-metrics: enabled=%t candidates=%d targets=%d docs=%d added=%d dur=%s skip=%s",
|
||||
prefetchMetrics.Enabled,
|
||||
prefetchMetrics.Candidates,
|
||||
prefetchMetrics.Targets,
|
||||
prefetchMetrics.Docs,
|
||||
prefetchMetrics.Added,
|
||||
prefetchMetrics.Duration.Round(time.Millisecond),
|
||||
firstNonEmpty(prefetchMetrics.SkipReason, "-"),
|
||||
slog.Info("redfish-prefetch-metrics",
|
||||
"enabled", prefetchMetrics.Enabled,
|
||||
"candidates", prefetchMetrics.Candidates,
|
||||
"targets", prefetchMetrics.Targets,
|
||||
"docs", prefetchMetrics.Docs,
|
||||
"added", prefetchMetrics.Added,
|
||||
"dur", prefetchMetrics.Duration.Round(time.Millisecond),
|
||||
"skip", firstNonEmpty(prefetchMetrics.SkipReason, "-"),
|
||||
)
|
||||
if recoveredN := c.recoverCriticalRedfishDocsPlanB(withRedfishTelemetryPhase(collectCtx, "critical_plan_b"), criticalClient, req, baseURL, criticalPaths, rawTree, fetchErrMap, acquisitionPlan.Tuning, emit); recoveredN > 0 {
|
||||
c.debugSnapshotf("critical plan-b recovered docs=%d", recoveredN)
|
||||
@@ -319,7 +317,7 @@ func (c *RedfishConnector) Collect(ctx context.Context, req Request, emit Progre
|
||||
}
|
||||
}
|
||||
if emit != nil {
|
||||
emit(Progress{Status: "running", Progress: 99, Message: "Redfish: анализ raw snapshot..."})
|
||||
emit(Progress{Status: "running", Progress: 99, Message: "Redfish: analyzing raw snapshot..."})
|
||||
}
|
||||
// Collect hardware event logs separately (not part of tree-walk to avoid bloat).
|
||||
rawLogEntries := c.collectRedfishLogEntries(withRedfishTelemetryPhase(ctx, "log_entries"), snapshotClient, req, baseURL, systemPaths, managerPaths)
|
||||
@@ -443,38 +441,36 @@ func (c *RedfishConnector) Collect(ctx context.Context, req Request, emit Progre
|
||||
}
|
||||
totalElapsed := time.Since(collectStart).Round(time.Second)
|
||||
if !result.InventoryLastModifiedAt.IsZero() {
|
||||
log.Printf("redfish-collect: inventory last modified at %s (age: %s)",
|
||||
result.InventoryLastModifiedAt.Format(time.RFC3339),
|
||||
time.Since(result.InventoryLastModifiedAt).Round(time.Minute),
|
||||
slog.Info("redfish-collect: inventory last modified",
|
||||
"at", result.InventoryLastModifiedAt.Format(time.RFC3339),
|
||||
"age", time.Since(result.InventoryLastModifiedAt).Round(time.Minute),
|
||||
)
|
||||
}
|
||||
log.Printf(
|
||||
"redfish-postprobe-metrics: nvme_candidates=%d nvme_selected=%d nvme_added=%d candidates=%d selected=%d skipped_explicit=%d added=%d dur=%s",
|
||||
postProbeMetrics.NVMECandidates,
|
||||
postProbeMetrics.NVMESelected,
|
||||
postProbeMetrics.NVMEAdded,
|
||||
postProbeMetrics.CollectionCandidates,
|
||||
postProbeMetrics.CollectionSelected,
|
||||
postProbeMetrics.SkippedExplicit,
|
||||
postProbeMetrics.Added,
|
||||
postProbeMetrics.Duration.Round(time.Millisecond),
|
||||
slog.Info("redfish-postprobe-metrics",
|
||||
"nvme_candidates", postProbeMetrics.NVMECandidates,
|
||||
"nvme_selected", postProbeMetrics.NVMESelected,
|
||||
"nvme_added", postProbeMetrics.NVMEAdded,
|
||||
"candidates", postProbeMetrics.CollectionCandidates,
|
||||
"selected", postProbeMetrics.CollectionSelected,
|
||||
"skipped_explicit", postProbeMetrics.SkippedExplicit,
|
||||
"added", postProbeMetrics.Added,
|
||||
"dur", postProbeMetrics.Duration.Round(time.Millisecond),
|
||||
)
|
||||
log.Printf(
|
||||
"redfish-telemetry: req=%d err=%d err_rate=%.2f avg=%dms p95=%dms throttled=%t snapshot_workers=%d prefetch_workers=%d timing_top=%s",
|
||||
telemetrySummary.Requests,
|
||||
telemetrySummary.Errors,
|
||||
telemetrySummary.ErrorRate,
|
||||
telemetrySummary.Avg.Milliseconds(),
|
||||
telemetrySummary.P95.Milliseconds(),
|
||||
throttled,
|
||||
acquisitionPlan.Tuning.SnapshotWorkers,
|
||||
acquisitionPlan.Tuning.PrefetchWorkers,
|
||||
firstNonEmpty(snapshotTimingSummary, "-"),
|
||||
slog.Info("redfish-telemetry",
|
||||
"req", telemetrySummary.Requests,
|
||||
"err", telemetrySummary.Errors,
|
||||
"err_rate", telemetrySummary.ErrorRate,
|
||||
"avg_ms", telemetrySummary.Avg.Milliseconds(),
|
||||
"p95_ms", telemetrySummary.P95.Milliseconds(),
|
||||
"throttled", throttled,
|
||||
"snapshot_workers", acquisitionPlan.Tuning.SnapshotWorkers,
|
||||
"prefetch_workers", acquisitionPlan.Tuning.PrefetchWorkers,
|
||||
"timing_top", firstNonEmpty(snapshotTimingSummary, "-"),
|
||||
)
|
||||
for _, line := range redfishPhaseTelemetryLogLines(phaseTelemetry) {
|
||||
log.Printf("redfish-telemetry-phase: %s", line)
|
||||
slog.Info("redfish-telemetry-phase", "line", line)
|
||||
}
|
||||
log.Printf("redfish-collect: completed in %s (docs=%d, fetch_errors=%d)", totalElapsed, len(rawTree), len(fetchErrMap))
|
||||
slog.Info("redfish-collect: completed", "elapsed", totalElapsed, "docs", len(rawTree), "fetch_errors", len(fetchErrMap))
|
||||
if emit != nil {
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
@@ -491,7 +487,7 @@ func (c *RedfishConnector) Collect(ctx context.Context, req Request, emit Progre
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 100,
|
||||
Message: fmt.Sprintf("Redfish: сбор завершен за %s", totalElapsed),
|
||||
Message: fmt.Sprintf("Redfish: collection completed in %s", totalElapsed),
|
||||
})
|
||||
}
|
||||
return result, nil
|
||||
@@ -611,7 +607,7 @@ func (c *RedfishConnector) prefetchCriticalRedfishDocs(
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 96,
|
||||
Message: fmt.Sprintf("Redfish: prefetch пропущен (адаптивно, кандидатов=%d)", metrics.Candidates),
|
||||
Message: fmt.Sprintf("Redfish: prefetch skipped (adaptive, candidates=%d)", metrics.Candidates),
|
||||
})
|
||||
}
|
||||
return nil, metrics
|
||||
@@ -620,7 +616,7 @@ func (c *RedfishConnector) prefetchCriticalRedfishDocs(
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 96,
|
||||
Message: fmt.Sprintf("Redfish: prefetch критичных endpoint (адаптивно %d/%d)...", len(targets), len(candidates)),
|
||||
Message: fmt.Sprintf("Redfish: prefetch critical endpoints (adaptive %d/%d)...", len(targets), len(candidates)),
|
||||
CurrentPhase: "prefetch",
|
||||
ETASeconds: int(estimateProgressETA(time.Now(), 0, len(targets), 2*time.Second).Seconds()),
|
||||
})
|
||||
@@ -706,7 +702,7 @@ func (c *RedfishConnector) prefetchCriticalRedfishDocs(
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 96,
|
||||
Message: fmt.Sprintf("Redfish: prefetch завершен (адаптивно targets=%d, docs=%d)", len(targets), len(out)),
|
||||
Message: fmt.Sprintf("Redfish: prefetch completed (adaptive targets=%d, docs=%d)", len(targets), len(out)),
|
||||
CurrentPhase: "prefetch",
|
||||
})
|
||||
}
|
||||
@@ -1397,7 +1393,7 @@ func (c *RedfishConnector) collectRawRedfishTree(ctx context.Context, client *ht
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 92 + int(minInt32(n/200, 6)),
|
||||
Message: fmt.Sprintf("Redfish snapshot: heartbeat документов=%d (ok=%d, seen=%d), ETA≈%s, корни=%s, последний=%s", n, outN, seenN, eta, strings.Join(roots, ", "), compactProgressPath(last)),
|
||||
Message: fmt.Sprintf("Redfish snapshot: heartbeat docs=%d (ok=%d, seen=%d), ETA≈%s, roots=%s, last=%s", n, outN, seenN, eta, strings.Join(roots, ", "), compactProgressPath(last)),
|
||||
CurrentPhase: "snapshot",
|
||||
ETASeconds: int(estimateSnapshotETA(crawlStart, int(n), seenN, len(jobs), workers, client.Timeout).Seconds()),
|
||||
})
|
||||
@@ -1434,7 +1430,7 @@ func (c *RedfishConnector) collectRawRedfishTree(ctx context.Context, client *ht
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 92 + int(minInt32(n/200, 6)),
|
||||
Message: fmt.Sprintf("Redfish snapshot: ошибка на %s", compactProgressPath(current)),
|
||||
Message: fmt.Sprintf("Redfish snapshot: error on %s", compactProgressPath(current)),
|
||||
})
|
||||
}
|
||||
wg.Done()
|
||||
@@ -1489,7 +1485,7 @@ func (c *RedfishConnector) collectRawRedfishTree(ctx context.Context, client *ht
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 92 + int(minInt32(n/200, 6)),
|
||||
Message: fmt.Sprintf("Redfish snapshot: ошибка на %s", compactProgressPath(current)),
|
||||
Message: fmt.Sprintf("Redfish snapshot: error on %s", compactProgressPath(current)),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1512,7 +1508,7 @@ func (c *RedfishConnector) collectRawRedfishTree(ctx context.Context, client *ht
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 92 + int(minInt32(n/200, 6)),
|
||||
Message: fmt.Sprintf("Redfish snapshot: документов=%d, ETA≈%s, корни=%s, последний=%s", n, eta, strings.Join(roots, ", "), compactProgressPath(last)),
|
||||
Message: fmt.Sprintf("Redfish snapshot: docs=%d, ETA≈%s, roots=%s, last=%s", n, eta, strings.Join(roots, ", "), compactProgressPath(last)),
|
||||
CurrentPhase: "snapshot",
|
||||
ETASeconds: int(estimateSnapshotETA(crawlStart, int(n), seenN, len(jobs), workers, client.Timeout).Seconds()),
|
||||
})
|
||||
@@ -1574,7 +1570,7 @@ func (c *RedfishConnector) collectRawRedfishTree(ctx context.Context, client *ht
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 97,
|
||||
Message: fmt.Sprintf("Redfish snapshot: post-probe NVMe (%d/%d, ETA≈%s), коллекция=%s", i+1, len(driveCollections), formatETA(estimateProgressETA(nvmeProbeStart, i, len(driveCollections), 2*time.Second)), compactProgressPath(path)),
|
||||
Message: fmt.Sprintf("Redfish snapshot: post-probe NVMe (%d/%d, ETA≈%s), collection=%s", i+1, len(driveCollections), formatETA(estimateProgressETA(nvmeProbeStart, i, len(driveCollections), 2*time.Second)), compactProgressPath(path)),
|
||||
CurrentPhase: "snapshot_postprobe_nvme",
|
||||
ETASeconds: int(estimateProgressETA(nvmeProbeStart, i, len(driveCollections), 2*time.Second).Seconds()),
|
||||
})
|
||||
@@ -1622,7 +1618,7 @@ func (c *RedfishConnector) collectRawRedfishTree(ctx context.Context, client *ht
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 98,
|
||||
Message: fmt.Sprintf("Redfish snapshot: post-probe коллекций (%d/%d, ETA≈%s), текущая=%s", i+1, len(postProbeCollections), formatETA(estimateProgressETA(postProbeStart, i, len(postProbeCollections), 3*time.Second)), compactProgressPath(path)),
|
||||
Message: fmt.Sprintf("Redfish snapshot: post-probe collections (%d/%d, ETA≈%s), current=%s", i+1, len(postProbeCollections), formatETA(estimateProgressETA(postProbeStart, i, len(postProbeCollections), 3*time.Second)), compactProgressPath(path)),
|
||||
CurrentPhase: "snapshot_postprobe_collections",
|
||||
ETASeconds: int(estimateProgressETA(postProbeStart, i, len(postProbeCollections), 3*time.Second).Seconds()),
|
||||
})
|
||||
@@ -1641,14 +1637,14 @@ func (c *RedfishConnector) collectRawRedfishTree(ctx context.Context, client *ht
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 98,
|
||||
Message: fmt.Sprintf("Redfish snapshot: post-probe добавлено %d документов", addedPostProbe),
|
||||
Message: fmt.Sprintf("Redfish snapshot: post-probe added %d docs", addedPostProbe),
|
||||
})
|
||||
}
|
||||
if emit != nil {
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 98,
|
||||
Message: fmt.Sprintf("Redfish snapshot: post-probe метрики candidates=%d selected=%d skipped_explicit=%d added=%d", postProbeMetrics.CollectionCandidates, postProbeMetrics.CollectionSelected, postProbeMetrics.SkippedExplicit, postProbeMetrics.Added),
|
||||
Message: fmt.Sprintf("Redfish snapshot: post-probe metrics candidates=%d selected=%d skipped_explicit=%d added=%d", postProbeMetrics.CollectionCandidates, postProbeMetrics.CollectionSelected, postProbeMetrics.SkippedExplicit, postProbeMetrics.Added),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1656,7 +1652,7 @@ func (c *RedfishConnector) collectRawRedfishTree(ctx context.Context, client *ht
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 98,
|
||||
Message: fmt.Sprintf("Redfish snapshot: собрано %d документов", len(out)),
|
||||
Message: fmt.Sprintf("Redfish snapshot: collected %d docs", len(out)),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1671,14 +1667,14 @@ func (c *RedfishConnector) collectRawRedfishTree(ctx context.Context, client *ht
|
||||
return asString(errorList[i]["path"]) < asString(errorList[j]["path"])
|
||||
})
|
||||
if summary := timings.Summary(12); summary != "" {
|
||||
log.Printf("redfish-snapshot-timing: %s", summary)
|
||||
slog.Info("redfish-snapshot-timing", "summary", summary)
|
||||
}
|
||||
if emit != nil {
|
||||
if summary := timings.Summary(3); summary != "" {
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 98,
|
||||
Message: fmt.Sprintf("Redfish snapshot: топ веток по времени: %s", summary),
|
||||
Message: fmt.Sprintf("Redfish snapshot: top branches by time: %s", summary),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -2979,14 +2975,14 @@ func (c *RedfishConnector) recoverCriticalRedfishDocsPlanB(ctx context.Context,
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 97,
|
||||
Message: fmt.Sprintf("Redfish: расширенная диагностика выключена, пропущено %d тяжелых diagnostic endpoint", skippedDiagnosticTargets),
|
||||
Message: fmt.Sprintf("Redfish: extended diagnostics disabled, skipped %d heavy diagnostic endpoints", skippedDiagnosticTargets),
|
||||
})
|
||||
}
|
||||
totalETA := redfishCriticalCooldown() + estimatePlanBETA(len(targets))
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 97,
|
||||
Message: fmt.Sprintf("Redfish: cooldown перед повторным добором критичных endpoint... ETA≈%s", formatETA(totalETA)),
|
||||
Message: fmt.Sprintf("Redfish: cooldown before retrying critical endpoints... ETA≈%s", formatETA(totalETA)),
|
||||
CurrentPhase: "critical_plan_b",
|
||||
ETASeconds: int(totalETA.Seconds()),
|
||||
})
|
||||
@@ -3072,17 +3068,17 @@ func (c *RedfishConnector) recoverCriticalRedfishDocsPlanB(ctx context.Context,
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 97,
|
||||
Message: fmt.Sprintf("Redfish: plan-B топ веток по времени: %s", summary),
|
||||
Message: fmt.Sprintf("Redfish: plan-B top branches by time: %s", summary),
|
||||
})
|
||||
}
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 97,
|
||||
Message: fmt.Sprintf("Redfish: plan-B завершен за %s (targets=%d, recovered=%d)", time.Since(planBStart).Round(time.Second), len(targets), recovered),
|
||||
Message: fmt.Sprintf("Redfish: plan-B completed in %s (targets=%d, recovered=%d)", time.Since(planBStart).Round(time.Second), len(targets), recovered),
|
||||
})
|
||||
}
|
||||
if summary := timings.Summary(12); summary != "" {
|
||||
log.Printf("redfish-planb-timing: %s", summary)
|
||||
slog.Info("redfish-planb-timing", "summary", summary)
|
||||
}
|
||||
return recovered
|
||||
}
|
||||
@@ -3143,7 +3139,7 @@ func (c *RedfishConnector) recoverProfilePlanBDocs(ctx context.Context, client *
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 98,
|
||||
Message: fmt.Sprintf("Redfish: profile plan-B добирает %d endpoint...", len(targets)),
|
||||
Message: fmt.Sprintf("Redfish: profile plan-B fetching %d endpoints...", len(targets)),
|
||||
CurrentPhase: "profile_plan_b",
|
||||
ETASeconds: int(estimateProgressETA(planBStart, 0, len(targets), 2*time.Second).Seconds()),
|
||||
})
|
||||
@@ -3167,19 +3163,18 @@ func (c *RedfishConnector) recoverProfilePlanBDocs(ctx context.Context, client *
|
||||
recovered++
|
||||
}
|
||||
if recovered > 0 {
|
||||
log.Printf(
|
||||
"redfish-profile-planb: mode=%s profiles=%s targets=%d recovered=%d",
|
||||
plan.Mode,
|
||||
strings.Join(plan.Profiles, ","),
|
||||
len(targets),
|
||||
recovered,
|
||||
slog.Info("redfish-profile-planb",
|
||||
"mode", plan.Mode,
|
||||
"profiles", strings.Join(plan.Profiles, ","),
|
||||
"targets", len(targets),
|
||||
"recovered", recovered,
|
||||
)
|
||||
}
|
||||
if emit != nil {
|
||||
emit(Progress{
|
||||
Status: "running",
|
||||
Progress: 98,
|
||||
Message: fmt.Sprintf("Redfish: profile plan-B завершен за %s (targets=%d, recovered=%d)", time.Since(planBStart).Round(time.Second), len(targets), recovered),
|
||||
Message: fmt.Sprintf("Redfish: profile plan-B completed in %s (targets=%d, recovered=%d)", time.Since(planBStart).Round(time.Second), len(targets), recovered),
|
||||
CurrentPhase: "profile_plan_b",
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user