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