Comments (6)
I used a workaround in the meantime. Install @sentry/tracing
and setup the module like so:
SentryModule.forRoot({
enabled: true,
dsn: process.env.SENTRY_DSN,
debug: false,
environment: 'production',
integrations: [
new Sentry.Integrations.Http({ tracing: true })
],
tracesSampleRate: 1.0,
})
Then if you want to trace requests, create a middleware, like trace.middleware.ts
like this:
import {
Injectable,
NestMiddleware,
} from '@nestjs/common';
import { NextFunction, Request, Response } from 'express';
import { InjectSentry, SentryService } from '@ntegral/nestjs-sentry';
@Injectable()
export class TraceMiddleware implements NestMiddleware {
constructor(@InjectSentry() private readonly sentry: SentryService) {}
use(req: Request, res: Response, next: NextFunction): void {
const transaction = this.sentry.instance().startTransaction({
op: 'request',
name: req.url,
});
this.sentry.instance().getCurrentHub().configureScope(scope => {
scope.addEventProcessor(event => {
event.request = {
method: req.method,
url: req.url,
};
return event;
});
});
this.sentry.instance().configureScope(scope => {
scope.setSpan(transaction);
});
req.on('close', () => {
transaction.setHttpStatus(res.statusCode);
transaction.finish();
});
next();
}
}
Then you can setup the middleware in app.module.ts
(or any module you want):
export class AppModule {
configure(consumer: MiddlewareConsumer): void {
consumer.apply(TraceMiddleware).forRoutes('*');
}
}
from nestjs-sentry.
Additional to answer above, if you have an error
TypeError: Cannot read property 'setHttpStatus' of undefined
You need to add
import * as SentryTracing from '@sentry/tracing';
SentryTracing.addExtensionMethods();
somewhere in main.ts (before app.listen).
from nestjs-sentry.
I think the name should be req.baseUrl , for some req.url is empty in my case
from nestjs-sentry.
That worked for me too. Thanks @foxted and @moshenskyDV
from nestjs-sentry.
Hey, having issue with @foxted code. I am using same code but my Performance tab is empty :-( Any hints?
https://i.imgur.com/y0kN5Ec.png
from nestjs-sentry.
For anyone else wondering how to add support for traces:
I created these two middlewares for handling transactions:
import { Injectable, NestMiddleware } from '@nestjs/common';
import { InjectSentry, SentryService } from '@ntegral/nestjs-sentry';
import { Handlers } from '@sentry/node';
import { NextFunction, Request, Response } from 'express';
@Injectable()
export class RequestMiddleware implements NestMiddleware {
private readonly handler = Handlers.requestHandler({
include: {
ip: true,
user: true,
request: true,
transaction: 'methodPath',
},
});
constructor(@InjectSentry() private readonly sentry: SentryService) {}
use(req: Request, res: Response, next: NextFunction): void {
this.handler(req, res, next);
}
}
import { Injectable, NestMiddleware } from '@nestjs/common';
import { InjectSentry, SentryService } from '@ntegral/nestjs-sentry';
import { Handlers } from '@sentry/node';
import { NextFunction, Request, Response } from 'express';
@Injectable()
export class TraceMiddleware implements NestMiddleware {
private readonly handler = Handlers.tracingHandler();
constructor(@InjectSentry() private readonly sentry: SentryService) {}
use(req: Request, res: Response, next: NextFunction): void {
this.handler(req, res, next);
}
}
Then added them to a module:
export class WebModule {
configure(consumer: MiddlewareConsumer): void {
consumer.apply(TraceMiddleware).forRoutes('*');
consumer.apply(RequestMiddleware).forRoutes('*');
}
}
I have also overridden the interceptor with (note that we only use HTTP
, didn't consider WS
and RPC
):
import { CallHandler, ExecutionContext, HttpException } from '@nestjs/common';
import {
SentryInterceptor as BaseInterceptor,
InjectSentry,
SentryService,
} from '@ntegral/nestjs-sentry';
import { Handlers } from '@sentry/node';
import { Observable, catchError, throwError } from 'rxjs';
import { EntityNotFoundError } from 'typeorm';
export class SentryInterceptor extends BaseInterceptor {
private readonly handler = Handlers.errorHandler();
constructor(@InjectSentry() private readonly sentry: SentryService) {
super({
filters: [
{
type: HttpException,
filter: (e: HttpException) => e.getStatus() < 500,
},
{
type: EntityNotFoundError,
},
],
});
}
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
return next.handle().pipe(
catchError((error) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
if (this.shouldReport(error)) {
const http = context.switchToHttp();
this.handler(error, http.getRequest(), http.getResponse(), () => {});
}
return throwError(() => error);
}),
);
}
}
And this is how I setup the Sentry module:
SentryCoreModule.forRootAsync({
inject: [ConfigService, VersionService, HttpAdapterHost],
useFactory: async (
config: ConfigService,
version: VersionService,
host: HttpAdapterHost,
) => ({
dsn: config.get('SENTRY_DSN'),
release: await version.release(),
environment: config.get('NODE_ENV'),
tracesSampleRate: 1.0,
integrations: [
new Sentry.Integrations.Http({ tracing: true }),
new Mysql(),
host?.httpAdapter
? new Tracing.Integrations.Express({
app: host.httpAdapter.getInstance(),
})
: null,
].filter((i) => !!i),
}),
}),
Note: I created my own version of Mysql
integration to support the mysql2
package:
import type { Hub } from '@sentry/core';
import type { EventProcessor, Integration } from '@sentry/types';
import { fill, loadModule, logger } from '@sentry/utils';
interface MysqlConnection {
createQuery: () => void;
}
/** Tracing integration for node-mysql package */
export class Mysql implements Integration {
/**
* @inheritDoc
*/
public static id = 'Mysql';
/**
* @inheritDoc
*/
public name: string = Mysql.id;
/**
* @inheritDoc
*/
public setupOnce(
_: (callback: EventProcessor) => void,
getCurrentHub: () => Hub,
): void {
const pkg = loadModule<MysqlConnection>('mysql2/lib/connection.js');
if (!pkg) {
__DEBUG_BUILD__ &&
logger.error(
'Mysql Integration was unable to require `mysql2` package.',
);
return;
}
fill(pkg, 'createQuery', function (orig: () => void) {
return function (
this: unknown,
sql: unknown,
values: unknown,
cb: Function,
config: any,
) {
let options: Record<string, any> = {
rowsAsArray: config?.rowsAsArray,
};
if (typeof sql === 'object') {
// query(options, cb)
options = sql;
if (typeof values === 'function') {
cb = values;
} else if (values !== undefined) {
options.values = values;
}
} else if (typeof values === 'function') {
// query(sql, cb)
cb = values;
options.sql = sql;
options.values = undefined;
} else {
// query(sql, values, cb)
options.sql = sql;
options.values = values;
}
const scope = getCurrentHub().getScope();
const parentSpan = scope?.getSpan();
const span = parentSpan?.startChild({
description: options.sql,
op: 'db',
});
const ret = orig.call(this, ...arguments); // eslint-disable-line prefer-rest-params
ret.on('end', () => {
span?.finish();
});
return ret;
};
});
}
}
from nestjs-sentry.
Related Issues (20)
- Custom exception does not work in SentryInterceptor HOT 4
- Sentry Profiling Integration doesn't work HOT 8
- Exception objectError does not work
- unmet peer rimraf@^3.0.2: found 4.1.2
- Make app name in sentryService customizable HOT 1
- Argument of type 'undefined' is not assignable to parameter of type 'string | symbol'
- Is this project still maintained? HOT 7
- nestjs 10 support HOT 5
- Getting error in the latest version of nestjs (v10) HOT 6
- Remove 'rimraf' unused dependency HOT 1
- Request for Updating 'reflect-metadata' Package Version in Project HOT 2
- Question: Is there way to access Sentry directly in app.ts
- Stacktraces don't show the relevant stack HOT 1
- mocking sentry injection HOT 1
- NestJs 9 Support HOT 7
- How to inject into another module? HOT 4
- Why does my Sentry errors look like this? HOT 1
- Add Performance Tracking HOT 3
- Integrate Sentry Prisma ORM HOT 2
- Update imports of `@sentry/hub` to use `@sentry/core`
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from nestjs-sentry.