create-dp-koa 1.1.1 → 1.1.3
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.
- package/package.json +1 -1
- package/template/scripts/sync-template.mjs +21 -0
- package/template/src/app.ts +1 -2
- package/template/src/{framework/plugins → plugins}/registry.ts +2 -2
- package/template/src/plugins/weboffice/http/routes.ts +2 -2
- package/template/src/plugins/weboffice/index.ts +3 -3
- package/template/src/plugins/weboffice/services/webofficeCallback.service.ts +3 -4
- package/template/src/utils/testDataInitializer.ts +1 -1
- package/template/tsconfig.json +6 -0
- package/template/src/annotations/decorators/ConfigManagement.ts +0 -9
- package/template/src/annotations/decorators/DistributedTracing.ts +0 -9
- package/template/src/annotations/decorators/EnterprisePerformance.ts +0 -9
- package/template/src/annotations/decorators/PerformanceMonitor.ts +0 -32
- package/template/src/annotations/decorators/SecurityAudit.ts +0 -9
- package/template/src/annotations/index.ts +0 -50
- package/template/src/annotations/processors/ConfigManagementProcessor.ts +0 -369
- package/template/src/annotations/processors/DistributedTracingProcessor.ts +0 -288
- package/template/src/annotations/processors/EnterprisePerformanceProcessor.ts +0 -189
- package/template/src/annotations/processors/PerformanceMonitorProcessor.ts +0 -101
- package/template/src/annotations/processors/SecurityAuditProcessor.ts +0 -345
- package/template/src/annotations/processors/SwaggerProcessor.ts +0 -612
- package/template/src/annotations/processors/index.ts +0 -10
- package/template/src/examples/InterceptorExampleRunner.ts +0 -284
- package/template/src/examples/ServiceInterceptorExample.ts +0 -214
- package/template/src/examples/cacheExamples.ts +0 -155
- package/template/src/framework/decorator/controller.ts +0 -311
- package/template/src/framework/decorator/processor/AnnotationDecorators.ts +0 -100
- package/template/src/framework/decorator/processor/AnnotationProcessor.ts +0 -160
- package/template/src/framework/decorator/processor/AnnotationProcessorConfig.ts +0 -45
- package/template/src/framework/decorator/processor/AnnotationRegistry.ts +0 -117
- package/template/src/framework/decorator/processor/AnnotationSystemInitializer.ts +0 -95
- package/template/src/framework/decorator/processor/ProcessorManager.ts +0 -76
- package/template/src/framework/decorator/processor/processors/CustomProcessors.ts +0 -126
- package/template/src/framework/decorator/processor/processors/DefaultProcessors.ts +0 -207
- package/template/src/framework/decorator/refactored/DecoratorFactory.ts +0 -99
- package/template/src/framework/decorator/refactored/DecoratorMetadataManager.ts +0 -125
- package/template/src/framework/decorator/refactored/DecoratorValidator.ts +0 -128
- package/template/src/framework/decorator/refactored/TypeSafeDecorators.ts +0 -139
- package/template/src/framework/decorator/refactored/index.ts +0 -98
- package/template/src/framework/decorator/swagger.ts +0 -150
- package/template/src/framework/interceptors/AdvancedServiceCallInterceptor.ts +0 -375
- package/template/src/framework/interceptors/ServiceCallInterceptor.ts +0 -348
- package/template/src/framework/interceptors/index.ts +0 -19
- package/template/src/framework/plugins/types.ts +0 -15
- package/template/src/framework/types/ServiceResult.ts +0 -151
- package/template/src/framework/types/index.ts +0 -16
- package/template/src/framework/utils/CacheManager.ts +0 -430
- package/template/src/framework/utils/CacheService.ts +0 -248
- package/template/src/framework/utils/DtoValidator.ts +0 -164
- package/template/src/framework/utils/MigrationHelper.ts +0 -179
- package/template/src/framework/utils/MigrationManager.ts +0 -256
- package/template/src/framework/utils/NewRouter.ts +0 -207
- package/template/src/framework/utils/TransactionManager.ts +0 -172
- package/template/src/framework/utils/bootstrap.ts +0 -445
- package/template/src/framework/utils/cache.ts +0 -269
- package/template/src/framework/utils/databaseConfig.ts +0 -148
- package/template/src/framework/utils/db.ts +0 -39
- package/template/src/framework/utils/dbMonitor.ts +0 -106
- package/template/src/framework/utils/function.ts +0 -61
- package/template/src/framework/utils/gracefulShutdown.ts +0 -131
- package/template/src/framework/utils/logger.ts +0 -388
- package/template/src/framework/utils/metrics.ts +0 -182
- package/template/src/framework/utils/router.ts +0 -417
- package/template/src/framework/utils/swagger.ts +0 -184
- package/template/src/framework/utils/testDb.ts +0 -19
- package/template/src/framework/utils/token.ts +0 -23
- package/template/src/framework/utils/transform.ts +0 -17
- package/template/src/libs/aokEmailSender.ts +0 -42
- package/template/src/libs/captcha.ts +0 -37
- package/template/src/libs/cos.ts +0 -45
- package/template/src/libs/mCache.ts +0 -7
- package/template/src/libs/serviceValidate.ts +0 -3
- package/template/src/libs/tecentSms.ts +0 -51
- package/template/src/middlewares/a.middleware.ts +0 -6
- package/template/src/middlewares/error.middleware.ts +0 -14
- package/template/src/middlewares/logging.middleware.ts +0 -187
- package/template/src/middlewares/static.middleware.ts +0 -79
- package/template/src/middlewares/swagger.middleware.ts +0 -70
- package/template/src/middlewares/token.middleware.ts +0 -32
- package/template/src/migrations/1700000000000-InitialDatabaseStructure.ts +0 -172
- package/template/src/migrations/index.ts +0 -6
- package/template/src/repository/base/BaseRepository.ts +0 -124
- package/template/src/repository/interfaces/IBaseRepository.ts +0 -67
- package/template/src/service/base.service.ts +0 -116
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 企业级分布式追踪注解处理器
|
|
3
|
-
* 提供跨服务的请求追踪和性能分析
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Context } from 'koa';
|
|
7
|
-
import { AnnotationProcessor } from '@src/framework/decorator/processor/AnnotationProcessor';
|
|
8
|
-
import { logger } from '@src/framework/utils/logger';
|
|
9
|
-
|
|
10
|
-
export interface TracingConfig {
|
|
11
|
-
enableTracing?: boolean;
|
|
12
|
-
traceIdHeader?: string;
|
|
13
|
-
spanIdHeader?: string;
|
|
14
|
-
parentSpanIdHeader?: string;
|
|
15
|
-
samplingRate?: number;
|
|
16
|
-
exportToJaeger?: boolean;
|
|
17
|
-
exportToZipkin?: boolean;
|
|
18
|
-
customTags?: Record<string, string>;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface TraceSpan {
|
|
22
|
-
traceId: string;
|
|
23
|
-
spanId: string;
|
|
24
|
-
parentSpanId?: string;
|
|
25
|
-
operationName: string;
|
|
26
|
-
startTime: number;
|
|
27
|
-
endTime?: number;
|
|
28
|
-
duration?: number;
|
|
29
|
-
tags: Record<string, any>;
|
|
30
|
-
logs: TraceLog[];
|
|
31
|
-
status: 'started' | 'completed' | 'error';
|
|
32
|
-
serviceName: string;
|
|
33
|
-
componentName: string;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface TraceLog {
|
|
37
|
-
timestamp: number;
|
|
38
|
-
level: 'info' | 'warn' | 'error';
|
|
39
|
-
message: string;
|
|
40
|
-
fields?: Record<string, any>;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export class DistributedTracingProcessor implements AnnotationProcessor {
|
|
44
|
-
readonly name = 'DistributedTracing';
|
|
45
|
-
readonly priority = 3;
|
|
46
|
-
|
|
47
|
-
private activeSpans: Map<string, TraceSpan> = new Map();
|
|
48
|
-
private completedSpans: TraceSpan[] = [];
|
|
49
|
-
private samplingRate: number = 1.0;
|
|
50
|
-
|
|
51
|
-
constructor() {
|
|
52
|
-
// 从环境变量读取采样率
|
|
53
|
-
this.samplingRate = parseFloat(process.env.TRACING_SAMPLING_RATE || '1.0');
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async process(
|
|
57
|
-
ctx: Context,
|
|
58
|
-
controller: any,
|
|
59
|
-
methodName: string,
|
|
60
|
-
annotationData: TracingConfig,
|
|
61
|
-
callParams: any[]
|
|
62
|
-
): Promise<boolean> {
|
|
63
|
-
const config = annotationData || {};
|
|
64
|
-
|
|
65
|
-
if (!config.enableTracing) return true;
|
|
66
|
-
|
|
67
|
-
// 决定是否采样
|
|
68
|
-
if (!this.shouldSample()) {
|
|
69
|
-
return true;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// 获取或创建追踪上下文
|
|
73
|
-
const traceContext = this.getOrCreateTraceContext(ctx, config);
|
|
74
|
-
|
|
75
|
-
// 创建新的 Span
|
|
76
|
-
const span = this.createSpan(traceContext, controller, methodName, config);
|
|
77
|
-
|
|
78
|
-
// 存储到上下文
|
|
79
|
-
ctx.state.traceSpan = span;
|
|
80
|
-
ctx.state.traceContext = traceContext;
|
|
81
|
-
|
|
82
|
-
// 添加追踪头到响应
|
|
83
|
-
ctx.set('X-Trace-Id', span.traceId);
|
|
84
|
-
ctx.set('X-Span-Id', span.spanId);
|
|
85
|
-
|
|
86
|
-
// 记录开始日志
|
|
87
|
-
this.addSpanLog(span, 'info', 'Span started', {
|
|
88
|
-
controller: controller.constructor.name,
|
|
89
|
-
method: methodName,
|
|
90
|
-
traceId: span.traceId,
|
|
91
|
-
spanId: span.spanId
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
logger.info(`[${this.name}] 开始追踪: ${span.operationName}`, {
|
|
95
|
-
traceId: span.traceId,
|
|
96
|
-
spanId: span.spanId,
|
|
97
|
-
parentSpanId: span.parentSpanId
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
return true;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
async postProcess(
|
|
104
|
-
ctx: Context,
|
|
105
|
-
controller: any,
|
|
106
|
-
methodName: string,
|
|
107
|
-
response: any
|
|
108
|
-
): Promise<void> {
|
|
109
|
-
const span = ctx.state.traceSpan;
|
|
110
|
-
if (!span) return;
|
|
111
|
-
|
|
112
|
-
// 完成 Span
|
|
113
|
-
span.endTime = Date.now();
|
|
114
|
-
span.duration = span.endTime - span.startTime;
|
|
115
|
-
span.status = 'completed';
|
|
116
|
-
|
|
117
|
-
// 添加响应信息到标签
|
|
118
|
-
span.tags['http.status_code'] = ctx.status;
|
|
119
|
-
span.tags['response.size'] = JSON.stringify(response).length;
|
|
120
|
-
span.tags['response.type'] = typeof response;
|
|
121
|
-
|
|
122
|
-
// 记录完成日志
|
|
123
|
-
this.addSpanLog(span, 'info', 'Span completed', {
|
|
124
|
-
duration: span.duration,
|
|
125
|
-
statusCode: ctx.status,
|
|
126
|
-
responseSize: span.tags['response.size']
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
// 移动到已完成列表
|
|
130
|
-
this.activeSpans.delete(span.spanId);
|
|
131
|
-
this.completedSpans.push(span);
|
|
132
|
-
|
|
133
|
-
// 导出到外部系统
|
|
134
|
-
await this.exportSpan(span);
|
|
135
|
-
|
|
136
|
-
logger.info(`[${this.name}] 完成追踪: ${span.operationName}`, {
|
|
137
|
-
traceId: span.traceId,
|
|
138
|
-
spanId: span.spanId,
|
|
139
|
-
duration: `${span.duration}ms`
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
private shouldSample(): boolean {
|
|
144
|
-
return Math.random() < this.samplingRate;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
private getOrCreateTraceContext(ctx: Context, config: TracingConfig): any {
|
|
148
|
-
const traceIdHeader = config.traceIdHeader || 'X-Trace-Id';
|
|
149
|
-
const spanIdHeader = config.spanIdHeader || 'X-Span-Id';
|
|
150
|
-
const parentSpanIdHeader = config.parentSpanIdHeader || 'X-Parent-Span-Id';
|
|
151
|
-
|
|
152
|
-
// 尝试从请求头获取现有的追踪上下文
|
|
153
|
-
const traceId = ctx.get(traceIdHeader) || this.generateTraceId();
|
|
154
|
-
const parentSpanId = ctx.get(parentSpanIdHeader);
|
|
155
|
-
|
|
156
|
-
return {
|
|
157
|
-
traceId,
|
|
158
|
-
parentSpanId,
|
|
159
|
-
headers: {
|
|
160
|
-
traceIdHeader,
|
|
161
|
-
spanIdHeader,
|
|
162
|
-
parentSpanIdHeader
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
private createSpan(traceContext: any, controller: any, methodName: string, config: TracingConfig): TraceSpan {
|
|
168
|
-
const spanId = this.generateSpanId();
|
|
169
|
-
const operationName = `${controller.constructor.name}.${methodName}`;
|
|
170
|
-
|
|
171
|
-
const span: TraceSpan = {
|
|
172
|
-
traceId: traceContext.traceId,
|
|
173
|
-
spanId,
|
|
174
|
-
parentSpanId: traceContext.parentSpanId,
|
|
175
|
-
operationName,
|
|
176
|
-
startTime: Date.now(),
|
|
177
|
-
tags: {
|
|
178
|
-
'component': 'controller',
|
|
179
|
-
'controller.name': controller.constructor.name,
|
|
180
|
-
'method.name': methodName,
|
|
181
|
-
'service.name': process.env.SERVICE_NAME || 'koa-framework',
|
|
182
|
-
'http.method': 'GET', // 这里应该从 ctx 获取
|
|
183
|
-
'http.url': '', // 这里应该从 ctx 获取
|
|
184
|
-
...config.customTags
|
|
185
|
-
},
|
|
186
|
-
logs: [],
|
|
187
|
-
status: 'started',
|
|
188
|
-
serviceName: process.env.SERVICE_NAME || 'koa-framework',
|
|
189
|
-
componentName: 'controller'
|
|
190
|
-
};
|
|
191
|
-
|
|
192
|
-
this.activeSpans.set(spanId, span);
|
|
193
|
-
return span;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
private addSpanLog(span: TraceSpan, level: TraceLog['level'], message: string, fields?: Record<string, any>): void {
|
|
197
|
-
span.logs.push({
|
|
198
|
-
timestamp: Date.now(),
|
|
199
|
-
level,
|
|
200
|
-
message,
|
|
201
|
-
fields
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
private async exportSpan(span: TraceSpan): Promise<void> {
|
|
206
|
-
try {
|
|
207
|
-
// 导出到 Jaeger
|
|
208
|
-
if (process.env.JAEGER_ENDPOINT) {
|
|
209
|
-
await this.exportToJaeger(span);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// 导出到 Zipkin
|
|
213
|
-
if (process.env.ZIPKIN_ENDPOINT) {
|
|
214
|
-
await this.exportToZipkin(span);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
// 导出到自定义系统
|
|
218
|
-
if (process.env.CUSTOM_TRACING_ENDPOINT) {
|
|
219
|
-
await this.exportToCustom(span);
|
|
220
|
-
}
|
|
221
|
-
} catch (error) {
|
|
222
|
-
logger.error(`[${this.name}] 导出追踪数据失败:`, error as Error);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
private async exportToJaeger(span: TraceSpan): Promise<void> {
|
|
227
|
-
// 这里应该实现 Jaeger 导出逻辑
|
|
228
|
-
logger.debug(`[${this.name}] 导出到 Jaeger: ${span.traceId}`);
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
private async exportToZipkin(span: TraceSpan): Promise<void> {
|
|
232
|
-
// 这里应该实现 Zipkin 导出逻辑
|
|
233
|
-
logger.debug(`[${this.name}] 导出到 Zipkin: ${span.traceId}`);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
private async exportToCustom(span: TraceSpan): Promise<void> {
|
|
237
|
-
// 这里应该实现自定义系统导出逻辑
|
|
238
|
-
logger.debug(`[${this.name}] 导出到自定义系统: ${span.traceId}`);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
private generateTraceId(): string {
|
|
242
|
-
return Math.random().toString(36).substring(2, 15) +
|
|
243
|
-
Math.random().toString(36).substring(2, 15);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
private generateSpanId(): string {
|
|
247
|
-
return Math.random().toString(36).substring(2, 15);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
* 获取追踪统计信息
|
|
252
|
-
*/
|
|
253
|
-
getTracingStats(): any {
|
|
254
|
-
const activeCount = this.activeSpans.size;
|
|
255
|
-
const completedCount = this.completedSpans.length;
|
|
256
|
-
|
|
257
|
-
const avgDuration = completedCount > 0
|
|
258
|
-
? this.completedSpans.reduce((sum, span) => sum + (span.duration || 0), 0) / completedCount
|
|
259
|
-
: 0;
|
|
260
|
-
|
|
261
|
-
return {
|
|
262
|
-
activeSpans: activeCount,
|
|
263
|
-
completedSpans: completedCount,
|
|
264
|
-
averageDuration: avgDuration,
|
|
265
|
-
samplingRate: this.samplingRate
|
|
266
|
-
};
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* 获取指定追踪的所有 Span
|
|
271
|
-
*/
|
|
272
|
-
getTraceSpans(traceId: string): TraceSpan[] {
|
|
273
|
-
return this.completedSpans.filter(span => span.traceId === traceId);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* 清理过期的 Span
|
|
278
|
-
*/
|
|
279
|
-
cleanupExpiredSpans(maxAge: number = 3600000): void { // 1小时
|
|
280
|
-
const cutoffTime = Date.now() - maxAge;
|
|
281
|
-
|
|
282
|
-
this.completedSpans = this.completedSpans.filter(span =>
|
|
283
|
-
span.startTime > cutoffTime
|
|
284
|
-
);
|
|
285
|
-
|
|
286
|
-
logger.info(`[${this.name}] 清理过期 Span 完成,保留 ${this.completedSpans.length} 个 Span`);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 企业级性能监控注解处理器
|
|
3
|
-
* 提供详细的性能指标、监控和告警
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { Context } from 'koa';
|
|
7
|
-
import { AnnotationProcessor } from '@src/framework/decorator/processor/AnnotationProcessor';
|
|
8
|
-
import { logger } from '@src/framework/utils/logger';
|
|
9
|
-
|
|
10
|
-
export interface PerformanceMetrics {
|
|
11
|
-
executionTime: number;
|
|
12
|
-
memoryUsage: {
|
|
13
|
-
rss: number;
|
|
14
|
-
heapUsed: number;
|
|
15
|
-
heapTotal: number;
|
|
16
|
-
external: number;
|
|
17
|
-
};
|
|
18
|
-
cpuUsage?: number;
|
|
19
|
-
requestSize?: number;
|
|
20
|
-
responseSize?: number;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export interface PerformanceConfig {
|
|
24
|
-
maxExecutionTime?: number;
|
|
25
|
-
maxMemoryUsage?: number;
|
|
26
|
-
enableMetrics?: boolean;
|
|
27
|
-
enableAlerts?: boolean;
|
|
28
|
-
alertThresholds?: {
|
|
29
|
-
executionTime?: number;
|
|
30
|
-
memoryUsage?: number;
|
|
31
|
-
errorRate?: number;
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export class EnterprisePerformanceProcessor implements AnnotationProcessor {
|
|
36
|
-
readonly name = 'EnterprisePerformance';
|
|
37
|
-
readonly priority = 1; // 最高优先级
|
|
38
|
-
|
|
39
|
-
private metrics: Map<string, PerformanceMetrics[]> = new Map();
|
|
40
|
-
private alertThresholds: Map<string, PerformanceConfig> = new Map();
|
|
41
|
-
|
|
42
|
-
async process(
|
|
43
|
-
ctx: Context,
|
|
44
|
-
controller: any,
|
|
45
|
-
methodName: string,
|
|
46
|
-
annotationData: PerformanceConfig,
|
|
47
|
-
callParams: any[]
|
|
48
|
-
): Promise<boolean> {
|
|
49
|
-
const startTime = process.hrtime.bigint();
|
|
50
|
-
const startMemory = process.memoryUsage();
|
|
51
|
-
const startCpu = process.cpuUsage();
|
|
52
|
-
|
|
53
|
-
// 存储性能监控数据
|
|
54
|
-
ctx.state.performanceMonitor = {
|
|
55
|
-
startTime,
|
|
56
|
-
startMemory,
|
|
57
|
-
startCpu,
|
|
58
|
-
methodName: `${controller.constructor.name}.${methodName}`,
|
|
59
|
-
config: annotationData || {},
|
|
60
|
-
requestSize: ctx.request.length || 0
|
|
61
|
-
};
|
|
62
|
-
|
|
63
|
-
// 记录开始时间
|
|
64
|
-
logger.info(`[${this.name}] 开始性能监控: ${controller.constructor.name}.${methodName}`);
|
|
65
|
-
|
|
66
|
-
return true;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async postProcess(
|
|
70
|
-
ctx: Context,
|
|
71
|
-
controller: any,
|
|
72
|
-
methodName: string,
|
|
73
|
-
response: any
|
|
74
|
-
): Promise<void> {
|
|
75
|
-
const monitor = ctx.state.performanceMonitor;
|
|
76
|
-
if (!monitor) return;
|
|
77
|
-
|
|
78
|
-
const endTime = process.hrtime.bigint();
|
|
79
|
-
const endMemory = process.memoryUsage();
|
|
80
|
-
const endCpu = process.cpuUsage();
|
|
81
|
-
|
|
82
|
-
// 计算性能指标
|
|
83
|
-
const executionTime = Number(endTime - monitor.startTime) / 1000000; // 毫秒
|
|
84
|
-
const memoryDelta = {
|
|
85
|
-
rss: endMemory.rss - monitor.startMemory.rss,
|
|
86
|
-
heapUsed: endMemory.heapUsed - monitor.startMemory.heapUsed,
|
|
87
|
-
heapTotal: endMemory.heapTotal - monitor.startMemory.heapTotal,
|
|
88
|
-
external: endMemory.external - monitor.startMemory.external
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
const cpuDelta = {
|
|
92
|
-
user: endCpu.user - monitor.startCpu.user,
|
|
93
|
-
system: endCpu.system - monitor.startCpu.system
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
const metrics: PerformanceMetrics = {
|
|
97
|
-
executionTime,
|
|
98
|
-
memoryUsage: memoryDelta,
|
|
99
|
-
cpuUsage: (cpuDelta.user + cpuDelta.system) / 1000000, // 微秒转毫秒
|
|
100
|
-
requestSize: monitor.requestSize,
|
|
101
|
-
responseSize: JSON.stringify(response).length
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
// 存储指标
|
|
105
|
-
this.storeMetrics(monitor.methodName, metrics);
|
|
106
|
-
|
|
107
|
-
// 检查告警阈值
|
|
108
|
-
this.checkAlerts(monitor.methodName, metrics, monitor.config);
|
|
109
|
-
|
|
110
|
-
// 记录性能日志
|
|
111
|
-
logger.info(`[${this.name}] 性能指标: ${monitor.methodName}`, {
|
|
112
|
-
executionTime: `${executionTime.toFixed(2)}ms`,
|
|
113
|
-
memoryUsage: `${(memoryDelta.heapUsed / 1024 / 1024).toFixed(2)}MB`,
|
|
114
|
-
cpuUsage: `${metrics.cpuUsage?.toFixed(2)}ms`,
|
|
115
|
-
requestSize: `${metrics.requestSize}B`,
|
|
116
|
-
responseSize: `${metrics.responseSize}B`
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
// 清理上下文
|
|
120
|
-
delete ctx.state.performanceMonitor;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
private storeMetrics(methodName: string, metrics: PerformanceMetrics): void {
|
|
124
|
-
if (!this.metrics.has(methodName)) {
|
|
125
|
-
this.metrics.set(methodName, []);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const methodMetrics = this.metrics.get(methodName)!;
|
|
129
|
-
methodMetrics.push(metrics);
|
|
130
|
-
|
|
131
|
-
// 只保留最近100条记录
|
|
132
|
-
if (methodMetrics.length > 100) {
|
|
133
|
-
methodMetrics.shift();
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
private checkAlerts(methodName: string, metrics: PerformanceMetrics, config: PerformanceConfig): void {
|
|
138
|
-
const thresholds = config.alertThresholds || {};
|
|
139
|
-
|
|
140
|
-
// 执行时间告警
|
|
141
|
-
if (thresholds.executionTime && metrics.executionTime > thresholds.executionTime) {
|
|
142
|
-
logger.warn(`[${this.name}] ⚠️ 执行时间告警: ${methodName}`, {
|
|
143
|
-
executionTime: `${metrics.executionTime.toFixed(2)}ms`,
|
|
144
|
-
threshold: `${thresholds.executionTime}ms`
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// 内存使用告警
|
|
149
|
-
if (thresholds.memoryUsage && Math.abs(metrics.memoryUsage.heapUsed) > thresholds.memoryUsage * 1024 * 1024) {
|
|
150
|
-
logger.warn(`[${this.name}] ⚠️ 内存使用告警: ${methodName}`, {
|
|
151
|
-
memoryUsage: `${(metrics.memoryUsage.heapUsed / 1024 / 1024).toFixed(2)}MB`,
|
|
152
|
-
threshold: `${thresholds.memoryUsage}MB`
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* 获取性能统计
|
|
159
|
-
*/
|
|
160
|
-
getPerformanceStats(methodName?: string): any {
|
|
161
|
-
if (methodName) {
|
|
162
|
-
const metrics = this.metrics.get(methodName) || [];
|
|
163
|
-
return this.calculateStats(metrics);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
const allStats: any = {};
|
|
167
|
-
this.metrics.forEach((metrics, name) => {
|
|
168
|
-
allStats[name] = this.calculateStats(metrics);
|
|
169
|
-
});
|
|
170
|
-
return allStats;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
private calculateStats(metrics: PerformanceMetrics[]): any {
|
|
174
|
-
if (metrics.length === 0) return null;
|
|
175
|
-
|
|
176
|
-
const executionTimes = metrics.map(m => m.executionTime);
|
|
177
|
-
const memoryUsages = metrics.map(m => m.memoryUsage.heapUsed);
|
|
178
|
-
|
|
179
|
-
return {
|
|
180
|
-
count: metrics.length,
|
|
181
|
-
avgExecutionTime: executionTimes.reduce((a, b) => a + b, 0) / executionTimes.length,
|
|
182
|
-
maxExecutionTime: Math.max(...executionTimes),
|
|
183
|
-
minExecutionTime: Math.min(...executionTimes),
|
|
184
|
-
avgMemoryUsage: memoryUsages.reduce((a, b) => a + b, 0) / memoryUsages.length,
|
|
185
|
-
maxMemoryUsage: Math.max(...memoryUsages),
|
|
186
|
-
minMemoryUsage: Math.min(...memoryUsages)
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
}
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { Context } from 'koa';
|
|
2
|
-
import { AnnotationProcessor } from '@src/framework/decorator/processor/AnnotationProcessor';
|
|
3
|
-
import { isDebug } from '@src/framework/utils/function';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* 性能监控注解处理器
|
|
7
|
-
* 监控方法执行时间、内存使用等性能指标
|
|
8
|
-
*/
|
|
9
|
-
export class PerformanceMonitorProcessor implements AnnotationProcessor {
|
|
10
|
-
readonly name = 'PerformanceMonitor';
|
|
11
|
-
readonly priority = 8; // 高优先级,在日志记录之前执行
|
|
12
|
-
|
|
13
|
-
async process(
|
|
14
|
-
ctx: Context,
|
|
15
|
-
controller: any,
|
|
16
|
-
methodName: string,
|
|
17
|
-
annotationData: any,
|
|
18
|
-
callParams: any[]
|
|
19
|
-
): Promise<boolean> {
|
|
20
|
-
const startTime = process.hrtime.bigint();
|
|
21
|
-
const startMemory = process.memoryUsage();
|
|
22
|
-
|
|
23
|
-
// 只在调试模式下输出详细日志
|
|
24
|
-
if (isDebug()) {
|
|
25
|
-
console.log(`[${this.name}] 开始性能监控: ${controller.constructor.name}.${methodName}`);
|
|
26
|
-
console.log(`[${this.name}] 配置参数:`, annotationData);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// 将性能监控数据存储到上下文中
|
|
30
|
-
ctx.state.performanceMonitor = {
|
|
31
|
-
startTime,
|
|
32
|
-
startMemory,
|
|
33
|
-
methodName: `${controller.constructor.name}.${methodName}`,
|
|
34
|
-
config: annotationData || {}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
return true;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* 后置处理方法
|
|
42
|
-
* 在控制器方法执行完成后自动调用
|
|
43
|
-
*/
|
|
44
|
-
async postProcess(
|
|
45
|
-
ctx: Context,
|
|
46
|
-
controller: any,
|
|
47
|
-
methodName: string,
|
|
48
|
-
response: any
|
|
49
|
-
): Promise<void> {
|
|
50
|
-
this.logPerformance(ctx);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* 记录性能监控结果
|
|
55
|
-
*/
|
|
56
|
-
private logPerformance(ctx: Context): void {
|
|
57
|
-
const monitor = ctx.state.performanceMonitor;
|
|
58
|
-
if (!monitor) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const endTime = process.hrtime.bigint();
|
|
63
|
-
const endMemory = process.memoryUsage();
|
|
64
|
-
|
|
65
|
-
// 计算执行时间(纳秒转毫秒)
|
|
66
|
-
const executionTime = Number(endTime - monitor.startTime) / 1000000;
|
|
67
|
-
|
|
68
|
-
// 计算内存使用变化
|
|
69
|
-
const memoryDelta = {
|
|
70
|
-
rss: endMemory.rss - monitor.startMemory.rss,
|
|
71
|
-
heapUsed: endMemory.heapUsed - monitor.startMemory.heapUsed,
|
|
72
|
-
heapTotal: endMemory.heapTotal - monitor.startMemory.heapTotal,
|
|
73
|
-
external: endMemory.external - monitor.startMemory.external
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
// 只在调试模式下输出详细日志
|
|
77
|
-
if (isDebug()) {
|
|
78
|
-
console.log(`[PerformanceMonitor] 性能监控结果: ${monitor.methodName}`);
|
|
79
|
-
console.log(`[PerformanceMonitor] 执行时间: ${executionTime.toFixed(2)}ms`);
|
|
80
|
-
console.log(`[PerformanceMonitor] 内存使用变化:`, {
|
|
81
|
-
rss: `${(memoryDelta.rss / 1024 / 1024).toFixed(2)}MB`,
|
|
82
|
-
heapUsed: `${(memoryDelta.heapUsed / 1024 / 1024).toFixed(2)}MB`,
|
|
83
|
-
heapTotal: `${(memoryDelta.heapTotal / 1024 / 1024).toFixed(2)}MB`,
|
|
84
|
-
external: `${(memoryDelta.external / 1024 / 1024).toFixed(2)}MB`
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// 性能警告(始终输出)
|
|
89
|
-
const config = monitor.config;
|
|
90
|
-
if (config.maxExecutionTime && executionTime > config.maxExecutionTime) {
|
|
91
|
-
console.warn(`[PerformanceMonitor] ⚠️ 执行时间超过阈值: ${executionTime.toFixed(2)}ms > ${config.maxExecutionTime}ms`);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (config.maxMemoryUsage && Math.abs(memoryDelta.heapUsed) > config.maxMemoryUsage * 1024 * 1024) {
|
|
95
|
-
console.warn(`[PerformanceMonitor] ⚠️ 内存使用变化过大: ${(memoryDelta.heapUsed / 1024 / 1024).toFixed(2)}MB`);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// 清理上下文
|
|
99
|
-
delete ctx.state.performanceMonitor;
|
|
100
|
-
}
|
|
101
|
-
}
|