| 1 | package main |
| 2 | |
| 3 | import ( |
| 4 | "fmt" |
| 5 | "time" |
| 6 | |
| 7 | "reasonix/internal/repair" |
| 8 | ) |
| 9 | |
| 10 | func (a *App) recordPreviousRunDiagnostics() { |
| 11 | previous := a.previousRun |
| 12 | if !previous.Abnormal { |
| 13 | return |
| 14 | } |
| 15 | report := previousRunReport(previous) |
| 16 | _ = writePendingReport(report, true) |
| 17 | if m := a.metrics.Load(); m != nil { |
| 18 | m.inc("desktop_exit", "abnormal") |
| 19 | m.inc("desktop_exit_phase", metricBucket(previous.Phase)) |
| 20 | m.inc("desktop_uptime", metricBucket(previous.UptimeBucket)) |
| 21 | m.inc("desktop_install", metricBucket(previous.InstallProfile)) |
| 22 | if previous.UpdateTo != "" { |
| 23 | m.inc("desktop_update_transition", "probationary") |
| 24 | } else { |
| 25 | m.inc("desktop_update_transition", "none") |
| 26 | } |
| 27 | m.persist() |
| 28 | } |
| 29 | } |
| 30 | |
| 31 | func previousRunReport(previous repair.PreviousRunObservation) crashReport { |
| 32 | phase := metricBucket(previous.Phase) |
| 33 | uptime := metricBucket(previous.UptimeBucket) |
| 34 | profile := metricBucket(previous.InstallProfile) |
| 35 | update := "none" |
| 36 | if previous.UpdateTo != "" { |
| 37 | update = sanitizeCrashField(previous.UpdateFrom+" -> "+previous.UpdateTo, 128) |
| 38 | } |
| 39 | message := fmt.Sprintf(`[desktop.abnormal_exit] |
| 40 | |
| 41 | Reasonix detected that the previous desktop process ended without a clean shutdown. |
| 42 | |
| 43 | --- lifecycle context --- |
| 44 | phase: %s |
| 45 | uptime bucket: %s |
| 46 | install profile: %s |
| 47 | previous version: %s |
| 48 | update transition: %s`, |
| 49 | phase, |
| 50 | uptime, |
| 51 | profile, |
| 52 | sanitizeCrashField(previous.Version, 64), |
| 53 | update, |
| 54 | ) |
| 55 | report := baseCrashReport("crash") |
| 56 | report.SchemaVersion = 2 |
| 57 | report.Source = "native.lifecycle" |
| 58 | report.Label = "desktop.abnormal_exit" |
| 59 | report.ErrorType = "AbnormalDesktopExit" |
| 60 | report.ErrorMessage = "The previous desktop process ended without recording a clean shutdown." |
| 61 | report.TopFrame = "desktop.lifecycle." + phase |
| 62 | report.FingerprintHint = "desktop.abnormal_exit." + phase |
| 63 | report.OccurredAt = time.Now().UTC().Format(time.RFC3339) |
| 64 | report.Message = sanitizeCrashText(message, maxCrashDetailBytes) |
| 65 | return report |
| 66 | } |
| 67 |