# Sentry

### Create Sentry Project

**Step 1: Create a New Project on Sentry**

1. Go to [Sentry](https://sentry.io/) and create new or log in to your account.
2. In your dashboard, select **Projects** > **Create Project**.
3. Choose NestJS as the platform.
4. Name your project, assign it to a team, and click **Create Project**.
5. After project creation, you’ll see a **DSN (Data Source Name)** key on the setup page. This DSN is essential for connecting your NestJS app to Sentry.
6. Copy the DSN, as you’ll need it for environment variables.

### API Setup

1. Install dependencies

```bash
yarn add @sentry/nestjs @sentry/profiling-node
```

2. Setup enviroment variables

{% code title=".env" %}

```
SENTRY_DNS=your_dsn
SENTRY_ENVIRONMENT=your_enviroment # 'development', 'production', etc.
```

{% endcode %}

{% code title="constants.ts" %}

```
SENTRY_DNS: process.env.SENTRY_DNS,
SENTRY_ENVIRONMENT: process.env.SENTRY_ENVIRONMENT,
```

{% endcode %}

3. Initialize Sentry

In Sentry initialization file, you can set up Sentry with tracing and profiling, along with advanced configuration options to manage error handling more effectively.

{% code title="instrument.ts" %}

```typescript
import * as Sentry from '@sentry/nestjs';
import { nodeProfilingIntegration } from '@sentry/profiling-node';
import constants from './constants';
import { httpIntegration } from '@sentry/nestjs';

Sentry.init({
    dsn: constants.SENTRY_DNS,
    environment: constants.SENTRY_ENVIRONMENT,
    includeLocalVariables: true,
    integrations: [nodeProfilingIntegration(), httpIntegration()],
    tracesSampleRate: 0.1,
    profilesSampleRate: 0.1,
    beforeSend(event, hint) {
        const error = hint?.originalException;

        if (error && typeof error === 'object' && 'status' in error) {
            const statusCode = (error as any).status;

            if (statusCode >= 400 && statusCode < 500) {
                // Do not send 4xx errors to Sentry
                return null;
            }
        }

        return event;
    },
});
```

{% endcode %}

4. Create Sentry filter

The Sentry filter allows you to add context to each error, making debugging more insightful by providing request details and user information without exposing sensitive data.

{% code title="sentry.filter.ts" %}

```typescript
import { Catch, ArgumentsHost } from '@nestjs/common';
import { BaseExceptionFilter } from '@nestjs/core';
import * as Sentry from '@sentry/node';

@Catch()
export class SentryFilter extends BaseExceptionFilter {
    catch(exception: unknown, host: ArgumentsHost) {
        const ctx = host.switchToHttp();
        const request = ctx.getRequest<Request>();

        Sentry.withScope(scope => {
            const headers = { ...request.headers };
            delete headers['authorization']; // Remove Authorization token

            scope.setExtras({
                method: request.method,
                url: request.url,
                headers: headers,
                user: request['user']
                    ? {
                          email: request['user']?.email,
                          roles: request['user']?.roles,
                          teamId: request['user']?.teamId,
                      }
                    : null,
            });

            Sentry.captureException(exception);
        });

        super.catch(exception, host);
    }
}
```

{% endcode %}

5. Initialize filter

In your main application module, register the Sentry filter globally.

```typescript
providers: [
    {
        provide: APP_FILTER,
        useClass: SentryGlobalFilter,
    },
],
```

After completing this steps you should be able to create test endopoint and catch your first error.

```javascript
@Get("/debug-sentry")
getError() {
  throw new Error("My first Sentry error!");
}
```
