Skip to content

Commit 40a4600

Browse files
committed
feat(angular): Add Ivy-compatible SDK package
1 parent e4d3146 commit 40a4600

22 files changed

+3261
-130
lines changed

.craft.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ targets:
2222
- name: github
2323
includeNames: /^sentry-.*$/
2424
- name: npm
25+
excludeNames: /^sentry-angular-ivy-.*/
2526
- name: registry
2627
sdks:
2728
'npm:@sentry/browser':

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
},
3737
"workspaces": [
3838
"packages/angular",
39+
"packages/angular-ivy",
3940
"packages/browser",
4041
"packages/core",
4142
"packages/e2e-tests",

packages/angular-ivy/.eslintrc.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module.exports = {
2+
env: {
3+
browser: true,
4+
},
5+
extends: ['../../.eslintrc.js'],
6+
ignorePatterns: ['setup-jest.ts'],
7+
};

packages/angular-ivy/LICENSE

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Copyright (c) 2023 Sentry (https://sentry.io) and individual contributors. All rights reserved.
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
4+
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
5+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
6+
persons to whom the Software is furnished to do so, subject to the following conditions:
7+
8+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
9+
Software.
10+
11+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
12+
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
13+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
14+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

packages/angular-ivy/README.md

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
<p align="center">
2+
<a href="https://sentry.io/?utm_source=github&utm_medium=logo" target="_blank">
3+
<img src="https://sentry-brand.storage.googleapis.com/sentry-wordmark-dark-280x84.png" alt="Sentry" width="280" height="84">
4+
</a>
5+
</p>
6+
7+
# Official Sentry SDK for Angular with Ivy Compatibility
8+
9+
## Links
10+
11+
- [Official SDK Docs](https://docs.sentry.io/platforms/javascript/angular/)
12+
- [TypeDoc](http://getsentry.github.io/sentry-javascript/)
13+
14+
## Angular Version Compatibility
15+
16+
The latest version of this SDK officially supports Angular 12-15 with Ivy.
17+
18+
If you're using Angular 10, 11 or a newer Angular version with View Engine instead of Ivy, please use [`@sentry/angular`](https://github.com/getsentry/sentry-javascript/blob/develop/packages/angular/README.md).
19+
20+
If you're using an older version of Angular and experience problems with the Angular SDK, we recommend downgrading the SDK to version 6.x.
21+
Please note that we don't provide any support for Angular versions below 10.
22+
23+
## General
24+
25+
This package is a wrapper around `@sentry/browser`, with added functionality related to Angular. All methods available
26+
in `@sentry/browser` can be imported from `@sentry/angular-ivy`.
27+
28+
To use this SDK, call `Sentry.init(options)` before you bootstrap your Angular application.
29+
30+
```javascript
31+
import { enableProdMode } from '@angular/core';
32+
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
33+
import { init } from '@sentry/angular-ivy';
34+
35+
import { AppModule } from './app/app.module';
36+
37+
init({
38+
dsn: '__DSN__',
39+
// ...
40+
});
41+
42+
// ...
43+
44+
enableProdMode();
45+
platformBrowserDynamic()
46+
.bootstrapModule(AppModule)
47+
.then(success => console.log(`Bootstrap success`))
48+
.catch(err => console.error(err));
49+
```
50+
51+
### ErrorHandler
52+
53+
`@sentry/angular-ivy` exports a function to instantiate an ErrorHandler provider that will automatically send Javascript errors
54+
captured by the Angular's error handler.
55+
56+
```javascript
57+
import { NgModule, ErrorHandler } from '@angular/core';
58+
import { createErrorHandler } from '@sentry/angular-ivy';
59+
60+
@NgModule({
61+
// ...
62+
providers: [
63+
{
64+
provide: ErrorHandler,
65+
useValue: createErrorHandler({
66+
showDialog: true,
67+
}),
68+
},
69+
],
70+
// ...
71+
})
72+
export class AppModule {}
73+
```
74+
75+
Additionally, `createErrorHandler` accepts a set of options that allows you to configure its behavior. For more details
76+
see `ErrorHandlerOptions` interface in `src/errorhandler.ts`.
77+
78+
### Tracing
79+
80+
`@sentry/angular-ivy` exports a Trace Service, Directive and Decorators that leverage the `@sentry/tracing` Tracing
81+
integration to add Angular related spans to transactions. If the Tracing integration is not enabled, this functionality
82+
will not work. The service itself tracks route changes and durations, where directive and decorators are tracking
83+
components initializations.
84+
85+
#### Install
86+
87+
Registering a Trace Service is a 3-step process.
88+
89+
1. Register and configure the `BrowserTracing` integration from `@sentry/tracing`, including custom Angular routing
90+
instrumentation:
91+
92+
```javascript
93+
import { init, instrumentAngularRouting } from '@sentry/angular-ivy';
94+
import { Integrations as TracingIntegrations } from '@sentry/tracing';
95+
96+
init({
97+
dsn: '__DSN__',
98+
integrations: [
99+
new TracingIntegrations.BrowserTracing({
100+
tracingOrigins: ['localhost', 'https://yourserver.io/api'],
101+
routingInstrumentation: instrumentAngularRouting,
102+
}),
103+
],
104+
tracesSampleRate: 1,
105+
});
106+
```
107+
108+
2. Register `SentryTrace` as a provider in Angular's DI system, with a `Router` as its dependency:
109+
110+
```javascript
111+
import { NgModule } from '@angular/core';
112+
import { Router } from '@angular/router';
113+
import { TraceService } from '@sentry/angular-ivy';
114+
115+
@NgModule({
116+
// ...
117+
providers: [
118+
{
119+
provide: TraceService,
120+
deps: [Router],
121+
},
122+
],
123+
// ...
124+
})
125+
export class AppModule {}
126+
```
127+
128+
3. Either require the `TraceService` from inside `AppModule` or use `APP_INITIALIZER` to force-instantiate Tracing.
129+
130+
```javascript
131+
@NgModule({
132+
// ...
133+
})
134+
export class AppModule {
135+
constructor(trace: TraceService) {}
136+
}
137+
```
138+
139+
or
140+
141+
```javascript
142+
import { APP_INITIALIZER } from '@angular/core';
143+
144+
@NgModule({
145+
// ...
146+
providers: [
147+
{
148+
provide: APP_INITIALIZER,
149+
useFactory: () => () => {},
150+
deps: [TraceService],
151+
multi: true,
152+
},
153+
],
154+
// ...
155+
})
156+
export class AppModule {}
157+
```
158+
159+
#### Use
160+
161+
To track Angular components as part of your transactions, you have 3 options.
162+
163+
_TraceDirective:_ used to track a duration between `OnInit` and `AfterViewInit` lifecycle hooks in template:
164+
165+
```javascript
166+
import { TraceModule } from '@sentry/angular-ivy';
167+
168+
@NgModule({
169+
// ...
170+
imports: [TraceModule],
171+
// ...
172+
})
173+
export class AppModule {}
174+
```
175+
176+
Then inside your components template (keep in mind that directive name attribute is required):
177+
178+
```html
179+
<app-header trace="header"></app-header>
180+
<articles-list trace="articles-list"></articles-list>
181+
<app-footer trace="footer"></app-footer>
182+
```
183+
184+
_TraceClassDecorator:_ used to track a duration between `OnInit` and `AfterViewInit` lifecycle hooks in components:
185+
186+
```javascript
187+
import { Component } from '@angular/core';
188+
import { TraceClassDecorator } from '@sentry/angular-ivy';
189+
190+
@Component({
191+
selector: 'layout-header',
192+
templateUrl: './header.component.html',
193+
})
194+
@TraceClassDecorator()
195+
export class HeaderComponent {
196+
// ...
197+
}
198+
```
199+
200+
_TraceMethodDecorator:_ used to track a specific lifecycle hooks as point-in-time spans in components:
201+
202+
```javascript
203+
import { Component, OnInit } from '@angular/core';
204+
import { TraceMethodDecorator } from '@sentry/angular-ivy';
205+
206+
@Component({
207+
selector: 'app-footer',
208+
templateUrl: './footer.component.html',
209+
})
210+
export class FooterComponent implements OnInit {
211+
@TraceMethodDecorator()
212+
ngOnInit() {}
213+
}
214+
```
215+
216+
You can also add your own custom spans by attaching them to the current active transaction using `getActiveTransaction`
217+
helper. For example, if you'd like to track the duration of Angular boostraping process, you can do it as follows:
218+
219+
```javascript
220+
import { enableProdMode } from '@angular/core';
221+
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
222+
import { init, getActiveTransaction } from '@sentry/angular-ivy';
223+
224+
import { AppModule } from './app/app.module';
225+
226+
// ...
227+
228+
const activeTransaction = getActiveTransaction();
229+
const boostrapSpan =
230+
activeTransaction &&
231+
activeTransaction.startChild({
232+
description: 'platform-browser-dynamic',
233+
op: 'ui.angular.bootstrap',
234+
});
235+
236+
platformBrowserDynamic()
237+
.bootstrapModule(AppModule)
238+
.then(() => console.log(`Bootstrap success`))
239+
.catch(err => console.error(err));
240+
.finally(() => {
241+
if (bootstrapSpan) {
242+
boostrapSpan.finish();
243+
}
244+
})
245+
```

packages/angular-ivy/angular.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/* To learn more about this file see: https://angular.io/guide/workspace-config */
2+
{
3+
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
4+
"version": 1, // version of angular.json
5+
"projects": {
6+
"sentry-angular-ivy": {
7+
"projectType": "library",
8+
"root": ".",
9+
"sourceRoot": "src",
10+
"architect": {
11+
"build": {
12+
"builder": "@angular-devkit/build-angular:ng-packagr",
13+
"options": {
14+
"project": "ng-package.json"
15+
},
16+
"configurations": {
17+
"production": {
18+
"tsConfig": "tsconfig.ngc.json"
19+
},
20+
"development": {
21+
"tsConfig": "tsconfig.ngc.json"
22+
}
23+
},
24+
"defaultConfiguration": "production"
25+
}
26+
}
27+
}
28+
},
29+
"defaultProject": "sentry-angular-ivy"
30+
}

packages/angular-ivy/ng-package.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"$schema": "node_modules/ng-packagr/ng-package.schema.json",
3+
"dest": "build",
4+
"lib": {
5+
"entryFile": "src/index.ts",
6+
"umdModuleIds": {
7+
"@sentry/browser": "Sentry",
8+
"@sentry/utils": "Sentry.util"
9+
}
10+
},
11+
"allowedNonPeerDependencies": ["@sentry/browser", "@sentry/utils", "@sentry/types", "tslib"],
12+
"assets": ["README.md", "LICENSE"]
13+
}

packages/angular-ivy/package.json

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
{
2+
"name": "@sentry/angular-ivy",
3+
"version": "7.38.0",
4+
"description": "Official Sentry SDK for Angular with full Ivy Support",
5+
"repository": "git://github.com/getsentry/sentry-javascript.git",
6+
"homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/angular-ivy",
7+
"author": "Sentry",
8+
"license": "MIT",
9+
"engines": {
10+
"node": ">=12"
11+
},
12+
"private": true,
13+
"main": "build/bundles/sentry-angular.umd.js",
14+
"module": "build/fesm2015/sentry-angular.js",
15+
"publishConfig": {
16+
"access": "public"
17+
},
18+
"peerDependencies": {
19+
"@angular/common": ">= 12.x <= 15.x",
20+
"@angular/core": ">= 12.x <= 15.x",
21+
"@angular/router": ">= 12.x <= 15.x",
22+
"rxjs": "^6.5.5 || ^7.x"
23+
},
24+
"dependencies": {
25+
"@sentry/browser": "7.38.0",
26+
"@sentry/types": "7.38.0",
27+
"@sentry/utils": "7.38.0",
28+
"tslib": "^2.3.0"
29+
},
30+
"devDependencies": {
31+
"@angular-devkit/build-angular": "~12.2.18",
32+
"@angular/cli": "~12.2.18",
33+
"@angular/common": "~12.2.0",
34+
"@angular/compiler": "~12.2.0",
35+
"@angular/compiler-cli": "~12.2.0",
36+
"@angular/core": "~12.2.0",
37+
"@angular/platform-browser": "~12.2.0",
38+
"@angular/platform-browser-dynamic": "~12.2.0",
39+
"@angular/router": "~12.2.0",
40+
"ng-packagr": "^12.1.1",
41+
"typescript": "~4.3.5",
42+
"zone.js": "~0.11.4"
43+
},
44+
"scripts": {
45+
"build": "yarn build:transpile",
46+
"build:transpile": "ng build",
47+
"build:dev": "yarn build",
48+
"build:watch": "yarn build:transpile:watch",
49+
"build:dev:watch": "yarn build:watch",
50+
"build:transpile:watch": "ng build --watch",
51+
"build:tarball": "npm pack ./build",
52+
"circularDepCheck": "madge --circular src/index.ts",
53+
"clean": "rimraf build coverage sentry-angular-*.tgz",
54+
"fix": "run-s fix:eslint fix:prettier",
55+
"fix:eslint": "eslint . --format stylish --fix",
56+
"fix:prettier": "prettier --write \"{src,test,scripts}/**/**.ts\"",
57+
"lint": "run-s lint:prettier lint:eslint",
58+
"lint:eslint": "eslint . --format stylish",
59+
"lint:prettier": "prettier --check \"{src,test,scripts}/**/**.ts\""
60+
},
61+
"volta": {
62+
"extends": "../../package.json"
63+
},
64+
"sideEffects": false
65+
}

packages/angular-ivy/src/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../angular/src/constants.ts

0 commit comments

Comments
 (0)