Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(nestjs): Add @sentry/nestjs #12613

Merged
merged 34 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d7141cb
Add nest js basic package
nicohrubec Jun 24, 2024
c470400
Fix build failure: Add missing npm config file
nicohrubec Jun 24, 2024
33d016a
Update yarn lock
nicohrubec Jun 24, 2024
c8a9c4a
Rename nest package to nestjs
nicohrubec Jun 24, 2024
5ad16dc
Fix package name
nicohrubec Jun 24, 2024
201fa58
Apply biome suggested changes
nicohrubec Jun 24, 2024
a461de8
Update build paths in package json
nicohrubec Jun 24, 2024
8e45888
Maybe fix build failure
nicohrubec Jun 24, 2024
075fe71
Add nestjs to verdaccio config
nicohrubec Jun 24, 2024
43d53b8
Update nest init method signature
nicohrubec Jun 25, 2024
bdfd89b
Merge branch 'develop' into nh/nest-sdk
nicohrubec Jun 25, 2024
c99d7a0
Remove yarn.lock in nest package
nicohrubec Jun 25, 2024
60aeb8d
Update README
nicohrubec Jun 25, 2024
aa1ecb5
Merge branch 'nh/nest-sdk' of github.com:getsentry/sentry-javascript …
nicohrubec Jun 25, 2024
f69273e
undo yarn lock changes
lforst Jun 25, 2024
acfc125
Fix yarn.lock
nicohrubec Jun 25, 2024
43a3d31
Merge branch 'nh/nest-sdk' of github.com:getsentry/sentry-javascript …
nicohrubec Jun 25, 2024
1502aaf
Remove unnecessary optional dependency
nicohrubec Jun 25, 2024
86c4864
Return client from nest init
nicohrubec Jun 25, 2024
bea2348
Update README
nicohrubec Jun 25, 2024
817d81e
Update README
nicohrubec Jun 25, 2024
dd9cd37
Run tests with vitest instead of jest
nicohrubec Jun 25, 2024
e337949
Lint
nicohrubec Jun 25, 2024
0b5e2fc
Update craft.yml
nicohrubec Jun 25, 2024
ac51900
Try to fix ci
nicohrubec Jun 25, 2024
4685987
Merge branch 'develop' into nh/nest-sdk
nicohrubec Jun 26, 2024
2fe22d4
Update node-nestjs e2e test
nicohrubec Jun 26, 2024
2928842
Update dependency
nicohrubec Jun 26, 2024
7c38b7f
Rename node-nestjs e2e to nestjs
nicohrubec Jun 26, 2024
b42918c
Revert "Rename node-nestjs e2e to nestjs"
nicohrubec Jun 26, 2024
957522f
Exclude nest package from node 14 unit tests
nicohrubec Jun 26, 2024
48a3a98
Rename node-nestjs e2e to nestjs
nicohrubec Jun 26, 2024
6ab0565
Drop prepack step
nicohrubec Jun 26, 2024
cb21e07
Address pr comments
nicohrubec Jun 26, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .craft.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ targets:
- name: npm
id: '@sentry/bun'
includeNames: /^sentry-bun-\d.*\.tgz$/
- name: npm
id: '@sentry/nestjs'
includeNames: /^sentry-nestjs-\d.*\.tgz$/

## 6. Fullstack/Meta Frameworks (depending on Node and Browser or Framework SDKs)
- name: npm
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1067,7 +1067,7 @@ jobs:
'generic-ts3.8',
'node-fastify',
'node-hapi',
'node-nestjs',
'nestjs',
'node-exports-test-app',
'node-koa',
'node-connect',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "node-nestjs",
"name": "nestjs",
"version": "0.0.1",
"private": true,
"scripts": {
Expand All @@ -18,7 +18,7 @@
"@nestjs/common": "^10.0.0",
"@nestjs/core": "^10.0.0",
"@nestjs/platform-express": "^10.0.0",
"@sentry/node": "latest || *",
"@sentry/nestjs": "latest || *",
"@sentry/types": "latest || *",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Injectable } from '@nestjs/common';
import * as Sentry from '@sentry/node';
import * as Sentry from '@sentry/nestjs';
import { makeHttpRequest } from './utils';

@Injectable()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as Sentry from '@sentry/node';
import * as Sentry from '@sentry/nestjs';

Sentry.init({
environment: 'qa', // dynamic sampling bias to keep transactions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import './instrument';

// Import other modules
import { BaseExceptionFilter, HttpAdapterHost, NestFactory } from '@nestjs/core';
import * as Sentry from '@sentry/node';
import * as Sentry from '@sentry/nestjs';
import { AppModule1, AppModule2 } from './app.module';

const app1Port = 3030;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ import { startEventProxyServer } from '@sentry-internal/test-utils';

startEventProxyServer({
port: 3031,
proxyServerName: 'node-nestjs',
proxyServerName: 'nestjs',
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { expect, test } from '@playwright/test';
import { waitForError } from '@sentry-internal/test-utils';

test('Sends exception to Sentry', async ({ baseURL }) => {
const errorEventPromise = waitForError('node-nestjs', event => {
const errorEventPromise = waitForError('nestjs', event => {
return !event.type && event.exception?.values?.[0]?.value === 'This is an exception with id 123';
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import { SpanJSON } from '@sentry/types';
test('Propagates trace for outgoing http requests', async ({ baseURL }) => {
const id = crypto.randomUUID();

const inboundTransactionPromise = waitForTransaction('node-nestjs', transactionEvent => {
const inboundTransactionPromise = waitForTransaction('nestjs', transactionEvent => {
return (
transactionEvent.contexts?.trace?.op === 'http.server' &&
transactionEvent.contexts?.trace?.data?.['http.target'] === `/test-inbound-headers/${id}`
);
});

const outboundTransactionPromise = waitForTransaction('node-nestjs', transactionEvent => {
const outboundTransactionPromise = waitForTransaction('nestjs', transactionEvent => {
return (
transactionEvent.contexts?.trace?.op === 'http.server' &&
transactionEvent.contexts?.trace?.data?.['http.target'] === `/test-outgoing-http/${id}`
Expand Down Expand Up @@ -121,14 +121,14 @@ test('Propagates trace for outgoing http requests', async ({ baseURL }) => {
test('Propagates trace for outgoing fetch requests', async ({ baseURL }) => {
const id = crypto.randomUUID();

const inboundTransactionPromise = waitForTransaction('node-nestjs', transactionEvent => {
const inboundTransactionPromise = waitForTransaction('nestjs', transactionEvent => {
return (
transactionEvent?.contexts?.trace?.op === 'http.server' &&
transactionEvent.contexts?.trace?.data?.['http.target'] === `/test-inbound-headers/${id}`
);
});

const outboundTransactionPromise = waitForTransaction('node-nestjs', transactionEvent => {
const outboundTransactionPromise = waitForTransaction('nestjs', transactionEvent => {
return (
transactionEvent?.contexts?.trace?.op === 'http.server' &&
transactionEvent.contexts?.trace?.data?.['http.target'] === `/test-outgoing-fetch/${id}`
Expand Down Expand Up @@ -234,7 +234,7 @@ test('Propagates trace for outgoing fetch requests', async ({ baseURL }) => {
});

test('Propagates trace for outgoing external http requests', async ({ baseURL }) => {
const inboundTransactionPromise = waitForTransaction('node-nestjs', transactionEvent => {
const inboundTransactionPromise = waitForTransaction('nestjs', transactionEvent => {
return (
transactionEvent?.contexts?.trace?.op === 'http.server' &&
transactionEvent.contexts?.trace?.data?.['http.target'] === `/test-outgoing-http-external-allowed`
Expand Down Expand Up @@ -271,7 +271,7 @@ test('Propagates trace for outgoing external http requests', async ({ baseURL })
});

test('Does not propagate outgoing http requests not covered by tracePropagationTargets', async ({ baseURL }) => {
const inboundTransactionPromise = waitForTransaction('node-nestjs', transactionEvent => {
const inboundTransactionPromise = waitForTransaction('nestjs', transactionEvent => {
return (
transactionEvent?.contexts?.trace?.op === 'http.server' &&
transactionEvent.contexts?.trace?.data?.['http.target'] === `/test-outgoing-http-external-disallowed`
Expand All @@ -295,7 +295,7 @@ test('Does not propagate outgoing http requests not covered by tracePropagationT
});

test('Propagates trace for outgoing external fetch requests', async ({ baseURL }) => {
const inboundTransactionPromise = waitForTransaction('node-nestjs', transactionEvent => {
const inboundTransactionPromise = waitForTransaction('nestjs', transactionEvent => {
return (
transactionEvent?.contexts?.trace?.op === 'http.server' &&
transactionEvent.contexts?.trace?.data?.['http.target'] === `/test-outgoing-fetch-external-allowed`
Expand Down Expand Up @@ -332,7 +332,7 @@ test('Propagates trace for outgoing external fetch requests', async ({ baseURL }
});

test('Does not propagate outgoing fetch requests not covered by tracePropagationTargets', async ({ baseURL }) => {
const inboundTransactionPromise = waitForTransaction('node-nestjs', transactionEvent => {
const inboundTransactionPromise = waitForTransaction('nestjs', transactionEvent => {
return (
transactionEvent?.contexts?.trace?.op === 'http.server' &&
transactionEvent.contexts?.trace?.data?.['http.target'] === `/test-outgoing-fetch-external-disallowed`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { expect, test } from '@playwright/test';
import { waitForTransaction } from '@sentry-internal/test-utils';

test('Sends an API route transaction', async ({ baseURL }) => {
const pageloadTransactionEventPromise = waitForTransaction('node-nestjs', transactionEvent => {
const pageloadTransactionEventPromise = waitForTransaction('nestjs', transactionEvent => {
return (
transactionEvent?.contexts?.trace?.op === 'http.server' &&
transactionEvent?.transaction === 'GET /test-transaction'
Expand Down
6 changes: 6 additions & 0 deletions dev-packages/e2e-tests/verdaccio-config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ packages:
unpublish: $all
# proxy: npmjs # Don't proxy for E2E tests!

'@sentry/nestjs':
access: $all
publish: $all
unpublish: $all
# proxy: npmjs # Don't proxy for E2E tests!

'@sentry/nextjs':
access: $all
publish: $all
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"packages/gatsby",
"packages/google-cloud-serverless",
"packages/integration-shims",
"packages/nestjs",
"packages/nextjs",
"packages/node",
"packages/nuxt",
Expand Down
6 changes: 6 additions & 0 deletions packages/nestjs/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
env: {
node: true,
},
extends: ['../../.eslintrc.js'],
};
21 changes: 21 additions & 0 deletions packages/nestjs/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 Functional Software, Inc. dba Sentry

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
43 changes: 43 additions & 0 deletions packages/nestjs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<p align="center">
<a href="https://sentry.io/?utm_source=github&utm_medium=logo" target="_blank">
<img src="https://sentry-brand.storage.googleapis.com/sentry-wordmark-dark-280x84.png" alt="Sentry" width="280" height="84">
</a>
</p>

# Official Sentry SDK for NestJS (EXPERIMENTAL)

[![npm version](https://img.shields.io/npm/v/@sentry/nestjs.svg)](https://www.npmjs.com/package/@sentry/nestjs)
[![npm dm](https://img.shields.io/npm/dm/@sentry/nestjs.svg)](https://www.npmjs.com/package/@sentry/nestjs)
[![npm dt](https://img.shields.io/npm/dt/@sentry/nestjs.svg)](https://www.npmjs.com/package/@sentry/nestjs)

This SDK is considered **experimental and in an alpha state**. It may experience breaking changes. Please reach out on
[GitHub](https://github.com/getsentry/sentry-javascript/issues/new/choose) if you have any feedback or concerns.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should flesh out the readme a bit more. Ideally we get it to a similar state as the readme of the @sentry/node package with basic setup instructions and how to use. Once we add more features to this package we can update this readme again.


## Installation

```bash
npm install @sentry/nestjs

# Or yarn
yarn add @sentry/nestjs
```

## Usage

```js
// CJS Syntax
const Sentry = require('@sentry/nestjs');
// ESM Syntax
import * as Sentry from '@sentry/nestjs';

Sentry.init({
dsn: '__DSN__',
// ...
});
```

Note that it is necessary to initialize Sentry **before you import any package that may be instrumented by us**.

## Links

- [Official SDK Docs](https://docs.sentry.io/quickstart/)
71 changes: 71 additions & 0 deletions packages/nestjs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"name": "@sentry/nestjs",
"version": "8.11.0",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be 8.12.0 now right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

"description": "Official Sentry SDK for NestJS",
"repository": "git://github.com/getsentry/sentry-javascript.git",
"homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/nestjs",
"author": "Sentry",
"license": "MIT",
"engines": {
"node": ">=14.18"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should align this with the minimum supported version of nest since we also don't test for 14.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

},
"files": [
"/build",
"LICENSE",
"README.md"
],
"main": "build/cjs/nestjs/index.js",
"module": "build/esm/nestjs/index.js",
"types": "build/types/index.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"import": {
"types": "./build/types/index.d.ts",
"default": "./build/esm/index.js"
},
"require": {
"types": "./build/types/index.d.ts",
"default": "./build/cjs/index.js"
}
}
},
"typesVersions": {
"<4.9": {
"build/types/index.d.ts": [
"build/types-ts3.8/index.d.ts"
]
}
},
"publishConfig": {
"access": "public"
},
"dependencies": {
"@sentry/core": "8.12.0",
"@sentry/node": "8.12.0"
},
"scripts": {
"build": "run-p build:transpile build:types",
"build:dev": "yarn build",
"build:transpile": "rollup -c rollup.npm.config.mjs",
"build:types": "run-s build:types:core build:types:downlevel",
"build:types:core": "tsc -p tsconfig.types.json",
"build:types:downlevel": "yarn downlevel-dts build/types build/types-ts3.8 --to ts3.8",
"build:watch": "run-p build:transpile:watch build:types:watch",
"build:dev:watch": "yarn build:watch",
"build:transpile:watch": "rollup -c rollup.npm.config.mjs --watch",
"build:types:watch": "tsc -p tsconfig.types.json --watch",
"build:tarball": "npm pack",
"circularDepCheck": "madge --circular src/index.ts",
"clean": "rimraf build coverage sentry-node-*.tgz",
"fix": "eslint . --format stylish --fix",
"lint": "eslint . --format stylish",
"test": "vitest run",
"test:watch": "vitest --watch",
"yalc:publish": "yalc publish --push --sig"
},
"volta": {
"extends": "../../package.json"
},
"sideEffects": false
}
3 changes: 3 additions & 0 deletions packages/nestjs/rollup.npm.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { makeBaseNPMConfig, makeNPMConfigVariants } from '@sentry-internal/rollup-utils';

export default makeNPMConfigVariants(makeBaseNPMConfig());
3 changes: 3 additions & 0 deletions packages/nestjs/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from '@sentry/node';

export { init } from './sdk';
16 changes: 16 additions & 0 deletions packages/nestjs/src/sdk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { applySdkMetadata } from '@sentry/core';
import type { NodeClient, NodeOptions } from '@sentry/node';
import { init as nodeInit } from '@sentry/node';

/**
* Initializes the NestJS SDK
*/
export function init(options: NodeOptions | undefined = {}): NodeClient | undefined {
const opts: NodeOptions = {
...options,
};

applySdkMetadata(opts, 'nestjs');

return nodeInit(opts);
}
34 changes: 34 additions & 0 deletions packages/nestjs/test/sdk.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import * as SentryNode from '@sentry/node';
import { SDK_VERSION } from '@sentry/utils';

import { vi } from 'vitest';
import { init as nestInit } from '../src/sdk';

const nodeInit = vi.spyOn(SentryNode, 'init');
const PUBLIC_DSN = 'https://username@domain/123';

describe('Initialize Nest SDK', () => {
beforeEach(() => {
vi.clearAllMocks();
});

it('has the correct metadata', () => {
const client = nestInit({
dsn: PUBLIC_DSN,
});

const expectedMetadata = {
_metadata: {
sdk: {
name: 'sentry.javascript.nestjs',
packages: [{ name: 'npm:@sentry/nestjs', version: SDK_VERSION }],
version: SDK_VERSION,
},
},
};

expect(client).not.toBeUndefined();
expect(nodeInit).toHaveBeenCalledTimes(1);
expect(nodeInit).toHaveBeenLastCalledWith(expect.objectContaining(expectedMetadata));
});
});
7 changes: 7 additions & 0 deletions packages/nestjs/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.json",

"include": ["src/**/*"],

"compilerOptions": {}
}
12 changes: 12 additions & 0 deletions packages/nestjs/tsconfig.test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"extends": "./tsconfig.json",

"include": ["test/**/*", "vite.config.ts"],

"compilerOptions": {
// should include all types from `./tsconfig.json` plus types for all test frameworks used
"types": ["vitest/globals"]

// other package-specific, test-specific options
}
}
Loading
Loading