front-cpu 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/README.md +475 -0
  2. package/README.zh-CN.md +474 -0
  3. package/dist/Pipeline.d.ts +119 -0
  4. package/dist/Pipeline.d.ts.map +1 -0
  5. package/dist/Pipeline.js +373 -0
  6. package/dist/Pipeline.js.map +1 -0
  7. package/dist/debug.d.ts +3 -0
  8. package/dist/debug.d.ts.map +1 -0
  9. package/dist/debug.js +12 -0
  10. package/dist/debug.js.map +1 -0
  11. package/dist/index.d.ts +20 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +19 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/interfaces.d.ts +49 -0
  16. package/dist/interfaces.d.ts.map +1 -0
  17. package/dist/interfaces.js +8 -0
  18. package/dist/interfaces.js.map +1 -0
  19. package/dist/isa/index.d.ts +20 -0
  20. package/dist/isa/index.d.ts.map +1 -0
  21. package/dist/isa/index.js +26 -0
  22. package/dist/isa/index.js.map +1 -0
  23. package/dist/isa/types.d.ts +144 -0
  24. package/dist/isa/types.d.ts.map +1 -0
  25. package/dist/isa/types.js +10 -0
  26. package/dist/isa/types.js.map +1 -0
  27. package/dist/logging/CPUConsole.d.ts +105 -0
  28. package/dist/logging/CPUConsole.d.ts.map +1 -0
  29. package/dist/logging/CPUConsole.js +471 -0
  30. package/dist/logging/CPUConsole.js.map +1 -0
  31. package/dist/logging/CPUDebugger.d.ts +91 -0
  32. package/dist/logging/CPUDebugger.d.ts.map +1 -0
  33. package/dist/logging/CPUDebugger.js +166 -0
  34. package/dist/logging/CPUDebugger.js.map +1 -0
  35. package/dist/logging/CPUEventCollector.d.ts +90 -0
  36. package/dist/logging/CPUEventCollector.d.ts.map +1 -0
  37. package/dist/logging/CPUEventCollector.js +353 -0
  38. package/dist/logging/CPUEventCollector.js.map +1 -0
  39. package/dist/logging/CPULogger.d.ts +150 -0
  40. package/dist/logging/CPULogger.d.ts.map +1 -0
  41. package/dist/logging/CPULogger.js +336 -0
  42. package/dist/logging/CPULogger.js.map +1 -0
  43. package/dist/logging/index.d.ts +10 -0
  44. package/dist/logging/index.d.ts.map +1 -0
  45. package/dist/logging/index.js +16 -0
  46. package/dist/logging/index.js.map +1 -0
  47. package/dist/logging/runtime.d.ts +37 -0
  48. package/dist/logging/runtime.d.ts.map +1 -0
  49. package/dist/logging/runtime.js +42 -0
  50. package/dist/logging/runtime.js.map +1 -0
  51. package/dist/logging/stack-parser.d.ts +22 -0
  52. package/dist/logging/stack-parser.d.ts.map +1 -0
  53. package/dist/logging/stack-parser.js +144 -0
  54. package/dist/logging/stack-parser.js.map +1 -0
  55. package/dist/logging/types.d.ts +73 -0
  56. package/dist/logging/types.d.ts.map +1 -0
  57. package/dist/logging/types.js +47 -0
  58. package/dist/logging/types.js.map +1 -0
  59. package/dist/scheduling/ResourceStrategyRegistry.d.ts +61 -0
  60. package/dist/scheduling/ResourceStrategyRegistry.d.ts.map +1 -0
  61. package/dist/scheduling/ResourceStrategyRegistry.js +109 -0
  62. package/dist/scheduling/ResourceStrategyRegistry.js.map +1 -0
  63. package/dist/scheduling/index.d.ts +6 -0
  64. package/dist/scheduling/index.d.ts.map +1 -0
  65. package/dist/scheduling/index.js +5 -0
  66. package/dist/scheduling/index.js.map +1 -0
  67. package/dist/scheduling/types.d.ts +44 -0
  68. package/dist/scheduling/types.d.ts.map +1 -0
  69. package/dist/scheduling/types.js +5 -0
  70. package/dist/scheduling/types.js.map +1 -0
  71. package/dist/stages/EX.d.ts +17 -0
  72. package/dist/stages/EX.d.ts.map +1 -0
  73. package/dist/stages/EX.js +95 -0
  74. package/dist/stages/EX.js.map +1 -0
  75. package/dist/stages/IF.d.ts +41 -0
  76. package/dist/stages/IF.d.ts.map +1 -0
  77. package/dist/stages/IF.js +83 -0
  78. package/dist/stages/IF.js.map +1 -0
  79. package/dist/stages/RES.d.ts +17 -0
  80. package/dist/stages/RES.d.ts.map +1 -0
  81. package/dist/stages/RES.js +37 -0
  82. package/dist/stages/RES.js.map +1 -0
  83. package/dist/stages/SCH.d.ts +77 -0
  84. package/dist/stages/SCH.d.ts.map +1 -0
  85. package/dist/stages/SCH.js +270 -0
  86. package/dist/stages/SCH.js.map +1 -0
  87. package/dist/stages/WB.d.ts +19 -0
  88. package/dist/stages/WB.d.ts.map +1 -0
  89. package/dist/stages/WB.js +102 -0
  90. package/dist/stages/WB.js.map +1 -0
  91. package/dist/types.d.ts +111 -0
  92. package/dist/types.d.ts.map +1 -0
  93. package/dist/types.js +26 -0
  94. package/dist/types.js.map +1 -0
  95. package/dist/utils/InstructionCancellation.d.ts +31 -0
  96. package/dist/utils/InstructionCancellation.d.ts.map +1 -0
  97. package/dist/utils/InstructionCancellation.js +53 -0
  98. package/dist/utils/InstructionCancellation.js.map +1 -0
  99. package/dist/utils/abortable.d.ts +30 -0
  100. package/dist/utils/abortable.d.ts.map +1 -0
  101. package/dist/utils/abortable.js +76 -0
  102. package/dist/utils/abortable.js.map +1 -0
  103. package/dist/utils/request.d.ts +27 -0
  104. package/dist/utils/request.d.ts.map +1 -0
  105. package/dist/utils/request.js +96 -0
  106. package/dist/utils/request.js.map +1 -0
  107. package/package.json +74 -0
  108. package/src/Pipeline.ts +475 -0
  109. package/src/debug.ts +15 -0
  110. package/src/index.ts +67 -0
  111. package/src/interfaces.ts +53 -0
  112. package/src/isa/index.ts +34 -0
  113. package/src/isa/types.ts +178 -0
  114. package/src/logging/CPUConsole.md +843 -0
  115. package/src/logging/CPUConsole.ts +631 -0
  116. package/src/logging/CPUDebugger.ts +235 -0
  117. package/src/logging/CPUEventCollector.ts +418 -0
  118. package/src/logging/CPULogger.ts +435 -0
  119. package/src/logging/CPU_LOGGING_DESIGN.md +1319 -0
  120. package/src/logging/USAGE_GUIDE.md +505 -0
  121. package/src/logging/index.ts +21 -0
  122. package/src/logging/runtime.ts +96 -0
  123. package/src/logging/stack-parser.ts +168 -0
  124. package/src/logging/types.ts +101 -0
  125. package/src/scheduling/ResourceStrategyRegistry.ts +124 -0
  126. package/src/scheduling/index.ts +13 -0
  127. package/src/scheduling/types.ts +47 -0
  128. package/src/stages/EX.ts +121 -0
  129. package/src/stages/IF.ts +103 -0
  130. package/src/stages/RES.ts +46 -0
  131. package/src/stages/SCH.ts +331 -0
  132. package/src/stages/WB.ts +127 -0
  133. package/src/types.ts +118 -0
  134. package/src/utils/InstructionCancellation.ts +73 -0
  135. package/src/utils/abortable.ts +89 -0
  136. package/src/utils/request.ts +125 -0
@@ -0,0 +1,235 @@
1
+ /**
2
+ * CPU 调试器
3
+ *
4
+ * 职责:
5
+ * 1. 提供调试器 API
6
+ * 2. 支持时间旅行调试
7
+ * 3. 支持指令重放
8
+ */
9
+
10
+ import { cpuLogger } from './CPULogger'
11
+ import { CPUEventType, type CPUEvent } from './types'
12
+
13
+ export class CPUDebugger {
14
+ /**
15
+ * 查询:执行最慢的指令
16
+ */
17
+ getSlowestInstructions(limit: number = 10): Array<{
18
+ instructionId: string
19
+ instructionType: string
20
+ duration: number
21
+ events: CPUEvent[]
22
+ }> {
23
+ const instructionTraces = Array.from(cpuLogger['eventsByInstruction'].entries())
24
+
25
+ const withDuration = instructionTraces
26
+ .map(([instructionId, events]) => {
27
+ const firstEvent = events[0]
28
+ const lastEvent = events[events.length - 1]
29
+ if (!firstEvent || !lastEvent) return null
30
+ const duration = lastEvent.timestamp - firstEvent.timestamp
31
+
32
+ return {
33
+ instructionId,
34
+ instructionType: firstEvent.instructionType,
35
+ duration,
36
+ events,
37
+ }
38
+ })
39
+ .filter((item): item is NonNullable<typeof item> => item !== null && item.duration > 0)
40
+
41
+ return withDuration.sort((a, b) => b.duration - a.duration).slice(0, limit)
42
+ }
43
+
44
+ /**
45
+ * 查询:失败的指令
46
+ */
47
+ getFailedInstructions(): Array<{
48
+ instructionId: string
49
+ instructionType: string
50
+ error: string
51
+ events: CPUEvent[]
52
+ }> {
53
+ const failEvents = cpuLogger.getEventsByType(CPUEventType.INSTRUCTION_FAILED)
54
+
55
+ return failEvents.map((failEvent) => ({
56
+ instructionId: failEvent.instructionId,
57
+ instructionType: failEvent.instructionType,
58
+ error: failEvent.payload?.error || 'Unknown error',
59
+ events: cpuLogger.getInstructionTrace(failEvent.instructionId),
60
+ }))
61
+ }
62
+
63
+ /**
64
+ * 查询:触发回滚的指令
65
+ */
66
+ getRolledBackInstructions(): Array<{
67
+ instructionId: string
68
+ instructionType: string
69
+ reason: string
70
+ events: CPUEvent[]
71
+ }> {
72
+ const rollbackEvents = cpuLogger.getEventsByType(CPUEventType.OPTIMISTIC_ROLLED_BACK)
73
+
74
+ return rollbackEvents.map((event) => ({
75
+ instructionId: event.instructionId,
76
+ instructionType: event.instructionType,
77
+ reason: event.payload.reason,
78
+ events: cpuLogger.getInstructionTrace(event.instructionId),
79
+ }))
80
+ }
81
+
82
+ /**
83
+ * 查询:资源冲突链
84
+ */
85
+ getResourceConflictChain(instructionId: string): Array<{
86
+ instructionId: string
87
+ instructionType: string
88
+ blockedBy: string[]
89
+ waitTime: number
90
+ }> {
91
+ const events = cpuLogger.getInstructionTrace(instructionId)
92
+ const conflictEvents = events.filter(
93
+ (e) => e.eventType === CPUEventType.SCHEDULER_CONFLICT_DETECTED
94
+ )
95
+
96
+ return conflictEvents.map((event) => ({
97
+ instructionId: event.instructionId,
98
+ instructionType: event.instructionType,
99
+ blockedBy: event.payload.conflictingInstructions,
100
+ waitTime: event.payload.waitTime,
101
+ }))
102
+ }
103
+
104
+ /**
105
+ * 时间旅行:重放指令
106
+ */
107
+ replayInstruction(instructionId: string): {
108
+ success: boolean
109
+ events: CPUEvent[]
110
+ timeline: Array<{ time: number; stage: string; event: string }>
111
+ } {
112
+ const events = cpuLogger.getInstructionTrace(instructionId)
113
+
114
+ const timeline = events.map((event) => ({
115
+ time: event.timestamp,
116
+ stage: event.pipelineStage,
117
+ event: event.eventType,
118
+ }))
119
+
120
+ return {
121
+ success: events.some((e) => e.eventType === CPUEventType.INSTRUCTION_COMMITTED),
122
+ events,
123
+ timeline,
124
+ }
125
+ }
126
+
127
+ /**
128
+ * 诊断:分析指令为什么慢
129
+ */
130
+ diagnoseSlowInstruction(instructionId: string): {
131
+ instructionId: string
132
+ totalDuration: number
133
+ bottleneck: { stage: string; duration: number; percentage: number }
134
+ breakdown: Array<{ stage: string; duration: number; percentage: number }>
135
+ suggestions: string[]
136
+ } {
137
+ const events = cpuLogger.getInstructionTrace(instructionId)
138
+ if (events.length === 0) {
139
+ throw new Error(`Instruction ${instructionId} not found`)
140
+ }
141
+
142
+ const firstEvent = events[0]!
143
+ const lastEvent = events[events.length - 1]!
144
+ const totalDuration = lastEvent.timestamp - firstEvent.timestamp
145
+
146
+ // 计算每个阶段的耗时
147
+ const stageBreakdown = new Map<string, number>()
148
+ for (let i = 1; i < events.length; i++) {
149
+ const prevEvent = events[i - 1]
150
+ const currEvent = events[i]
151
+ const duration = currEvent.timestamp - prevEvent.timestamp
152
+ const stage = `${prevEvent.pipelineStage}→${currEvent.pipelineStage}`
153
+ stageBreakdown.set(stage, (stageBreakdown.get(stage) || 0) + duration)
154
+ }
155
+
156
+ const breakdown = Array.from(stageBreakdown.entries())
157
+ .map(([stage, duration]) => ({
158
+ stage,
159
+ duration,
160
+ percentage: (duration / totalDuration) * 100,
161
+ }))
162
+ .sort((a, b) => b.duration - a.duration)
163
+
164
+ const bottleneck = breakdown[0]
165
+
166
+ // 生成建议
167
+ const suggestions: string[] = []
168
+ if (bottleneck.stage.includes('EX')) {
169
+ suggestions.push('网络请求耗时较长,考虑优化后端性能或使用缓存')
170
+ }
171
+ if (bottleneck.stage.includes('SCH')) {
172
+ suggestions.push('调度器等待时间较长,存在资源冲突')
173
+ }
174
+ if (bottleneck.percentage > 80) {
175
+ suggestions.push(
176
+ `${bottleneck.stage} 占总耗时 ${bottleneck.percentage.toFixed(1)}%,是主要瓶颈`
177
+ )
178
+ }
179
+
180
+ return {
181
+ instructionId,
182
+ totalDuration,
183
+ bottleneck,
184
+ breakdown,
185
+ suggestions,
186
+ }
187
+ }
188
+
189
+ /**
190
+ * 实时监控:获取最近 N 秒的统计
191
+ */
192
+ getRealtimeStats(windowSeconds: number = 5): {
193
+ instructionsPerSecond: number
194
+ avgLatency: number
195
+ errorRate: number
196
+ topInstructionTypes: Array<{ type: string; count: number }>
197
+ } {
198
+ const now = Date.now()
199
+ const startTime = now - windowSeconds * 1000
200
+ const recentEvents = cpuLogger.getEventsByTimeRange(startTime, now)
201
+
202
+ const instructionIds = new Set(recentEvents.map((e) => e.instructionId))
203
+ const failedIds = new Set(
204
+ recentEvents
205
+ .filter((e) => e.eventType === CPUEventType.INSTRUCTION_FAILED)
206
+ .map((e) => e.instructionId)
207
+ )
208
+
209
+ const latencies = recentEvents.filter((e) => e.latency !== undefined).map((e) => e.latency!)
210
+
211
+ const avgLatency = latencies.reduce((a, b) => a + b, 0) / latencies.length || 0
212
+
213
+ const typeCount = new Map<string, number>()
214
+ for (const event of recentEvents) {
215
+ if (event.eventType === CPUEventType.INSTRUCTION_CREATED) {
216
+ typeCount.set(event.instructionType, (typeCount.get(event.instructionType) || 0) + 1)
217
+ }
218
+ }
219
+
220
+ const topInstructionTypes = Array.from(typeCount.entries())
221
+ .map(([type, count]) => ({ type, count }))
222
+ .sort((a, b) => b.count - a.count)
223
+ .slice(0, 5)
224
+
225
+ return {
226
+ instructionsPerSecond: instructionIds.size / windowSeconds,
227
+ avgLatency,
228
+ errorRate: failedIds.size / instructionIds.size || 0,
229
+ topInstructionTypes,
230
+ }
231
+ }
232
+ }
233
+
234
+ export const cpuDebugger = new CPUDebugger()
235
+
@@ -0,0 +1,418 @@
1
+ /**
2
+ * CPU 事件采集器
3
+ *
4
+ * 职责:
5
+ * 1. 在流水线各阶段捕获事件
6
+ * 2. 批量异步发送给 CPULogger
7
+ * 3. 零侵入、零延迟
8
+ */
9
+
10
+ import type { QueuedInstruction } from '../types'
11
+ import { PipelineStage, InstructionStatus } from '../types'
12
+ import { CPUEventType, type CPUEvent } from './types'
13
+
14
+ export class CPUEventCollector {
15
+ private eventQueue: CPUEvent[] = []
16
+ private flushInterval: number = 50 // 50ms 批量刷新
17
+ private maxBatchSize: number = 100
18
+ private enabled: boolean = true
19
+ private flushTimer: ReturnType<typeof setInterval> | null = null
20
+
21
+ constructor() {
22
+ this.startAutoFlush()
23
+ }
24
+
25
+ /**
26
+ * 启动自动刷新
27
+ */
28
+ private startAutoFlush(): void {
29
+ this.flushTimer = globalThis.setInterval(() => {
30
+ this.flush()
31
+ }, this.flushInterval)
32
+ }
33
+
34
+ /**
35
+ * 停止自动刷新
36
+ */
37
+ destroy(): void {
38
+ if (this.flushTimer !== null) {
39
+ globalThis.clearInterval(this.flushTimer)
40
+ this.flushTimer = null
41
+ }
42
+ this.flush() // 最后刷新一次
43
+ }
44
+
45
+ /**
46
+ * 发送事件(异步,不阻塞流水线)
47
+ */
48
+ emit(event: Partial<CPUEvent>): void {
49
+ if (!this.enabled) return
50
+
51
+ const fullEvent: CPUEvent = {
52
+ eventId: this.generateEventId(),
53
+ timestamp: Date.now(),
54
+ ...event,
55
+ } as CPUEvent
56
+
57
+ this.eventQueue.push(fullEvent)
58
+
59
+ // 触发批量刷新
60
+ if (this.eventQueue.length >= this.maxBatchSize) {
61
+ this.flush()
62
+ }
63
+ }
64
+
65
+ /**
66
+ * 批量刷新事件
67
+ */
68
+ private flush(): void {
69
+ if (this.eventQueue.length === 0) return
70
+
71
+ const batch = this.eventQueue.splice(0, this.maxBatchSize)
72
+
73
+ // 异步发送给 Logger(使用 queueMicrotask 确保不阻塞)
74
+ queueMicrotask(() => {
75
+ // 动态导入避免循环依赖
76
+ import('./CPULogger').then(({ cpuLogger }) => {
77
+ cpuLogger.ingestBatch(batch)
78
+ })
79
+ })
80
+ }
81
+
82
+ /**
83
+ * 便捷方法:指令创建
84
+ */
85
+ onInstructionCreated(instruction: QueuedInstruction): void {
86
+ this.emit({
87
+ eventType: CPUEventType.INSTRUCTION_CREATED,
88
+ instructionId: instruction.id,
89
+ instructionType: instruction.type,
90
+ correlationId: instruction.context.correlationId,
91
+ pipelineStage: PipelineStage.IF,
92
+ instructionStatus: InstructionStatus.PENDING,
93
+ callSource: instruction.context.callSource, // 🔍 记录调用源
94
+ payload: {
95
+ instructionType: instruction.type,
96
+ payload: instruction.payload,
97
+ origin: 'user',
98
+ },
99
+ })
100
+ }
101
+
102
+ /**
103
+ * 便捷方法:指令发射
104
+ */
105
+ onInstructionIssued(instruction: QueuedInstruction): void {
106
+ this.emit({
107
+ eventType: CPUEventType.INSTRUCTION_ISSUED,
108
+ instructionId: instruction.id,
109
+ instructionType: instruction.type,
110
+ correlationId: instruction.context.correlationId,
111
+ pipelineStage: PipelineStage.SCH,
112
+ instructionStatus: InstructionStatus.ISSUED,
113
+ payload: {},
114
+ })
115
+ }
116
+
117
+ /**
118
+ * 便捷方法:指令执行
119
+ */
120
+ onInstructionExecuting(instruction: QueuedInstruction): void {
121
+ this.emit({
122
+ eventType: CPUEventType.INSTRUCTION_EXECUTING,
123
+ instructionId: instruction.id,
124
+ instructionType: instruction.type,
125
+ correlationId: instruction.context.correlationId,
126
+ pipelineStage: PipelineStage.EX,
127
+ instructionStatus: InstructionStatus.EXECUTING,
128
+ payload: {},
129
+ })
130
+ }
131
+
132
+ /**
133
+ * 便捷方法:指令完成
134
+ */
135
+ onInstructionCommitted(instruction: QueuedInstruction): void {
136
+ // 计算总执行时间
137
+ const totalDuration = instruction.timestamps.WB && instruction.timestamps.IF
138
+ ? instruction.timestamps.WB - instruction.timestamps.IF
139
+ : undefined
140
+
141
+ // 计算各阶段耗时
142
+ const stageDurations = {
143
+ ifToSch: instruction.timestamps.SCH && instruction.timestamps.IF
144
+ ? instruction.timestamps.SCH - instruction.timestamps.IF : undefined,
145
+ schToEx: instruction.timestamps.EX && instruction.timestamps.SCH
146
+ ? instruction.timestamps.EX - instruction.timestamps.SCH : undefined,
147
+ exToWb: instruction.timestamps.WB && instruction.timestamps.EX
148
+ ? instruction.timestamps.WB - instruction.timestamps.EX : undefined,
149
+ }
150
+
151
+ this.emit({
152
+ eventType: CPUEventType.INSTRUCTION_COMMITTED,
153
+ instructionId: instruction.id,
154
+ instructionType: instruction.type,
155
+ correlationId: instruction.context.correlationId,
156
+ pipelineStage: PipelineStage.WB,
157
+ instructionStatus: InstructionStatus.COMMITTED,
158
+ callSource: instruction.context.callSource,
159
+ payload: {
160
+ // 🔥 包含完整的指令执行信息
161
+ originalPayload: instruction.payload,
162
+ result: instruction.result,
163
+ totalDuration,
164
+ stageDurations,
165
+ writeBackExecution: instruction.writeBackExecution,
166
+ hasOptimisticUpdate: !!instruction.optimisticSnapshot,
167
+ retryCount: instruction.context.retryCount,
168
+ timestamps: instruction.timestamps,
169
+ },
170
+ latency: totalDuration,
171
+ metadata: {
172
+ tags: ['committed', 'success'],
173
+ ...(instruction.writeBackExecution?.hasCommit && { hasCommit: true }),
174
+ ...(instruction.optimisticSnapshot && { optimisticUpdate: true }),
175
+ },
176
+ })
177
+ }
178
+
179
+ /**
180
+ * 便捷方法:指令被取消
181
+ */
182
+ onInstructionCancelled(instruction: QueuedInstruction): void {
183
+ // 计算取消时的执行时间
184
+ const totalDuration = instruction.timestamps.WB && instruction.timestamps.IF
185
+ ? instruction.timestamps.WB - instruction.timestamps.IF
186
+ : undefined
187
+
188
+ this.emit({
189
+ eventType: CPUEventType.INSTRUCTION_CANCELLED,
190
+ instructionId: instruction.id,
191
+ instructionType: instruction.type,
192
+ correlationId: instruction.context.correlationId,
193
+ pipelineStage: PipelineStage.WB,
194
+ instructionStatus: InstructionStatus.CANCELLED,
195
+ callSource: instruction.context.callSource,
196
+ payload: {
197
+ originalPayload: instruction.payload,
198
+ cancelReason: instruction.cancelReason,
199
+ cancelledAt: instruction.cancelledAt,
200
+ totalDuration,
201
+ },
202
+ })
203
+ }
204
+
205
+ /**
206
+ * 便捷方法:指令失败
207
+ */
208
+ onInstructionFailed(instruction: QueuedInstruction, error: Error): void {
209
+ // 计算总执行时间(失败时也需要记录)
210
+ const totalDuration = instruction.timestamps.WB && instruction.timestamps.IF
211
+ ? instruction.timestamps.WB - instruction.timestamps.IF
212
+ : undefined
213
+
214
+ // 计算各阶段耗时
215
+ const stageDurations = {
216
+ ifToSch: instruction.timestamps.SCH && instruction.timestamps.IF
217
+ ? instruction.timestamps.SCH - instruction.timestamps.IF : undefined,
218
+ schToEx: instruction.timestamps.EX && instruction.timestamps.SCH
219
+ ? instruction.timestamps.EX - instruction.timestamps.SCH : undefined,
220
+ exToWb: instruction.timestamps.WB && instruction.timestamps.EX
221
+ ? instruction.timestamps.WB - instruction.timestamps.EX : undefined,
222
+ }
223
+
224
+ this.emit({
225
+ eventType: CPUEventType.INSTRUCTION_FAILED,
226
+ instructionId: instruction.id,
227
+ instructionType: instruction.type,
228
+ correlationId: instruction.context.correlationId,
229
+ pipelineStage: PipelineStage.WB,
230
+ instructionStatus: InstructionStatus.FAILED,
231
+ callSource: instruction.context.callSource,
232
+ payload: {
233
+ // 🔥 包含完整的指令执行信息
234
+ originalPayload: instruction.payload,
235
+ error: error.message,
236
+ stack: error.stack,
237
+ totalDuration,
238
+ stageDurations,
239
+ writeBackExecution: instruction.writeBackExecution,
240
+ hasOptimisticUpdate: !!instruction.optimisticSnapshot,
241
+ rollbackExecuted: instruction.writeBackExecution?.rollbackExecuted,
242
+ retryCount: instruction.context.retryCount,
243
+ timestamps: instruction.timestamps,
244
+ },
245
+ latency: totalDuration,
246
+ metadata: {
247
+ tags: ['error', 'failure'],
248
+ ...(instruction.writeBackExecution?.rollbackExecuted && { rollbackExecuted: true }),
249
+ ...(instruction.optimisticSnapshot && { optimisticUpdate: true }),
250
+ },
251
+ })
252
+ }
253
+
254
+ /**
255
+ * 便捷方法:乐观更新应用
256
+ */
257
+ onOptimisticApplied(
258
+ instructionId: string,
259
+ instructionType: string,
260
+ correlationId: string,
261
+ snapshot: any,
262
+ changes: any
263
+ ): void {
264
+ this.emit({
265
+ eventType: CPUEventType.OPTIMISTIC_APPLIED,
266
+ instructionId,
267
+ instructionType,
268
+ correlationId,
269
+ pipelineStage: PipelineStage.EX,
270
+ instructionStatus: InstructionStatus.EXECUTING,
271
+ payload: { snapshot, changes },
272
+ metadata: { tags: ['optimistic'] },
273
+ })
274
+ }
275
+
276
+ /**
277
+ * 便捷方法:乐观更新回滚
278
+ */
279
+ onOptimisticRolledBack(
280
+ instructionId: string,
281
+ instructionType: string,
282
+ correlationId: string,
283
+ snapshot: any,
284
+ reason: string,
285
+ error?: Error
286
+ ): void {
287
+ this.emit({
288
+ eventType: CPUEventType.OPTIMISTIC_ROLLED_BACK,
289
+ instructionId,
290
+ instructionType,
291
+ correlationId,
292
+ pipelineStage: PipelineStage.WB,
293
+ instructionStatus: InstructionStatus.FAILED,
294
+ payload: { snapshot, reason, error: error?.message },
295
+ metadata: { tags: ['rollback', 'failure'] },
296
+ })
297
+ }
298
+
299
+ /**
300
+ * 便捷方法:资源冲突检测
301
+ */
302
+ onSchedulerConflict(
303
+ instructionId: string,
304
+ instructionType: string,
305
+ correlationId: string,
306
+ conflictingInstructions: string[],
307
+ conflictingResources: string[],
308
+ waitTime: number
309
+ ): void {
310
+ this.emit({
311
+ eventType: CPUEventType.SCHEDULER_CONFLICT_DETECTED,
312
+ instructionId,
313
+ instructionType,
314
+ correlationId,
315
+ pipelineStage: PipelineStage.SCH,
316
+ instructionStatus: InstructionStatus.ISSUED,
317
+ payload: {
318
+ conflictingInstructions,
319
+ conflictingResources,
320
+ waitTime,
321
+ },
322
+ metadata: {
323
+ resourceIds: conflictingResources,
324
+ tags: ['conflict', 'scheduler'],
325
+ },
326
+ })
327
+ }
328
+
329
+ /**
330
+ * 便捷方法:网络请求
331
+ */
332
+ onNetworkRequest(
333
+ instructionId: string,
334
+ instructionType: string,
335
+ correlationId: string,
336
+ method: string,
337
+ url: string
338
+ ): void {
339
+ this.emit({
340
+ eventType: CPUEventType.NETWORK_REQUEST_SENT,
341
+ instructionId,
342
+ instructionType,
343
+ correlationId,
344
+ pipelineStage: PipelineStage.EX,
345
+ instructionStatus: InstructionStatus.EXECUTING,
346
+ payload: { method, url },
347
+ metadata: { tags: ['network'] },
348
+ })
349
+ }
350
+
351
+ /**
352
+ * 便捷方法:网络响应
353
+ */
354
+ onNetworkResponse(
355
+ instructionId: string,
356
+ instructionType: string,
357
+ correlationId: string,
358
+ status: number,
359
+ latency: number,
360
+ size: number
361
+ ): void {
362
+ this.emit({
363
+ eventType: CPUEventType.NETWORK_RESPONSE_RECEIVED,
364
+ instructionId,
365
+ instructionType,
366
+ correlationId,
367
+ pipelineStage: PipelineStage.EX,
368
+ instructionStatus: InstructionStatus.EXECUTING,
369
+ payload: { status, latency, size },
370
+ latency,
371
+ metadata: { tags: ['network'] },
372
+ })
373
+
374
+ // 🔥 自动检测性能警告
375
+ if (latency > 1000) {
376
+ this.emit({
377
+ eventType: CPUEventType.PERFORMANCE_WARNING,
378
+ instructionId,
379
+ instructionType,
380
+ correlationId,
381
+ pipelineStage: PipelineStage.EX,
382
+ instructionStatus: InstructionStatus.EXECUTING,
383
+ payload: {
384
+ metric: 'latency',
385
+ threshold: 1000,
386
+ actual: latency,
387
+ suggestion: `网络请求耗时 ${latency}ms,超过阈值 1000ms`,
388
+ },
389
+ metadata: { tags: ['performance', 'warning'] },
390
+ })
391
+ }
392
+ }
393
+
394
+ /**
395
+ * 生成事件 ID
396
+ */
397
+ private generateEventId(): string {
398
+ return `evt_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`
399
+ }
400
+
401
+ /**
402
+ * 启用/禁用采集
403
+ */
404
+ enable(): void {
405
+ this.enabled = true
406
+ }
407
+
408
+ disable(): void {
409
+ this.enabled = false
410
+ }
411
+
412
+ isEnabled(): boolean {
413
+ return this.enabled
414
+ }
415
+ }
416
+
417
+ // 导出全局单例
418
+ export const cpuEventCollector = new CPUEventCollector()