├── .commitlintrc.json ├── .editorconfig ├── .eslintrc.json ├── .github ├── auto_assign.yml ├── labels.yml ├── stale.yml └── workflows │ ├── labels.yml │ ├── publish.yml │ └── test.yml ├── .gitignore ├── .husky ├── commit-msg └── pre-commit ├── .lintstagedrc.json ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── angular.json ├── ngx-sentry.code-workspace ├── package.json ├── projects └── ngx-sentry │ ├── ng-package.json │ ├── ng-package.prod.json │ ├── package.json │ ├── src │ ├── exports.ts │ └── lib │ │ ├── sentry.handler.ts │ │ ├── sentry.interceptor.ts │ │ ├── sentry.provider.ts │ │ ├── sentry.service.ts │ │ └── tokens.ts │ ├── tsconfig.lib.json │ └── tsconfig.lib.prod.json ├── renovate.json ├── src ├── app │ ├── app.component.html │ ├── app.component.ts │ └── app.config.ts ├── assets │ └── .gitkeep ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── favicon.ico ├── index.html ├── main.ts └── styles.scss ├── tsconfig.app.json ├── tsconfig.json └── yarn.lock /.commitlintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["@commitlint/config-conventional"], 3 | "rules": { 4 | "header-max-length": [2, "always", 100] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most editorconfig file 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | insert_final_newline = true 10 | trim_trailing_whitespace = true 11 | 12 | [.*rc] 13 | indent_size = 2 14 | 15 | [*.{yml,json,lock}] 16 | indent_size = 2 17 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "extends": "@pascaliske/eslint-config/angular", 4 | "parserOptions": { 5 | "project": ["./tsconfig.json"], 6 | "createDefaultProgram": true 7 | }, 8 | "env": { 9 | "browser": true, 10 | "node": true 11 | }, 12 | "globals": { 13 | "APP_ID": "readonly", 14 | "APP_VERSION": "readonly" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.github/auto_assign.yml: -------------------------------------------------------------------------------- 1 | addReviewers: true 2 | addAssignees: true 3 | reviewers: 4 | - pascaliske 5 | assignees: 6 | - pascaliske 7 | -------------------------------------------------------------------------------- /.github/labels.yml: -------------------------------------------------------------------------------- 1 | - name: bug 2 | color: 'd73a4a' 3 | description: Something isn't working 4 | - name: dependencies 5 | color: '0366d6' 6 | description: Dependency related things 7 | - name: documentation 8 | color: '7057ff' 9 | description: Improvements or additions to documentation 10 | - name: duplicate 11 | color: 'cfd3d7' 12 | description: This item already exists 13 | - name: enhancement 14 | color: '008672' 15 | description: New feature or request 16 | - name: invalid 17 | color: 'e4e669' 18 | description: This doesn't seem right 19 | - name: todo 20 | color: '00b0d8' 21 | description: This will be worked on 22 | - name: wontfix 23 | color: 'ffffff' 24 | description: This will not be worked on 25 | - name: inactivity 26 | color: 'be3903' 27 | description: Stale because of inactivity 28 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | staleLabel: inactivity 2 | daysUntilStale: 60 3 | daysUntilClose: 7 4 | exemptLabels: 5 | - dependencies 6 | -------------------------------------------------------------------------------- /.github/workflows/labels.yml: -------------------------------------------------------------------------------- 1 | name: Labels 2 | on: push 3 | 4 | jobs: 5 | labels: 6 | name: Labels 7 | runs-on: ubuntu-latest 8 | steps: 9 | # checkout 10 | - uses: actions/checkout@v5 11 | 12 | # sync labels 13 | - uses: crazy-max/ghaction-github-labeler@v5 14 | if: success() 15 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish package 2 | on: 3 | push: 4 | tags: 5 | - '*' 6 | 7 | jobs: 8 | publish: 9 | runs-on: ubuntu-latest 10 | steps: 11 | # checkout 12 | - uses: actions/checkout@v5 13 | 14 | # prepare 15 | - uses: actions/setup-node@v4.4.0 16 | with: 17 | node-version: '22' 18 | registry-url: 'https://registry.npmjs.org' 19 | - run: yarn install --frozen-lockfile 20 | 21 | # build 22 | - run: yarn run lint 23 | - run: yarn run build 24 | 25 | # publish 26 | - run: yarn publish 27 | working-directory: dist/ngx-sentry 28 | env: 29 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 30 | 31 | # generate release notes 32 | - name: Generate release notes 33 | if: startsWith(github.ref, 'refs/tags/v') 34 | id: changelog 35 | run: | 36 | npx standard-changelog -i /dev/null -o CHANGES.md 37 | 38 | # create github release 39 | - uses: ncipollo/release-action@v1 40 | if: startsWith(github.ref, 'refs/tags/v') 41 | with: 42 | tag: ${{ github.ref_name }} 43 | name: Release ${{ github.ref_name }} 44 | bodyFile: CHANGES.md 45 | prerelease: ${{ steps.changelog.outputs.status == 'prereleased' }} 46 | draft: ${{ steps.changelog.outputs.status == 'unreleased' }} 47 | token: ${{ secrets.GITHUB_TOKEN }} 48 | artifacts: README.md,LICENSE.md 49 | -------------------------------------------------------------------------------- /.github/workflows/test.yml: -------------------------------------------------------------------------------- 1 | name: Test package 2 | on: [push] 3 | 4 | jobs: 5 | test: 6 | runs-on: ubuntu-latest 7 | steps: 8 | # checkout 9 | - uses: actions/checkout@v5 10 | 11 | # prepare 12 | - uses: actions/setup-node@v4.4.0 13 | with: 14 | node-version: '22' 15 | registry-url: 'https://registry.npmjs.org' 16 | - run: yarn install --frozen-lockfile 17 | 18 | # build 19 | - run: yarn run lint 20 | - run: yarn run build 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | /node_modules 10 | 11 | # profiling files 12 | chrome-profiler-events.json 13 | speed-measure-plugin.json 14 | 15 | # IDEs and editors 16 | /.idea 17 | .envrc 18 | .project 19 | .classpath 20 | .c9/ 21 | *.launch 22 | .settings/ 23 | *.sublime-workspace 24 | 25 | # IDE - VSCode 26 | .vscode/* 27 | !.vscode/settings.json 28 | !.vscode/tasks.json 29 | !.vscode/launch.json 30 | !.vscode/extensions.json 31 | 32 | # misc 33 | /.angular/cache 34 | /.sass-cache 35 | /connect.lock 36 | /coverage 37 | /libpeerconnection.log 38 | npm-debug.log 39 | yarn-error.log 40 | testem.log 41 | /typings 42 | 43 | # System Files 44 | .DS_Store 45 | Thumbs.db 46 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # -*- coding: utf-8 -*- 3 | 4 | # commitlint --env HUSKY_GIT_PARAMS 5 | yarn commitlint --edit $1 6 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # -*- coding: utf-8 -*- 3 | 4 | # lint-staged 5 | yarn lint-staged 6 | -------------------------------------------------------------------------------- /.lintstagedrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "{src,projects}/**/*.ts": [ 3 | "prettier --write" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [6.0.4](https://github.com/pascaliske/ngx-sentry/compare/v6.0.3...v6.0.4) (2025-07-20) 2 | 3 | 4 | ### Features 5 | 6 | * upgrade angular to v19.0.5 ([74e9ab9](https://github.com/pascaliske/ngx-sentry/commit/74e9ab9)) 7 | * upgrade angular to v19.2.0 ([ed9e4b2](https://github.com/pascaliske/ngx-sentry/commit/ed9e4b2)) 8 | * upgrade angular to v20 ([d1fea16](https://github.com/pascaliske/ngx-sentry/commit/d1fea16)) 9 | * upgrade eslint stack ([92f2d43](https://github.com/pascaliske/ngx-sentry/commit/92f2d43)) 10 | 11 | 12 | 13 | ## [6.0.3](https://github.com/pascaliske/ngx-sentry/compare/v6.0.2...v6.0.3) (2024-12-11) 14 | 15 | 16 | ### Features 17 | 18 | * upgrade angular to v19.0.4 ([e992f10](https://github.com/pascaliske/ngx-sentry/commit/e992f10b175fba65fccd12b8adc65498215a1856)) 19 | 20 | 21 | 22 | ## [6.0.2](https://github.com/pascaliske/ngx-sentry/compare/v6.0.1...v6.0.2) (2024-12-05) 23 | 24 | 25 | ### Features 26 | 27 | * upgrade angular to v19.0.3 ([30c7845](https://github.com/pascaliske/ngx-sentry/commit/30c7845cd6a005d9ed567df4e45ac05636f04949)) 28 | 29 | 30 | 31 | ## [6.0.1](https://github.com/pascaliske/ngx-sentry/compare/v6.0.0...v6.0.1) (2024-11-27) 32 | 33 | 34 | 35 | # [6.0.0](https://github.com/pascaliske/ngx-sentry/compare/v5.0.1...v6.0.0) (2024-11-27) 36 | 37 | 38 | ### Features 39 | 40 | * migrate to a provider function based library ([e5319dc](https://github.com/pascaliske/ngx-sentry/commit/e5319dcb58f7cb32c73ce06f23f48d1b2c1b275a)) 41 | * rename options token in preparation for provider based library ([d560da8](https://github.com/pascaliske/ngx-sentry/commit/d560da8f960246fbebd10e3fe9c589a497705468)) 42 | * upgrade angular to v19 ([d09fd93](https://github.com/pascaliske/ngx-sentry/commit/d09fd93f847a936a5ee81bf86b892cf47a56fe72)) 43 | 44 | 45 | ### BREAKING CHANGES 46 | 47 | * The bootstrap process of this library changed from a 48 | module based one to a provider function based one. Replace calls to 49 | `SentryModule.forRoot()` with `provideSentry()`. 50 | * In preparation for a standalone compatible library the 51 | options token interface was renamed from `ModuleOptions` to 52 | `SentryOptions`. 53 | 54 | 55 | 56 | ## [5.0.1](https://github.com/pascaliske/ngx-sentry/compare/v5.0.0...v5.0.1) (2024-08-24) 57 | 58 | 59 | ### Bug Fixes 60 | 61 | * **deps:** update dependency zone.js to ~0.15.0 ([8da4b18](https://github.com/pascaliske/ngx-sentry/commit/8da4b184f2f63956d7a11c5ed7cdbd57769b2209)) 62 | 63 | 64 | ### Features 65 | 66 | * update angular to v18.2.1 ([20a811c](https://github.com/pascaliske/ngx-sentry/commit/20a811c5e4f5308758e6b2cc4097616f0a4fff85)) 67 | 68 | 69 | 70 | # [5.0.0](https://github.com/pascaliske/ngx-sentry/compare/v4.2.0...v5.0.0) (2024-08-19) 71 | 72 | 73 | ### Bug Fixes 74 | 75 | * **deps:** update dependency zone.js to ~0.14.0 ([cd3ce42](https://github.com/pascaliske/ngx-sentry/commit/cd3ce42116acb5cd36169fd0bc4f88f28f9faf41)) 76 | 77 | 78 | ### Features 79 | 80 | * update angular to v18 ([4626928](https://github.com/pascaliske/ngx-sentry/commit/4626928acc6358f6c9fb91c838cc06e9799adca4)) 81 | * update angular-eslint stack to latest versions ([7441a77](https://github.com/pascaliske/ngx-sentry/commit/7441a77ef018ac3185382dcbab2c75c4a9db3e19)) 82 | 83 | 84 | 85 | # [4.2.0](https://github.com/pascaliske/ngx-sentry/compare/v4.1.0...v4.2.0) (2023-06-19) 86 | 87 | 88 | ### Bug Fixes 89 | 90 | * **deps:** update dependency rxjs to ~7.6.0 ([26c2357](https://github.com/pascaliske/ngx-sentry/commit/26c23570d9da6fd11674e9688c557d9d0babb1c7)) 91 | * **deps:** update dependency rxjs to ~7.8.0 ([ad871f0](https://github.com/pascaliske/ngx-sentry/commit/ad871f0527d4465105ce1d225a2b2bb0f2eb9d81)) 92 | * **deps:** update dependency zone.js to ~0.12.0 ([8264bbb](https://github.com/pascaliske/ngx-sentry/commit/8264bbb02aca4ffb421ce5e118acdf0d4d60b161)) 93 | * **deps:** update dependency zone.js to ~0.13.0 ([e883112](https://github.com/pascaliske/ngx-sentry/commit/e883112a5f8129ba39cd3b2fec148cb5a7b9bfac)) 94 | 95 | 96 | ### Features 97 | 98 | * upgrade angular to v16 ([dc9b5d2](https://github.com/pascaliske/ngx-sentry/commit/dc9b5d29d1c1c9de7945bb83e9ff476eeccc7200)) 99 | 100 | 101 | 102 | # [4.1.0](https://github.com/pascaliske/ngx-sentry/compare/v4.0.2...v4.1.0) (2022-07-12) 103 | 104 | 105 | ### Features 106 | 107 | * implement angular 14 compatibility ([66ca897](https://github.com/pascaliske/ngx-sentry/commit/66ca897a2dbdcd99e260d985d9dc07edab170efa)) 108 | 109 | 110 | 111 | ## [4.0.2](https://github.com/pascaliske/ngx-sentry/compare/v4.0.1...v4.0.2) (2022-03-03) 112 | 113 | 114 | 115 | ## [4.0.1](https://github.com/pascaliske/ngx-sentry/compare/v4.0.0...v4.0.1) (2022-02-15) 116 | 117 | 118 | 119 | # [4.0.0](https://github.com/pascaliske/ngx-sentry/compare/v3.0.1...v4.0.0) (2022-02-14) 120 | 121 | 122 | ### Features 123 | 124 | * enable partial compilation mode using ivy ([14c3b9b](https://github.com/pascaliske/ngx-sentry/commit/14c3b9bd6425b5d9b0a65f3af4492686d441f2f9)) 125 | 126 | 127 | ### BREAKING CHANGES 128 | 129 | * This library is now distributed using partial compilation mode for Angular Ivy. 130 | See here for more information: https://github.com/angular/angular/issues/38366 131 | 132 | 133 | 134 | ## [3.0.1](https://github.com/pascaliske/ngx-sentry/compare/v3.0.0...v3.0.1) (2021-05-02) 135 | 136 | 137 | ### Bug Fixes 138 | 139 | * rename deprecated peer dependency setting ([bca8611](https://github.com/pascaliske/ngx-sentry/commit/bca8611ce70461ca07a571378a0b021784ab2f42)) 140 | * **handler:** do not re-throw error after logging to sentry ([f0a2bb0](https://github.com/pascaliske/ngx-sentry/commit/f0a2bb0124f980989981e4b133955c61cef65f8b)) 141 | * **handler:** provide handler service in root injector ([63d0c90](https://github.com/pascaliske/ngx-sentry/commit/63d0c9036b2d1007abea2587aded74342ed09828)) 142 | 143 | 144 | 145 | # [3.0.0](https://github.com/pascaliske/ngx-sentry/compare/v2.3.1...v3.0.0) (2021-05-01) 146 | 147 | 148 | 149 | ## [2.3.1](https://github.com/pascaliske/ngx-sentry/compare/v2.3.0...v2.3.1) (2020-07-25) 150 | 151 | 152 | 153 | # [2.3.0](https://github.com/pascaliske/ngx-sentry/compare/v2.2.3...v2.3.0) (2020-07-25) 154 | 155 | 156 | 157 | ## [2.2.3](https://github.com/pascaliske/ngx-sentry/compare/v2.2.2...v2.2.3) (2020-03-24) 158 | 159 | 160 | 161 | ## [2.2.2](https://github.com/pascaliske/ngx-sentry/compare/v2.2.1...v2.2.2) (2020-02-28) 162 | 163 | 164 | ### Bug Fixes 165 | 166 | * **interceptor:** always clone requests before handling ([52eb9d6](https://github.com/pascaliske/ngx-sentry/commit/52eb9d60b410ac54aa3b70b2a3d4ff76f6dbc139)) 167 | 168 | 169 | 170 | ## [2.2.1](https://github.com/pascaliske/ngx-sentry/compare/v2.2.0...v2.2.1) (2020-02-14) 171 | 172 | 173 | 174 | # [2.2.0](https://github.com/pascaliske/ngx-sentry/compare/v2.1.3...v2.2.0) (2020-02-14) 175 | 176 | 177 | 178 | ## [2.1.4](https://github.com/pascaliske/ngx-sentry/compare/v2.1.3...v2.1.4) (2020-01-13) 179 | 180 | 181 | 182 | ## [2.1.3](https://github.com/pascaliske/ngx-sentry/compare/v2.1.2...v2.1.3) (2019-06-28) 183 | 184 | 185 | 186 | ## [2.1.2](https://github.com/pascaliske/ngx-sentry/compare/v2.1.1...v2.1.2) (2019-06-27) 187 | 188 | 189 | 190 | ## [2.1.1](https://github.com/pascaliske/ngx-sentry/compare/v2.1.0...v2.1.1) (2019-06-18) 191 | 192 | 193 | 194 | # [2.1.0](https://github.com/pascaliske/ngx-sentry/compare/v2.0.0...v2.1.0) (2019-06-05) 195 | 196 | 197 | ### Features 198 | 199 | * compatibility update for angular v8 ([288fc99](https://github.com/pascaliske/ngx-sentry/commit/288fc99)), closes [#42](https://github.com/pascaliske/ngx-sentry/issues/42) [#43](https://github.com/pascaliske/ngx-sentry/issues/43) [#47](https://github.com/pascaliske/ngx-sentry/issues/47) [#48](https://github.com/pascaliske/ngx-sentry/issues/48) [#49](https://github.com/pascaliske/ngx-sentry/issues/49) 200 | 201 | 202 | 203 | # [2.0.0](https://github.com/pascaliske/ngx-sentry/compare/v1.4.1...v2.0.0) (2019-04-03) 204 | 205 | 206 | ### Bug Fixes 207 | 208 | * **package:** update core-js to version 3.0.0 ([e26b349](https://github.com/pascaliske/ngx-sentry/commit/e26b349)) 209 | 210 | 211 | ### BREAKING CHANGES 212 | 213 | * Upgrade peer dependency of @sentry/browser to >= v5.0.5 for smaller bundle sizes. 214 | 215 | 216 | 217 | ## [1.4.1](https://github.com/pascaliske/ngx-sentry/compare/v1.4.0...v1.4.1) (2019-03-19) 218 | 219 | 220 | ### Bug Fixes 221 | 222 | * optional and missing http property should not raise error ([375ff99](https://github.com/pascaliske/ngx-sentry/commit/375ff99)) 223 | 224 | 225 | 226 | # [1.4.0](https://github.com/pascaliske/ngx-sentry/compare/v1.3.4...v1.4.0) (2019-03-04) 227 | 228 | 229 | ### Bug Fixes 230 | 231 | * **sentry:** change sentry imports ([255ec57](https://github.com/pascaliske/ngx-sentry/commit/255ec57)) 232 | * **sentry:** move sentry library to peer dependencies ([e882e02](https://github.com/pascaliske/ngx-sentry/commit/e882e02)) 233 | 234 | 235 | 236 | ## [1.3.4](https://github.com/pascaliske/ngx-sentry/compare/v1.3.3...v1.3.4) (2019-02-22) 237 | 238 | 239 | 240 | ## [1.3.3](https://github.com/pascaliske/ngx-sentry/compare/v1.3.2...v1.3.3) (2019-02-22) 241 | 242 | 243 | ### Bug Fixes 244 | 245 | * **exports:** export all parts manually ([cdcc86a](https://github.com/pascaliske/ngx-sentry/commit/cdcc86a)) 246 | 247 | 248 | ### Features 249 | 250 | * **sentry:** add scope methods for configuring and using sentry scopes ([cd6e299](https://github.com/pascaliske/ngx-sentry/commit/cd6e299)) 251 | 252 | 253 | 254 | ## [1.3.2](https://github.com/pascaliske/ngx-sentry/compare/v1.3.1...v1.3.2) (2019-02-01) 255 | 256 | 257 | 258 | ## [1.3.1](https://github.com/pascaliske/ngx-sentry/compare/v1.2.2...v1.3.1) (2019-01-17) 259 | 260 | 261 | ### Bug Fixes 262 | 263 | * **sentry:** move report dialog call to init function ([ae35c04](https://github.com/pascaliske/ngx-sentry/commit/ae35c04)) 264 | 265 | 266 | ### Features 267 | 268 | * **sentry:** use new esm build for smaller build sizes ([5d8ed70](https://github.com/pascaliske/ngx-sentry/commit/5d8ed70)) 269 | 270 | 271 | 272 | ## [1.2.2](https://github.com/pascaliske/ngx-sentry/compare/v1.2.1...v1.2.2) (2019-01-14) 273 | 274 | 275 | ### Bug Fixes 276 | 277 | * **interceptor:** fix http message placeholder replacement ([8d17135](https://github.com/pascaliske/ngx-sentry/commit/8d17135)), closes [#6](https://github.com/pascaliske/ngx-sentry/issues/6) 278 | 279 | 280 | 281 | ## [1.2.1](https://github.com/pascaliske/ngx-sentry/compare/v1.2.0...v1.2.1) (2019-01-09) 282 | 283 | 284 | ### Bug Fixes 285 | 286 | * **demo:** update demo app ([222c530](https://github.com/pascaliske/ngx-sentry/commit/222c530)) 287 | * **exports:** export service in public api ([5183f8a](https://github.com/pascaliske/ngx-sentry/commit/5183f8a)) 288 | 289 | 290 | 291 | ## [1.2.0](https://github.com/pascaliske/ngx-sentry/compare/v1.1.0...v1.2.0) (2019-01-08) 292 | 293 | 294 | ### Bug Fixes 295 | 296 | * **interceptor:** move interceptor config into http namespace and allow disabling http interception ([5cbfcc5](https://github.com/pascaliske/ngx-sentry/commit/5cbfcc5)) 297 | 298 | 299 | ### Features 300 | 301 | * **handler,interceptor:** allow optional user reporting with the built in report dialog ([733c589](https://github.com/pascaliske/ngx-sentry/commit/733c589)) 302 | * **interceptor:** allow custom message for capturing http errors ([441694f](https://github.com/pascaliske/ngx-sentry/commit/441694f)) 303 | * **sentry:** add an sentry service for reporting manual events to sentry ([fb19f9c](https://github.com/pascaliske/ngx-sentry/commit/fb19f9c)) 304 | * **sentry:** allow configuring the report dialog ([dd60724](https://github.com/pascaliske/ngx-sentry/commit/dd60724)) 305 | 306 | 307 | 308 | ## [1.1.0](https://github.com/pascaliske/ngx-sentry/compare/v1.0.0...v1.1.0) (2018-12-04) 309 | 310 | 311 | ### Features 312 | 313 | * **module:** add injectable sentry http interceptor ([0a7d936](https://github.com/pascaliske/ngx-sentry/commit/0a7d936)) 314 | 315 | 316 | 317 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License 2 | 3 | Copyright 2022 Pascal Iske, 4 | 5 | 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: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | 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. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `@pascaliske/ngx-sentry` 2 | 3 | [![npm (scoped)](https://img.shields.io/npm/v/@pascaliske/ngx-sentry.svg?style=flat-square)](https://www.npmjs.com/package/@pascaliske/ngx-sentry) [![GitHub Tag](https://img.shields.io/github/tag/pascaliske/ngx-sentry.svg?style=flat-square)](https://github.com/pascaliske/ngx-sentry) [![Build Status](https://img.shields.io/github/workflow/status/pascaliske/ngx-sentry/Test%20package/main?label=test&style=flat-square)](https://github.com/pascaliske/ngx-sentry/actions) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](https://opensource.org/licenses/MIT) [![GitHub Last Commit](https://img.shields.io/github/last-commit/pascaliske/ngx-sentry?style=flat-square)](https://github.com/pascaliske/ngx-sentry) [![Awesome Badges](https://img.shields.io/badge/badges-awesome-green.svg?style=flat-square)](https://github.com/Naereen/badges) 4 | 5 | This library provides an [`ErrorHandler`](https://angular.io/api/core/ErrorHandler) and a [`HttpInterceptor`](https://angular.io/guide/http#intercepting-requests-and-responses) for connecting an Angular application with [Sentry](https://sentry.io) service. 6 | 7 | ## Requirements 8 | 9 | To use this library you need to install the `@sentry/browser` library into your project 10 | 11 | ```bash 12 | $ yarn add @sentry/browser 13 | ``` 14 | 15 | ## Installation 16 | 17 | To install the library itself use the following command: 18 | 19 | ```bash 20 | $ yarn add @pascaliske/ngx-sentry 21 | ``` 22 | 23 | ## Usage 24 | 25 | Import the `provideSentry()` function in your application configuration file. The function expects an object with at least the following two keys: `enabled`, `sentry`. More options can be found in the [`SentryOptions` section](#sentryoptions) below. 26 | 27 | ```typescript 28 | import type { ApplicationConfig } from '@angular/core' 29 | import { provideSentry } from '@pascaliske/ngx-sentry' 30 | 31 | export const appConfig: ApplicationConfig = { 32 | providers: [ 33 | provideExperimentalZonelessChangeDetection(), 34 | provideSentry({ 35 | enabled: true, 36 | sentry: { 37 | dsn: 'https://your-sentry-dsn@sentry.io', 38 | }, 39 | }), 40 | ], 41 | } 42 | ``` 43 | 44 | ## `SentryService` 45 | 46 | You can use the `SentryService` injectable to manually capture errors or events as follows: 47 | 48 | ```typescript 49 | @Component({ 50 | // [...] 51 | }) 52 | export class AppComponent { 53 | public constructor(private sentryService: SentryService) {} 54 | 55 | public ngOnInit(): void { 56 | // capture single error 57 | this.sentryService.captureException(new Error('')) 58 | 59 | // capture single error with additional context information 60 | this.sentryService.withScope(scope => { 61 | scope.setExtra('currentPage', window.location.href) 62 | this.sentryService.captureException(new Error('')) 63 | }) 64 | } 65 | } 66 | 67 | ``` 68 | 69 | > **Note:** The `SentryService` inherits all methods directly from the Sentry library. For more information about their APIs you can visit [their documentation](https://docs.sentry.io/enriching-error-data/context/?platform=browser). 70 | 71 | ## `SentryOptions` 72 | 73 | You can configure the library for yourself. The possible options for the `provideSentry()` function are: 74 | 75 | ### enabled 76 | 77 | Type: `boolean`
78 | Required: `true` 79 | 80 | This flag allows to enable or disable the whole sentry tracking. 81 | 82 | ### sentry 83 | 84 | Type: `object`
85 | Required: `true` 86 | 87 | Configure Sentry, see [here](https://docs.sentry.io/error-reporting/quickstart/?platform=browser#configure-the-sdk) for more information. 88 | 89 | ### dialog 90 | 91 | Type: `boolean` | [`ReportDialogOptions`](https://docs.sentry.io/enriching-error-data/user-feedback/?platform=browser#customizing-the-widget)
92 | Required: `false`
93 | Default: `false` 94 | 95 | Enable or disable the [reporting dialog](https://docs.sentry.io/enriching-error-data/user-feedback/?platform=browser). 96 | 97 | ### http 98 | 99 | Type: `object`
100 | Required: `false`
101 | 102 | Configure the HTTP interceptor. 103 | 104 | #### http.enabled 105 | 106 | Type: `boolean`
107 | Required: `false`
108 | Default: `true` 109 | 110 | Enable or disable HTTP intercepting. 111 | 112 | #### http.message 113 | 114 | Type: `string`
115 | Required: `false`
116 | Default: `Http request failed. ({method}, {status}, {url})` 117 | 118 | Customize the captured message for all intercepted HTTP errors. There are a few placeholders which get replaced before sending: 119 | 120 | - `{method}` - The request method 121 | - `{url}` - The requested url 122 | - `{status}` - The response status 123 | - `{message}` - The response message 124 | 125 | #### http.whitelist 126 | 127 | Type: `Array`
128 | Required: `false`
129 | Default: `null` 130 | 131 | Use a whitelist of HTTP status codes to filter the intercepted HTTP requests. Only responses with whitelisted status codes get reported. 132 | 133 | #### http.blacklist 134 | 135 | Type: `Array`
136 | Required: `false`
137 | Default: `null` 138 | 139 | Use a blacklist of HTTP status codes to filter the intercepted HTTP requests. All responses with blacklisted status codes will be skipped. 140 | 141 | ## License 142 | 143 | MIT © [Pascal Iske](https://pascaliske.dev) 144 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "cli": { 6 | "packageManager": "yarn" 7 | }, 8 | "schematics": { 9 | "@schematics/angular:component": { 10 | "style": "scss", 11 | "type": "component" 12 | }, 13 | "@schematics/angular:directive": { 14 | "type": "directive" 15 | }, 16 | "@schematics/angular:service": { 17 | "type": "service" 18 | }, 19 | "@schematics/angular:guard": { 20 | "typeSeparator": "." 21 | }, 22 | "@schematics/angular:interceptor": { 23 | "typeSeparator": "." 24 | }, 25 | "@schematics/angular:module": { 26 | "typeSeparator": "." 27 | }, 28 | "@schematics/angular:pipe": { 29 | "typeSeparator": "." 30 | }, 31 | "@schematics/angular:resolver": { 32 | "typeSeparator": "." 33 | } 34 | }, 35 | "projects": { 36 | "ngx-sentry-demo": { 37 | "root": "", 38 | "sourceRoot": "src", 39 | "projectType": "application", 40 | "prefix": "app", 41 | "schematics": {}, 42 | "architect": { 43 | "build": { 44 | "builder": "@angular/build:application", 45 | "options": { 46 | "outputPath": { 47 | "base": "dist/ngx-sentry-demo" 48 | }, 49 | "index": "src/index.html", 50 | "browser": "src/main.ts", 51 | "polyfills": [], 52 | "tsConfig": "tsconfig.app.json", 53 | "assets": [ 54 | "src/favicon.ico" 55 | ], 56 | "styles": [], 57 | "scripts": [], 58 | "extractLicenses": false, 59 | "sourceMap": true, 60 | "optimization": false, 61 | "namedChunks": true 62 | }, 63 | "configurations": { 64 | "production": { 65 | "fileReplacements": [ 66 | { 67 | "replace": "src/environments/environment.ts", 68 | "with": "src/environments/environment.prod.ts" 69 | } 70 | ], 71 | "optimization": true, 72 | "outputHashing": "all", 73 | "sourceMap": false, 74 | "namedChunks": false, 75 | "extractLicenses": true, 76 | "budgets": [ 77 | { 78 | "type": "initial", 79 | "maximumWarning": "2mb", 80 | "maximumError": "5mb" 81 | }, 82 | { 83 | "type": "anyComponentStyle", 84 | "maximumWarning": "6kb" 85 | } 86 | ] 87 | } 88 | } 89 | }, 90 | "serve": { 91 | "builder": "@angular/build:dev-server", 92 | "options": { 93 | "buildTarget": "ngx-sentry-demo:build" 94 | }, 95 | "configurations": { 96 | "production": { 97 | "buildTarget": "ngx-sentry-demo:build:production" 98 | } 99 | } 100 | }, 101 | "lint": { 102 | "builder": "@angular-eslint/builder:lint", 103 | "options": { 104 | "lintFilePatterns": ["src/**/*.ts"] 105 | } 106 | } 107 | } 108 | }, 109 | "ngx-sentry": { 110 | "root": "projects/ngx-sentry", 111 | "sourceRoot": "projects/ngx-sentry/src", 112 | "projectType": "library", 113 | "prefix": "lib", 114 | "architect": { 115 | "build": { 116 | "builder": "@angular-devkit/build-ng-packagr:build", 117 | "options": { 118 | "tsConfig": "projects/ngx-sentry/tsconfig.lib.json", 119 | "project": "projects/ngx-sentry/ng-package.json" 120 | }, 121 | "configurations": { 122 | "production": { 123 | "project": "projects/ngx-sentry/ng-package.prod.json", 124 | "tsConfig": "projects/ngx-sentry/tsconfig.lib.prod.json" 125 | } 126 | } 127 | }, 128 | "lint": { 129 | "builder": "@angular-eslint/builder:lint", 130 | "options": { 131 | "lintFilePatterns": ["projects/ngx-sentry/src/**/*.ts"] 132 | } 133 | } 134 | } 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /ngx-sentry.code-workspace: -------------------------------------------------------------------------------- 1 | { 2 | "folders": [ 3 | { 4 | "path": "." 5 | }, 6 | { 7 | "name": "package", 8 | "path": "./projects/ngx-sentry" 9 | }, 10 | { 11 | "name": "testing", 12 | "path": "./src" 13 | } 14 | ], 15 | "settings": { 16 | "editor.formatOnSave": true, 17 | "editor.formatOnType": true, 18 | "tslint.autoFixOnSave": true, 19 | "typescript.tsdk": "ngx-sentry/node_modules/typescript/lib", 20 | "[yaml]": { 21 | "editor.formatOnSave": false, 22 | "editor.formatOnType": false 23 | }, 24 | "[json]": { 25 | "editor.formatOnSave": false, 26 | "editor.formatOnType": false 27 | }, 28 | "[jsonc]": { 29 | "editor.formatOnSave": false, 30 | "editor.formatOnType": false 31 | }, 32 | "[html]": { 33 | "editor.formatOnSave": false, 34 | "editor.formatOnType": false 35 | }, 36 | "[scss]": { 37 | "editor.formatOnSave": false, 38 | "editor.formatOnType": false 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-sentry", 3 | "description": "Angular ErrorHandler and HttpInterceptor for Sentry.", 4 | "version": "6.0.4", 5 | "license": "MIT", 6 | "author": { 7 | "name": "Pascal Iske", 8 | "email": "info@pascaliske.dev", 9 | "url": "https://pascaliske.dev" 10 | }, 11 | "repository": { 12 | "url": "https://github.com/pascaliske/ngx-sentry.git", 13 | "type": "git" 14 | }, 15 | "bugs": { 16 | "url": "https://github.com/pascaliske/ngx-sentry/issues" 17 | }, 18 | "private": true, 19 | "scripts": { 20 | "ng": "ng", 21 | "prepare": "husky", 22 | "start": "ng serve ngx-sentry-demo", 23 | "build": "ng build ngx-sentry --configuration production", 24 | "postbuild": "cp README.md dist/ngx-sentry/README.md && cp LICENSE.md dist/ngx-sentry/LICENSE.md && cp CHANGELOG.md dist/ngx-sentry/CHANGELOG.md", 25 | "lint": "ng lint", 26 | "format": "prettier --write \"{src,projects}/**/*.ts\"", 27 | "version": "bump --yes package.json projects/ngx-sentry/package.json", 28 | "changelog": "standard-changelog", 29 | "link": "yarn run build && cd dist/ngx-sentry && yarn link", 30 | "unlink": "cd dist/ngx-sentry && yarn unlink" 31 | }, 32 | "packageManager": "yarn@1.22.22", 33 | "prettier": "@pascaliske/prettier-config", 34 | "dependencies": { 35 | "@angular/animations": "^20.1.2", 36 | "@angular/common": "^20.1.2", 37 | "@angular/compiler": "^20.1.2", 38 | "@angular/core": "^20.1.2", 39 | "@angular/forms": "^20.1.2", 40 | "@angular/platform-browser": "^20.1.2", 41 | "@angular/platform-browser-dynamic": "^20.1.2", 42 | "@angular/router": "^20.1.2", 43 | "core-js": "^3.44.0", 44 | "rxjs": "~7.8.2", 45 | "tslib": "^2.8.1" 46 | }, 47 | "devDependencies": { 48 | "@angular-devkit/build-ng-packagr": "^0.1002.0", 49 | "@angular-eslint/builder": "20.1.1", 50 | "@angular-eslint/eslint-plugin": "20.1.1", 51 | "@angular-eslint/eslint-plugin-template": "20.1.1", 52 | "@angular-eslint/schematics": "20.1.1", 53 | "@angular-eslint/template-parser": "20.1.1", 54 | "@angular/build": "^20.1.1", 55 | "@angular/cli": "^20.1.1", 56 | "@angular/compiler-cli": "^20.1.2", 57 | "@angular/language-service": "^20.1.2", 58 | "@commitlint/cli": "^20.0.0", 59 | "@commitlint/config-conventional": "^20.0.0", 60 | "@pascaliske/eslint-config": "^3.0.1", 61 | "@pascaliske/prettier-config": "^1.3.0", 62 | "@rstacruz/bump-cli": "^2.0.1", 63 | "@sentry/browser": "^9.40.0", 64 | "@types/node": "^24.1.0", 65 | "@typescript-eslint/eslint-plugin": "^8.38.0", 66 | "@typescript-eslint/parser": "^8.38.0", 67 | "codelyzer": "^6.0.2", 68 | "eslint": "^9.28.0", 69 | "husky": "^9.1.7", 70 | "lint-staged": "^16.1.2", 71 | "ng-packagr": "^20.1.0", 72 | "prettier": "^3.6.2", 73 | "standard-changelog": "^7.0.0", 74 | "ts-node": "~10.9.2", 75 | "typescript": "~5.8.3" 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /projects/ngx-sentry/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngx-sentry", 4 | "deleteDestPath": false, 5 | "allowedNonPeerDependencies": [], 6 | "lib": { 7 | "entryFile": "src/exports.ts" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /projects/ngx-sentry/ng-package.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/ngx-sentry", 4 | "allowedNonPeerDependencies": [], 5 | "lib": { 6 | "entryFile": "src/exports.ts" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /projects/ngx-sentry/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@pascaliske/ngx-sentry", 3 | "description": "Angular ErrorHandler and HttpInterceptor for Sentry.", 4 | "version": "6.0.4", 5 | "license": "MIT", 6 | "author": { 7 | "name": "Pascal Iske", 8 | "email": "info@pascaliske.dev", 9 | "url": "https://pascaliske.dev" 10 | }, 11 | "repository": { 12 | "url": "https://github.com/pascaliske/ngx-sentry.git", 13 | "type": "git" 14 | }, 15 | "bugs": { 16 | "url": "https://github.com/pascaliske/ngx-sentry/issues" 17 | }, 18 | "publishConfig": { 19 | "access": "public" 20 | }, 21 | "peerDependencies": { 22 | "@angular/common": "^18.0.0 || ^19.0.0 || ^20.0.0", 23 | "@angular/core": "^18.0.0 || ^19.0.0 || ^20.0.0", 24 | "@sentry/browser": "^9.0.0" 25 | }, 26 | "dependencies": { 27 | "tslib": "^2.2.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /projects/ngx-sentry/src/exports.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Public API Surface of ngx-sentry 3 | */ 4 | export { provideSentry } from './lib/sentry.provider' 5 | export { SentryOptions, INITIALIZER, OPTIONS } from './lib/tokens' 6 | export { SentryErrorHandler } from './lib/sentry.handler' 7 | export { SentryErrorInterceptor } from './lib/sentry.interceptor' 8 | export { SentryService } from './lib/sentry.service' 9 | -------------------------------------------------------------------------------- /projects/ngx-sentry/src/lib/sentry.handler.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, ErrorHandler, inject } from '@angular/core' 2 | import { captureException } from '@sentry/browser' 3 | import { SentryOptions, OPTIONS } from './tokens' 4 | 5 | /** 6 | * Injectable error handler for Sentry. 7 | */ 8 | @Injectable({ 9 | providedIn: 'root', 10 | }) 11 | export class SentryErrorHandler implements ErrorHandler { 12 | private readonly options: SentryOptions = inject(OPTIONS) 13 | 14 | /** 15 | * Handles any errors. 16 | * 17 | * @param - The error to handle. 18 | */ 19 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 20 | public handleError(error: any): void { 21 | // log to Sentry 22 | if (this.options.enabled) { 23 | captureException(error.originalError || error) 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /projects/ngx-sentry/src/lib/sentry.interceptor.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, inject } from '@angular/core' 2 | import { 3 | HttpInterceptor, 4 | HttpRequest, 5 | HttpHandler, 6 | HttpEvent, 7 | HttpErrorResponse, 8 | } from '@angular/common/http' 9 | import { captureMessage } from '@sentry/browser' 10 | import { Observable, throwError } from 'rxjs' 11 | import { catchError } from 'rxjs/operators' 12 | import { SentryOptions, OPTIONS } from './tokens' 13 | 14 | /** 15 | * Injectable HTTP interceptor for Sentry. 16 | */ 17 | @Injectable() 18 | export class SentryErrorInterceptor implements HttpInterceptor { 19 | private readonly options: SentryOptions = inject(OPTIONS) 20 | 21 | /** 22 | * Intercepts HTTP requests and handles any HTTP errors. 23 | * 24 | * @param - The intercepted request. 25 | * @returns - An observable with the request 26 | */ 27 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 28 | public intercept(request: HttpRequest, next: HttpHandler): Observable { 29 | return next.handle(request.clone()).pipe( 30 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 31 | catchError, any>(response => { 32 | // log to Sentry 33 | if (response instanceof HttpErrorResponse && this.filter(response)) { 34 | captureMessage(this.getMessage(request, response)) 35 | } 36 | 37 | // re-throw error 38 | return throwError(() => response) 39 | }), 40 | ) 41 | } 42 | 43 | /** 44 | * Checks if the response should be sent to Sentry. 45 | * 46 | * @param - The HttpErrorResponse 47 | * @returns - An boolean describing if the response should be handled 48 | */ 49 | private filter(response: HttpErrorResponse): boolean { 50 | if (!this.options.enabled) { 51 | return false 52 | } 53 | 54 | if (!this.options.http || this.options.http.enabled === false) { 55 | return false 56 | } 57 | 58 | // apply whitelist 59 | if (this.options.http.whitelist && this.options.http.whitelist.length > 0) { 60 | return this.options.http.whitelist.includes(response.status) 61 | } 62 | 63 | // apply blacklist 64 | if (this.options.http.blacklist && this.options.http.blacklist.length > 0) { 65 | return !this.options.http.blacklist.includes(response.status) 66 | } 67 | 68 | return true 69 | } 70 | 71 | /** 72 | * Builds the message for capturing. 73 | * 74 | * @param - The HTTP request object 75 | * @param - The HTTP response object 76 | * @returns - The built message to capture 77 | */ 78 | private getMessage(request: HttpRequest, response: HttpErrorResponse): string { 79 | const defaultMessage = 'Http request failed. ({method}, {status}, {url})' 80 | const replace = (msg: string): string => { 81 | const map = { 82 | method: request.method, 83 | url: request.url, 84 | status: response.status, 85 | message: response.message, 86 | } 87 | 88 | // replace all keys with their values 89 | Object.keys(map).forEach(key => { 90 | msg = msg.replace(new RegExp(`{${key}}`, 'g'), map[key] as string) 91 | }) 92 | 93 | return msg 94 | } 95 | 96 | // use custom message 97 | if (this.options?.http?.message) { 98 | return replace(this.options.http.message) 99 | } 100 | 101 | // use default message 102 | return replace(defaultMessage) 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /projects/ngx-sentry/src/lib/sentry.provider.ts: -------------------------------------------------------------------------------- 1 | import { EnvironmentProviders, ErrorHandler, makeEnvironmentProviders } from '@angular/core' 2 | import { HTTP_INTERCEPTORS } from '@angular/common/http' 3 | import { init, showReportDialog } from '@sentry/browser' 4 | import { SentryErrorHandler } from './sentry.handler' 5 | import { SentryErrorInterceptor } from './sentry.interceptor' 6 | import { SentryOptions, OPTIONS, INITIALIZER } from './tokens' 7 | 8 | /** 9 | * Initializer function to setup sentry logging. 10 | * 11 | * @param - The module options 12 | * @returns - A promise for waiting to be resolved 13 | */ 14 | function initializer(options: SentryOptions): void { 15 | // configure sentry's browser library 16 | if (options.enabled) { 17 | // show report dialog 18 | if (options.dialog) { 19 | options.sentry.beforeSend = event => { 20 | if (event.exception) { 21 | // show dialog with options 22 | if (typeof options.dialog === 'object') { 23 | showReportDialog(options.dialog) 24 | return event 25 | } 26 | 27 | // show dialog without options 28 | showReportDialog() 29 | } 30 | 31 | return event 32 | } 33 | } 34 | 35 | init(options.sentry) 36 | } 37 | } 38 | 39 | export const provideSentry = (options: SentryOptions): EnvironmentProviders => { 40 | return makeEnvironmentProviders([ 41 | { 42 | provide: OPTIONS, 43 | useValue: options, 44 | }, 45 | { 46 | provide: INITIALIZER, 47 | useFactory: initializer, 48 | deps: [OPTIONS], 49 | }, 50 | { 51 | provide: ErrorHandler, 52 | useClass: SentryErrorHandler, 53 | deps: [OPTIONS, INITIALIZER], 54 | }, 55 | { 56 | provide: HTTP_INTERCEPTORS, 57 | useClass: SentryErrorInterceptor, 58 | deps: [OPTIONS, INITIALIZER], 59 | multi: true, 60 | }, 61 | ]) 62 | } 63 | -------------------------------------------------------------------------------- /projects/ngx-sentry/src/lib/sentry.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core' 2 | import { 3 | addBreadcrumb, 4 | captureMessage, 5 | captureException, 6 | captureEvent, 7 | getCurrentScope, 8 | withScope, 9 | Breadcrumb, 10 | SeverityLevel, 11 | Event, 12 | Scope, 13 | } from '@sentry/browser' 14 | import { OPTIONS, INITIALIZER } from './tokens' 15 | 16 | @Injectable({ 17 | providedIn: 'root', 18 | deps: [OPTIONS, INITIALIZER], 19 | }) 20 | export class SentryService { 21 | /** 22 | * Add an {@link Breadcrumb} to Sentry. 23 | * 24 | * @param - The breadcrumb to add 25 | * @returns - Returns nothing 26 | */ 27 | public addBreadcrumb(breadcrumb: Breadcrumb): void { 28 | return addBreadcrumb(breadcrumb) 29 | } 30 | 31 | /** 32 | * Capture a message. 33 | * 34 | * @param - The message to report 35 | * @param - The severity level of the message 36 | * @returns - Returns the generated event id 37 | */ 38 | public captureMessage(message: string, level: SeverityLevel): string { 39 | return captureMessage(message, level) 40 | } 41 | 42 | /** 43 | * Capture an exception. 44 | * 45 | * @param - The exception to report 46 | * @returns - Returns the generated event id 47 | */ 48 | public captureException(exception: T): string { 49 | return captureException(exception) 50 | } 51 | 52 | /** 53 | * Capture an {@link Event}. 54 | * 55 | * @param - The event to report 56 | * @returns - Returns the generated event id 57 | */ 58 | public captureEvent(event: Event): string { 59 | return captureEvent(event) 60 | } 61 | 62 | /** 63 | * Get the current {@link Scope}. 64 | * 65 | * @returns - Returns the current scope 66 | */ 67 | public getCurrentScope(): Scope { 68 | return getCurrentScope() 69 | } 70 | 71 | /** 72 | * Using a local {@link Scope}. 73 | * 74 | * @param - A callback for using the scope 75 | */ 76 | public withScope(callback: (scope: Scope) => void): void { 77 | withScope(callback) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /projects/ngx-sentry/src/lib/tokens.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from '@angular/core' 2 | import { BrowserOptions, ReportDialogOptions } from '@sentry/browser' 3 | 4 | /** 5 | * Module options. 6 | */ 7 | export interface SentryOptions { 8 | enabled: boolean 9 | sentry: BrowserOptions 10 | dialog?: true | ReportDialogOptions 11 | http?: { 12 | enabled?: boolean 13 | message?: string 14 | whitelist?: number[] 15 | blacklist?: number[] 16 | } 17 | } 18 | 19 | /** 20 | * Injection tokens. 21 | */ 22 | export const INITIALIZER = new InjectionToken('initializer') 23 | export const OPTIONS = new InjectionToken('options') 24 | -------------------------------------------------------------------------------- /projects/ngx-sentry/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../out-tsc/lib", 5 | "target": "es2015", 6 | "module": "es2015", 7 | "moduleResolution": "bundler", 8 | "declaration": true, 9 | "sourceMap": true, 10 | "inlineSources": true, 11 | "emitDecoratorMetadata": true, 12 | "experimentalDecorators": true, 13 | "importHelpers": true, 14 | "types": [], 15 | "lib": [ 16 | "dom", 17 | "es2018" 18 | ] 19 | }, 20 | "angularCompilerOptions": { 21 | "skipTemplateCodegen": true, 22 | "strictMetadataEmit": true, 23 | "fullTemplateTypeCheck": true, 24 | "strictInjectionParameters": true, 25 | "enableResourceInlining": true 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /projects/ngx-sentry/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "angularCompilerOptions": { 4 | "compilationMode": "partial" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["config:base", ":preserveSemverRanges", ":disableRateLimiting"], 4 | "assigneesFromCodeOwners": true, 5 | "labels": ["dependencies"], 6 | "packageRules": [ 7 | { 8 | "matchPackagePatterns": ["commitlint"], 9 | "groupName": "commitlint" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 |

Welcome!

3 | Angular Logo 4 |
5 | 6 |
7 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, inject } from '@angular/core' 2 | import { SentryService } from '@pascaliske/ngx-sentry' 3 | 4 | @Component({ 5 | selector: 'cmp-root', 6 | templateUrl: './app.component.html', 7 | }) 8 | export class AppComponent { 9 | private readonly sentryService: SentryService = inject(SentryService) 10 | 11 | public trigger(): void { 12 | this.sentryService.captureException(new Error('DEMO!')) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/app/app.config.ts: -------------------------------------------------------------------------------- 1 | import type { ApplicationConfig } from '@angular/core' 2 | import { provideZonelessChangeDetection } from '@angular/core' 3 | import { provideSentry } from '@pascaliske/ngx-sentry' 4 | 5 | export const appConfig: ApplicationConfig = { 6 | providers: [ 7 | provideZonelessChangeDetection(), 8 | provideSentry({ 9 | enabled: true, 10 | sentry: { 11 | dsn: 'https://your-sentry-dsn@sentry.io', 12 | }, 13 | http: { 14 | enabled: true, 15 | }, 16 | dialog: true, 17 | }), 18 | ], 19 | } 20 | -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pascaliske/ngx-sentry/b7609a77a1223314ac658e0e1034d7f651297bf2/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | } 4 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: false, 3 | } 4 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pascaliske/ngx-sentry/b7609a77a1223314ac658e0e1034d7f651297bf2/src/favicon.ico -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NgxSentryDemo 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { bootstrapApplication } from '@angular/platform-browser' 2 | import { AppComponent } from './app/app.component' 3 | import { appConfig } from './app/app.config' 4 | 5 | bootstrapApplication(AppComponent, appConfig).catch(err => { 6 | console.error(err) 7 | }) 8 | -------------------------------------------------------------------------------- /src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/app", 5 | "types": [] 6 | }, 7 | "files": ["src/main.ts"] 8 | } 9 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "esModuleInterop": true, 8 | "declaration": false, 9 | "module": "es2020", 10 | "strictNullChecks": true, 11 | "moduleResolution": "bundler", 12 | "emitDecoratorMetadata": true, 13 | "experimentalDecorators": true, 14 | "useDefineForClassFields": false, 15 | "importHelpers": true, 16 | "target": "es2022", 17 | "typeRoots": [ 18 | "node_modules/@types" 19 | ], 20 | "lib": [ 21 | "es2018", 22 | "dom" 23 | ], 24 | "paths": { 25 | "@pascaliske/ngx-sentry": [ 26 | "dist/ngx-sentry" 27 | ], 28 | "@pascaliske/ngx-sentry/*": [ 29 | "dist/ngx-sentry/*" 30 | ] 31 | } 32 | } 33 | } 34 | --------------------------------------------------------------------------------