|
|
|
@@ -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",
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|