Skip to content

Commit ec59ee5

Browse files
authored
feat: datadog RUM implementation (DEV-50) (#546)
* feat: datadog RUM implementation * test(login-form): fixes tests * refactor(login-form): adds and uses config token properties for datadog init
1 parent 77d8a1f commit ec59ee5

11 files changed

Lines changed: 210 additions & 43 deletions

‎package-lock.json‎

Lines changed: 91 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"test-local": "ng test",
1919
"test-e2e-protractor": "ng e2e --prod=true --protractor-config=./e2e/protractor-ci.conf.js --webdriver-update=false",
2020
"webdriver-update": "webdriver-manager update --standalone false --gecko false --versions.chrome 2.37",
21-
"yalc-add-lib": "rm -rf .yalc/@dasch-swiss && yalc add @dasch-swiss/dsp-js && npm install"
21+
"yalc-add-lib": "rm -rf .yalc/@dasch-swiss && yalc add @dasch-swiss/dsp-js && yalc add @dasch-swiss/dsp-ui && npm install"
2222
},
2323
"private": true,
2424
"dependencies": {
@@ -34,6 +34,7 @@
3434
"@angular/router": "^11.2.9",
3535
"@ckeditor/ckeditor5-angular": "^1.2.3",
3636
"@dasch-swiss/dsp-js": "^4.1.0",
37+
"@datadog/browser-rum": "^3.6.3",
3738
"@ngx-translate/core": "^12.1.2",
3839
"@ngx-translate/http-loader": "5.0.0",
3940
"3d-force-graph": "^1.60.12",

‎src/app/app-init.service.ts‎

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Injectable } from '@angular/core';
22
import { KnoraApiConfig } from '@dasch-swiss/dsp-js';
3+
import { DspDataDogConfig } from './main/declarations/dsp-dataDog-config';
34
import { DspIiifConfig } from './main/declarations/dsp-iiif-config';
45

56
@Injectable({
@@ -9,6 +10,7 @@ export class AppInitService {
910

1011
dspApiConfig: KnoraApiConfig;
1112
dspIiifConfig: DspIiifConfig;
13+
dspDatadogConfig: DspDataDogConfig;
1214

1315
config: object;
1416

@@ -29,7 +31,7 @@ export class AppInitService {
2931

3032

3133
// check for presence of apiProtocol and apiHost
32-
if (typeof dspAppConfig.apiProtocol !== 'string' || typeof dspAppConfig.apiHost !== 'string') {
34+
if (typeof dspAppConfig.apiProtocol !== 'string' || typeof dspAppConfig.apiHost !== 'string') {
3335
throw new Error('config misses required members: apiProtocol and/or apiHost');
3436
}
3537

@@ -60,6 +62,15 @@ export class AppInitService {
6062
iiifPath
6163
);
6264

65+
// init datadog configuration
66+
this.dspDatadogConfig = new DspDataDogConfig(
67+
dspAppConfig.dataDogLogging,
68+
dspAppConfig.dataDogApplicationId,
69+
dspAppConfig.dataDogClientToken,
70+
dspAppConfig.dataDogSite,
71+
dspAppConfig.dataDogService,
72+
);
73+
6374
// get all options from config
6475
this.config = dspAppConfig;
6576

@@ -75,6 +86,11 @@ export class AppInitService {
7586
this.config['iiifPort'] = iiifPort;
7687
this.config['iiifPath'] = iiifPath;
7788
this.config['iiifUrl'] = this.dspIiifConfig.iiifUrl;
89+
this.config['dataDogLogging'] = this.dspDatadogConfig.dataDogLogging;
90+
this.config['dataDogApplicationId'] = this.dspDatadogConfig.dataDogApplicationId;
91+
this.config['dataDogClientToken'] = this.dspDatadogConfig.dataDogClientToken;
92+
this.config['dataDogSite'] = this.dspDatadogConfig.dataDogSite;
93+
this.config['dataDogService'] = this.dspDatadogConfig.dataDogService;
7894

7995
resolve();
8096
}

‎src/app/app.module.ts‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { SelectedResourcesComponent } from './main/action/selected-resources/sel
2626
import { SortButtonComponent } from './main/action/sort-button/sort-button.component';
2727
import { StringLiteralInputComponent } from './main/action/string-literal-input/string-literal-input.component';
2828
import { CookiePolicyComponent } from './main/cookie-policy/cookie-policy.component';
29-
import { DspApiConfigToken, DspApiConnectionToken } from './main/declarations/dsp-api-tokens';
29+
import { DspApiConfigToken, DspApiConnectionToken, DspDataDogConfigToken } from './main/declarations/dsp-api-tokens';
3030
import { DialogHeaderComponent } from './main/dialog/dialog-header/dialog-header.component';
3131
import { DialogComponent } from './main/dialog/dialog.component';
3232
import { AdminImageDirective } from './main/directive/admin-image/admin-image.directive';
@@ -348,6 +348,11 @@ export function httpLoaderFactory(httpClient: HttpClient) {
348348
useFactory: (appInitService: AppInitService) => appInitService.dspApiConfig,
349349
deps: [AppInitService]
350350
},
351+
{
352+
provide: DspDataDogConfigToken,
353+
useFactory: (appInitService: AppInitService) => appInitService.dspDatadogConfig,
354+
deps: [AppInitService]
355+
},
351356
{
352357
provide: DspApiConnectionToken,
353358
useFactory: (appInitService: AppInitService) => new KnoraApiConnection(appInitService.dspApiConfig),

‎src/app/main/action/login-form/login-form.component.spec.ts‎

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
77
import {
88
ApiResponseData,
99
AuthenticationEndpointV2,
10+
KnoraApiConfig,
1011
LoginResponse,
1112
LogoutResponse,
1213
MockUsers,
1314
UsersEndpointAdmin
1415
} from '@dasch-swiss/dsp-js';
1516
import { of } from 'rxjs';
1617
import { AjaxResponse } from 'rxjs/ajax';
17-
import { DspApiConnectionToken } from '../../declarations/dsp-api-tokens';
18+
import { DspApiConfigToken, DspApiConnectionToken, DspDataDogConfigToken } from '../../declarations/dsp-api-tokens';
19+
import { DspDataDogConfig } from '../../declarations/dsp-dataDog-config';
1820
import { Session, SessionService } from '../../services/session.service';
1921
import { LoginFormComponent } from './login-form.component';
2022

@@ -54,6 +56,10 @@ describe('LoginFormComponent', () => {
5456
let sessionService: SessionService;
5557

5658
beforeEach(waitForAsync(() => {
59+
const dspConfSpy = new KnoraApiConfig('http', 'localhost', 3333, undefined, undefined, true);
60+
61+
const dspDatadogSpy = new DspDataDogConfig(false, '', '', '', '');
62+
5763
const dspConnSpy = {
5864
admin: {
5965
usersEndpoint: jasmine.createSpyObj('usersEndpoint', ['getUser'])
@@ -74,6 +80,14 @@ describe('LoginFormComponent', () => {
7480
provide: DspApiConnectionToken,
7581
useValue: dspConnSpy
7682
},
83+
{
84+
provide: DspApiConfigToken,
85+
useValue: dspConfSpy
86+
},
87+
{
88+
provide: DspDataDogConfigToken,
89+
useValue: dspDatadogSpy
90+
},
7791
FormBuilder,
7892
SessionService
7993
],

‎src/app/main/action/login-form/login-form.component.ts‎

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import { Component, EventEmitter, Inject, Input, OnInit, Output } from '@angular/core';
2+
import { inject } from '@angular/core/testing';
23
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
3-
import { ApiResponseData, ApiResponseError, KnoraApiConnection, LoginResponse, LogoutResponse } from '@dasch-swiss/dsp-js';
4-
import { DspApiConnectionToken } from '../../declarations/dsp-api-tokens';
4+
import { ApiResponseData, ApiResponseError, KnoraApiConfig, KnoraApiConnection, LoginResponse, LogoutResponse } from '@dasch-swiss/dsp-js';
5+
import { datadogRum, RumFetchResourceEventDomainContext } from '@datadog/browser-rum';
6+
import { DspApiConfigToken, DspApiConnectionToken, DspDataDogConfigToken } from '../../declarations/dsp-api-tokens';
7+
import { DspDataDogConfig } from '../../declarations/dsp-dataDog-config';
58
import { NotificationService } from '../../services/notification.service';
69
import { Session, SessionService } from '../../services/session.service';
710

@@ -101,6 +104,8 @@ export class LoginFormComponent implements OnInit {
101104

102105
constructor(
103106
@Inject(DspApiConnectionToken) private _dspApiConnection: KnoraApiConnection,
107+
@Inject(DspApiConfigToken) private _dspApiConfig: KnoraApiConfig,
108+
@Inject(DspDataDogConfigToken) private _dspDataDogConfig: DspDataDogConfig,
104109
private _notification: NotificationService,
105110
private _sessionService: SessionService,
106111
private _fb: FormBuilder
@@ -151,6 +156,29 @@ export class LoginFormComponent implements OnInit {
151156
this.session = this._sessionService.getSession();
152157
this.loginSuccess.emit(true);
153158
this.loading = false;
159+
if (this._dspDataDogConfig.dataDogLogging) {
160+
datadogRum.init({
161+
applicationId: this._dspDataDogConfig.dataDogApplicationId,
162+
clientToken: this._dspDataDogConfig.dataDogClientToken,
163+
site: this._dspDataDogConfig.dataDogSite,
164+
service: this._dspDataDogConfig.dataDogService,
165+
// specify a version number to identify the deployed version of your application in Datadog
166+
// version: '1.0.0',
167+
sampleRate: 100,
168+
trackInteractions: true,
169+
beforeSend: (event, context) => {
170+
// collect a RUM resource's response headers
171+
if (event.type === 'resource' && event.resource.type === 'xhr') {
172+
event.context = { ...event.context, responseHeaders: (context as RumFetchResourceEventDomainContext).response.body };
173+
}
174+
},
175+
});
176+
177+
datadogRum.setUser({
178+
id: identifier,
179+
identifierType: identifierType
180+
});
181+
}
154182
}
155183
);
156184
},
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import { InjectionToken } from '@angular/core';
22
import { KnoraApiConfig, KnoraApiConnection } from '@dasch-swiss/dsp-js';
3+
import { DspDataDogConfig } from './dsp-dataDog-config';
34

45
// config for dsp-js-lib (@dasch-swiss/dsp-js) config object
56
export const DspApiConfigToken = new InjectionToken<KnoraApiConfig>('DSP api configuration');
67

78
// connection config for dsp-js-lib (@dasch-swiss/dsp-js) connection
89
export const DspApiConnectionToken = new InjectionToken<KnoraApiConnection>('DSP api connection instance');
10+
11+
// config for datadog
12+
export const DspDataDogConfigToken = new InjectionToken<DspDataDogConfig>('DSP DataDog configuration');
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export class DspDataDogConfig {
2+
constructor(public dataDogLogging: boolean,
3+
public dataDogApplicationId: string,
4+
public dataDogClientToken: string,
5+
public dataDogSite: string,
6+
public dataDogService: string) { }
7+
}

‎src/config/config.dev.json‎

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
{
2-
"apiProtocol": "http",
3-
"apiHost": "0.0.0.0",
4-
"apiPort": 3333,
5-
"apiPath": "",
6-
"iiifProtocol": "http",
7-
"iiifHost": "0.0.0.0",
8-
"iiifPort": 1024,
9-
"iiifPath": "",
10-
"geonameToken": "knora",
11-
"jsonWebToken": "",
12-
"logErrors": true
2+
"apiProtocol": "http",
3+
"apiHost": "0.0.0.0",
4+
"apiPort": 3333,
5+
"apiPath": "",
6+
"iiifProtocol": "http",
7+
"iiifHost": "0.0.0.0",
8+
"iiifPort": 1024,
9+
"iiifPath": "",
10+
"geonameToken": "knora",
11+
"jsonWebToken": "",
12+
"logErrors": true,
13+
"dataDogLogging": false,
14+
"dataDogApplicationId": "",
15+
"dataDogClientToken": "",
16+
"dataDogSite": "",
17+
"dataDogService": ""
1318
}

‎src/config/config.prod.json‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,10 @@
99
"iiifPath": "",
1010
"geonameToken": "knora",
1111
"jsonWebToken": "",
12-
"logErrors": false
12+
"logErrors": false,
13+
"dataDogLogging": false,
14+
"dataDogApplicationId": "",
15+
"dataDogClientToken": "",
16+
"dataDogSite": "",
17+
"dataDogService": ""
1318
}

0 commit comments

Comments
 (0)