Skip to content

Commit

Permalink
Merge pull request #1 from devmasx/track-error-type--nestjs-controlle…
Browse files Browse the repository at this point in the history
…r-span

Track error type in Nestjs controller span
  • Loading branch information
MiguelSavignano authored Jan 2, 2023
2 parents 60c2354 + 3834ee9 commit bd52eb7
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 3 deletions.
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DynamicModule, MiddlewareConsumer, NestModule } from '@nestjs/common';
import 'reflect-metadata';
import { OpenTelemetryModule, OpenTelemetryModuleConfig } from '@metinseylan/nestjs-opentelemetry';
export { Span, TraceService } from '@metinseylan/nestjs-opentelemetry';
import { ExporterConfig } from '@opentelemetry/exporter-jaeger';
Expand Down
52 changes: 51 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,63 @@ var OpenTelemetrySetupModule_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.OpenTelemetrySetupModule = exports.TraceService = exports.Span = void 0;
const common_1 = require("@nestjs/common");
require("reflect-metadata");
const api_1 = require("@opentelemetry/api");
const nestjs_opentelemetry_1 = require("@metinseylan/nestjs-opentelemetry");
var nestjs_opentelemetry_2 = require("@metinseylan/nestjs-opentelemetry");
Object.defineProperty(exports, "Span", { enumerable: true, get: function () { return nestjs_opentelemetry_2.Span; } });
Object.defineProperty(exports, "TraceService", { enumerable: true, get: function () { return nestjs_opentelemetry_2.TraceService; } });
const exporter_jaeger_1 = require("@opentelemetry/exporter-jaeger");
const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base");
class ControllerInjectorWithError extends nestjs_opentelemetry_1.ControllerInjector {
wrap(prototype, traceName, attributes = {}) {
const method = {
[prototype.name]: function (...args) {
const tracer = api_1.trace.getTracer('default');
const currentSpan = tracer.startSpan(traceName);
return api_1.context.with(api_1.trace.setSpan(api_1.context.active(), currentSpan), () => {
currentSpan.setAttributes(attributes);
if (prototype.constructor.name === 'AsyncFunction') {
return prototype
.apply(this, args)
.catch((error) => ControllerInjectorWithError.recordException(error, currentSpan))
.finally(() => {
currentSpan.end();
});
}
else {
try {
const result = prototype.apply(this, args);
currentSpan.end();
return result;
}
catch (error) {
ControllerInjectorWithError.recordException(error, currentSpan);
}
finally {
currentSpan.end();
}
}
});
},
}[prototype.name];
Reflect.defineMetadata(nestjs_opentelemetry_1.Constants.TRACE_METADATA, traceName, method);
this.affect(method);
this.reDecorate(prototype, method);
return method;
}
static recordException(error, span) {
var _a;
span.recordException(error);
span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
span.setAttributes({
track_error: true,
error_type: ((_a = error.constructor) === null || _a === void 0 ? void 0 : _a.name) || error.name,
error_message: error.message,
});
throw error;
}
}
let OpenTelemetrySetupModule = OpenTelemetrySetupModule_1 = class OpenTelemetrySetupModule extends nestjs_opentelemetry_1.OpenTelemetryModule {
static async forRoot(configuration = {}) {
const forRoot = await super.forRoot(Object.assign(Object.assign({}, configuration), { traceAutoInjectors: this.traceAutoInjectors(), spanProcessor: new sdk_trace_base_1.SimpleSpanProcessor(new exporter_jaeger_1.JaegerExporter(this.jaegerExporterOptions())) }));
Expand All @@ -33,7 +83,7 @@ let OpenTelemetrySetupModule = OpenTelemetrySetupModule_1 = class OpenTelemetryS
}
static traceAutoInjectors() {
return [
nestjs_opentelemetry_1.ControllerInjector,
ControllerInjectorWithError,
nestjs_opentelemetry_1.GuardInjector,
nestjs_opentelemetry_1.EventEmitterInjector,
nestjs_opentelemetry_1.ScheduleInjector,
Expand Down
64 changes: 62 additions & 2 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import {
Module,
NestModule,
} from '@nestjs/common';
import { context, trace } from '@opentelemetry/api';
import 'reflect-metadata';
import { context, Span, SpanStatusCode, trace } from '@opentelemetry/api';

import {
Constants,
ControllerInjector,
EventEmitterInjector,
GuardInjector,
Expand All @@ -22,6 +24,64 @@ export { Span, TraceService } from '@metinseylan/nestjs-opentelemetry';
import { ExporterConfig, JaegerExporter } from '@opentelemetry/exporter-jaeger';
import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base';

class ControllerInjectorWithError extends ControllerInjector {
protected wrap(prototype: Record<any, any>, traceName, attributes = {}) {
const method = {
[prototype.name]: function (...args: any[]) {
const tracer = trace.getTracer('default');
const currentSpan = tracer.startSpan(traceName);

return context.with(
trace.setSpan(context.active(), currentSpan),
() => {
currentSpan.setAttributes(attributes);
if (prototype.constructor.name === 'AsyncFunction') {
return prototype
.apply(this, args)
.catch((error) =>
ControllerInjectorWithError.recordException(
error,
currentSpan,
),
)
.finally(() => {
currentSpan.end();
});
} else {
try {
const result = prototype.apply(this, args);
currentSpan.end();
return result;
} catch (error) {
ControllerInjectorWithError.recordException(error, currentSpan);
} finally {
currentSpan.end();
}
}
},
);
},
}[prototype.name];

Reflect.defineMetadata(Constants.TRACE_METADATA, traceName, method);
this.affect(method);
this.reDecorate(prototype, method);

return method;
}

protected static recordException(error, span: Span) {
span.recordException(error);
span.setStatus({ code: SpanStatusCode.ERROR, message: error.message });
span.setAttributes({
track_error: true,
error_type: error.constructor?.name || error.name,
error_message: error.message,
});
throw error;
}
}

@Module({})
export class OpenTelemetrySetupModule
extends OpenTelemetryModule
Expand Down Expand Up @@ -57,7 +117,7 @@ export class OpenTelemetrySetupModule

static traceAutoInjectors(): Array<any> {
return [
ControllerInjector,
ControllerInjectorWithError,
GuardInjector,
EventEmitterInjector,
ScheduleInjector,
Expand Down

0 comments on commit bd52eb7

Please sign in to comment.