├── .nvmrc
├── src
├── assets
│ ├── .gitkeep
│ ├── sentry-pattern.png
│ └── sentry-glyph-black.png
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── styles.css
├── favicon.ico
├── main.ts
├── index.html
├── test.ts
├── app
│ ├── app.component.ts
│ ├── app.component.spec.ts
│ ├── app.component.css
│ ├── app.component.html
│ └── app.module.ts
└── polyfills.ts
├── .env
├── .editorconfig
├── tsconfig.app.json
├── tsconfig.spec.json
├── tsconfig.json
├── .gitignore
├── config-env.ts
├── Makefile
├── protractor.conf.js
├── karma.conf.js
├── angular-cli.json
├── package.json
├── README.md
├── tslint.json
└── angular.json
/.nvmrc:
--------------------------------------------------------------------------------
1 | 10.13
2 |
--------------------------------------------------------------------------------
/src/assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | version=54176c10d0532d31262d26b694f374e4fdfbc2fb
2 |
--------------------------------------------------------------------------------
/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | release: ''
3 | };
4 |
--------------------------------------------------------------------------------
/src/styles.css:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ndmanvar/ng-conf-2020-sentry-workshop/HEAD/src/favicon.ico
--------------------------------------------------------------------------------
/src/assets/sentry-pattern.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ndmanvar/ng-conf-2020-sentry-workshop/HEAD/src/assets/sentry-pattern.png
--------------------------------------------------------------------------------
/src/assets/sentry-glyph-black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ndmanvar/ng-conf-2020-sentry-workshop/HEAD/src/assets/sentry-glyph-black.png
--------------------------------------------------------------------------------
/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | release: 'This Will Be Replaced With A Value In Environment.prod.ts'
3 | };
4 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 |
4 | import { AppModule } from './app/app.module';
5 | import { environment } from './environments/environment';
6 |
7 | platformBrowserDynamic().bootstrapModule(AppModule)
8 | .catch(err => console.error(err));
9 |
--------------------------------------------------------------------------------
/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/app",
6 | "types": []
7 | },
8 | "files": [
9 | "src/main.ts",
10 | "src/polyfills.ts"
11 | ],
12 | "include": [
13 | "src/**/*.d.ts"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/spec",
6 | "types": [
7 | "jasmine"
8 | ]
9 | },
10 | "files": [
11 | "src/test.ts",
12 | "src/polyfills.ts"
13 | ],
14 | "include": [
15 | "src/**/*.spec.ts",
16 | "src/**/*.d.ts"
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Angular
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | Loading...
16 |
17 |
18 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "compileOnSave": false,
4 | "compilerOptions": {
5 | "baseUrl": "./",
6 | "outDir": "./dist/out-tsc",
7 | "sourceMap": true,
8 | "declaration": false,
9 | "downlevelIteration": true,
10 | "experimentalDecorators": true,
11 | "moduleResolution": "node",
12 | "importHelpers": true,
13 | "target": "es2015",
14 | "module": "es2020",
15 | "lib": [
16 | "es2018",
17 | "dom"
18 | ]
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 |
7 | # dependencies
8 | /node_modules
9 |
10 | # IDEs and editors
11 | /.idea
12 | .project
13 | .classpath
14 | .c9/
15 | *.launch
16 | .settings/
17 |
18 | # IDE - VSCode
19 | .vscode/*
20 | !.vscode/settings.json
21 | !.vscode/tasks.json
22 | !.vscode/launch.json
23 | !.vscode/extensions.json
24 |
25 | # misc
26 | /.sass-cache
27 | /connect.lock
28 | /coverage/*
29 | /libpeerconnection.log
30 | npm-debug.log
31 | testem.log
32 | /typings
33 |
34 | # e2e
35 | /e2e/*.js
36 | /e2e/*.map
37 |
38 | #System Files
39 | .DS_Store
40 | Thumbs.db
41 |
42 | # src/.ts-e.js
43 | **/*.ts-e
44 |
45 | .env
46 |
--------------------------------------------------------------------------------
/config-env.ts:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | // Configure Angular `environment.ts` file path
3 | const targetPath = './src/environments/environment.prod.ts';
4 |
5 | // Load node modules
6 | const colors = require('colors');
7 | require('dotenv').config();
8 |
9 | // `environment.ts` file structure
10 | const envConfigFile = `export const environment = {
11 | release: '${process.env.version}'
12 | };
13 | `;
14 |
15 | console.log(colors.magenta('The file `environment.prod.ts` will be written with the following content: \n'));
16 |
17 | console.log(colors.grey(envConfigFile));
18 | fs.writeFile(targetPath, envConfigFile, function (err) {
19 | if (err) {
20 | throw console.error(err);
21 | } else {
22 | console.log(colors.magenta(`Angular environment.ts file generated correctly at ${targetPath} \n`));
23 | }
24 | });
25 |
--------------------------------------------------------------------------------
/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/dist/zone-testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import {
6 | BrowserDynamicTestingModule,
7 | platformBrowserDynamicTesting
8 | } from '@angular/platform-browser-dynamic/testing';
9 |
10 | declare const require: {
11 | context(path: string, deep?: boolean, filter?: RegExp): {
12 | keys(): string[];
13 | (id: string): T;
14 | };
15 | };
16 |
17 | // First, initialize the Angular testing environment.
18 | getTestBed().initTestEnvironment(
19 | BrowserDynamicTestingModule,
20 | platformBrowserDynamicTesting()
21 | );
22 | // Then we find all the tests.
23 | const context = require.context('./', true, /\.spec\.ts$/);
24 | // And load the modules.
25 | context.keys().map(context);
26 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Must have `sentry-cli` installed globally
2 | # Following variable must be passed in
3 | # SENTRY_AUTH_TOKEN
4 |
5 | SENTRY_ORG=mycompany1
6 | SENTRY_PROJECT=mycompany1
7 | PREFIX=dist
8 | SENTRY_CLI=./node_modules/.bin/sentry-cli
9 | VERSION=`$(SENTRY_CLI) releases propose-version`
10 |
11 | # setup_release:
12 | # echo "TODO: "
13 |
14 | setup_release: create_release upload_sourcemaps
15 |
16 | create_release:
17 | $(SENTRY_CLI) releases -o $(SENTRY_ORG) new -p $(SENTRY_PROJECT) $(VERSION)
18 |
19 | associate_commits:
20 | -$(SENTRY_CLI) releases -o $(SENTRY_ORG) -p $(SENTRY_PROJECT) set-commits --local $(VERSION)
21 |
22 | upload_sourcemaps:
23 | $(SENTRY_CLI) releases -o $(SENTRY_ORG) -p $(SENTRY_PROJECT) files \
24 | $(VERSION) upload-sourcemaps --url-prefix "~/" --rewrite --validate $(PREFIX)
25 |
26 | create_env:
27 | @echo "version=${VERSION}" > .env
28 |
--------------------------------------------------------------------------------
/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // Protractor configuration file, see link for more information
2 | // https://github.com/angular/protractor/blob/master/lib/config.ts
3 |
4 | /*global jasmine */
5 | var SpecReporter = require('jasmine-spec-reporter');
6 |
7 | exports.config = {
8 | allScriptsTimeout: 11000,
9 | specs: [
10 | './e2e/**/*.e2e-spec.ts'
11 | ],
12 | capabilities: {
13 | 'browserName': 'chrome'
14 | },
15 | directConnect: true,
16 | baseUrl: 'http://localhost:4200/',
17 | framework: 'jasmine',
18 | jasmineNodeOpts: {
19 | showColors: true,
20 | defaultTimeoutInterval: 30000,
21 | print: function() {}
22 | },
23 | useAllAngular2AppRoots: true,
24 | beforeLaunch: function() {
25 | require('ts-node').register({
26 | project: 'e2e'
27 | });
28 | },
29 | onPrepare: function() {
30 | jasmine.getEnv().addReporter(new SpecReporter());
31 | }
32 | };
33 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, './coverage/angular-project'),
20 | reports: ['html', 'lcovonly', 'text-summary'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false,
30 | restartOnFileChange: true
31 | });
32 | };
33 |
--------------------------------------------------------------------------------
/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | // import * as Sentry from "@sentry/browser";
3 |
4 | @Component({
5 | selector: 'app-root',
6 | templateUrl: './app.component.html',
7 | styleUrls: ['./app.component.css']
8 | })
9 |
10 | export class AppComponent {
11 | color = 'black';
12 | textValue = '';
13 | currentUser = '';
14 |
15 | changeColor() {
16 | var that = this;
17 | this.color = 'red';
18 | setTimeout(() => {
19 | that.color = 'black'
20 | }, 1500);
21 | }
22 |
23 | handleSubmit() {
24 | this.currentUser = this.textValue;
25 | // Sentry.configureScope(scope => {
26 | // scope.setUser({email: this.currentUser});
27 | // });
28 | }
29 |
30 | malformed() {
31 | decodeURIComponent('%');
32 | }
33 |
34 | // ERRORS
35 | notAFunctionError() {
36 | var someArray = [{ func: function () {}}];
37 | someArray[1].func();
38 | }
39 |
40 | uriError() {
41 | decodeURIComponent('%');
42 | }
43 |
44 | syntaxError() {
45 | eval('foo bar');
46 | }
47 |
48 | rangeError() {
49 | throw new RangeError('Parameter must be between 1 and 100');
50 | }
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/src/app/app.component.spec.ts:
--------------------------------------------------------------------------------
1 | /* tslint:disable:no-unused-variable */
2 |
3 | import { TestBed, async } from '@angular/core/testing';
4 | import { AppComponent } from './app.component';
5 |
6 | describe('AppComponent', () => {
7 | beforeEach(() => {
8 | TestBed.configureTestingModule({
9 | declarations: [
10 | AppComponent
11 | ],
12 | });
13 | TestBed.compileComponents();
14 | });
15 |
16 | it('should create the app', async(() => {
17 | const fixture = TestBed.createComponent(AppComponent);
18 | const app = fixture.debugElement.componentInstance;
19 | expect(app).toBeTruthy();
20 | }));
21 |
22 | it(`should have as title 'app works!'`, async(() => {
23 | const fixture = TestBed.createComponent(AppComponent);
24 | const app = fixture.debugElement.componentInstance;
25 | expect(app.title).toEqual('app works!');
26 | }));
27 |
28 | it('should render title in a h1 tag', async(() => {
29 | const fixture = TestBed.createComponent(AppComponent);
30 | fixture.detectChanges();
31 | const compiled = fixture.debugElement.nativeElement;
32 | expect(compiled.querySelector('h1').textContent).toContain('app works!');
33 | }));
34 | });
35 |
--------------------------------------------------------------------------------
/src/app/app.component.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | background-image: url('../assets/sentry-pattern.png');
4 | height: 100%;
5 | background-position: center;
6 | background-repeat: no-repeat;
7 | background-size: cover;
8 | }
9 |
10 | .App-logo {
11 | /* animation: App-logo-spin infinite 20s linear; */
12 | height: 80px;
13 | }
14 |
15 | .App-header {
16 | /* background-image: url('../assets/sentry-pattern.png'); */
17 | height: 150px;
18 | padding: 20px;
19 | color: black;
20 | }
21 |
22 | .App-intro {
23 | font-size: large;
24 | }
25 |
26 | h3 {
27 | font: bold 20px/1.5 Helvetica, Verdana, sans-serif;
28 | }
29 |
30 | li img {
31 | float: left;
32 | /* margin: 0 15px 0 0; */
33 | height: 50px;
34 | }
35 |
36 | li:hover {
37 | background: #eee;
38 | cursor: pointer;
39 | }
40 |
41 | .center {
42 | margin: auto;
43 | width: 50%;
44 | padding: 10px;
45 | }
46 |
47 | .left {
48 | /* margin: auto; */
49 | width: 50%;
50 | padding: 10px;
51 | float: left;
52 | }
53 |
54 | .right {
55 | /* margin: auto; */
56 | width: 50%;
57 | padding: 10px;
58 | float: right;
59 | }
60 |
61 | html,
62 | body {
63 | margin: 0;
64 | padding: 0;
65 | font-family: sans-serif;
66 | height: 100%
67 | }
68 |
69 | #root {
70 | height: 100%;
71 | }
72 |
--------------------------------------------------------------------------------
/angular-cli.json:
--------------------------------------------------------------------------------
1 | {
2 | "project": {
3 | "version": "1.0.0-beta.28.3",
4 | "name": "angular"
5 | },
6 | "apps": [
7 | {
8 | "root": "src",
9 | "outDir": "dist",
10 | "assets": [
11 | "assets",
12 | "favicon.ico"
13 | ],
14 | "index": "index.html",
15 | "main": "main.ts",
16 | "polyfills": "polyfills.ts",
17 | "test": "test.ts",
18 | "tsconfig": "tsconfig.json",
19 | "prefix": "app",
20 | "styles": [
21 | "styles.css"
22 | ],
23 | "scripts": [],
24 | "environmentSource": "environments/environment.ts",
25 | "environments": {
26 | "dev": "environments/environment.ts",
27 | "prod": "environments/environment.prod.ts"
28 | }
29 | }
30 | ],
31 | "e2e": {
32 | "protractor": {
33 | "config": "./protractor.conf.js"
34 | }
35 | },
36 | "lint": [
37 | {
38 | "files": "src/**/*.ts",
39 | "project": "src/tsconfig.json"
40 | },
41 | {
42 | "files": "e2e/**/*.ts",
43 | "project": "e2e/tsconfig.json"
44 | }
45 | ],
46 | "test": {
47 | "karma": {
48 | "config": "./karma.conf.js"
49 | }
50 | },
51 | "defaults": {
52 | "styleExt": "css",
53 | "prefixInterfaces": false,
54 | "inline": {
55 | "style": false,
56 | "template": false
57 | },
58 | "spec": {
59 | "class": false,
60 | "component": true,
61 | "directive": true,
62 | "module": false,
63 | "pipe": true,
64 | "service": true
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
16 |
17 |
Hi {{currentUser ? currentUser : "Guest"}}
18 |
19 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { BrowserModule } from '@angular/platform-browser';
2 | import {APP_INITIALIZER, ErrorHandler, NgModule} from "@angular/core";
3 | import { FormsModule } from '@angular/forms';
4 | import { HttpClientModule } from '@angular/common/http';
5 | import { Router, RouterModule } from "@angular/router";
6 | import { AppComponent } from './app.component';
7 | import { environment } from './../environments/environment.prod';
8 |
9 | import * as Sentry from "@sentry/angular";
10 | import { Integrations } from "@sentry/tracing";
11 |
12 | Sentry.init({
13 | dsn: "https://e117778702c244d1af1afabd3b786566@o477548.ingest.sentry.io/5518792",
14 | release: environment.release,
15 | integrations: [
16 | new Integrations.BrowserTracing({
17 | tracingOrigins: ["localhost", "https://yourserver.io/api"],
18 | routingInstrumentation: Sentry.routingInstrumentation,
19 | }),
20 | ],
21 |
22 | // We recommend adjusting this value in production, or using tracesSampler
23 | // for finer control
24 | tracesSampleRate: 1.0,
25 | });
26 |
27 | @NgModule({
28 | declarations: [AppComponent],
29 | imports: [BrowserModule, FormsModule, HttpClientModule, RouterModule.forRoot([
30 | { path: '', component: AppComponent },
31 | ])],
32 | providers: [
33 | {
34 | provide: ErrorHandler,
35 | useValue: Sentry.createErrorHandler({
36 | showDialog: true,
37 | }),
38 | },
39 | {
40 | provide: Sentry.TraceService,
41 | deps: [Router],
42 | },
43 | {
44 | provide: APP_INITIALIZER,
45 | useFactory: () => () => {},
46 | deps: [Sentry.TraceService],
47 | multi: true,
48 | },
49 | ],
50 | bootstrap: [AppComponent],
51 | })
52 | export class AppModule {}
53 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "ng": "ng",
6 | "config": "ts-node config-env.ts",
7 | "start": "ng serve",
8 | "test": "ng test",
9 | "pree2e": "webdriver-manager update --standalone false --gecko false",
10 | "e2e": "protractor",
11 | "predeploy": "make create_env && npm run config && ng build --configuration production && make",
12 | "deploy": "serve -s dist"
13 | },
14 | "private": true,
15 | "dependencies": {
16 | "@angular-devkit/schematics": "^10.1.6",
17 | "@angular/animations": "^10.1.6",
18 | "@angular/common": "^10.1.6",
19 | "@angular/compiler": "^10.1.6",
20 | "@angular/core": "^10.1.6",
21 | "@angular/forms": "^10.1.6",
22 | "@angular/platform-browser": "^10.1.6",
23 | "@angular/platform-browser-dynamic": "^10.1.6",
24 | "@angular/router": "^10.1.6",
25 | "@sentry/angular": "^5.27.4",
26 | "@sentry/tracing": "^5.27.4",
27 | "colors": "^1.4.0",
28 | "rxjs": "^6.6.3",
29 | "serve": "^11.3.2",
30 | "tslib": "^2.0.3",
31 | "zone.js": "^0.11.1"
32 | },
33 | "devDependencies": {
34 | "@angular-builders/dev-server": "^7.3.1",
35 | "@angular-devkit/build-angular": "^0.1001.6",
36 | "@angular/cli": "~10.1.6",
37 | "@angular/compiler-cli": "~10.1.6",
38 | "@sentry/cli": "^1.59.0",
39 | "@types/jasmine": "~3.5.0",
40 | "@types/jasminewd2": "~2.0.3",
41 | "@types/node": "^14.11.8",
42 | "codelyzer": "^6.0.0",
43 | "dotenv": "^8.2.0",
44 | "jasmine-core": "~3.6.0",
45 | "jasmine-spec-reporter": "~6.0.0",
46 | "karma": "~5.2.3",
47 | "karma-chrome-launcher": "~3.1.0",
48 | "karma-coverage-istanbul-reporter": "~3.0.2",
49 | "karma-jasmine": "~4.0.1",
50 | "karma-jasmine-html-reporter": "^1.5.0",
51 | "protractor": "~7.0.0",
52 | "ts-node": "~9.0.0",
53 | "tslint": "~6.1.0",
54 | "typescript": "~4.0.3"
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/guide/browser-support
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */
22 | // import 'classlist.js'; // Run `npm install --save classlist.js`.
23 |
24 | /**
25 | * Web Animations `@angular/platform-browser/animations`
26 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
27 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
28 | */
29 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`.
30 |
31 | /**
32 | * By default, zone.js will patch all possible macroTask and DomEvents
33 | * user can disable parts of macroTask/DomEvents patch by setting following flags
34 | * because those flags need to be set before `zone.js` being loaded, and webpack
35 | * will put import in the top of bundle, so user need to create a separate file
36 | * in this directory (for example: zone-flags.ts), and put the following flags
37 | * into that file, and then add the following code before importing zone.js.
38 | * import './zone-flags';
39 | *
40 | * The flags allowed in zone-flags.ts are listed here.
41 | *
42 | * The following flags will work for all browsers.
43 | *
44 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
45 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
46 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
47 | *
48 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
49 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
50 | *
51 | * (window as any).__Zone_enable_cross_context_check = true;
52 | *
53 | */
54 |
55 | /***************************************************************************************************
56 | * Zone JS is required by default for Angular itself.
57 | */
58 | import 'zone.js/dist/zone'; // Included with Angular CLI.
59 |
60 |
61 | /***************************************************************************************************
62 | * APPLICATION IMPORTS
63 | */
64 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started with Error Monitoring for Angular
2 |
3 | ## Pre-Installation Directions: Setup and deploy angular app
4 |
5 | 1. Be sure to have node, NVM, and git installed.
6 |
7 | 2. Fork this repository and clone. Set node version as specified:
8 | ```
9 | git clone https://github.com//ng-conf-sample-app
10 | nvm use
11 | ```
12 | 3. Then install with
13 | ```
14 | npm install
15 | ```
16 | 4. Then build and run server with
17 | ```
18 | npm run deploy
19 | ```
20 | 5. Verify web server is running properly and app can be loaded (go to http://localhost:5000 in the browser and trigger errors)
21 |
22 | 6. You should be set for the workshop, where you will add Sentry into this angular application to monitor errors.
23 |
24 |
25 | ## Setup Sentry + install SDK
26 | 1. Go to https://sentry.io/signup + 'create your account'.
27 |
28 | 2. Follow onboarding steps (select angular project) and instrument code as specified.
29 |
30 | 3. Then build and run server with
31 | ```
32 | npm run deploy
33 | ```
34 | 4. Go to http://localhost:5000 and trigger errors. The Sentry onboarding (part-3) should note that event was successfully. Follow link to event in Sentry.io.
35 |
36 | ### Upload source maps (so we can see actual names and stacktraces)
37 | 1. Specify `release` in Sentry SDK
38 | ```
39 | Sentry.init({
40 | ...,
41 | release: environment.release
42 | })
43 | ```
44 |
45 | 2. Install sentry-cli to upload sourcemaps
46 | ```
47 | npm install --save-dev @sentry/cli
48 | ```
49 |
50 | 3. Create production bundles and sourcemaps
51 | ```
52 | # In angular.json, this is already done. Checkout source maps at dist/
53 | "sourceMap": true
54 | ```
55 |
56 | 4. In Makefile, remove placeholder `setup_release` and uncomment actual one (which is calling `upload_sourcemaps`).
57 |
58 | 5. Create 'New Internal Integration' to obtain AUTH_TOKEN.
59 | > _Organization Settings -> Developer Settings -> 'New Internal Integration'_
60 |
61 | > **_NOTE:_** `Release: Admin` + `Organization: Read & Write` permissions are needed
62 |
63 | 6. Specify SENTRY_AUTH_TOKEN as environment variable
64 | ```
65 | export SENTRY_AUTH_TOKEN=
66 | ```
67 |
68 | 7. Specify `SENTRY_ORG` and `SENTRY_PROJECT` accordingly in Makefile
69 |
70 | 8. Run build/deploy:
71 | ```
72 | npm run deploy
73 | ```
74 | Verify Source Maps are uploaded
75 |
76 | > _Project Settings -> Source Maps_
77 |
78 | 9. Trigger new errors (http://localhost:5000) and verify filename/stacktrace
79 |
80 |
81 | ## Sentry Performance
82 | 1. Head over to `Performance` on left hand side
83 |
84 | 2. Drill down on transaction to view distributed trace
85 |
86 |
87 | ## Integrations
88 |
89 | ### Slack (alerting/nofication)
90 | 1. Enable Business Trial (to enable integrations + full feature set)
91 | > _Organization Settings -> Subscription -> 'Activate Your Trial'_
92 |
93 | 2. Add Slack integration
94 | > _Organization Settings -> Integrations -> Slack_
95 |
96 | 3. Specify in alert rule
97 |
98 | 4. Trigger error and verify alert
99 |
100 | ### GitHub
101 | 1. Add GitHub integration
102 | > _Organization Settings -> Integrations -> GitHub_
103 |
104 | 2. Add `associate_commits` to `setup_release` in Makefile
105 |
106 | 3. Run build/deploy + trigger errors
107 | ```
108 | npm run deploy
109 | ```
110 | Go to http://localhost:5000 + click on errors
111 |
112 | 4. Pull up error/issue on Sentry. You should see 'Suspect Commit' and 'Suggested Assignee'
113 |
114 | # Notes
115 | In case you get lost, the working code can be found in the `final-state` branch (https://github.com/ndmanvar/ng-conf-2020-sentry-workshop/tree/final-code)
116 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "tslint:recommended",
3 | "rules": {
4 | "align": {
5 | "options": [
6 | "parameters",
7 | "statements"
8 | ]
9 | },
10 | "array-type": false,
11 | "arrow-return-shorthand": true,
12 | "curly": true,
13 | "deprecation": {
14 | "severity": "warning"
15 | },
16 | "component-class-suffix": true,
17 | "contextual-lifecycle": true,
18 | "directive-class-suffix": true,
19 | "directive-selector": [
20 | true,
21 | "attribute",
22 | "app",
23 | "camelCase"
24 | ],
25 | "component-selector": [
26 | true,
27 | "element",
28 | "app",
29 | "kebab-case"
30 | ],
31 | "eofline": true,
32 | "import-blacklist": [
33 | true,
34 | "rxjs/Rx"
35 | ],
36 | "import-spacing": true,
37 | "indent": {
38 | "options": [
39 | "spaces"
40 | ]
41 | },
42 | "max-classes-per-file": false,
43 | "max-line-length": [
44 | true,
45 | 140
46 | ],
47 | "member-ordering": [
48 | true,
49 | {
50 | "order": [
51 | "static-field",
52 | "instance-field",
53 | "static-method",
54 | "instance-method"
55 | ]
56 | }
57 | ],
58 | "no-console": [
59 | true,
60 | "debug",
61 | "info",
62 | "time",
63 | "timeEnd",
64 | "trace"
65 | ],
66 | "no-empty": false,
67 | "no-inferrable-types": [
68 | true,
69 | "ignore-params"
70 | ],
71 | "no-non-null-assertion": true,
72 | "no-redundant-jsdoc": true,
73 | "no-switch-case-fall-through": true,
74 | "no-var-requires": false,
75 | "object-literal-key-quotes": [
76 | true,
77 | "as-needed"
78 | ],
79 | "quotemark": [
80 | true,
81 | "single"
82 | ],
83 | "semicolon": {
84 | "options": [
85 | "always"
86 | ]
87 | },
88 | "space-before-function-paren": {
89 | "options": {
90 | "anonymous": "never",
91 | "asyncArrow": "always",
92 | "constructor": "never",
93 | "method": "never",
94 | "named": "never"
95 | }
96 | },
97 | "typedef": [
98 | true,
99 | "call-signature"
100 | ],
101 | "typedef-whitespace": {
102 | "options": [
103 | {
104 | "call-signature": "nospace",
105 | "index-signature": "nospace",
106 | "parameter": "nospace",
107 | "property-declaration": "nospace",
108 | "variable-declaration": "nospace"
109 | },
110 | {
111 | "call-signature": "onespace",
112 | "index-signature": "onespace",
113 | "parameter": "onespace",
114 | "property-declaration": "onespace",
115 | "variable-declaration": "onespace"
116 | }
117 | ]
118 | },
119 | "variable-name": {
120 | "options": [
121 | "ban-keywords",
122 | "check-format",
123 | "allow-pascal-case"
124 | ]
125 | },
126 | "whitespace": {
127 | "options": [
128 | "check-branch",
129 | "check-decl",
130 | "check-operator",
131 | "check-separator",
132 | "check-type",
133 | "check-typecast"
134 | ]
135 | },
136 | "no-conflicting-lifecycle": true,
137 | "no-host-metadata-property": true,
138 | "no-input-rename": true,
139 | "no-inputs-metadata-property": true,
140 | "no-output-native": true,
141 | "no-output-on-prefix": true,
142 | "no-output-rename": true,
143 | "no-outputs-metadata-property": true,
144 | "template-banana-in-box": true,
145 | "template-no-negated-async": true,
146 | "use-lifecycle-interface": true,
147 | "use-pipe-transform-interface": true
148 | },
149 | "rulesDirectory": [
150 |
151 | "codelyzer"
152 |
153 | ]
154 |
155 | }
156 |
157 |
--------------------------------------------------------------------------------
/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "angular-project": {
7 | "projectType": "application",
8 | "schematics": {},
9 | "root": "",
10 | "sourceRoot": "src",
11 | "prefix": "app",
12 | "architect": {
13 | "build": {
14 | "builder": "@angular-devkit/build-angular:browser",
15 | "options": {
16 |
17 | "outputPath": "dist",
18 | "index": "src/index.html",
19 | "main": "src/main.ts",
20 | "polyfills": "src/polyfills.ts",
21 | "tsConfig": "tsconfig.app.json",
22 | "aot": true,
23 | "assets": [
24 | "src/favicon.ico",
25 | "src/assets"
26 | ],
27 | "styles": [
28 | "src/styles.css"
29 | ],
30 | "scripts": []
31 | },
32 | "configurations": {
33 | "production": {
34 | "fileReplacements": [
35 | {
36 | "replace": "src/environments/environment.ts",
37 | "with": "src/environments/environment.prod.ts"
38 | }
39 | ],
40 | "optimization": true,
41 | "outputHashing": "all",
42 | "sourceMap": true,
43 | "extractCss": true,
44 | "namedChunks": false,
45 | "extractLicenses": true,
46 | "vendorChunk": false,
47 | "buildOptimizer": true,
48 | "budgets": [
49 | {
50 | "type": "initial",
51 | "maximumWarning": "2mb",
52 | "maximumError": "5mb"
53 | },
54 | {
55 | "type": "anyComponentStyle",
56 | "maximumWarning": "6kb",
57 | "maximumError": "10kb"
58 | }
59 | ]
60 | }
61 | }
62 | },
63 | "serve": {
64 | "builder": "@angular-devkit/build-angular:dev-server",
65 | "options": {
66 | "browserTarget": "angular-project:build"
67 | },
68 | "configurations": {
69 | "production": {
70 | "browserTarget": "angular-project:build:production"
71 | }
72 | }
73 | },
74 | "extract-i18n": {
75 | "builder": "@angular-devkit/build-angular:extract-i18n",
76 | "options": {
77 | "browserTarget": "angular-project:build"
78 | }
79 | },
80 | "test": {
81 | "builder": "@angular-devkit/build-angular:karma",
82 | "options": {
83 | "main": "src/test.ts",
84 | "polyfills": "src/polyfills.ts",
85 | "tsConfig": "tsconfig.spec.json",
86 | "karmaConfig": "karma.conf.js",
87 | "assets": [
88 | "src/favicon.ico",
89 | "src/assets"
90 | ],
91 | "styles": [
92 | "src/styles.css"
93 | ],
94 | "scripts": []
95 | }
96 | },
97 | "lint": {
98 | "builder": "@angular-devkit/build-angular:tslint",
99 | "options": {
100 | "tsConfig": [
101 | "tsconfig.app.json",
102 | "tsconfig.spec.json",
103 | "e2e/tsconfig.json"
104 | ],
105 | "exclude": [
106 | "**/node_modules/**"
107 | ]
108 | }
109 | },
110 | "e2e": {
111 | "builder": "@angular-devkit/build-angular:protractor",
112 | "options": {
113 | "protractorConfig": "e2e/protractor.conf.js",
114 | "devServerTarget": "angular-project:serve"
115 | },
116 | "configurations": {
117 | "production": {
118 | "devServerTarget": "angular-project:serve:production"
119 | }
120 | }
121 | }
122 | }
123 | }
124 | },
125 | "defaultProject": "angular-project",
126 | "cli": {
127 | "analytics": false
128 | }
129 | }
130 |
--------------------------------------------------------------------------------