-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJoyRideDiagnostics.ts
More file actions
141 lines (131 loc) · 5.01 KB
/
Copy pathJoyRideDiagnostics.ts
File metadata and controls
141 lines (131 loc) · 5.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/**
* [LAYER: CORE]
* Structured JoyRide diagnostic reports for maintainers and deactivate flows.
*/
import { Logger } from "@shared/services/Logger"
import { getJoyRideCacheHitAuditCount, getJoyRideCacheHitAuditTrail } from "./JoyRideAudit"
import type { JoyRideCache } from "./JoyRideCache"
import {
explainJoyRideConfig,
getJoyRideConfig,
getJoyRideDegradedReason,
isJoyRideDegraded,
type JoyRideOperationalConfig,
} from "./JoyRideConfig"
import { getJoyRideDecisionLog, getLastJoyRideDecision } from "./JoyRideDecisionLog"
import type { JoyRideCacheStats } from "./types"
export interface JoyRideDiagnosticReport {
generatedAt: number
config: JoyRideOperationalConfig
configExplanation: string
degraded: boolean
degradedReason?: string
stats: JoyRideCacheStats
decisionLogSize: number
recentAuditTrail: ReturnType<typeof getJoyRideCacheHitAuditTrail>
recentDecisions: ReturnType<typeof getJoyRideDecisionLog>
lastDecision?: ReturnType<typeof getLastJoyRideDecision>
summary: {
isEnabled: boolean
isHelping: boolean
activeReuseCount: number
auditTrailCount: number
unsafeRejections: number
lateWriteRejections: number
cleanupFailures: number
staleDiagnostics: number
verificationReuseCount: number
pressureTrimEvents: number
emergencyTrimEvents: number
decisionLogSize: number
lastFlushDurationMs: number
lastShutdownDurationMs: number
}
}
export function buildJoyRideDiagnosticReport(cache: JoyRideCache): JoyRideDiagnosticReport {
const config = getJoyRideConfig()
const stats = cache.getStats()
const recentAuditTrail = getJoyRideCacheHitAuditTrail(16)
const recentDecisions = getJoyRideDecisionLog(16)
const decisionLogSize = getJoyRideDecisionLog(128).length
return {
generatedAt: Date.now(),
config,
configExplanation: explainJoyRideConfig(),
degraded: isJoyRideDegraded(),
degradedReason: getJoyRideDegradedReason(),
stats,
decisionLogSize,
recentAuditTrail,
recentDecisions,
lastDecision: getLastJoyRideDecision(),
summary: {
isEnabled: config.mode === "enabled",
isHelping: stats.isHelping,
activeReuseCount: stats.hitCount,
auditTrailCount: getJoyRideCacheHitAuditCount(),
unsafeRejections: stats.rejectedUnsafeEntryCount,
lateWriteRejections: stats.lateWriteRejectionCount,
cleanupFailures: stats.cleanupFailureCount,
staleDiagnostics: stats.staleDiagnosticCount,
verificationReuseCount: stats.verificationCacheReuseCount,
pressureTrimEvents: stats.pressureTrimEvents,
emergencyTrimEvents: stats.emergencyTrimEvents,
decisionLogSize,
lastFlushDurationMs: stats.lastFlushDurationMs,
lastShutdownDurationMs: stats.lastShutdownDurationMs,
},
}
}
export function formatJoyRideDiagnosticReport(report: JoyRideDiagnosticReport): string {
const { stats, summary, recentAuditTrail, recentDecisions, configExplanation, degraded, degradedReason } = report
const lines = [
"=== JoyRide Diagnostic Report ===",
configExplanation,
`helping=${summary.isHelping} hits=${stats.hitCount} misses=${stats.missCount} hitRate=${stats.hitRate.toFixed(3)}`,
`degraded=${degraded}${degradedReason ? ` reason=${degradedReason}` : ""}`,
`entries=${stats.entryCount} memoryBytes=${stats.memoryUsageEstimate} staleDiagnostics=${summary.staleDiagnostics}`,
`rejected=${stats.rejectedAdmissionCount} unsafe=${summary.unsafeRejections} lateWrites=${summary.lateWriteRejections} cleanupFailures=${summary.cleanupFailures}`,
`verificationReuse=${summary.verificationReuseCount} auditTrail=${summary.auditTrailCount}`,
`lastFlushMs=${summary.lastFlushDurationMs} lastShutdownMs=${summary.lastShutdownDurationMs}`,
]
if (recentDecisions.length > 0) {
lines.push("recent_decisions:")
for (const d of recentDecisions.slice(-5)) {
lines.push(` - ${d.type} canReuse=${d.canReuse} reason=${d.reasonCode} fallback=${d.fallbackBehavior}`)
}
}
if (recentAuditTrail.length > 0) {
lines.push("recent_skips:")
for (const hit of recentAuditTrail.slice(-5)) {
lines.push(
` - ${hit.hitSource} task=${hit.ownerTaskId} ageMs=${hit.entryAgeMs} reason=${hit.reuseReason} key=${hit.key.slice(0, 48)}`,
)
}
}
return lines.join("\n")
}
export function dumpJoyRideDiagnostics(cache: JoyRideCache): JoyRideDiagnosticReport {
const report = buildJoyRideDiagnosticReport(cache)
Logger.info(formatJoyRideDiagnosticReport(report))
return report
}
export function summarizeJoyRideHealth(cache: JoyRideCache): string {
const report = buildJoyRideDiagnosticReport(cache)
return [
`helping=${report.summary.isHelping}`,
`hits=${report.stats.hitCount}`,
`entries=${report.stats.entryCount}`,
`degraded=${report.degraded}`,
`decisions=${report.recentDecisions.length}`,
].join(" ")
}
export function createJoyRideBugReportSnapshot(cache: JoyRideCache): string {
return JSON.stringify(buildJoyRideDiagnosticReport(cache), null, 2)
}
export function getJoyRideStats(cache: JoyRideCache): JoyRideCacheStats {
return cache.getStats()
}
export function logJoyRideDiagnostics(cache: JoyRideCache): void {
Logger.info(formatJoyRideDiagnosticReport(buildJoyRideDiagnosticReport(cache)))
}