feat(SPG-126) Monitoring APM
parent
1124307453
commit
bbff8352af
|
@ -0,0 +1,36 @@
|
||||||
|
import {
|
||||||
|
Injectable,
|
||||||
|
NestInterceptor,
|
||||||
|
ExecutionContext,
|
||||||
|
CallHandler,
|
||||||
|
HttpException,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { catchError } from 'rxjs/operators';
|
||||||
|
import { ApmService } from './apm.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ApmInterceptor implements NestInterceptor {
|
||||||
|
constructor(private readonly apmService: ApmService) {}
|
||||||
|
|
||||||
|
intercept(
|
||||||
|
context: ExecutionContext,
|
||||||
|
next: CallHandler,
|
||||||
|
): Observable<Response> {
|
||||||
|
const request = context.switchToHttp().getRequest<Request>();
|
||||||
|
const user = request.headers['e-user'];
|
||||||
|
const rules = request.headers['e-rules'];
|
||||||
|
this.apmService.setCustomContext({ user, rules });
|
||||||
|
|
||||||
|
return next.handle().pipe(
|
||||||
|
catchError((error) => {
|
||||||
|
if (error instanceof HttpException) {
|
||||||
|
this.apmService.captureError(error.message);
|
||||||
|
} else {
|
||||||
|
this.apmService.captureError(error);
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import { DynamicModule } from '@nestjs/common';
|
||||||
|
import { ApmService } from './apm.service';
|
||||||
|
import { APP_INTERCEPTOR } from '@nestjs/core';
|
||||||
|
import { ApmInterceptor } from './apm.interceptor';
|
||||||
|
// import { startAPM } from './start'
|
||||||
|
|
||||||
|
export class ApmModule {
|
||||||
|
static register(): DynamicModule {
|
||||||
|
return {
|
||||||
|
module: ApmModule,
|
||||||
|
imports: [],
|
||||||
|
providers: [
|
||||||
|
ApmService,
|
||||||
|
{
|
||||||
|
provide: APP_INTERCEPTOR,
|
||||||
|
useClass: ApmInterceptor,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
exports: [ApmService],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import * as APM from 'elastic-apm-node';
|
||||||
|
import apm = require('elastic-apm-node');
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class ApmService {
|
||||||
|
private readonly apm: apm.Agent;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.apm = APM;
|
||||||
|
}
|
||||||
|
|
||||||
|
captureError(data: Error | string): void {
|
||||||
|
this.apm.captureError(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
startTransaction(
|
||||||
|
name?: string,
|
||||||
|
options?: apm.TransactionOptions,
|
||||||
|
): apm.Transaction | null {
|
||||||
|
return this.apm.startTransaction(name, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTransactionName(name: string): void {
|
||||||
|
this.apm.setTransactionName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
startSpan(name?: string, options?: apm.SpanOptions): apm.Span | null {
|
||||||
|
return this.apm.startSpan(name, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
setCustomContext(context: Record<string, unknown>): void {
|
||||||
|
this.apm.setCustomContext(context);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
export * from './start';
|
||||||
|
export * from './apm.module';
|
||||||
|
export * from './apm.service';
|
||||||
|
export * from './apm.interceptor';
|
|
@ -0,0 +1,27 @@
|
||||||
|
import * as dotenv from 'dotenv';
|
||||||
|
dotenv.config(); //
|
||||||
|
|
||||||
|
import * as apmAgent from 'elastic-apm-node';
|
||||||
|
|
||||||
|
const options: apmAgent.AgentConfigOptions = {
|
||||||
|
active: process.env.ELASTIC_APM_ACTIVATE === 'true',
|
||||||
|
};
|
||||||
|
if (process.env.ELASTIC_APM_SERVICE_NAME) {
|
||||||
|
options['serviceName'] = process.env.ELASTIC_APM_SERVICE_NAME;
|
||||||
|
}
|
||||||
|
if (process.env.ELASTIC_APM_SECRET_TOKEN) {
|
||||||
|
options['secretToken'] = process.env.ELASTIC_APM_SECRET_TOKEN;
|
||||||
|
}
|
||||||
|
if (process.env.ELASTIC_APM_API_KEY) {
|
||||||
|
options['apiKey'] = process.env.ELASTIC_APM_API_KEY;
|
||||||
|
}
|
||||||
|
if (process.env.ELASTIC_APM_SERVER_URL) {
|
||||||
|
options['serverUrl'] = process.env.ELASTIC_APM_SERVER_URL;
|
||||||
|
}
|
||||||
|
if (process.env.ELASTIC_APM_DISABLE_INSTRUMENTATIONS) {
|
||||||
|
options['disableInstrumentations'] =
|
||||||
|
process.env.ELASTIC_APM_DISABLE_INSTRUMENTATIONS.split(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
const apm: apmAgent.Agent = apmAgent.start(options);
|
||||||
|
export { apm };
|
Loading…
Reference in New Issue