Merge pull request #1456 from microsoft/lxiao/angular-plugin-update

update angular plugin
This commit is contained in:
Xiao Li 2021-02-05 13:31:11 -08:00 коммит произвёл GitHub
Родитель dc5808f327 fbb3508c11
Коммит 35d46aea61
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
39 изменённых файлов: 561 добавлений и 1099 удалений

68
common/config/rush/npm-shrinkwrap.json сгенерированный
Просмотреть файл

@ -51,11 +51,11 @@
}
},
"node_modules/@babel/code-frame": {
"version": "7.12.11",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
"integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz",
"integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==",
"dependencies": {
"@babel/highlight": "^7.10.4"
"@babel/highlight": "^7.12.13"
}
},
"node_modules/@babel/helper-validator-identifier": {
@ -64,11 +64,11 @@
"integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw=="
},
"node_modules/@babel/highlight": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
"integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz",
"integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==",
"dependencies": {
"@babel/helper-validator-identifier": "^7.10.4",
"@babel/helper-validator-identifier": "^7.12.11",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
}
@ -545,9 +545,9 @@
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw=="
},
"node_modules/@types/node": {
"version": "14.14.22",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.22.tgz",
"integrity": "sha512-g+f/qj/cNcqKkc3tFqlXOYjrmZA+jNBiDzbP3kH+B+otKFqAdPgVTGP1IeKRdMml/aE69as5S4FqtxAbl+LaMw=="
"version": "14.14.25",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.25.tgz",
"integrity": "sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ=="
},
"node_modules/@types/qunit": {
"version": "2.11.1",
@ -4005,9 +4005,9 @@
}
},
"node_modules/rollup": {
"version": "2.38.3",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.38.3.tgz",
"integrity": "sha512-FVx/XzR2DtCozKNDBjHJCHIgkC12rNg/ruAeoYWjLeeKfSKgwhh+lDLDhuCkuRG/fsup8py8dKBTlHdvUFX32A==",
"version": "2.38.5",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.38.5.tgz",
"integrity": "sha512-VoWt8DysFGDVRGWuHTqZzT02J0ASgjVq/hPs9QcBOGMd7B+jfTr/iqMVEyOi901rE3xq+Deq66GzIT1yt7sGwQ==",
"dependencies": {
"fsevents": "~2.3.1"
},
@ -4030,9 +4030,9 @@
}
},
"node_modules/rollup/node_modules/fsevents": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.1.tgz",
"integrity": "sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==",
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"hasInstallScript": true,
"optional": true,
"os": [
@ -5100,11 +5100,11 @@
},
"dependencies": {
"@babel/code-frame": {
"version": "7.12.11",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
"integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz",
"integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==",
"requires": {
"@babel/highlight": "^7.10.4"
"@babel/highlight": "^7.12.13"
}
},
"@babel/helper-validator-identifier": {
@ -5113,11 +5113,11 @@
"integrity": "sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw=="
},
"@babel/highlight": {
"version": "7.10.4",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz",
"integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==",
"version": "7.12.13",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.12.13.tgz",
"integrity": "sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww==",
"requires": {
"@babel/helper-validator-identifier": "^7.10.4",
"@babel/helper-validator-identifier": "^7.12.11",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
},
@ -5543,9 +5543,9 @@
"integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw=="
},
"@types/node": {
"version": "14.14.22",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.22.tgz",
"integrity": "sha512-g+f/qj/cNcqKkc3tFqlXOYjrmZA+jNBiDzbP3kH+B+otKFqAdPgVTGP1IeKRdMml/aE69as5S4FqtxAbl+LaMw=="
"version": "14.14.25",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.25.tgz",
"integrity": "sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ=="
},
"@types/qunit": {
"version": "2.11.1",
@ -8223,17 +8223,17 @@
}
},
"rollup": {
"version": "2.38.3",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.38.3.tgz",
"integrity": "sha512-FVx/XzR2DtCozKNDBjHJCHIgkC12rNg/ruAeoYWjLeeKfSKgwhh+lDLDhuCkuRG/fsup8py8dKBTlHdvUFX32A==",
"version": "2.38.5",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.38.5.tgz",
"integrity": "sha512-VoWt8DysFGDVRGWuHTqZzT02J0ASgjVq/hPs9QcBOGMd7B+jfTr/iqMVEyOi901rE3xq+Deq66GzIT1yt7sGwQ==",
"requires": {
"fsevents": "~2.3.1"
},
"dependencies": {
"fsevents": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.1.tgz",
"integrity": "sha512-YR47Eg4hChJGAB1O3yEAOkGO+rlzutoICGqGo9EZ4lKWokzZRSyIW1QmTzqjtw8MJdj9srP869CuWw/hyzSiBw==",
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"optional": true
}
}

Просмотреть файл

@ -8,6 +8,9 @@ indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.ts]
quote_type = single
[*.md]
max_line_length = off
trim_trailing_whitespace = false

Просмотреть файл

@ -11,8 +11,8 @@
/node_modules
# profiling files
chrome-profiler-events.json
speed-measure-plugin.json
chrome-profiler-events*.json
speed-measure-plugin*.json
# IDEs and editors
/.idea

Просмотреть файл

@ -8,8 +8,4 @@
!tsconfig.json
!/README.md
!/LICENSE
!dist-esm/**
!dist/**
!browser/**
!types/**
!src/**
!dist/**

Просмотреть файл

@ -8,7 +8,6 @@ Angular Plugin for the Application Insights Javascript SDK, enables the followin
> ***Note:*** Angular plugin is NOT es3 compatible
- Tracking of router changes
- Angular components usage statistics
Angular Plugin for the Application Insights Javascript SDK
@ -24,9 +23,9 @@ npm install @microsoft/applicationinsights-angularplugin-js
Set up an instance of Application Insights in the entry component in your app:
```js
import { Component, OnInit } from '@angular/core';
import { Component } from '@angular/core';
import { ApplicationInsights } from '@microsoft/applicationinsights-web';
import { AngularPlugin, AngularPluginService } from '@microsoft/applicationinsights-angularplugin-js';
import { AngularPlugin } from '@microsoft/applicationinsights-angularplugin-js';
import { Router } from '@angular/router';
@Component({
@ -34,62 +33,22 @@ import { Router } from '@angular/router';
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
private appInsights;
export class AppComponent {
constructor(
private router: Router,
private angularPluginService: AngularPluginService
private router: Router
){
var angularPlugin = new AngularPlugin();
this.angularPluginService.init(angularPlugin, this.router);
this.appInsights = new ApplicationInsights({ config: {
const appInsights = new ApplicationInsights({ config: {
instrumentationKey: 'YOUR_INSTRUMENTATION_KEY_GOES_HERE',
extensions: [angularPlugin],
extensionConfig: {
[angularPlugin.identifier]: { router: this.router }
}
} });
}
ngOnInit() {
this.appInsights.loadAppInsights();
appInsights.loadAppInsights();
}
}
```
If you need to use trackMetric method to track Angular component usage, add `AngularPluginService` as a provider in providers list in `app.module.ts` file:
```js
import { AngularPluginService } from '@microsoft/applicationinsights-angularplugin-js';
@NgModule({
...
providers: [ AngularPluginService ],
})
export class AppModule { }
```
Make the `trackMetric` call in the `ngOnDestroy` method in the component you want to track the lifetime with. When this component gets destroyed, it will trigger a trackMetric event sent with the time user stayed on this page, and the component name.
```js
import { Component, OnDestroy, HostListener } from '@angular/core';
import { AngularPluginService } from '@microsoft/applicationinsights-angularplugin-js';
@Component({
selector: 'app-test',
templateUrl: './test.component.html',
styleUrls: ['./test.component.css']
})
export class TestComponent implements OnDestroy {
constructor(private angularPluginService: AngularPluginService) {}
@HostListener('window:beforeunload')
ngOnDestroy() {
this.angularPluginService.trackMetric();
}
}
```
## Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a

Просмотреть файл

@ -1,27 +0,0 @@
# TestApp
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.1.2.
## Development server
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
## Code scaffolding
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
## Build
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
## Running unit tests
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
## Running end-to-end tests
Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
## Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).

Просмотреть файл

@ -1,120 +0,0 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"test-app": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/test-app",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": false,
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
}
]
}
}
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "test-app:build"
},
"configurations": {
"production": {
"browserTarget": "test-app:build:production"
}
}
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "test-app:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": []
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "test-app:serve"
},
"configurations": {
"production": {
"devServerTarget": "test-app:serve:production"
}
}
}
}
}},
"defaultProject": "test-app"
}

Просмотреть файл

@ -1,12 +0,0 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# You can see what browsers were selected by your queries by running:
# npx browserslist
> 0.5%
last 2 versions
Firefox ESR
not dead
not IE 9-11 # For IE 9-11 support, remove 'not'.

Просмотреть файл

@ -1,47 +0,0 @@
{
"name": "test-app",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "~8.1.2",
"@angular/common": "~8.1.2",
"@angular/compiler": "~8.1.2",
"@angular/core": "~8.1.2",
"@angular/forms": "~8.1.2",
"@angular/platform-browser": "~8.1.2",
"@angular/platform-browser-dynamic": "~8.1.2",
"@angular/router": "~8.1.2",
"@microsoft/applicationinsights-angularplugin-js": "file:../../",
"rxjs": "~6.4.0",
"zone.js": "~0.9.1"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.801.2",
"@angular/cli": "~8.1.2",
"@angular/compiler-cli": "~8.1.2",
"@angular/language-service": "~8.1.2",
"@types/node": "~8.9.4",
"@types/jasmine": "~3.3.8",
"@types/jasminewd2": "~2.0.3",
"codelyzer": "^5.0.0",
"jasmine-core": "~3.4.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~4.1.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-jasmine": "~2.0.1",
"karma-jasmine-html-reporter": "^1.4.0",
"protractor": "~5.4.0",
"ts-node": "~7.0.0",
"tslint": "~5.15.0",
"typescript": "~3.4.3"
}
}

Просмотреть файл

@ -1,64 +0,0 @@
import { AppInsightsCore, IConfiguration, ITelemetryItem, IPlugin } from '@microsoft/applicationinsights-core-js';
export class ChannelPlugin implements IPlugin {
public isFlushInvoked = false;
public isTearDownInvoked = false;
public isResumeInvoked = false;
public isPauseInvoked = false;
public identifier = 'Sender';
public priority = 1001;
constructor() {
this.processTelemetry = this._processTelemetry.bind(this);
}
public pause(): void {
this.isPauseInvoked = true;
}
public resume(): void {
this.isResumeInvoked = true;
}
public teardown(): void {
this.isTearDownInvoked = true;
}
flush(async?: boolean, callBack?: () => void): void {
this.isFlushInvoked = true;
if (callBack) {
callBack();
}
}
public processTelemetry(env: ITelemetryItem) { }
setNextPlugin(next: any) {
// no next setup
}
public initialize = (config: IConfiguration, core: AppInsightsCore, plugin: IPlugin[]) => {
}
private _processTelemetry(env: ITelemetryItem) {
}
}
export const analyticsExtension = {
initialize: (config, core, extensions) => { },
trackEvent: (event, customProperties) => { },
trackPageView: (pageView, customProperties) => { },
trackException: (exception, customProperties) => { },
trackTrace: (trace, customProperties) => { },
trackMetric: (metric, customProperties) => { },
_onerror: (exception) => { },
startTrackPage: (name) => { },
stopTrackPage: (name, properties, measurements) => { },
startTrackEvent: (name) => { },
stopTrackEvent: (name, properties, measurements) => { },
addTelemetryInitializer: (telemetryInitializer) => { },
trackPageViewPerformance: (pageViewPerformance, customProperties) => { },
processTelemetry: (env) => { },
setNextPlugin: (next) => { },
identifier: 'ApplicationInsightsAnalytics'
};

Просмотреть файл

@ -1,38 +0,0 @@
import { Component, HostListener, OnDestroy } from '@angular/core';
import { Routes } from '@angular/router';
import { AngularPluginService } from '../../../../src/AngularPluginService';
@Component({
template: `Search`
})
export class SearchComponent implements OnDestroy {
constructor(private angularPluginService: AngularPluginService){};
@HostListener('window:beforeunload')
ngOnDestroy() {
this.angularPluginService.trackMetric();
}
}
@Component({
template: `Home`
})
export class HomeComponent implements OnDestroy {
constructor(private angularPluginService: AngularPluginService){};
@HostListener('window:beforeunload')
ngOnDestroy() {
this.angularPluginService.trackMetric();
}
}
@Component({
template: `<router-outlet></router-outlet>`
})
export class AppComponent {
constructor(private angularPluginService: AngularPluginService){};
}
export const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full'},
{ path: 'home', component: HomeComponent },
{ path: 'search', component: SearchComponent }
];

Просмотреть файл

@ -1,122 +0,0 @@
import { TestBed, fakeAsync, tick } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AngularPlugin } from '@microsoft/applicationinsights-angularplugin-js';
import { AppInsightsCore, IConfiguration, DiagnosticLogger } from '@microsoft/applicationinsights-core-js';
import { IPageViewTelemetry } from '@microsoft/applicationinsights-common';
import { ChannelPlugin, analyticsExtension } from './Common';
let angularPlugin: AngularPlugin;
let core: AppInsightsCore;
let angularPluginTrackPageViewSpy;
let angularPluginTrackMetricSpy;
import { Location } from '@angular/common';
import { Router } from '@angular/router';
import { HomeComponent, SearchComponent, AppComponent, routes } from './TestComponent';
describe('Angular Plugin basic events tracking tests', () => {
let location: Location;
let router: Router;
let fixture;
function init() {
core = new AppInsightsCore();
core.logger = new DiagnosticLogger();
angularPlugin = new AngularPlugin();
fixture.componentInstance.angularPluginService.init(angularPlugin, router);
}
beforeEach(() => {
TestBed.configureTestingModule({
imports: [RouterTestingModule.withRoutes(routes)],
declarations: [HomeComponent, SearchComponent, AppComponent]
});
router = TestBed.get(Router);
location = TestBed.get(Location);
fixture = TestBed.createComponent(AppComponent);
router.initialNavigation();
});
it('navigate to "" redirects you to /home', fakeAsync(() => {
router.navigate(['']).then(() => {
tick(500);
expect(location.path()).toBe('/home');
});
}));
it('navigate to "search" takes you to /search', fakeAsync(() => {
router.navigate(['/search']).then(() => {
tick(500);
expect(location.path()).toBe('/search');
});
}));
it('Angular Plugin: router change triggers trackPageView event', fakeAsync(() => {
init();
angularPluginTrackPageViewSpy = spyOn(angularPlugin, 'trackPageView');
const channel = new ChannelPlugin();
const config: IConfiguration = {
instrumentationKey: 'instrumentation_key',
extensionConfig: {
[angularPlugin.identifier]: {
router
},
}
};
core.initialize(config, [angularPlugin, analyticsExtension, channel]);
// trackPageView is called on plugin intialize
// default route is '/'
expect(angularPluginTrackPageViewSpy).toHaveBeenCalledTimes(1);
expect(angularPluginTrackPageViewSpy).toHaveBeenCalledWith({ uri: '/' } as IPageViewTelemetry);
// Simulate navigation to different URL-addressed pages - tick is used to simulate the asynchronous passage of time for the timers in the fakeAsync zone.
// This equals to .then() and is more clear
// navigate to / - first time router navigates, this is needed here to simulate user opens up browser, this call simulates the router behavior when core gets initialized
router.navigate(['/']);
tick(500);
// navigate to /search
router.navigate(['search']);
tick(500);
expect(angularPluginTrackPageViewSpy).toHaveBeenCalledTimes(2);
expect(angularPluginTrackPageViewSpy).toHaveBeenCalledWith({ uri: '/search' } as IPageViewTelemetry);
// navigate to /home
router.navigate(['home']);
tick(500);
expect(angularPluginTrackPageViewSpy).toHaveBeenCalledTimes(3);
expect(angularPluginTrackPageViewSpy).toHaveBeenCalledWith({ uri: '/home' } as IPageViewTelemetry);
}));
it('Angular Plugin: component destroy triggers trackMetrics event', fakeAsync(() => {
init();
angularPluginTrackMetricSpy = spyOn(angularPlugin, 'trackMetric');
const channel = new ChannelPlugin();
const config: IConfiguration = {
instrumentationKey: 'instrumentation_key',
extensionConfig: {
[angularPlugin.identifier]: {
router
},
}
};
core.initialize(config, [angularPlugin, analyticsExtension, channel]);
// navigate to / - first time router navigates, home component is added
router.navigate(['/']);
tick(500);
// navigate to /search, home component is destroyed
router.navigate(['search']);
tick(500);
expect(angularPluginTrackMetricSpy).toHaveBeenCalledTimes(1);
expect(angularPluginTrackMetricSpy).toHaveBeenCalledWith({average: 0.5, name: 'Angular Component Existed Time (seconds)'}, {'Component Name': 'HomeComponent'});
// navigate to /home, search component is destroyed
router.navigate(['home']);
tick(500);
expect(angularPluginTrackMetricSpy).toHaveBeenCalledTimes(2);
expect(angularPluginTrackMetricSpy).toHaveBeenCalledWith({average: 0.5, name: 'Angular Component Existed Time (seconds)'}, {'Component Name': 'SearchComponent'});
}));
});

Просмотреть файл

@ -1,63 +0,0 @@
/**
* This file includes polyfills needed by Angular and is loaded before the app.
* You can add your own extra polyfills to this file.
*
* This file is divided into 2 sections:
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
* file.
*
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
*
* Learn more in https://angular.io/guide/browser-support
*/
/***************************************************************************************************
* BROWSER POLYFILLS
*/
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js'; // Run `npm install --save classlist.js`.
/**
* Web Animations `@angular/platform-browser/animations`
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
*/
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
/**
* By default, zone.js will patch all possible macroTask and DomEvents
* user can disable parts of macroTask/DomEvents patch by setting following flags
* because those flags need to be set before `zone.js` being loaded, and webpack
* will put import in the top of bundle, so user need to create a separate file
* in this directory (for example: zone-flags.ts), and put the following flags
* into that file, and then add the following code before importing zone.js.
* import './zone-flags.ts';
*
* The flags allowed in zone-flags.ts are listed here.
*
* The following flags will work for all browsers.
*
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
*
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
* with the following flag, it will bypass `zone.js` patch for IE/Edge
*
* (window as any).__Zone_enable_cross_context_check = true;
*
*/
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/
import 'zone.js/dist/zone'; // Included with Angular CLI.
/***************************************************************************************************
* APPLICATION IMPORTS
*/

Просмотреть файл

@ -1,14 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"include": [
"src/**/*.ts"
],
"exclude": [
"src/test.ts",
"src/**/*.spec.ts"
]
}

Просмотреть файл

@ -1,27 +0,0 @@
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"module": "esnext",
"moduleResolution": "node",
"importHelpers": false,
"noEmitHelpers": false,
"target": "es2015",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
]
},
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictInjectionParameters": true
}
}

Просмотреть файл

@ -1,18 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jasmine",
"node"
]
},
"files": [
"src/test.ts",
"src/polyfills.ts"
],
"include": [
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}

Просмотреть файл

@ -1,92 +0,0 @@
{
"extends": "tslint:recommended",
"rules": {
"array-type": false,
"arrow-parens": false,
"deprecation": {
"severity": "warning"
},
"component-class-suffix": true,
"contextual-lifecycle": true,
"directive-class-suffix": true,
"directive-selector": [
true,
"attribute",
"app",
"camelCase"
],
"component-selector": [
true,
"element",
"app",
"kebab-case"
],
"import-blacklist": [
true,
"rxjs/Rx"
],
"interface-name": false,
"max-classes-per-file": false,
"max-line-length": [
true,
140
],
"member-access": false,
"member-ordering": [
true,
{
"order": [
"static-field",
"instance-field",
"static-method",
"instance-method"
]
}
],
"no-consecutive-blank-lines": false,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-empty": false,
"no-inferrable-types": [
true,
"ignore-params"
],
"no-non-null-assertion": true,
"no-redundant-jsdoc": true,
"no-switch-case-fall-through": true,
"no-use-before-declare": true,
"no-var-requires": false,
"object-literal-key-quotes": [
true,
"as-needed"
],
"object-literal-sort-keys": false,
"ordered-imports": false,
"quotemark": [
true,
"single"
],
"trailing-comma": false,
"no-conflicting-lifecycle": true,
"no-host-metadata-property": true,
"no-input-rename": true,
"no-inputs-metadata-property": true,
"no-output-native": true,
"no-output-on-prefix": true,
"no-output-rename": true,
"no-outputs-metadata-property": true,
"template-banana-in-box": true,
"template-no-negated-async": true,
"use-lifecycle-interface": true,
"use-pipe-transform-interface": true
},
"rulesDirectory": [
"codelyzer"
]
}

Просмотреть файл

@ -0,0 +1,48 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"applicationinsights-angularplugin-js": {
"projectType": "library",
"root": "projects/applicationinsights-angularplugin-js",
"sourceRoot": "projects/applicationinsights-angularplugin-js/src",
"prefix": "lib",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:ng-packagr",
"options": {
"tsConfig": "projects/applicationinsights-angularplugin-js/tsconfig.lib.json",
"project": "projects/applicationinsights-angularplugin-js/ng-package.json"
},
"configurations": {
"production": {
"tsConfig": "projects/applicationinsights-angularplugin-js/tsconfig.lib.prod.json"
}
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"main": "projects/applicationinsights-angularplugin-js/src/test.ts",
"tsConfig": "projects/applicationinsights-angularplugin-js/tsconfig.spec.json",
"karmaConfig": "projects/applicationinsights-angularplugin-js/karma.conf.js"
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"projects/applicationinsights-angularplugin-js/tsconfig.lib.json",
"projects/applicationinsights-angularplugin-js/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
}
},
"defaultProject": "applicationinsights-angularplugin-js"
}

Просмотреть файл

@ -1,48 +1,56 @@
{
"name": "@microsoft/applicationinsights-angularplugin-js",
"version": "2.5.10",
"description": "Microsoft Application Insights Angular plugin",
"main": "dist/applicationinsights-angularplugin-js.js",
"module": "dist-esm/applicationinsights-angularplugin-js.js",
"types": "types/applicationinsights-angularplugin-js.d.ts",
"sideEffects": false,
"repository": {
"type": "git",
"url": "https://github.com/microsoft/ApplicationInsights-JS/tree/master/extensions/applicationinsights-angularplugin-js"
},
"scripts": {
"prepublishOnly": "npm install && npm run build",
"build": "npm run build:esm && npm run build:browser",
"build:esm": "tsc -p tsconfig.json",
"build:browser": "rollup -c",
"test": "cd Tests/test-app && npm install && ng test",
"lint": "tslint -p tsconfig.json"
},
"devDependencies": {
"@microsoft/applicationinsights-rollup-es3": "1.1.3",
"@microsoft/applicationinsights-properties-js": "2.5.10",
"@angular/core": "~8.1.2",
"@angular/router": "~8.1.2",
"grunt": "1.0.1",
"rollup": "^0.66.0",
"rollup-plugin-commonjs": "^9.3.4",
"rollup-plugin-node-resolve": "^3.4.0",
"rollup-plugin-replace": "^2.1.0",
"rollup-plugin-uglify": "^6.0.0",
"ts-node": "^8.3.0",
"typescript": "~3.4.3",
"rxjs": "~6.4.0",
"types": "^0.1.1",
"zone.js": "~0.9.1",
"@angular/common": "~8.1.2",
"@angular/platform-browser": "~8.1.2",
"tslint": "^5.19.0",
"tslint-config-prettier": "^1.18.0"
},
"dependencies": {
"@microsoft/applicationinsights-shims": "^1.0.3",
"@microsoft/applicationinsights-common": "2.5.10",
"@microsoft/applicationinsights-core-js": "2.5.10"
},
"license": "MIT"
"name": "@microsoft/applicationinsights-angularplugin-js",
"version": "2.5.11",
"description": "Microsoft Application Insights Angular plugin",
"main": "dist/bundles/microsoft-applicationinsights-angularplugin-js.umd.js",
"module": "dist/fesm2015/microsoft-applicationinsights-angularplugin-js.js",
"types": "dist/microsoft-applicationinsights-angularplugin-js.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/microsoft/ApplicationInsights-JS/tree/master/extensions/applicationinsights-angularplugin-js"
},
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build --prod",
"test": "ng test",
"lint": "ng lint"
},
"private": true,
"dependencies": {
"@angular/animations": "~11.0.6",
"@angular/common": "~11.0.6",
"@angular/compiler": "~11.0.6",
"@angular/core": "~11.0.6",
"@angular/forms": "~11.0.6",
"@angular/platform-browser": "~11.0.6",
"@angular/platform-browser-dynamic": "~11.0.6",
"@angular/router": "~11.0.6",
"rxjs": "~6.6.0",
"tslib": "^2.0.0",
"zone.js": "~0.10.2",
"@microsoft/applicationinsights-core-js": "2.5.11",
"@microsoft/applicationinsights-common": "2.5.11"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.1100.6",
"@angular/cli": "~11.0.6",
"@angular/compiler-cli": "~11.0.6",
"@types/jasmine": "~3.6.0",
"@types/node": "^12.11.1",
"codelyzer": "^6.0.0",
"jasmine-core": "~3.6.0",
"jasmine-spec-reporter": "~5.0.0",
"karma": "~5.1.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.0.3",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.5.0",
"ng-packagr": "^11.0.0",
"protractor": "~7.0.0",
"ts-node": "~8.3.0",
"tslint": "~6.1.0",
"typescript": "~4.0.2",
"@microsoft/applicationinsights-properties-js": "2.5.11"
}
}

Просмотреть файл

@ -0,0 +1,24 @@
# ApplicationinsightsAngularpluginJs
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 11.0.6.
## Code scaffolding
Run `ng generate component component-name --project applicationinsights-angularplugin-js` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module --project applicationinsights-angularplugin-js`.
> Note: Don't forget to add `--project applicationinsights-angularplugin-js` or else it will be added to the default project in your `angular.json` file.
## Build
Run `ng build applicationinsights-angularplugin-js` to build the project. The build artifacts will be stored in the `dist/` directory.
## Publishing
After building your library with `ng build applicationinsights-angularplugin-js`, go to the dist folder `cd dist/applicationinsights-angularplugin-js` and run `npm publish`.
## Running unit tests
Run `ng test applicationinsights-angularplugin-js` to execute the unit tests via [Karma](https://karma-runner.github.io).
## Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.

Просмотреть файл

@ -9,16 +9,28 @@ module.exports = function (config) {
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage-istanbul-reporter'),
require('karma-coverage'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
jasmine: {
// you can add configuration options for Jasmine here
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
// for example, you can disable the random execution with `random: false`
// or set a specific seed with `seed: 4321`
},
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageIstanbulReporter: {
dir: require('path').join(__dirname, './coverage/test-app'),
reports: ['html', 'lcovonly', 'text-summary'],
fixWebpackSourcePaths: true
jasmineHtmlReporter: {
suppressAll: true // removes the duplicated traces
},
coverageReporter: {
dir: require('path').join(__dirname, '../../coverage/applicationinsights-angularplugin-js'),
subdir: '.',
reporters: [
{ type: 'html' },
{ type: 'text-summary' }
]
},
reporters: ['progress', 'kjhtml'],
port: 9876,

Просмотреть файл

@ -0,0 +1,14 @@
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist",
"lib": {
"entryFile": "src/public-api.ts"
},
"whitelistedNonPeerDependencies": [
"@microsoft/applicationinsights-common",
"@microsoft/applicationinsights-core-js",
"@microsoft/applicationinsights-properties-js",
"@microsoft/applicationinsights-rollup-es3",
"@microsoft/applicationinsights-shims"
]
}

Просмотреть файл

@ -0,0 +1,16 @@
{
"name": "@microsoft/applicationinsights-angularplugin-js",
"version": "2.5.11",
"peerDependencies": {
"@angular/common": "^11.0.6",
"@angular/core": "^11.0.6"
},
"dependencies": {
"@microsoft/applicationinsights-common": "^2.5.11",
"@microsoft/applicationinsights-core-js": "^2.5.11",
"@microsoft/applicationinsights-properties-js": "^2.5.11",
"@microsoft/applicationinsights-rollup-es3": "^1.1.3",
"@microsoft/applicationinsights-shims": "^1.0.3",
"tslib": "^2.0.0"
}
}

Просмотреть файл

@ -0,0 +1,93 @@
import { Component } from '@angular/core';
import {
IConfig, IPageViewTelemetry, IAppInsights, PropertiesPluginIdentifier, Util
} from '@microsoft/applicationinsights-common';
import {
IPlugin, IConfiguration, IAppInsightsCore,
ITelemetryPlugin, BaseTelemetryPlugin, CoreUtils, ITelemetryItem, ITelemetryPluginChain,
IProcessTelemetryContext, _InternalMessageId, LoggingSeverity, getLocation
} from '@microsoft/applicationinsights-core-js';
import { Router } from '@angular/router';
// For types only
import * as properties from '@microsoft/applicationinsights-properties-js';
interface IAngularExtensionConfig {
/**
* Angular router for enabling Application Insights PageView tracking.
*/
router?: Router;
}
const NAVIGATIONEND = 'NavigationEnd';
@Component({
selector: 'lib-applicationinsights-angularplugin-js',
template: ``,
styles: []
})
// tslint:disable-next-line:component-class-suffix
export class AngularPlugin extends BaseTelemetryPlugin {
public priority = 186;
public identifier = 'AngularPlugin';
private analyticsPlugin: IAppInsights;
private propertiesPlugin: properties.PropertiesPlugin;
initialize(config: IConfiguration & IConfig, core: IAppInsightsCore, extensions: IPlugin[], pluginChain?: ITelemetryPluginChain) {
super.initialize(config, core, extensions, pluginChain);
const ctx = this._getTelCtx();
const extConfig = ctx.getExtCfg<IAngularExtensionConfig>(this.identifier, { router: null });
CoreUtils.arrForEach(extensions, ext => {
const identifier = (ext as ITelemetryPlugin).identifier;
if (identifier === 'ApplicationInsightsAnalytics') {
this.analyticsPlugin = (ext as any) as IAppInsights;
}
if (identifier === PropertiesPluginIdentifier) {
this.propertiesPlugin = (ext as any) as properties.PropertiesPlugin;
}
});
if (extConfig.router) {
let isPageInitialLoad = true;
if (isPageInitialLoad) {
const pageViewTelemetry: IPageViewTelemetry = {
uri: extConfig.router.url
};
this.trackPageView(pageViewTelemetry);
}
extConfig.router.events.subscribe(event => {
if (event.constructor.name === NAVIGATIONEND) {
// for page initial load, do not call trackPageView twice
if (isPageInitialLoad) {
isPageInitialLoad = false;
return;
}
const pageViewTelemetry: IPageViewTelemetry = { uri: extConfig.router.url };
this.trackPageView(pageViewTelemetry);
}
});
}
}
/**
* Add Part A fields to the event
* @param event The event that needs to be processed
*/
processTelemetry(event: ITelemetryItem, itemCtx?: IProcessTelemetryContext) {
this.processNext(event, itemCtx);
}
trackPageView(pageView: IPageViewTelemetry) {
if (this.analyticsPlugin) {
const location = getLocation();
if (this.propertiesPlugin && this.propertiesPlugin.context && this.propertiesPlugin.context.telemetryTrace) {
this.propertiesPlugin.context.telemetryTrace.traceID = Util.generateW3CId();
this.propertiesPlugin.context.telemetryTrace.name = location && location.pathname || '_unknown_';
}
this.analyticsPlugin.trackPageView(pageView);
} else {
this.diagLog().throwInternal(
// tslint:disable-next-line:max-line-length
LoggingSeverity.CRITICAL, _InternalMessageId.TelemetryInitializerFailed, 'Analytics plugin is not available, Angular plugin telemetry will not be sent: ');
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@
import { NgModule } from '@angular/core';
import { AngularPlugin } from './applicationinsights-angularplugin-js.component';
@NgModule({
declarations: [AngularPlugin],
imports: [
],
exports: [AngularPlugin]
})
export class ApplicationinsightsAngularpluginJsModule { }

Просмотреть файл

@ -0,0 +1,6 @@
/*
* Public API Surface of applicationinsights-angularplugin-js
*/
export * from './lib/applicationinsights-angularplugin-js.component';
export * from './lib/applicationinsights-angularplugin-js.module';

Просмотреть файл

@ -1,5 +1,6 @@
// This file is required by karma.conf.js and loads recursively all the .spec and framework files
import 'zone.js/dist/zone';
import 'zone.js/dist/zone-testing';
import { getTestBed } from '@angular/core/testing';
import {
@ -7,7 +8,12 @@ import {
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
declare const require: any;
declare const require: {
context(path: string, deep?: boolean, filter?: RegExp): {
keys(): string[];
<T>(id: string): T;
};
};
// First, initialize the Angular testing environment.
getTestBed().initTestEnvironment(

Просмотреть файл

@ -0,0 +1,25 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/lib",
"target": "es2015",
"declaration": true,
"declarationMap": true,
"inlineSources": true,
"types": [],
"lib": [
"dom",
"es2018"
]
},
"angularCompilerOptions": {
"skipTemplateCodegen": true,
"strictMetadataEmit": true,
"enableResourceInlining": true
},
"exclude": [
"src/test.ts",
"**/*.spec.ts"
]
}

Просмотреть файл

@ -0,0 +1,10 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.lib.json",
"compilerOptions": {
"declarationMap": false
},
"angularCompilerOptions": {
"enableIvy": false
}
}

Просмотреть файл

@ -0,0 +1,17 @@
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/spec",
"types": [
"jasmine"
]
},
"files": [
"src/test.ts"
],
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
}

Просмотреть файл

@ -0,0 +1,17 @@
{
"extends": "../../tslint.json",
"rules": {
"directive-selector": [
true,
"attribute",
"lib",
"camelCase"
],
"component-selector": [
true,
"element",
"lib",
"kebab-case"
]
}
}

Просмотреть файл

@ -1,122 +0,0 @@
import nodeResolve from "rollup-plugin-node-resolve";
import {uglify} from "rollup-plugin-uglify";
import replace from "rollup-plugin-replace";
import commonjs from "rollup-plugin-commonjs";
import { es3Poly, es3Check, importCheck } from "@microsoft/applicationinsights-rollup-es3";
const version = require("./package.json").version;
const outputName = "applicationinsights-angularplugin-js";
const banner = [
"/*!",
` * Application Insights JavaScript SDK - Angular Plugin, ${version}`,
" * Copyright (c) Microsoft and contributors. All rights reserved.",
" */"
].join("\n");
const browserRollupConfigFactory = isProduction => {
const browserRollupConfig = {
input: `dist-esm/${outputName}.js`,
output: {
file: `browser/${outputName}.js`,
banner: banner,
format: "umd",
name: "Microsoft.ApplicationInsights",
extend: true,
freeze: false,
sourcemap: true
},
plugins: [
replace({
delimiters: ["", ""],
values: {
"// Copyright (c) Microsoft Corporation. All rights reserved.": "",
"// Licensed under the MIT License.": ""
}
}),
importCheck({ exclude: [ "applicationinsights-angularplugin-js" ] }),
nodeResolve({
browser: false,
preferBuiltins: false
}),
commonjs({
include: 'node_modules/**'
}),
]
};
if (isProduction) {
browserRollupConfig.output.file = `browser/${outputName}.min.js`;
browserRollupConfig.plugins.push(
uglify({
ie8: true,
toplevel: true,
compress: {
passes:3,
unsafe: true
},
output: {
preamble: banner,
webkit:true
}
})
);
}
return browserRollupConfig;
};
const nodeUmdRollupConfigFactory = (isProduction) => {
const nodeRollupConfig = {
input: `dist-esm/${outputName}.js`,
output: {
file: `dist/${outputName}.js`,
banner: banner,
format: "umd",
name: "Microsoft.ApplicationInsights",
extend: true,
freeze: false,
sourcemap: true
},
plugins: [
replace({
delimiters: ["", ""],
values: {
"// Copyright (c) Microsoft Corporation. All rights reserved.": "",
"// Licensed under the MIT License.": ""
}
}),
importCheck({ exclude: [ "applicationinsights-angularplugin-js" ] }),
nodeResolve({ preferBuiltins: true }),
commonjs({
include: 'node_modules/**'
}),
]
};
if (isProduction) {
nodeRollupConfig.output.file = `dist/${outputName}.min.js`;
nodeRollupConfig.plugins.push(
uglify({
ie8: true,
toplevel: true,
compress: {
passes:3,
unsafe: true
},
output: {
preamble: banner,
webkit:true
}
})
);
}
return nodeRollupConfig;
};
export default [
browserRollupConfigFactory(true),
browserRollupConfigFactory(false),
nodeUmdRollupConfigFactory(true),
nodeUmdRollupConfigFactory(false)
];

Просмотреть файл

@ -1,92 +0,0 @@
/**
* Angular.ts
* @copyright Microsoft 2019
*/
import {
IConfig, IPageViewTelemetry, IMetricTelemetry, IAppInsights, PropertiesPluginIdentifier, Util
} from "@microsoft/applicationinsights-common";
import {
IPlugin, IConfiguration, IAppInsightsCore,
ITelemetryPlugin, BaseTelemetryPlugin, CoreUtils, ITelemetryItem, ITelemetryPluginChain,
IProcessTelemetryContext, _InternalMessageId, LoggingSeverity, ICustomProperties, getLocation
} from "@microsoft/applicationinsights-core-js";
import { IAngularExtensionConfig } from './Interfaces/IAngularExtensionConfig';
// For types only
import * as properties from "@microsoft/applicationinsights-properties-js";
const NAVIGATIONEND = "NavigationEnd";
export default class AngularPlugin extends BaseTelemetryPlugin {
public priority = 186;
public identifier = 'AngularPlugin';
private _analyticsPlugin: IAppInsights;
private _propertiesPlugin: properties.PropertiesPlugin;
initialize(config: IConfiguration & IConfig, core: IAppInsightsCore, extensions: IPlugin[], pluginChain?: ITelemetryPluginChain) {
super.initialize(config, core, extensions, pluginChain);
let ctx = this._getTelCtx();
let extConfig = ctx.getExtCfg<IAngularExtensionConfig>(this.identifier, { router: null });
CoreUtils.arrForEach(extensions, ext => {
const identifier = (ext as ITelemetryPlugin).identifier;
if (identifier === 'ApplicationInsightsAnalytics') {
this._analyticsPlugin = (ext as any) as IAppInsights;
}
if (identifier === PropertiesPluginIdentifier) {
this._propertiesPlugin = (ext as any) as properties.PropertiesPlugin;
}
});
if (extConfig.router) {
let isPageInitialLoad = true;
if (isPageInitialLoad) {
const pageViewTelemetry: IPageViewTelemetry = {
uri: extConfig.router.url
};
this.trackPageView(pageViewTelemetry);
}
extConfig.router.events.subscribe(event => {
if (event.constructor.name === NAVIGATIONEND) {
// for page initial load, do not call trackPageView twice
if (isPageInitialLoad) {
isPageInitialLoad = false;
return;
}
const pageViewTelemetry: IPageViewTelemetry = { uri: extConfig.router.url };
this.trackPageView(pageViewTelemetry);
}
});
}
}
/**
* Add Part A fields to the event
* @param event The event that needs to be processed
*/
processTelemetry(event: ITelemetryItem, itemCtx?: IProcessTelemetryContext) {
this.processNext(event, itemCtx);
}
trackMetric(metric: IMetricTelemetry, customProperties: ICustomProperties) {
if (this._analyticsPlugin) {
this._analyticsPlugin.trackMetric(metric, customProperties);
} else {
this.diagLog().throwInternal(
LoggingSeverity.CRITICAL, _InternalMessageId.TelemetryInitializerFailed, "Analytics plugin is not available, Angular plugin telemetry will not be sent: ");
}
}
trackPageView(pageView: IPageViewTelemetry) {
if (this._analyticsPlugin) {
const location = getLocation();
if (this._propertiesPlugin && this._propertiesPlugin.context && this._propertiesPlugin.context.telemetryTrace) {
this._propertiesPlugin.context.telemetryTrace.traceID = Util.generateW3CId();
this._propertiesPlugin.context.telemetryTrace.name = location && location.pathname || "_unknown_";
}
this._analyticsPlugin.trackPageView(pageView);
} else {
this.diagLog().throwInternal(
LoggingSeverity.CRITICAL, _InternalMessageId.TelemetryInitializerFailed, "Analytics plugin is not available, Angular plugin telemetry will not be sent: ");
}
}
}

Просмотреть файл

@ -1,54 +0,0 @@
import { Injectable } from '@angular/core';
import { Router, ResolveEnd } from '@angular/router';
import AngularPlugin from './AngularPlugin';
import { IMetricTelemetry } from '@microsoft/applicationinsights-common';
import { CoreUtils } from "@microsoft/applicationinsights-core-js";
const RESOLVEEND = "ResolveEnd";
@Injectable({
providedIn: 'root'
})
export class AngularPluginService {
private _prevMountTimestamp: number = 0;
private _mountTimestamp: number = 0;
private _prevComponentName: string ='';
private _componentName: string = '';
private angularPlugin: AngularPlugin;
private router: Router;
// "router: any" to avoid build error - Types have separate declarations of a private property 'rootComponentType'.
init(angularPlugin: AngularPlugin, router: any): void {
this.angularPlugin = angularPlugin;
this.router = router;
this.router.events.subscribe((event) => {
if (event.constructor.name === RESOLVEEND) {
const resolveEndEvent = event as ResolveEnd;
this._prevMountTimestamp = this._mountTimestamp;
this._mountTimestamp = CoreUtils.dateNow();
this._prevComponentName = this._componentName;
this._componentName = resolveEndEvent.state.root.firstChild.routeConfig.component && resolveEndEvent.state.root.firstChild.routeConfig.component.name || '';
}
});
}
trackMetric() {
if (this._mountTimestamp === 0) {
throw new Error('AngularPluginService: mountTimestamp is not initialized.');
}
// for the case when user opens up the page and close tab without going to any other pages
if (this._prevMountTimestamp === 0 && this._prevComponentName === '') {
this._prevMountTimestamp = this._mountTimestamp;
this._prevComponentName = this._componentName;
}
const componentLifeTime = ( CoreUtils.dateNow() - this._prevMountTimestamp ) / 1000;
const metricData: IMetricTelemetry = {
average: componentLifeTime,
name: 'Angular Component Existed Time (seconds)'
};
const additionalProperties: { [key: string]: any } = { 'Component Name': this._prevComponentName };
this.angularPlugin.trackMetric(metricData, additionalProperties);
}
}

Просмотреть файл

@ -1,17 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import { Router } from '@angular/router';
/**
* Settings to initialize a AngularAI instance.
*/
export interface IAngularExtensionConfig {
/**
* Angular router for enabling Application Insights PageView tracking.
*
* @type {Router}
* @memberof IAngularAISettings
*/
router?: Router
}

Просмотреть файл

@ -1,9 +0,0 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
import '@microsoft/applicationinsights-shims';
import AngularPlugin from "./AngularPlugin";
import { AngularPluginService } from "./AngularPluginService";
import { IAngularExtensionConfig } from "./Interfaces/IAngularExtensionConfig";
export { AngularPlugin, AngularPluginService, IAngularExtensionConfig };

Просмотреть файл

@ -1,26 +1,25 @@
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "src",
"module": "es6",
"outDir": "dist-esm",
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": true,
"declarationDir": "./types",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"target": "es5",
"rootDir": "./src",
"moduleResolution": "node",
"importHelpers": true,
"target": "es2015",
"module": "es2020",
"lib": [
"es2017",
"es2018",
"dom"
]
},
"include": [
"./src/*.ts"
],
"exclude": [
"node_modules"
]
],
"paths": {
"applicationinsights-angularplugin-js": [
"dist/applicationinsights-angularplugin-js/applicationinsights-angularplugin-js",
"dist/applicationinsights-angularplugin-js"
]
}
}
}

Просмотреть файл

@ -1,5 +1,140 @@
{
"extends": [
"../../tslint-base.json"
]
"extends": "tslint:recommended",
"rulesDirectory": [
"codelyzer"
],
"rules": {
"align": {
"options": [
"parameters",
"statements"
]
},
"array-type": false,
"arrow-return-shorthand": true,
"curly": true,
"deprecation": {
"severity": "warning"
},
"eofline": true,
"import-blacklist": [
true,
"rxjs/Rx"
],
"import-spacing": true,
"indent": {
"options": [
"spaces"
]
},
"max-classes-per-file": false,
"max-line-length": [
true,
140
],
"member-ordering": [
true,
{
"order": [
"static-field",
"instance-field",
"static-method",
"instance-method"
]
}
],
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-empty": false,
"no-inferrable-types": [
true,
"ignore-params"
],
"no-non-null-assertion": true,
"no-redundant-jsdoc": true,
"no-switch-case-fall-through": true,
"no-var-requires": false,
"object-literal-key-quotes": [
true,
"as-needed"
],
"quotemark": [
true,
"single"
],
"semicolon": {
"options": [
"always"
]
},
"space-before-function-paren": {
"options": {
"anonymous": "never",
"asyncArrow": "always",
"constructor": "never",
"method": "never",
"named": "never"
}
},
"typedef": [
true,
"call-signature"
],
"typedef-whitespace": {
"options": [
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
},
{
"call-signature": "onespace",
"index-signature": "onespace",
"parameter": "onespace",
"property-declaration": "onespace",
"variable-declaration": "onespace"
}
]
},
"variable-name": {
"options": [
"ban-keywords",
"check-format",
"allow-pascal-case"
]
},
"whitespace": {
"options": [
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type",
"check-typecast"
]
},
"component-class-suffix": true,
"contextual-lifecycle": true,
"directive-class-suffix": true,
"no-conflicting-lifecycle": true,
"no-host-metadata-property": true,
"no-input-rename": true,
"no-inputs-metadata-property": true,
"no-output-native": true,
"no-output-on-prefix": true,
"no-output-rename": true,
"no-outputs-metadata-property": true,
"template-banana-in-box": true,
"template-no-negated-async": true,
"use-lifecycle-interface": true,
"use-pipe-transform-interface": true
}
}