Coder Social home page Coder Social logo

trilonio / angular-application-insights Goto Github PK

View Code? Open in Web Editor NEW
135.0 11.0 38.0 2.02 MB

Angular & Azure Application Insights module - Find out performance and usage of your app by connecting Microsoft Azure Application insights with your Angular application by @TrilonIO

Home Page: https://www.trilon.io

License: MIT License

TypeScript 100.00%
ng-application-insights azure microsofts-application-insights application-insights angular angular2 angular5 trilon

angular-application-insights's Introduction

Angular Azure Application Insights implementation

Connect your Angular client-side to Microsofts Application Insights with this easy-to-use Module

Application Insights is an extensible Application Performance Management (APM) service for web developers on multiple platforms. Use it to monitor your live web application. It will automatically detect performance anomalies. It includes powerful analytics tools to help you diagnose issues and to understand what users actually do with your app.

npm Minzipped Size NPM Downloads MIT License


Trilon.io - Angular Universal, NestJS, JavaScript Application Consulting Development and Training

Made with ❤️ by Trilon.io


Installation

Install & save the library to your package.json:

$ npm i -S @markpieszak/ng-application-insights

# yarn

$ yarn add @markpieszak/ng-application-insights

AppModule Setup

Now add ApplicationInsightsModule to your Angular Root AppModule:

// 1) Import the Application Insights module and the service provider
import { ApplicationInsightsModule, AppInsightsService } from '@markpieszak/ng-application-insights';

@NgModule({
  imports: [
    // 2) Add the Module to your imports
    ApplicationInsightsModule.forRoot({
      instrumentationKey: 'Your-Application-Insights-instrumentationKey'
    })
  ],
  providers: [ 
     // 3) Add AppInsightsService to your providers list
     AppInsightsService
  ]
})
export class YourRootModule { }

What if you don't know your instrumentationKey right away?

// Use instrumentationKeySetLater
ApplicationInsightsModule.forRoot({
  instrumentationKeySetLater: true // <--
})

// Then later in your Application somewhere
constructor(
  private appInsightsService: AppInsightsService
) {
  appInsightsService.config = {
    instrumentationKey: __env.APPINSIGHTS_INSTRUMENTATIONKEY // <-- set it later sometime
  }
  // then make sure to initialize and start-up app insights
  appInsightsService.init();
}

Usage

Through out your application you can now use the AppInsightsService class to fire off AppInsights functionality.

import { AppInsightsService } from '@markpieszak/ng-application-insights';

export class ShoppingCartComponent {
  public cart: [];
  constructor(private appInsightsService: AppInsightsService) {}

  saveCart(user) {
    // MOCK Example of sending a trackEvent()
    // Saving some sample user & cart product data
    this.appInsightsService.trackEvent('ShoppingCart Saved', { 'user': user.id, 'cart': cart.id });
  }
}

Usage with Aspnetcore-Angular2-Universal repo or JavaScriptServices ( apps w/ Server-side rendering )

ie: https://github.com/TrilonIO/aspnetcore-angular-universal

First, make sure you are only importing the library & the server within the browser-app.module NgModule (do not share it within a common one, as the server isn't able to use this library during it's server-renders).

Secondly, make sure you are calling the injector to get AppInsightsService during ngOnInit:

export class HomeComponent implements OnInit {

  private AIService: AppInsightsService;
  private isBrowser: boolean;

  constructor(@Inject(PLATFORM_ID) private platformId, private injector: Injector) {
    this.isBrowser = isPlatformBrowser(this.platformId);
  }

  ngOnInit() { // <-- 
    if (this.isBrowser) { // <-- only run if isBrowser
      this.AIService = <AppInsightsService>this.injector.get(AppInsightsService); // <-- using the Injector, get the Service
      this.AIService.trackEvent('Testing', { 'user': 'me' });
    } 
  }
}

API

You can see a list of the API here: https://github.com/Microsoft/ApplicationInsights-JS/blob/master/API-reference.md#class-appinsights

AppInsightsService.trackEvent()
AppInsightsService.startTrackEvent()
AppInsightsService.stopTrackEvent()
AppInsightsService.trackPageView()
AppInsightsService.startTrackPage()
AppInsightsService.stopTrackPage()
AppInsightsService.trackMetric()
AppInsightsService.trackException()
AppInsightsService.trackTrace()
AppInsightsService.trackDependency()
AppInsightsService.flush()
AppInsightsService.setAuthenticatedUserContext()
AppInsightsService.clearAuthenticatedUserContext()

How to Contribute?

ng-Application-Insights Development

To generate all *.js, *.js.map and *.d.ts files:

npm run build

To lint all *.ts files:

npm run lint

License

MIT License

Copyright (c) 2016-2022 Mark Pieszak

Twitter Follow


Trilon - JavaScript, ASP.NET, Node, NestJS - Consulting | Training | Development

Check out Trilon.io for more info!

Contact us at [email protected], and let's talk about your projects needs.

Trilon.io - Angular Universal, NestJS, JavaScript Application Consulting Development and Training

Follow Trilon online

Twitter: @Trilon_io

angular-application-insights's People

Contributors

alisd23 avatar andrelmp avatar andreybespamyatnov avatar anthonymackinnon avatar dependabot[bot] avatar dfederm avatar gustavoamerico avatar inyutin-maxim avatar jycouet avatar kiseln avatar markpieszak avatar viperguynaz avatar worldspawn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

angular-application-insights's Issues

Can't use with JavaScriptServices app

I'm sure the 'issue' here is the end user, but unsure where I'm going wrong
Using the https://github.com/aspnet/JavaScriptServices starter

Running Angular 4.1.2 with 2.0.0 version of angular-application-insights

This is my app.module.client.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { sharedConfig } from './app.module.shared';
import { SharedService } from './services/shared.service';
import { ApplicationInsightsModule, AppInsightsService } from '@markpieszak/ng-application-insights';

@NgModule({
    bootstrap: sharedConfig.bootstrap,
    declarations: sharedConfig.declarations,
    imports: [
        BrowserModule,
        FormsModule,
        HttpModule,
        ApplicationInsightsModule.forRoot({
            instrumentationKey: 'key-removed-for-github'
        }),
        ...sharedConfig.imports
    ],
    providers: [
        { provide: 'ORIGIN_URL', useValue: location.origin }, SharedService, AppInsightsService
    ]
})
export class AppModule {
}

And this is the console error I get in Chrome

Angular application insights Error [downloadAndSetup]:  TypeError: applicationinsights_js_1.AppInsights.downloadAndSetup is not a function
    at AppInsightsService.init (main-client.js:1481)
    at new ApplicationInsightsModule (main-client.js:1281)
    at AppModuleInjector.createInternal (ng:///AppModule/module.ngfactory.js:262)
    at AppModuleInjector.NgModuleInjector.create (vendor.js:14073)
    at NgModuleFactory.create (vendor.js:14046)
    at vendor.js:15287
    at ZoneDelegate.invoke (vendor.js:83283)
    at Object.onInvoke (vendor.js:14664)
    at ZoneDelegate.invoke (vendor.js:83282)
    at Zone.run (vendor.js:83043)

Any ideas?

Cannot find type definition file for 'applicationinsights-js'

Hey Mark,

Thank you for the work you do.

I would like to post a new bug that has appeared recently, in the latest version of the library (5.0.4)

Type: Bug
Environment:

  1. NodeJS - 8.9.0
  2. npm - 5.5.1
  3. Angular - ^6.1.6
  4. Angular CLI - ^6.1.5

Steps to recreate:

  1. Create a new project on Angular 6
  2. Include ng-application-insights library following the instructions
  3. Run ng serve
  4. Check the console
Date: 2018-09-17T16:20:02.648Z
Hash: 49ac821e4e4d98eadfa2
Time: 15821ms
chunk {main} main.js, main.js.map (main) 1.88 kB [initial] [rendered]
chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 660 bytes [initial] [rendered]
chunk {runtime} runtime.js, runtime.js.map (runtime) 5.22 kB [entry] [rendered]
chunk {styles} styles.js, styles.js.map (styles) 625 kB [initial] [rendered]
chunk {vendor} vendor.js, vendor.js.map (vendor) 325 kB [initial] [rendered]

ERROR in node_modules/@markpieszak/ng-application-insights/dist/src/app-insight.service.d.ts(1,23): error TS2688: Cannot find type definition file for 'applicationinsights-js'.
node_modules/@markpieszak/ng-application-insights/dist/src/app-insight.service.d.ts(3,23): error TS2503: Cannot find namespace 'Microsoft'.
node_modules/@markpieszak/ng-application-insights/dist/src/app-insight.service.d.ts(4,51): error TS2503: Cannot find namespace 'Microsoft'.
node_modules/@markpieszak/ng-application-insights/dist/src/app-insight.service.d.ts(43,14): error TS2503: Cannot find namespace 'Microsoft'.
node_modules/@markpieszak/ng-application-insights/dist/src/app-insight.service.d.ts(76,24): error TS2503: Cannot find namespace 'AI'.
node_modules/@markpieszak/ng-application-insights/dist/src/app-insight.service.d.ts(79,24): error TS2503: Cannot find namespace 'AI'.

Example with webpack integration

Hi

I tried to include this library in an asp.net core Angular JavascriptServices application and have the hardest time to get it up and running. Do you have an example how it does need to be configured? I installed the package and change my root module but I am not sure what else needs to be done.

Thank you in advance!
Torsten

Run time error when using an AoT build

I'm using Angular 4.0.1, Angular-CLI 1.0.0, and ng-application-insights 1.0.0

Everything works perfectly when I run a debug build. However, once I add the --aot flag I receive 2 compile time warnings and a run time error.

Please let me know if you need more information.

Compile time warnings:

WARNING in ./~/@markpieszak/ng-application-insights/~/@angular/router/src/private_import_core.js 9:40-41 "export '__core_private__' (imported as 'r') was not found in '@angular/core'

WARNING in ./~/@markpieszak/ng-application-insights/~/@angular/router/src/private_import_core.js 10:43-44 "export '__core_private__' (imported as 'r') was not found in '@angular/core'

Run time error:

Uncaught TypeError: Cannot read property 'isPromise' of undefined
    at Object.<anonymous> (http://localhost:4200/vendor.bundle.js:66581:97)
    at __webpack_require__ (http://localhost:4200/inline.bundle.js:53:30)
    at Object.<anonymous> (http://localhost:4200/vendor.bundle.js:41327:79)
    at __webpack_require__ (http://localhost:4200/inline.bundle.js:53:30)
    at Object.<anonymous> (http://localhost:4200/vendor.bundle.js:55237:76)
    at __webpack_require__ (http://localhost:4200/inline.bundle.js:53:30)
    at Object.<anonymous> (http://localhost:4200/vendor.bundle.js:65278:80)
    at __webpack_require__ (http://localhost:4200/inline.bundle.js:53:30)
    at Object.RouterOutletMap.registerOutlet.outlet._outlets.(anonymous function) (http://localhost:4200/vendor.bundle.js:67022:76)
    at __webpack_require__ (http://localhost:4200/inline.bundle.js:53:30)
    at Object.389 (http://localhost:4200/main.bundle.js:3675:135)
    at __webpack_require__ (http://localhost:4200/inline.bundle.js:53:30)
    at Object.351 (http://localhost:4200/main.bundle.js:390:88)
    at __webpack_require__ (http://localhost:4200/inline.bundle.js:53:30)
    at Object.894 (http://localhost:4200/main.bundle.js:10298:18)

Here is the relevant part of my app.module file:

import { ApplicationInsightsModule, AppInsightsService } from '@markpieszak/ng-application-insights';
@NgModule({
  imports: [
    ...
    ApplicationInsightsModule.forRoot({ instrumentationKey: 'My-Key' })
  ],
   ...

  providers: [
     ...
    AppInsightsService,
   ...
  ]

Here is the relevant part of my component:

import { AppInsightsService } from '@markpieszak/ng-application-insights';
...

constructor(
   ...
   private appInsightsService: AppInsightsService
) {}

...
doSomething() {
     this.appInsightsService.trackEvent('WelcomePage')

NavigationCancel/NavigationError events do not call stopTrackPage

Currently, the service starts tracking a page on a NavigationStart event, and stops tracking a page on NavigationEnd only.

The service should also stop tracking a page on the following events:

  • NavigationCancel: An event triggered when navigation is canceled. This is due to a Route Guard returning false during navigation.
  • NavigationError: An event triggered when navigation fails due to an unexpected error.

Link for Angular routing events: https://angular.io/guide/router#router-events

Missing properties on config

There are some properties missing on component config. Those properties already exists on applicationinsights-js

  appId?: string;
  correlationHeaderExcludedDomains?: string[];
  enableCorsCorrelation?: boolean;
  isBeaconApiDisabled?: boolean;
  isBrowserLinkTrackingEnabled?: boolean;

all those are defined in Microsoft.ApplicationInsights.IConfig

Unmet peer dependency

The new version (2.2.0) breaks my npm dependencies. It depends on 4.1.1 angular packages while it probably should depend on all 4.x packages. I'm running Angular 4.2.5. Version 2.0.0 works fine so I'm using it until this gets fixed.

No provider for Router! Angular CLI 1.3.2

I have just created a new empty project using the current Angular CLI (1.3.2) and the current angular-application-insights (2.3.1) and get a "No provider for Router!" error.

zone.js:661 Unhandled Promise rejection: No provider for Router! ; Zone: <root> ; Task: Promise.then ; Value: Error: No provider for Router!
    at injectionError (core.es5.js:1169)
    at noProviderError (core.es5.js:1207)
    at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_._throwOrNull (core.es5.js:2649)
    at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_._getByKeyDefault (core.es5.js:2688)
    at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_._getByKey (core.es5.js:2620)
    at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_.get (core.es5.js:2489)
    at resolveNgModuleDep (core.es5.js:9481)
    at _createClass (core.es5.js:9524)
    at _createProviderInstance$1 (core.es5.js:9492)
    at initNgModule (core.es5.js:9446) Error: No provider for Router!
    at injectionError (http://localhost:4200/vendor.bundle.js:47653:90)
    at noProviderError (http://localhost:4200/vendor.bundle.js:47691:12)
    at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_._throwOrNull (http://localhost:4200/vendor.bundle.js:49133:19)
    at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_._getByKeyDefault (http://localhost:4200/vendor.bundle.js:49172:25)
    at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_._getByKey (http://localhost:4200/vendor.bundle.js:49104:25)
    at ReflectiveInjector_.webpackJsonp.../../../core/@angular/core.es5.js.ReflectiveInjector_.get (http://localhost:4200/vendor.bundle.js:48973:21)
    at resolveNgModuleDep (http://localhost:4200/vendor.bundle.js:55965:25)
    at _createClass (http://localhost:4200/vendor.bundle.js:56008:65)
    at _createProviderInstance$1 (http://localhost:4200/vendor.bundle.js:55976:26)
    at initNgModule (http://localhost:4200/vendor.bundle.js:55930:13)

npm list --depth=0

package.json

{
  "name": "ngcli",
  "version": "0.0.0",
  "license": "MIT",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^4.2.4",
    "@angular/common": "^4.2.4",
    "@angular/compiler": "^4.2.4",
    "@angular/core": "^4.2.4",
    "@angular/forms": "^4.2.4",
    "@angular/http": "^4.2.4",
    "@angular/platform-browser": "^4.2.4",
    "@angular/platform-browser-dynamic": "^4.2.4",
    "@angular/router": "^4.2.4",
    "@markpieszak/ng-application-insights": "^2.3.1",
    "core-js": "^2.4.1",
    "rxjs": "^5.4.2",
    "zone.js": "^0.8.14"
  },
  "devDependencies": {
    "@angular/cli": "1.3.2",
    "@angular/compiler-cli": "^4.2.4",
    "@angular/language-service": "^4.2.4",
    "@types/jasmine": "~2.5.53",
    "@types/jasminewd2": "~2.0.2",
    "@types/node": "~6.0.60",
    "codelyzer": "~3.1.1",
    "jasmine-core": "~2.6.2",
    "jasmine-spec-reporter": "~4.1.0",
    "karma": "~1.7.0",
    "karma-chrome-launcher": "~2.1.1",
    "karma-cli": "~1.0.1",
    "karma-coverage-istanbul-reporter": "^1.2.1",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.1.2",
    "ts-node": "~3.2.0",
    "tslint": "~5.3.2",
    "typescript": "~2.3.3"
  }
}

Cannot find namespace 'Microsoft'.

Thanks for your hard work!

I've hit a compilation error and I don't know how to solve it. Can you take a look at this for me?
I'm using Angular 4.0.1, Angular-CLI 1.0.0, and your module @markpieszak/ng-application-insights 1.0.0-rc.1

Please let me know if you need more information.

ERROR in c:/master/node_modules/@markpieszak/ng-application-insights/dist/src/app-insight.service.d.ts (4,23): Cannot find namespace 'Microsoft'.
c:/master/node_modules/@markpieszak/ng-application-insights/dist/src/app-insight.service.d.ts (5,51): Cannot find namespace 'Microsoft'.
c:/master/node_modules/@markpieszak/ng-application-insights/dist/src/app-insight.service.d.ts (37,14): Cannot find namespace 'Microsoft'.
c:/master/node_modules/@markpieszak/ng-application-insights/dist/src/app-insight.service.d.ts (39,13): Cannot find namespace 'Microsoft'.
c:/master/node_modules/@markpieszak/ng-application-insights/dist/src/app-insight.service.d.ts (70,24): Cannot find namespace 'AI'.
c:/master/node_modules/@markpieszak/ng-application-insights/dist/src/app-insight.service.d.ts (1,1): Cannot find type definition file for 'applicationinsights-js'.

Here is the relevant part of my app.module file:

import { ApplicationInsightsModule, AppInsightsService } from '@markpieszak/ng-application-insights';
@NgModule({
  imports: [
    ...
    ApplicationInsightsModule.forRoot({ instrumentationKey: 'My-Key' })
  ],
   ...

  providers: [
     ...
    AppInsightsService,
   ...
  ]

Here is the relevant part of my component:

import { AppInsightsService } from '@markpieszak/ng-application-insights';
...

constructor(
   ...
   private appInsightsService: AppInsightsService) {}

...
doSomething() {
     this.appInsightsService.trackPageView('WelcomePage')
}

[AppInsightsService -> Router]: NullInjectorError: No provider for Router! (Angular 6)

I am currently updating my insights service to angular 6 and after the update when i try to run ng serve i get the message

Error: StaticInjectorError(InsightsModule)[AppInsightsService -> Router]: 
  StaticInjectorError(Platform: core)[AppInsightsService -> Router]: 
    NullInjectorError: No provider for Router!
    at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (core.js:979)
    at resolveToken (core.js:1232)
    at tryResolveToken (core.js:1182)
    at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:1077)
    at resolveToken (core.js:1232)
    at tryResolveToken (core.js:1182)
    at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:1077)
    at resolveNgModuleDep (core.js:9217)
    at _createClass (core.js:9264)
    at _createProviderInstance$1 (core.js:9234)

I'm not sure on what to do... everything was working fine with angular 5.2

Multiple imports

Hi,

So I wanted to define a module (ModuleB) that imports (among) other things appinsightsmodule and then have my app module import that. My lazy loaded modules also import the same module.

Now ModuleB implements forRoot to stop a instance being made of every service for each lazy module. If I import AppInsightsModule here I really should be getting these errors 'ApplicationInsightsModule is already loaded. Import it in the AppModule only'

Rather the service instance that is passed to the Module should be checked to see if its already initialised or simply assume that it is if there is a parent module.

I wrote my own module to import and it seems to be working fine, though not a lot of testing has happened yet.

Note it provides the AppInsightsService in the forRoot.

@NgModule({
  imports: [ CommonModule ],
  declarations: [],
  exports: [],
  providers: [ AppInsightsService ]
})
export class ApplicationInsightsModule {

  constructor (
    @Optional() @SkipSelf() parentModule: ApplicationInsightsModule,
    appInsightsService: AppInsightsService
  ) {
    if (!parentModule) {
      appInsightsService.init();
      // throw new Error(
      //   'ApplicationInsightsModule is already loaded. Import it in the AppModule only');
    }


  }

  static forRoot(config: AppInsightsConfig): ModuleWithProviders {
    return {
      ngModule: ApplicationInsightsModule,
      providers: [
        { provide: AppInsightsConfig, useValue: config },
        AppInsightsService
      ]
    };
  }
}

My understanding of forRoot is not great but I think that because you prevent it from being imported more than once its kind of redundant to implment forRoot at all

AI is not defined

When trying to set the severity level of a call to trackTrace, I get the following runtime error:

ReferenceError: AI is not defined

The call looks like this:

this.applicationInsights.trackTrace(message, properties, AI.SeverityLevel.Information);

I've tried several imports to resolve this reference but can't seem to find the right one. Any thoughts?

instrumentationKey set later

Hi,

I would like to know if it's possible to set the instrumentationKey later and not in @NgModule?

ApplicationInsightsModule.forRoot({
    instrumentationKey: 'INSERT_instrumentationKey_HERE'
})

(and not having the log: "An instrumentationKey value is required to initialize AppInsightsService")

Because depending on my environement I would like to set different "instrumentationKey".

Thank you

npm dependency warning

I've just upgraded to angular 7.0.4 and 6.0.1 and got this npm warning. I have this in my package file

"@markpieszak/ng-application-insights": "^6.0.1"
"@angular/router": "^7.0.4",

this is the warning

npm WARN @markpieszak/[email protected] requires a peer of @angular/router@^6.0.0 but none is installed. You must install peer dependencies yourself.

Rxjs Pipeable operators

I have started seeing the following screen shot.

screen shot 2018-02-06 at 2 00 54 pm

Looking at the code in Chrome Dev Tools it looks like the rxjs/add/operator/filter is not getting added to my bundle which means that filter is not available on the this.router.events subject.

I have a PR to follow that will update the rxjs dependency to ^5.5.5 and switches to using the pipeable version of filter.

** Note ** - I'm using Angular & Angular-cli master so I didn't dig too deep on why this started popping up but that could be the reason why it is no longer added to Observable prototype. I'm also completely using pipeable operators throughout my app so I'm guessing the bundle excludes the add operators code.

Release 2.3.3 breaks build

Moving the typings dependency from dev to peer forces people using the package to include the typings package to their dev dependency package list.

Maybe this is as intended, but then it should be included in the readme I guess.

Compilation error in ng2 app: Calling function 'ApplicationInsightsModule', function calls are not supported

Hi,

I am facing a compilation issue today. he exact same code was compiling fine last week.
Here is the offending line in my app.module.ts as per the TS compiler:
import { ApplicationInsightsModule } from '@markpieszak/ng-application-insights'; ... imports: [ ... ApplicationInsightsModule.forRoot({ appID: <myid>, appName: <myproj> }) ],

Here is the compiler error:
ERROR in Error encountered resolving symbol values statically. Calling function 'ApplicationInsightsModule', function calls are not supported. Consider replacing the function or lambda with a reference to an exported function

Is there a new way to initialize the AppInsights module?
I am running off 1.0.0-rc.0 version.

Update: I am using Angular CLI 1.0.0-rc.2 to compile

Rgds

Cannot read property 'isPromise' of undefined

This is looks like similar to #10
But, i have Angular 4.2.1 with
"dependencies": {
"attherate markpieszak/ng-application-insights": "^2.4.2",
}

Runtime Error
Cannot read property 'isPromise' of undefined

Stack:
TypeError: Cannot read property 'isPromise' of undefined
at Object. (http://localhost:8100/build/main.js:144370:98)
at webpack_require (http://localhost:8100/build/main.js:20:30)
at Object. (http://localhost:8100/build/main.js:34023:79)
at webpack_require (http://localhost:8100/build/main.js:20:30)
at Object. (http://localhost:8100/build/main.js:52567:76)
at webpack_require (http://localhost:8100/build/main.js:20:30)
at Object. (http://localhost:8100/build/main.js:142966:80)
at webpack_require (http://localhost:8100/build/main.js:20:30)
at Object. (http://localhost:8100/build/main.js:51037:76)
at webpack_require (http://localhost:8100/build/main.js:20:30)

Ionic Framework: 3.3.0
Ionic App Scripts: 1.3.7
Angular Core: 4.1.2
Angular Compiler CLI: 4.1.2
Node: 6.11.4
OS Platform: Windows 7
Navigator Platform: Win32
User Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36

Window not defined issue server-side

Should the repo as of today support using the module for server-side prerendering? I'm getting the familiar window not defined issue:

Exception: Call to Node module failed with error: Prerendering failed because of error: ReferenceError: window is not defined
at Function.get [as appInsightsInstance] (D:\Dev\PCTS\metrosouth-digital\src\MyApp\Client\dist\main-server.js:158644:22)

If I look at that line in main-server.js there are many references to window:

Object.defineProperty(AppInsightsModule, "appInsightsInstance", {
            get: function () {
                if (!window[AppInsightsModule.appInsightsName]) {
                    window[AppInsightsModule.appInsightsName] = {
                        downloadAndSetup: AppInsightsModule._download,
                        // exposing it for unit tests only, not part of interface
                        _defineLazyMethods: AppInsightsModule._defineLazyMethods
                    };
                    AppInsightsModule._defineLazyMethods();
                }
                return window[AppInsightsModule.appInsightsName];
            },
            enumerable: true,
            configurable: true
        });

StringValueTooLong message:"string value is too long.

Hi! i m making an App with AD B2C and yours Git for AI, and every time the app get the AccesToken throw this warning:

AI: StringValueTooLong message:"string value is too long. It has been truncated to 1024 characters." props:"

image

At first, I thought it was the problem of the Application-Js repository, so I asked them:https://github.com/Microsoft/ApplicationInsights-JS/issues/174

But they replied that the latest version (1.0.16) has already solved that problem, and they saw that in their repository they are using as dependency a previous version (1.0.15).
https://github.com/Microsoft/ApplicationInsights-JS/issues/566

There is a way to make this fix local until the new version comes?

forRoot() with observable

Hi Mark,

First of all; Love the package, easy setup and use!

My 'issue' is as follows:

I want to load configuration settings that contain the instrumentation key. This instrumentation key is therefore not directly known when the app.module is executed. So calling the forRoot() with the key is not an option.

Would it be possible to use an observable (preferred) or promise to set the key? I could then use the Route Resolver or the APP_INITIALIZER to retrieve the configuration settings. When the key becomes available it could set it in the ApplicationInsightsModule.

If you have a working alternative for my problem, I would love to know your solution!

Thanks in advance,

Stephan Kaneman

Karma Tests with angular-application-insights

Hi @MarkPieszak. I'm trying to write karma tests for my app. I'm pretty new to karma so this probably a problem with me and not your package. But when I run my tests I get an error that says:

 Error: No provider for AppInsightsService!

Do you know how to fix this? Or do you know of any other projects that run karma tests with your package so I can see how they fix this problem?

Thanks!

Package depends on itself?

I see in package.json that "@markpieszak/ng-application-insights": "^2.3.0" is a dependency... which is this package.

Intentional?

Initialize instrumentationKey via http request

Hi.
I have multiple application insight instances, which correspond to my runtime environments (DEV, ACT, PROD). I am searching for the best way to set up the instrumentationKey dependent on the environment it was distributed from. I was thinking about requesting the corresponding server, if this is possible in any way.
Do you know how I could achieve this the best?

AppInsightsService.context is null, unable to add telemetry initializer

Disregard! After posting this I restarted the ng server and the context started being populated. I'm guessing something didn't get built properly after the package update. Sorry!!

I'm working with the latest version and the context always seems to be null. I'm not able to use the addTelemetryInitializer to track a custom tag.

Versions
@markpieszak/ng-application-insights = 6.0.1
angular = 6.1.10

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';
import { CoreModule } from './core/core.module';

import { ApplicationInsightsModule, AppInsightsService } from '@markpieszak/ng-application-insights';

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    AppRoutingModule,
    ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production }),
    CoreModule.forRoot(),
    ApplicationInsightsModule.forRoot({ instrumentationKey: environment.applicationInsights.instrumentationKey })
  ],
  providers: [AppInsightsService],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.comonent.ts

import { Component, OnInit } from '@angular/core';
import { AdalService } from 'adal-angular4';
import { environment } from '../environments/environment';
import { SocketService } from './core/services/socket.service';
import { AppInsightsService } from '@markpieszak/ng-application-insights';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent  {

  constructor(private adalService: AdalService, private socketService: SocketService, private appInsights: AppInsightsService) {
    adalService.init(environment.config);

    console.log('AppComponent ngOnInit', this.appInsights);

    this.appInsights.queue.push(() => {
      console.log('appInsights queue', this.appInsights, this.appInsights.context);

      this.appInsights.context.addTelemetryInitializer((envelope: Microsoft.ApplicationInsights.IEnvelope) => {
        console.log('telemetry init', envelope);
        envelope.tags['ai.device.roleName'] = "FetErp.Web";
      });

      console.log('appInsights queue end', this.appInsights, this.appInsights.context);
    });

    
  }
}

console output

app.component.ts:17 AppComponent ngOnInit AppInsightsService {_injector: NgModuleRef_, config: {…}, queue: Array(0), context: undefined}
app.component.ts:20 appInsights queue AppInsightsService {_injector: NgModuleRef_, config: {…}, queue: Array(2), context: undefined} undefined

The console logs for "telemetry init" and "appInsights queue end" are never displayed.

Should I be calling this from another location besides the app.component constructor?

Telemetry not cached during network disconnects

Tracking of telemetry appears to be lost if TRACK POST is performed while network is down.

Reproduction Steps:
With Network On
Perform a trackEvent
Wait for TRACK POST
Perform a trackEvent
Turn off Network
Wait for TRACK POST
Turn on network
Perform a trackEvent
Wait for TRACK POST

In Insights, only trackEvent 1 and 3 are captured.

Is it possible to use navigator.online to decide whether or not to perform TRACK POST?

'ReferenceError: define is not defined' in dotnet SpaServices angular template with SSR

I am trying to use the library with the dotnet angular template provided by the aspnet templating team.
I am using the aspnet 2.1 with angular 5.2 version of the template and v4.0.2 of @markpieszak/ng-application-insights.

I did everything exactly as stated in the documentation.
I have a shared AppModule and one for the server and another one for the browser. During ssr only the server one and the shared one used. I load the appinsights module in the browser AppModule.
I am injecting the AppInsightsService through the injector only if it is running in the browser.

Still, I get an error during prerendering:

Microsoft.AspNetCore.NodeServices.HostingModels.NodeInvocationException: Prerendering failed because of error: ReferenceError: define is not defined
    at Object.<anonymous> (<local_app_folder>\AngularServerSideRenderingApplicationInsights\ClientApp\node_modules\applicationinsights-js\bundle\ai.module.js:187:1)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (<local_app_folder>\AngularServerSideRenderingApplicationInsights\ClientApp\node_modules\@markpieszak\ng-application-insights\dist\src\app-insight.service.js:5:32)
    at Module._compile (module.js:652:30)
Current directory is: <local_app_folder>\AngularServerSideRenderingApplicationInsights

   at Microsoft.AspNetCore.NodeServices.HostingModels.HttpNodeInstance.InvokeExportAsync[T](NodeInvocationInfo invocationInfo, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.NodeServices.HostingModels.OutOfProcessNodeInstance.InvokeExportAsync[T](CancellationToken cancellationToken, String moduleName, String exportNameOrNull, Object[] args)
   at Microsoft.AspNetCore.NodeServices.NodeServicesImpl.InvokeExportWithPossibleRetryAsync[T](String moduleName, String exportedFunctionName, Object[] args, Boolean allowRetry, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.NodeServices.NodeServicesImpl.InvokeExportWithPossibleRetryAsync[T](String moduleName, String exportedFunctionName, Object[] args, Boolean allowRetry, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Builder.SpaPrerenderingExtensions.<>c__DisplayClass0_0.<<UseSpaPrerendering>b__1>d.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

The problem occurs at applicationinsights-js\bundle\ai.module.js:187:1, so this line is the problematic one:
define("JavaScriptSDK.Module/AppInsightsModule", ["require", "exports"], function (require, exports).

Just to be sure I have tried the https://github.com/MarkPieszak/aspnetcore-angular2-universal starter project and it works fine with this module, so the problem only occurs with Microsoft's template.

I have created a repro repository here: https://github.com/dominikfoldi/AngularSSRAppInsightsRepro
If you comment out the injection of the AppInsightsService in app.component.ts the error is gone, but otherwise it fails during SSR.

@MarkPieszak or others do you have any idea how to resolve this?

Ability to override startTrackPage name and stopTrackPage name

Within the init() function of app-insight.service.ts startTrackPage() and stopTrackPage() gets called for me with the name specified as event.url. It would be nice to be able to provide a custom name of my choosing for page view events.

Proposed Solution:
Enable the ability to set a flag to disable this functionality, so that I can create my own implementation without having duplicate page views show up in app insights.

Cyclic dependency when injecting AppInsightService in another service

Hi,
We are using Angular 6.0.2 with angular CLi 6.0.1

i am trying to log to app insights by using a globalerror handler and loggerservice.
When trying to inject AppInsightservice to Loggerservice getting cyclicDependency error.

But when i put the service in a specific component it works, but i want to log all errors not component specific.

GlobalErrorHandler
`import { LoggerService } from './../services/logger.service';
import { ErrorHandler, Injectable, Injector } from '@angular/core';

@Injectable()
export class GlobalErrorHandler extends ErrorHandler {
constructor(private logger: LoggerService) {
super();
}
handleError(error: any) {
this.logger.log(error);

    super.handleError(error);
};

}`

LoggerService
`import { Injectable } from '@angular/core';
import { AppInsightsService } from '@markpieszak/ng-application-insights';
@Injectable()
export class LoggerService {

constructor(private appInsightsService: AppInsightsService) { }
log(error) {
console.log('Logger', error);
//this.appInsightsService.trackEvent('ShoppingCart Saved', { 'user': 'test', 'cart': 'test1' });
}
}
`

compiler.js:11362 Uncaught Error: Provider parse errors:
Cannot instantiate cyclic dependency! ApplicationRef ("[ERROR ->]"): in NgModule AppModule in ./AppModule@-1:-1
at NgModuleProviderAnalyzer.push../node_modules/@angular/compiler/fesm5/compiler.js.NgModuleProviderAnalyzer.parse (compiler.js:11362)
at NgModuleCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.NgModuleCompiler.compile (compiler.js:11731)
at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._compileModule (compiler.js:22591)
at compiler.js:22550
at Object.then (compiler.js:206)
at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler._compileModuleAndComponents (compiler.js:22548)
at JitCompiler.push../node_modules/@angular/compiler/fesm5/compiler.js.JitCompiler.compileModuleAsync (compiler.js:22508)
at CompilerImpl.push../node_modules/@angular/platform-browser-dynamic/fesm5/platform-browser-dynamic.js.CompilerImpl.compileModuleAsync (platform-browser-dynamic.js:143)
at PlatformRef.push../node_modules/@angular/core/fesm5/core.js.PlatformRef.bootstrapModule (core.js:4790)
at Object../src/pos.main.ts (pos.main.ts:11)

Any help is appreciated.
Thanks
K

Dependency on @angular/router breaks compatibility with Ionic

We're currently trying to use angular-application-insights across our various Angular applications, one of which is built in Ionic. Given the current version of Ionic (v.3) does not use @angular/router, we are getting the same error mentioned in Issue #25 Unhandled Promise rejection: No provider for Router!, which is due to the hard dependency on Angular Router inside AppInsightsService.

Track sent but not received in application Application Insights

I installed version in 6.0.1, imported the module and specified the right instrumentation key from my Application Insights App (type: node.js). A track is sent with status code 200 but I don't see any data shown in Azure.

angular-application-insights_issue

Is there something I overlook here?

overrideTrackPageMetrics not included in typings file

The overrideTrackPageMetrics property in the AppInsightsConfig is not being included in the app-insight.service.d.ts typings file in the dist folder. Running npm run build on a local branch of the code seems to generate the typings file with this property. However, when doing an npm install overrideTrackPageMetrics does not appear in the typings file.

Previously this was not an issue in version 2.2.0, but since the release of version 2.3.0 this doesn't work in either version (2.2.0 and 2.3.0).

Angular 6

Hi,

Does this support Angular 6 as well?

ApplicationInsights context set to undefined

Hi,


Version information

  • @markpieszak/ng-application-insights: 4.0.2
  • Angular: 5.2.9
  • rxjs: 5.5.7

I have an AnalyticsService I use to encapsulate the AppInsightsService from this library. My service looks something like this:

import { Injectable} from "@angular/core";
import { AppInsightsService } from "@markpieszak/ng-application-insights";

@Injectable()
export class AnalyticsService {
	constructor(
		private appInsightsService: AppInsightsService) {}

	public init(): void {
		this.setInstrumentationKey();
		this.appInsightsService.init();

		this.addAnalyticsFiltering();
	}

	private setInstrumentationKey(): void {
                ...
	}

	private addAnalyticsFiltering(): void {
		this.appInsightsService.queue.push(() => {
			console.log("Adding to queue");
			console.log(this.appInsightsService.queue);
			this.appInsightsService.context.addTelemetryInitializer((envelope: Microsoft.ApplicationInsights.IEnvelope) => {
				console.log("Adding to context");
				console.log(this.appInsightsService.context);

				envelope.data.baseData.url = envelope.data.baseData.url.split("/")
					.map(part => part.split("?")[0])
					.map(part => part.split("#")[0])
					.filter(part => !part.match(/^\d+$|^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/))
					.join("/");

				return true;
			});
		});
	}
}

My AnalyticsModule looks like this:

import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { AnalyticsService } from "./analytics.service";
import { ApplicationInsightsModule, AppInsightsService } from "@markpieszak/ng-application-insights";
import { environment } from "../../../../environments/environment";

@NgModule({
	imports: [
		CommonModule,
		ApplicationInsightsModule.forRoot({
			instrumentationKeySetlater: true
		})
	],
	providers : [
		AnalyticsService
	],
	declarations: []
})
export class AnalyticsModule {
}

As you can see, I'm setting my instrumentation key later and have an init function that's called by my AppComponent (so that the service can start tracking all pageviews/ajax calls/exceptions right away).

Now the issue I'm having is in the addAnalyticsFiltering function. I have some log statements as you can see, to let me know if my TelemetryInitializer is being added correctly (I need to pre-process the data sent to Application Insights).

However, the console.log("Adding to context"); is never reached. So I debugged the application and inspected this.appInsightsService and it turns out the context is set to undefined.

Why is the context set to undefined and how do I get it to initialize correctly? None of my TelementryInitializers are working because of this.

An instrumentationKey value is required to initialize AppInsightsService

I am using this in conjunction with this and I am getting above error on App Load in console. I assume this is order of operations issue since the key is injected into the service at some point (Api calls to AppInsights are successful). Here is what I am doing in main.server.ts (as well as aot)

  return ngAspnetCoreEngine(setupOptions).then(response => {
    // Apply your transferData to response.globals
    response.globals.transferData = createTransferScript({
        AppInsightsId: 'Key'
    });

and in browser-app.module

  ApplicationInsightsModule.forRoot({
            instrumentationKey: window['TRANSFER_CACHE']['AppInsightsId']
        }),

The key is on the window object, yet I get this error when the site loads. I have 2 questions.

  1. When do I inject the key into the service to make that warning go away
  2. I am currently storing it in the main.server.ts, but I want to supply it from Server side. what would that look like? I am already putting it on TransferData in HomeController, but this line
AppInsightsId2: params.data.AppInsightsId

Never gets populated.

TypeError when running ng serve in production mode

Hi,

I have an issue since version 5.0.4 when building my application with --prod option (ng serve --prod).

Angular application insights Error [downloadAndSetup]:  TypeError: this._injector.get is not a function
    at e.get [as router] (main.b0d98d02747b3ebe4744.js:1)
    at e.init (main.b0d98d02747b3ebe4744.js:1)
    at new <anonymous> (main.b0d98d02747b3ebe4744.js:1)
    at wa (main.b0d98d02747b3ebe4744.js:1)
    at ya (main.b0d98d02747b3ebe4744.js:1)
    at Za (main.b0d98d02747b3ebe4744.js:1)
    at Wa (main.b0d98d02747b3ebe4744.js:1)
    at Object.ps [as createRootView] (main.b0d98d02747b3ebe4744.js:1)
    at t.create (main.b0d98d02747b3ebe4744.js:1)
    at t.create (main.b0d98d02747b3ebe4744.js:1)

When building my app in dev mode, everything is ok. I think that the issue is due to this change ee3df01. I investigated a bit and when the app is build in production mode, the parameters in the AppInsightsService are not what we are expecting. _injector is the Router.

I tried to investigate more but with no significant results. I will probably rollback to 5.0.3 but if have a fix to provide, it would be nice :)

I'm using dev deps:

    "@angular/compiler-cli": "6.1.10",
    "@angular/cli": "6.2.6",

and deps:

"@angular/animations": "6.1.10",
    "@angular/cdk": "6.4.7",
    "@angular/common": "6.1.10",
    "@angular/compiler": "6.1.10",
    "@angular/core": "6.1.10",
    "@angular/flex-layout": "6.0.0-beta.18",
    "@angular/forms": "6.1.10",
    "@angular/material": "6.4.7",
    "@angular/material-moment-adapter": "6.4.7",
    "@angular/platform-browser": "6.1.10",
    "@angular/platform-browser-dynamic": "6.1.10",
    "@angular/router": "6.1.10",

Thank you

UIRouterModule not working with the ng-application-insights

Im using Angular v6 and UiRouterModule instead of RouterModule. The application insights module seems to look for RouterModule explicitly? So it fails with the following:

app-insight.service.js:214 Angular application insights Error [downloadAndSetup]: Error: StaticInjectorError(AppModule)[Router]:
StaticInjectorError(Platform: core)[Router]:
NullInjectorError: No provider for Router!
at NullInjector.push../node_modules/@angular/core/fesm5/core.js.NullInjector.get (core.js:1062)
at resolveToken (core.js:1300)
at tryResolveToken (core.js:1244)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:1141)
at resolveToken (core.js:1300)
at tryResolveToken (core.js:1244)
at StaticInjector.push../node_modules/@angular/core/fesm5/core.js.StaticInjector.get (core.js:1141)
at resolveNgModuleDep (core.js:8376)
at NgModuleRef_.push../node_modules/@angular/core/fesm5/core.js.NgModuleRef_.get (core.js:9064)
at AppInsightsService.get [as router] (app-insight.service.js:230)

accessing this.router throws it.

There is a similar issue to this - #46 , but it was closed.

Support Angular 5

Angular 5 has been out now for a little while, so it'd be nice to add support for it.

At a glance at least in my app, it just works as-is. I'm just getting this error with npm install:

npm WARN @markpieszak/[email protected] requires a peer of @angular/router@^4.0.0 but none is installed. You must install peer dependencies yourself.

So optimistically, only the package.json needs to be updated and it'll just work.

Update of ApplicationInsights-JS used

Hi,
Thank you for this easy to use module,
I'm a new user of Azure Insights, and as I was looking into Error object format to use for a better integration in Insights, I saw that you based your module on ApplicationInsights-JS.
Is it the 1.0.7 that is actually used ?
Do you plan to update this dependency ?
Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.