@crimson-education/browser-logger 5.0.0-beta.17 → 5.0.0-beta.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/reporters/amplifyReporter.js +1 -1
- package/lib/reporters/amplifyReporter.js.map +1 -1
- package/package.json +5 -5
- package/lib/logger/index.test.d.ts +0 -2
- package/lib/logger/index.test.d.ts.map +0 -1
- package/lib/logger/index.test.js +0 -58
- package/lib/logger/index.test.js.map +0 -1
- package/lib/reporters/amplifyReporter.test.d.ts +0 -2
- package/lib/reporters/amplifyReporter.test.d.ts.map +0 -1
- package/lib/reporters/amplifyReporter.test.js +0 -48
- package/lib/reporters/amplifyReporter.test.js.map +0 -1
- package/lib/utils.test.d.ts +0 -2
- package/lib/utils.test.d.ts.map +0 -1
- package/lib/utils.test.js +0 -30
- package/lib/utils.test.js.map +0 -1
- package/src/index.ts +0 -64
- package/src/logger/consoleTransport.ts +0 -101
- package/src/logger/datadogTransport.ts +0 -20
- package/src/logger/index.test.ts +0 -68
- package/src/logger/index.ts +0 -139
- package/src/logger/utils.ts +0 -28
- package/src/reporters/amplifyReporter.test.ts +0 -61
- package/src/reporters/amplifyReporter.ts +0 -460
- package/src/reporters/datadogReporter.ts +0 -359
- package/src/reporters/gtmReporter.ts +0 -74
- package/src/reporters/index.ts +0 -232
- package/src/reporters/logReporter.ts +0 -86
- package/src/types/index.ts +0 -2
- package/src/types/logger.ts +0 -85
- package/src/types/reporter.ts +0 -180
- package/src/utils.test.ts +0 -32
- package/src/utils.ts +0 -42
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
IReporter,
|
|
3
|
-
ReporterBreadcrumb,
|
|
4
|
-
ReporterEvent,
|
|
5
|
-
Metadata,
|
|
6
|
-
ReportError,
|
|
7
|
-
ReportUser,
|
|
8
|
-
ServiceInfo,
|
|
9
|
-
ReporterConfigBase,
|
|
10
|
-
ReporterFlag,
|
|
11
|
-
} from '../types';
|
|
12
|
-
import { MatchOption } from '@datadog/browser-core';
|
|
13
|
-
import { datadogLogs, HandlerType, LogsInitConfiguration } from '@datadog/browser-logs';
|
|
14
|
-
import { datadogRum, DefaultPrivacyLevel, RumInitConfiguration } from '@datadog/browser-rum';
|
|
15
|
-
import { logTransports } from '../logger';
|
|
16
|
-
import { DatadogLogTransportConfig, datadogTransport } from '../logger/datadogTransport';
|
|
17
|
-
|
|
18
|
-
// User frustration detection for Datadog Gen2
|
|
19
|
-
class DatadogFrustrationDetector {
|
|
20
|
-
private config: DatadogReporterConfig;
|
|
21
|
-
private frustrationEvents: Array<{ type: string; timestamp: number }> = [];
|
|
22
|
-
private readonly FRUSTRATION_THRESHOLD = 3; // Number of events to trigger frustration
|
|
23
|
-
private readonly FRUSTRATION_WINDOW = 5000; // Time window in ms
|
|
24
|
-
|
|
25
|
-
constructor(config: DatadogReporterConfig) {
|
|
26
|
-
this.config = config;
|
|
27
|
-
if (config.trackFrustrations) {
|
|
28
|
-
this.setupFrustrationDetection();
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
private setupFrustrationDetection() {
|
|
33
|
-
// Track rapid clicks (potential frustration)
|
|
34
|
-
let clickCount = 0;
|
|
35
|
-
let lastClickTime = 0;
|
|
36
|
-
|
|
37
|
-
document.addEventListener('click', () => {
|
|
38
|
-
const now = Date.now();
|
|
39
|
-
if (now - lastClickTime < 1000) {
|
|
40
|
-
// Rapid clicks within 1 second
|
|
41
|
-
clickCount++;
|
|
42
|
-
if (clickCount >= 3) {
|
|
43
|
-
this.recordFrustrationEvent('rapid_clicks');
|
|
44
|
-
clickCount = 0;
|
|
45
|
-
}
|
|
46
|
-
} else {
|
|
47
|
-
clickCount = 1;
|
|
48
|
-
}
|
|
49
|
-
lastClickTime = now;
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
// Track form errors (potential frustration)
|
|
53
|
-
document.addEventListener('invalid', () => {
|
|
54
|
-
this.recordFrustrationEvent('form_validation_error');
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
// Track 404 errors (potential frustration)
|
|
58
|
-
window.addEventListener('error', (event) => {
|
|
59
|
-
if (event.message.includes('404') || event.message.includes('Not Found')) {
|
|
60
|
-
this.recordFrustrationEvent('page_not_found');
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
// Track network errors (potential frustration)
|
|
65
|
-
window.addEventListener('unhandledrejection', (event) => {
|
|
66
|
-
if (event.reason && typeof event.reason === 'object' && 'status' in event.reason) {
|
|
67
|
-
const status = (event.reason as any).status;
|
|
68
|
-
if (status >= 400) {
|
|
69
|
-
this.recordFrustrationEvent('network_error');
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
private recordFrustrationEvent(type: string) {
|
|
76
|
-
const now = Date.now();
|
|
77
|
-
this.frustrationEvents.push({ type, timestamp: now });
|
|
78
|
-
|
|
79
|
-
// Clean old events outside the window
|
|
80
|
-
this.frustrationEvents = this.frustrationEvents.filter((event) => now - event.timestamp < this.FRUSTRATION_WINDOW);
|
|
81
|
-
|
|
82
|
-
// Check if we have enough events to trigger frustration
|
|
83
|
-
if (this.frustrationEvents.length >= this.FRUSTRATION_THRESHOLD) {
|
|
84
|
-
this.triggerFrustrationDetection();
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
private triggerFrustrationDetection() {
|
|
89
|
-
const frustrationData = {
|
|
90
|
-
frustrationType: 'user_frustration_detected',
|
|
91
|
-
frustrationEvents: this.frustrationEvents.map((e) => e.type),
|
|
92
|
-
frustrationCount: this.frustrationEvents.length,
|
|
93
|
-
pageUrl: window.location.href,
|
|
94
|
-
timestamp: new Date().toISOString(),
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
// Send frustration event to Datadog
|
|
98
|
-
if (typeof datadogRum !== 'undefined') {
|
|
99
|
-
datadogRum.addAction('User Frustration Detected', frustrationData);
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Clear events after reporting
|
|
103
|
-
this.frustrationEvents = [];
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export interface DatadogReporterConfig extends ReporterConfigBase {
|
|
108
|
-
/** The RUM application ID. */
|
|
109
|
-
applicationId: string;
|
|
110
|
-
/** A Datadog client token (Generated in the RUM Page) */
|
|
111
|
-
clientToken: string;
|
|
112
|
-
/** The Datadog site parameter of your organization. */
|
|
113
|
-
site: string;
|
|
114
|
-
/** The Application's version (Overrides the browser logger version) */
|
|
115
|
-
version?: string;
|
|
116
|
-
/** Optional proxy URL */
|
|
117
|
-
proxyUrl?: string;
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Controls the percentage of overall sessions being tracked. It defaults to 100, so every session is tracked by default.
|
|
121
|
-
*
|
|
122
|
-
* More specific sample rate options take priority over this option. For instance, if `logSampleRate` is 50 and `sampleRate`
|
|
123
|
-
* is 75, then the sample rate used for log messages will be `50`.
|
|
124
|
-
*
|
|
125
|
-
* @deprecated Prefer using the dedicated `logSampleRate`, `rumSampleRate`, and `replaySampleRate` options.
|
|
126
|
-
*/
|
|
127
|
-
sampleRate?: number;
|
|
128
|
-
sessionSampleRate?: number;
|
|
129
|
-
sessionReplaySampleRate?: number;
|
|
130
|
-
/**
|
|
131
|
-
* Sampling rate for browser log collection. Defaults to 100, meaning every log message is sent to Datadog.
|
|
132
|
-
*/
|
|
133
|
-
logSampleRate?: number;
|
|
134
|
-
/**
|
|
135
|
-
* Sampling rate for RUM session collection. Defaults to 100, meaning every browser session is tracked.
|
|
136
|
-
*
|
|
137
|
-
* RUM can be used to track things like core web vitals.
|
|
138
|
-
*
|
|
139
|
-
* @see https://www.datadoghq.com/product/real-user-monitoring/
|
|
140
|
-
*/
|
|
141
|
-
rumSampleRate?: number;
|
|
142
|
-
/**
|
|
143
|
-
* Applied after the RUM sample rate, and controls the percentage of sessions tracked as Browser RUM & Session Replay.
|
|
144
|
-
* It defaults to 100, so every session is tracked as Browser RUM & Session Replay by default.
|
|
145
|
-
*
|
|
146
|
-
* These sessions end up with a session replay available in Datadog.
|
|
147
|
-
*/
|
|
148
|
-
replaySampleRate?: number;
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Use a secure session cookie. This disables RUM events sent on insecure (non-HTTPS) connections.
|
|
152
|
-
*/
|
|
153
|
-
useSecureSessionCookie?: boolean;
|
|
154
|
-
/**
|
|
155
|
-
* Use a secure cross-site session cookie.
|
|
156
|
-
* This allows the RUM Browser SDK to run when the site is loaded from another one (iframe). Implies `useSecureSessionCookie`
|
|
157
|
-
*/
|
|
158
|
-
useCrossSiteSessionCookie?: boolean;
|
|
159
|
-
/**
|
|
160
|
-
* Preserve the session across subdomains for the same site.
|
|
161
|
-
*/
|
|
162
|
-
trackSessionAcrossSubdomains?: boolean;
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Forward console.error logs, uncaught exceptions and network errors to Datadog.
|
|
166
|
-
* Defaults to false.
|
|
167
|
-
*/
|
|
168
|
-
forwardConsoleLogs?: boolean;
|
|
169
|
-
/**
|
|
170
|
-
* Enables automatic collection of users actions.
|
|
171
|
-
*/
|
|
172
|
-
trackInteractions?: boolean;
|
|
173
|
-
/**
|
|
174
|
-
* Enables automatic collection of user frustrations. Implies `trackInteractions`: true.
|
|
175
|
-
*/
|
|
176
|
-
trackFrustrations?: boolean;
|
|
177
|
-
/**
|
|
178
|
-
* Allows you to control RUM views creation.
|
|
179
|
-
* You will need to call `Logger.setPageName()` to create a new view.
|
|
180
|
-
*/
|
|
181
|
-
trackViewsManually?: boolean;
|
|
182
|
-
/**
|
|
183
|
-
* Specify your own attribute to be used to name actions.
|
|
184
|
-
* Defaults to `data-analytics-name` to coincide with analytics attributes used across reporters.
|
|
185
|
-
*/
|
|
186
|
-
actionNameAttribute?: string;
|
|
187
|
-
/**
|
|
188
|
-
* Allows you to modify RUM events before they are sent to Datadog.
|
|
189
|
-
*/
|
|
190
|
-
beforeSend?: RumInitConfiguration['beforeSend'];
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Toggles/configures the Datadog Log Transport.
|
|
194
|
-
* Defaults to true.
|
|
195
|
-
*/
|
|
196
|
-
logTransport?: boolean | DatadogLogTransportConfig;
|
|
197
|
-
/**
|
|
198
|
-
* Allows you to modify Log events before they are sent to Datadog (Can only be set at ).
|
|
199
|
-
*/
|
|
200
|
-
beforeLogsSend?: LogsInitConfiguration['beforeSend'];
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* By enabling Session Replay, you can automatically mask sensitive elements from being recorded through the RUM Browser SDK.
|
|
204
|
-
*
|
|
205
|
-
* See https://docs.datadoghq.com/real_user_monitoring/session_replay/privacy_options
|
|
206
|
-
*/
|
|
207
|
-
defaultPrivacyLevel?: DefaultPrivacyLevel;
|
|
208
|
-
/**
|
|
209
|
-
* A list of request origins used to inject tracing headers, to be able to connect RUM and backend tracing.
|
|
210
|
-
*/
|
|
211
|
-
allowedTrackingOrigins?: (string | RegExp)[];
|
|
212
|
-
allowedTracingUrls?: (string | RegExp)[];
|
|
213
|
-
/**
|
|
214
|
-
* Enables action tracking for user interactions. This enables the Heatmap tab within Datadog
|
|
215
|
-
*/
|
|
216
|
-
trackUserInteractions?: boolean;
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* To improve the accuracy of activity determination
|
|
220
|
-
*
|
|
221
|
-
* See https://docs.datadoghq.com/real_user_monitoring/browser/monitoring_page_performance/#how-page-activity-is-calculated
|
|
222
|
-
*/
|
|
223
|
-
excludedActivityUrls?: MatchOption[];
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
export function datadogReporter(info: ServiceInfo, config: DatadogReporterConfig): IReporter {
|
|
227
|
-
const isLocalhost = window.location.hostname === 'localhost';
|
|
228
|
-
|
|
229
|
-
// Don't forward error logs by default, do enable the log transport by default
|
|
230
|
-
// forwardErrorsToLogs incorrectly is called forwardConsoleLogs, this is for backwards compatibility
|
|
231
|
-
const forwardErrorsToLogs = config.forwardConsoleLogs ?? false;
|
|
232
|
-
const enableLogTransport = config.logTransport !== false;
|
|
233
|
-
|
|
234
|
-
// Only init datadog logs if something is using it.
|
|
235
|
-
if (forwardErrorsToLogs === true || enableLogTransport === true) {
|
|
236
|
-
datadogLogs.init({
|
|
237
|
-
site: config.site as any,
|
|
238
|
-
clientToken: config.clientToken,
|
|
239
|
-
service: info.service,
|
|
240
|
-
env: info.environment,
|
|
241
|
-
version: config.version ?? info.version,
|
|
242
|
-
|
|
243
|
-
beforeSend: config.beforeLogsSend,
|
|
244
|
-
|
|
245
|
-
useSecureSessionCookie: config.useSecureSessionCookie ?? !isLocalhost,
|
|
246
|
-
// Note: useCrossSiteSessionCookie is not available in newer Datadog versions
|
|
247
|
-
trackSessionAcrossSubdomains: config.trackSessionAcrossSubdomains,
|
|
248
|
-
|
|
249
|
-
forwardErrorsToLogs,
|
|
250
|
-
allowedTrackingOrigins: config.allowedTrackingOrigins,
|
|
251
|
-
});
|
|
252
|
-
datadogLogs.logger.setHandler(HandlerType.http);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// Add the datadog log transport
|
|
256
|
-
if (enableLogTransport) {
|
|
257
|
-
logTransports.push(datadogTransport(typeof config.logTransport === 'boolean' ? {} : config.logTransport));
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
datadogRum.init({
|
|
261
|
-
enableExperimentalFeatures: ['feature_flags'],
|
|
262
|
-
site: config.site as any,
|
|
263
|
-
clientToken: config.clientToken,
|
|
264
|
-
applicationId: config.applicationId,
|
|
265
|
-
service: info.service,
|
|
266
|
-
env: info.environment,
|
|
267
|
-
version: config.version ?? info.version,
|
|
268
|
-
|
|
269
|
-
// Use correct Datadog v6 SDK options
|
|
270
|
-
sessionSampleRate: config.sessionSampleRate ?? config.rumSampleRate ?? config.sampleRate ?? 100,
|
|
271
|
-
sessionReplaySampleRate: config.sessionReplaySampleRate?? config.replaySampleRate ?? 100,
|
|
272
|
-
|
|
273
|
-
// Track interactions (Note: trackFrustrations is not available in Datadog v6)
|
|
274
|
-
trackUserInteractions: config.trackUserInteractions ?? config.trackInteractions ?? false,
|
|
275
|
-
|
|
276
|
-
useSecureSessionCookie: config.useSecureSessionCookie ?? !isLocalhost,
|
|
277
|
-
// Note: useCrossSiteSessionCookie is not available in newer Datadog versions
|
|
278
|
-
trackSessionAcrossSubdomains: config.trackSessionAcrossSubdomains,
|
|
279
|
-
trackViewsManually: config.trackViewsManually ?? false,
|
|
280
|
-
actionNameAttribute: config.actionNameAttribute ?? 'data-analytics-name',
|
|
281
|
-
beforeSend: config.beforeSend,
|
|
282
|
-
|
|
283
|
-
defaultPrivacyLevel: config.defaultPrivacyLevel ?? 'mask-user-input',
|
|
284
|
-
allowedTracingUrls: config.allowedTracingUrls ?? config.allowedTrackingOrigins,
|
|
285
|
-
|
|
286
|
-
excludedActivityUrls: config.excludedActivityUrls,
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
// Initialize frustration detector
|
|
290
|
-
new DatadogFrustrationDetector(config);
|
|
291
|
-
|
|
292
|
-
const reporter: IReporter = {
|
|
293
|
-
trackEvent: function (event: ReporterEvent): void {
|
|
294
|
-
datadogRum.addAction(event.message, {
|
|
295
|
-
level: event.level,
|
|
296
|
-
...event.metadata,
|
|
297
|
-
...event.tags,
|
|
298
|
-
...event.metrics,
|
|
299
|
-
});
|
|
300
|
-
},
|
|
301
|
-
addBreadcrumb: function (breadcrumb: ReporterBreadcrumb): void {
|
|
302
|
-
datadogRum.addAction(breadcrumb.message, {
|
|
303
|
-
...breadcrumb.metadata,
|
|
304
|
-
category: breadcrumb.category,
|
|
305
|
-
});
|
|
306
|
-
},
|
|
307
|
-
addMetadata: function (metadata: Metadata): void {
|
|
308
|
-
for (const [key, value] of Object.entries(metadata)) {
|
|
309
|
-
if (value !== null) {
|
|
310
|
-
datadogRum.setGlobalContextProperty(key, value);
|
|
311
|
-
|
|
312
|
-
// Note, this will add duplicate context data in logs.
|
|
313
|
-
// But this is valuable for logs ingested outside of the browser logger.
|
|
314
|
-
datadogLogs.setGlobalContextProperty(key, value);
|
|
315
|
-
} else {
|
|
316
|
-
datadogRum.removeGlobalContextProperty(key);
|
|
317
|
-
|
|
318
|
-
// But this is valuable for logs ingested outside of the browser logger.
|
|
319
|
-
datadogLogs.removeGlobalContextProperty(key);
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
},
|
|
323
|
-
setUser: function (user: ReportUser | null): void {
|
|
324
|
-
if (user) {
|
|
325
|
-
datadogRum.setUser({
|
|
326
|
-
...user,
|
|
327
|
-
id: user.id,
|
|
328
|
-
email: user.email,
|
|
329
|
-
name: user.name ?? user.email,
|
|
330
|
-
});
|
|
331
|
-
} else {
|
|
332
|
-
datadogRum.setUser({});
|
|
333
|
-
}
|
|
334
|
-
},
|
|
335
|
-
setRouteName: function (routeName: string): void {
|
|
336
|
-
reporter.addMetadata({ routeName });
|
|
337
|
-
},
|
|
338
|
-
setPageName: function (pageName: string): void {
|
|
339
|
-
if (config.trackViewsManually) {
|
|
340
|
-
datadogRum.startView(pageName);
|
|
341
|
-
} else {
|
|
342
|
-
reporter.addMetadata({ pageName });
|
|
343
|
-
}
|
|
344
|
-
},
|
|
345
|
-
reportError: function (error: ReportError, metadata?: Metadata): void {
|
|
346
|
-
datadogRum.addError(error, metadata);
|
|
347
|
-
},
|
|
348
|
-
reportFeatureFlag: function (flag: ReporterFlag): void {
|
|
349
|
-
datadogRum.addFeatureFlagEvaluation(flag.name, flag.value);
|
|
350
|
-
},
|
|
351
|
-
recordSession: function (): void {
|
|
352
|
-
datadogRum.startSessionReplayRecording();
|
|
353
|
-
},
|
|
354
|
-
recordSessionStop: function (): void {
|
|
355
|
-
datadogRum.stopSessionReplayRecording();
|
|
356
|
-
},
|
|
357
|
-
};
|
|
358
|
-
return reporter;
|
|
359
|
-
}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
IReporter,
|
|
3
|
-
ReporterBreadcrumb,
|
|
4
|
-
ReporterEvent,
|
|
5
|
-
Metadata,
|
|
6
|
-
ReportUser,
|
|
7
|
-
ServiceInfo,
|
|
8
|
-
ReporterConfigBase,
|
|
9
|
-
} from '../types';
|
|
10
|
-
|
|
11
|
-
export type GTMReporterConfig = ReporterConfigBase;
|
|
12
|
-
|
|
13
|
-
declare global {
|
|
14
|
-
interface Window {
|
|
15
|
-
dataLayer?: Record<string, any>[];
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function gtmReporter(info: ServiceInfo, config: GTMReporterConfig): IReporter {
|
|
20
|
-
let loadedDataLayer = !!window.dataLayer;
|
|
21
|
-
const baseMetadata = {
|
|
22
|
-
service: info.service,
|
|
23
|
-
domain: window.location.host,
|
|
24
|
-
environment: info.environment,
|
|
25
|
-
version: info.version,
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const reporter: IReporter = {
|
|
29
|
-
...config,
|
|
30
|
-
addMetadata: function (metadata: Metadata): void {
|
|
31
|
-
if (window.dataLayer) {
|
|
32
|
-
// Lazy load base metadata, e.g. if GTM isn't ready yet.
|
|
33
|
-
if (!loadedDataLayer) {
|
|
34
|
-
window.dataLayer.push(baseMetadata);
|
|
35
|
-
loadedDataLayer = true;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
window.dataLayer.push(metadata);
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
trackEvent: function (event: ReporterEvent): void {
|
|
42
|
-
reporter.addMetadata({
|
|
43
|
-
...event.metadata,
|
|
44
|
-
...event.tags,
|
|
45
|
-
...event.metrics,
|
|
46
|
-
event: event.message,
|
|
47
|
-
level: event.level,
|
|
48
|
-
});
|
|
49
|
-
},
|
|
50
|
-
addBreadcrumb: function (breadcrumb: ReporterBreadcrumb): void {
|
|
51
|
-
reporter.addMetadata({
|
|
52
|
-
...breadcrumb.metadata,
|
|
53
|
-
event: breadcrumb.message,
|
|
54
|
-
});
|
|
55
|
-
},
|
|
56
|
-
setUser: function (user: ReportUser | null): void {
|
|
57
|
-
if (user) {
|
|
58
|
-
reporter.addMetadata({ user });
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
setRouteName: function (routeName: string): void {
|
|
62
|
-
reporter.addMetadata({ routeName });
|
|
63
|
-
},
|
|
64
|
-
setPageName: function (pageName: string): void {
|
|
65
|
-
reporter.addMetadata({ pageName });
|
|
66
|
-
},
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
if (loadedDataLayer) {
|
|
70
|
-
reporter.addMetadata(baseMetadata);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return reporter;
|
|
74
|
-
}
|
package/src/reporters/index.ts
DELETED
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
import { isAboveLevel } from '../logger/utils';
|
|
2
|
-
import {
|
|
3
|
-
IReporter,
|
|
4
|
-
LogLevel,
|
|
5
|
-
Metadata,
|
|
6
|
-
ReporterBreadcrumb,
|
|
7
|
-
ReporterEvent,
|
|
8
|
-
ReporterFilters,
|
|
9
|
-
ReporterFlag,
|
|
10
|
-
ReportError,
|
|
11
|
-
ReporterType,
|
|
12
|
-
ReportUser,
|
|
13
|
-
TrackedReporterEvent,
|
|
14
|
-
} from '../types';
|
|
15
|
-
import { filterReporterMetadata } from '../utils';
|
|
16
|
-
|
|
17
|
-
export const reporters: Partial<Record<ReporterType, IReporter>> = {};
|
|
18
|
-
|
|
19
|
-
export let globalEventLevel: LogLevel | undefined;
|
|
20
|
-
/**
|
|
21
|
-
* Sets the global event level.
|
|
22
|
-
*/
|
|
23
|
-
export function setEventLevel(level: LogLevel | null): void {
|
|
24
|
-
globalEventLevel = level ?? undefined;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Gets reporters, optionally with filters.
|
|
29
|
-
* @param filters Filters to remove or specify specific reporters.
|
|
30
|
-
* @returns Selected reporters, or all registered reporters.
|
|
31
|
-
*/
|
|
32
|
-
function getReporters(filters?: ReporterFilters) {
|
|
33
|
-
let result = Object.entries(reporters);
|
|
34
|
-
if (filters?.excludeReporters) {
|
|
35
|
-
result = result.filter(([key]) => !filters?.excludeReporters?.includes(key as ReporterType));
|
|
36
|
-
}
|
|
37
|
-
if (filters?.toReporters) {
|
|
38
|
-
result = result.filter(([key]) => filters?.toReporters?.includes(key as ReporterType));
|
|
39
|
-
}
|
|
40
|
-
return result.map(([, reporter]) => reporter);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Tracks an Analytics event.
|
|
45
|
-
*/
|
|
46
|
-
export function trackEvent(event: ReporterEvent): void {
|
|
47
|
-
if (globalEventLevel && event.level && !isAboveLevel(event.level, globalEventLevel)) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
for (const reporter of getReporters(event)) {
|
|
52
|
-
if (reporter.endpoints?.trackEvent === false) {
|
|
53
|
-
continue;
|
|
54
|
-
} else if (reporter.eventLevel && event.level && !isAboveLevel(event.level, reporter.eventLevel)) {
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const reporterEvent = { ...event };
|
|
59
|
-
reporterEvent.metadata = filterReporterMetadata(event.metadata, reporter);
|
|
60
|
-
reporterEvent.metrics = filterReporterMetadata(event.metrics, reporter);
|
|
61
|
-
reporterEvent.tags = filterReporterMetadata(event.tags, reporter);
|
|
62
|
-
reporter.trackEvent(reporterEvent);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Tracks an Analytics event, recording the time since the last event, if available.
|
|
68
|
-
*/
|
|
69
|
-
export function trackEventSinceLastAction(event: ReporterEvent): void {
|
|
70
|
-
if (globalEventLevel && event.level && !isAboveLevel(event.level, globalEventLevel)) {
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const lastEvent = getLastTrackedEvent();
|
|
75
|
-
if (lastEvent) {
|
|
76
|
-
const duration = new Date().getTime() - lastEvent.occurred.getTime();
|
|
77
|
-
trackEvent({
|
|
78
|
-
...event,
|
|
79
|
-
metadata: {
|
|
80
|
-
...event.metadata,
|
|
81
|
-
lastEventName: lastEvent.message,
|
|
82
|
-
timeSinceLastEvent: duration,
|
|
83
|
-
},
|
|
84
|
-
});
|
|
85
|
-
} else {
|
|
86
|
-
trackEvent(event);
|
|
87
|
-
}
|
|
88
|
-
sessionStorage.setItem('loggerLastEvent', JSON.stringify({ ...event, occurred: new Date() }));
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Gets the last tracked event, if available.
|
|
93
|
-
*/
|
|
94
|
-
export function getLastTrackedEvent(): TrackedReporterEvent | null {
|
|
95
|
-
const eventStr = sessionStorage.getItem('loggerLastEvent');
|
|
96
|
-
if (!eventStr) return null;
|
|
97
|
-
|
|
98
|
-
const event: TrackedReporterEvent = JSON.parse(eventStr);
|
|
99
|
-
event.occurred = new Date(event.occurred);
|
|
100
|
-
return event;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Breadcrumbs to create a trail of events that happened prior to an issue.
|
|
105
|
-
* These events are very similar to traditional logs, but can record more rich structured data.
|
|
106
|
-
*/
|
|
107
|
-
export function addBreadcrumb(breadcrumb: ReporterBreadcrumb): void {
|
|
108
|
-
for (const reporter of getReporters(breadcrumb)) {
|
|
109
|
-
if (reporter.endpoints?.addBreadcrumb === false) {
|
|
110
|
-
continue;
|
|
111
|
-
} else if (breadcrumb.category && reporter.ignoreBreadcrumbCategories?.includes(breadcrumb.category)) {
|
|
112
|
-
continue;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const reporterBreadcrumb = { ...breadcrumb };
|
|
116
|
-
reporterBreadcrumb.metadata = filterReporterMetadata(breadcrumb.metadata, reporter);
|
|
117
|
-
reporter.addBreadcrumb(reporterBreadcrumb);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Adds global metadata to all events and logs.
|
|
123
|
-
* @param metadata Metadata to add.
|
|
124
|
-
* @param filters Optional filters to specify which reporters to add metadata to.
|
|
125
|
-
*/
|
|
126
|
-
export function addMetadata(metadata: Metadata, filters?: ReporterFilters): void {
|
|
127
|
-
for (const reporter of getReporters(filters)) {
|
|
128
|
-
if (reporter.endpoints?.addMetadata === false) {
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
reporter.addMetadata(filterReporterMetadata(metadata, reporter));
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Sets the user information in Analytics.
|
|
137
|
-
* @param user User information, or null to clear.
|
|
138
|
-
* @param filters Optional filters to specify which reporters to set the user for.
|
|
139
|
-
*/
|
|
140
|
-
export function setUser(user: ReportUser | null, filters?: ReporterFilters): void {
|
|
141
|
-
for (const reporter of getReporters(filters)) {
|
|
142
|
-
if (reporter.endpoints?.setUser === false) {
|
|
143
|
-
continue;
|
|
144
|
-
}
|
|
145
|
-
reporter.setUser(user);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Sets the route name in Analytics.
|
|
151
|
-
* Some Analytics services use this differentiate SPA Route vs Page changes.
|
|
152
|
-
* @param routeName Name of the Route.
|
|
153
|
-
* @param filters Optional filters to specify which reporters to set the route name for.
|
|
154
|
-
*/
|
|
155
|
-
export function setRouteName(routeName: string, filters?: ReporterFilters): void {
|
|
156
|
-
for (const reporter of getReporters(filters)) {
|
|
157
|
-
if (reporter.endpoints?.setRouteName === false) {
|
|
158
|
-
continue;
|
|
159
|
-
}
|
|
160
|
-
reporter.setRouteName(routeName);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Sets the page name in Analytics.
|
|
166
|
-
* @param pageName Name of the Page.
|
|
167
|
-
* @param filters Optional filters to specify which reporters to set the page name for.
|
|
168
|
-
*/
|
|
169
|
-
export function setPageName(pageName: string, filters?: ReporterFilters): void {
|
|
170
|
-
for (const reporter of getReporters(filters)) {
|
|
171
|
-
if (reporter.endpoints?.setPageName === false) {
|
|
172
|
-
continue;
|
|
173
|
-
}
|
|
174
|
-
reporter.setPageName(pageName);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* Reports an Error in Reporters that support error tracking.
|
|
180
|
-
* @param error Error data.
|
|
181
|
-
* @param metadata Metadata to add to the error.
|
|
182
|
-
* @param filters Optional filters to specify which reporters to report the error to.
|
|
183
|
-
*/
|
|
184
|
-
export function reportError(error: ReportError, metadata?: Metadata, filters?: ReporterFilters): void {
|
|
185
|
-
for (const reporter of getReporters(filters)) {
|
|
186
|
-
if (reporter.endpoints?.reportError === false) {
|
|
187
|
-
continue;
|
|
188
|
-
}
|
|
189
|
-
reporter.reportError?.(error, filterReporterMetadata(metadata, reporter));
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Report a feature flag evaluation, e.g. for surfacing in Datadog RUM.
|
|
195
|
-
*
|
|
196
|
-
* @param flag Details about the feature flag evaluation
|
|
197
|
-
* @param filters Filters to specify which reporters to start a session recording for.
|
|
198
|
-
*/
|
|
199
|
-
export function reportFeatureFlag(flag: ReporterFlag, filters?: ReporterFilters): void {
|
|
200
|
-
for (const reporter of getReporters(filters)) {
|
|
201
|
-
if (reporter.endpoints?.reportFeatureFlag === false) {
|
|
202
|
-
continue;
|
|
203
|
-
}
|
|
204
|
-
reporter.reportFeatureFlag?.(flag);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Starts a session recording in Analytics, e.g. RUM Session Replay
|
|
210
|
-
* @param filters Optional filters to specify which reporters to start a session recording for.
|
|
211
|
-
*/
|
|
212
|
-
export function recordSession(filters?: ReporterFilters): void {
|
|
213
|
-
for (const reporter of getReporters(filters)) {
|
|
214
|
-
if (reporter.endpoints?.recordSession === false) {
|
|
215
|
-
continue;
|
|
216
|
-
}
|
|
217
|
-
reporter.recordSession?.();
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Stops a session recording in Analytics, e.g. RUM Session Replay
|
|
223
|
-
* @param filters Optional filters to specify which reporters to stop a session recording for.
|
|
224
|
-
*/
|
|
225
|
-
export function recordSessionStop(filters?: ReporterFilters): void {
|
|
226
|
-
for (const reporter of getReporters(filters)) {
|
|
227
|
-
if (reporter.endpoints?.recordSessionStop === false) {
|
|
228
|
-
continue;
|
|
229
|
-
}
|
|
230
|
-
reporter.recordSessionStop?.();
|
|
231
|
-
}
|
|
232
|
-
}
|