@dash0/sdk-web 0.13.1 → 0.13.3
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/README.md +15 -1
- package/dist/dash0.iife.js +1 -1
- package/dist/dash0.iife.js.map +1 -1
- package/dist/dash0.js +1 -1
- package/dist/dash0.js.map +1 -1
- package/dist/dash0.umd.cjs +1 -1
- package/dist/dash0.umd.cjs.map +1 -1
- package/dist/modules/api/log-level.js +1 -0
- package/dist/modules/entrypoint/npm-package.js +1 -0
- package/dist/modules/entrypoint/script.js +2 -0
- package/dist/modules/instrumentations/http/fetch.js +5 -2
- package/dist/modules/semantic-conventions.js +2 -0
- package/dist/modules/transport/fetch.js +2 -1
- package/dist/modules/utils/debug.js +20 -10
- package/dist/modules/utils/performance.js +43 -19
- package/dist/modules/vars.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/api/log-level.d.ts +2 -0
- package/dist/types/entrypoint/npm-package.d.ts +1 -0
- package/dist/types/semantic-conventions.d.ts +1 -0
- package/dist/types/utils/debug.d.ts +11 -1
- package/dist/types/vars.d.ts +1 -1
- package/package.json +1 -1
- package/src/api/log-level.ts +2 -0
- package/src/entrypoint/npm-package.ts +1 -0
- package/src/entrypoint/script.ts +2 -0
- package/src/instrumentations/http/fetch.ts +5 -1
- package/src/semantic-conventions.ts +3 -0
- package/src/transport/fetch.ts +3 -1
- package/src/utils/debug.ts +25 -10
- package/src/utils/performance.ts +55 -22
- package/src/vars.ts +2 -2
package/src/utils/debug.ts
CHANGED
|
@@ -1,25 +1,40 @@
|
|
|
1
1
|
import { noop } from "./fn";
|
|
2
2
|
|
|
3
|
+
const logLevels = {
|
|
4
|
+
debug: 0,
|
|
5
|
+
info: 1,
|
|
6
|
+
warn: 2,
|
|
7
|
+
error: 3,
|
|
8
|
+
} as const;
|
|
9
|
+
|
|
10
|
+
export type LogLevel = keyof typeof logLevels;
|
|
11
|
+
|
|
12
|
+
let activeLogLevel: number = logLevels.warn;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Changes the logging verbosity of Dash0's web SDK. By default, only warnings and errors are logged.
|
|
16
|
+
*/
|
|
17
|
+
export function setActiveLogLevel(level: LogLevel) {
|
|
18
|
+
activeLogLevel = logLevels[level] ?? logLevels.warn;
|
|
19
|
+
}
|
|
20
|
+
|
|
3
21
|
type Logger = (...args: any[]) => void;
|
|
4
22
|
|
|
5
|
-
export const log: Logger = createLogger("log");
|
|
6
23
|
export const info: Logger = createLogger("info");
|
|
7
24
|
export const warn: Logger = createLogger("warn");
|
|
8
25
|
export const error: Logger = createLogger("error");
|
|
9
26
|
export const debug: Logger = createLogger("debug");
|
|
10
27
|
|
|
11
|
-
function createLogger(
|
|
12
|
-
if (typeof console
|
|
13
|
-
|
|
14
|
-
}
|
|
28
|
+
function createLogger(logLevel: LogLevel): Logger {
|
|
29
|
+
if (typeof console !== "undefined" && console[logLevel] && typeof console[logLevel].apply === "function") {
|
|
30
|
+
const numericLogLevel = logLevels[logLevel];
|
|
15
31
|
|
|
16
|
-
if (console[method] && typeof console[method].apply === "function") {
|
|
17
32
|
return function () {
|
|
18
|
-
|
|
33
|
+
if (numericLogLevel >= activeLogLevel) {
|
|
34
|
+
console[logLevel].apply(console, arguments as any);
|
|
35
|
+
}
|
|
19
36
|
};
|
|
20
37
|
}
|
|
21
38
|
|
|
22
|
-
return
|
|
23
|
-
console.log.apply(console, arguments as any);
|
|
24
|
-
};
|
|
39
|
+
return noop;
|
|
25
40
|
}
|
package/src/utils/performance.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { addEventListener, removeEventListener } from "./listeners";
|
|
|
6
6
|
|
|
7
7
|
const TEN_MINUTES_IN_MILLIS = 1000 * 60 * 10;
|
|
8
8
|
const ONE_DAY_IN_MILLIS = 1000 * 60 * 60 * 24;
|
|
9
|
+
const OBSERVER_WAIT_TIME_MS = 300;
|
|
9
10
|
|
|
10
11
|
export const isResourceTimingAvailable = !!(perf && perf.getEntriesByType);
|
|
11
12
|
export const isPerformanceObserverAvailable =
|
|
@@ -57,6 +58,8 @@ type PerformanceObservationContoller = {
|
|
|
57
58
|
cancel: () => void;
|
|
58
59
|
};
|
|
59
60
|
|
|
61
|
+
const usedResources = new WeakSet<PerformanceResourceTiming>();
|
|
62
|
+
|
|
60
63
|
export function observeResourcePerformance(opts: ObserveResourcePerformanceOptions): PerformanceObservationContoller {
|
|
61
64
|
if (!isPerformanceObserverAvailable) return observeWithoutPerformanceObserverSupport(opts.onEnd);
|
|
62
65
|
|
|
@@ -64,7 +67,7 @@ export function observeResourcePerformance(opts: ObserveResourcePerformanceOptio
|
|
|
64
67
|
let startTime: number;
|
|
65
68
|
let endTime: number;
|
|
66
69
|
|
|
67
|
-
|
|
70
|
+
const resources: PerformanceResourceTiming[] = [];
|
|
68
71
|
|
|
69
72
|
// Global resources that will need to be disposed
|
|
70
73
|
let observer: PerformanceObserver | undefined;
|
|
@@ -100,43 +103,40 @@ export function observeResourcePerformance(opts: ObserveResourcePerformanceOptio
|
|
|
100
103
|
endTime = perf.now();
|
|
101
104
|
cancelFallbackEndNeverCalledTimer();
|
|
102
105
|
|
|
103
|
-
if (
|
|
104
|
-
end();
|
|
105
|
-
} else {
|
|
106
|
-
addEventListener(doc!, "visibilitychange", onVisibilityChanged);
|
|
107
|
-
fallbackNoResourceFoundTimerHandle = setTimeout(end, opts.maxWaitForResourceMillis);
|
|
106
|
+
if (!isWaitingAcceptable()) {
|
|
107
|
+
return end();
|
|
108
108
|
}
|
|
109
|
+
|
|
110
|
+
setTimeout(() => end(), Math.min(OBSERVER_WAIT_TIME_MS, opts.maxWaitForResourceMillis));
|
|
111
|
+
addEventListener(doc!, "visibilitychange", onVisibilityChanged);
|
|
112
|
+
fallbackNoResourceFoundTimerHandle = setTimeout(end, opts.maxWaitForResourceMillis);
|
|
109
113
|
}
|
|
110
114
|
|
|
111
115
|
function end() {
|
|
112
116
|
disposeGlobalResources();
|
|
113
117
|
|
|
118
|
+
const resource = findBestMatchingResource();
|
|
119
|
+
|
|
114
120
|
// In some old web browsers, e.g. Chrome 31, the value provided as the duration
|
|
115
121
|
// can be very wrong. We have seen cases where this value is measured in years.
|
|
116
122
|
// If this does seem be the case, then we will ignore the duration property and
|
|
117
123
|
// instead prefer our approximation.
|
|
118
124
|
if (resource?.duration && resource.duration < ONE_DAY_IN_MILLIS) {
|
|
119
|
-
opts.onEnd({ resource, duration:
|
|
125
|
+
opts.onEnd({ resource, duration: resource.duration });
|
|
120
126
|
} else {
|
|
121
|
-
opts.onEnd({ resource, duration:
|
|
127
|
+
opts.onEnd({ resource, duration: endTime - startTime });
|
|
122
128
|
}
|
|
123
129
|
}
|
|
124
130
|
|
|
125
131
|
function onResourceFound(list: PerformanceObserverEntryList) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
entry
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
if (!r) return;
|
|
137
|
-
|
|
138
|
-
resource = r as PerformanceResourceTiming;
|
|
139
|
-
if (endTime) end();
|
|
132
|
+
list
|
|
133
|
+
.getEntriesByType("resource")
|
|
134
|
+
.filter((e) => {
|
|
135
|
+
// This polymorphism is not properly represented in the api types. The cast is safe since we're only accessing the resource timings.
|
|
136
|
+
const entry = e as PerformanceResourceTiming;
|
|
137
|
+
return entry.startTime >= startTime && opts.resourceMatcher(entry);
|
|
138
|
+
})
|
|
139
|
+
.forEach((entry) => resources.push(entry as PerformanceResourceTiming));
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
function onVisibilityChanged() {
|
|
@@ -179,6 +179,39 @@ export function observeResourcePerformance(opts: ObserveResourcePerformanceOptio
|
|
|
179
179
|
if (!doc) return;
|
|
180
180
|
removeEventListener(doc, "visibilitychange", onVisibilityChanged);
|
|
181
181
|
}
|
|
182
|
+
|
|
183
|
+
function findBestMatchingResource(): PerformanceResourceTiming | undefined {
|
|
184
|
+
if (!resources.length) return undefined;
|
|
185
|
+
|
|
186
|
+
let bestMatch: PerformanceResourceTiming | undefined;
|
|
187
|
+
const matchingResources = resources.filter(
|
|
188
|
+
(res) => res.responseEnd <= endTime + opts.maxToleranceForResourceTimingsMillis && !usedResources.has(res)
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
if (!matchingResources.length) {
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (matchingResources.length === 1) {
|
|
196
|
+
bestMatch = matchingResources[0];
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
let bestScore: number | undefined;
|
|
200
|
+
if (!bestMatch) {
|
|
201
|
+
for (const res of matchingResources) {
|
|
202
|
+
const score = Math.abs(endTime - startTime - res.duration) + Math.abs(res.responseEnd - endTime);
|
|
203
|
+
if (bestScore === undefined || score < bestScore) {
|
|
204
|
+
bestScore = score;
|
|
205
|
+
bestMatch = res;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (!bestMatch) return;
|
|
211
|
+
|
|
212
|
+
usedResources.add(bestMatch);
|
|
213
|
+
return bestMatch;
|
|
214
|
+
}
|
|
182
215
|
}
|
|
183
216
|
|
|
184
217
|
// We may only wait for resource data to arrive as long as the document is visible or in the process
|
package/src/vars.ts
CHANGED
|
@@ -129,7 +129,7 @@ export type Vars = {
|
|
|
129
129
|
* applied when matching a request to its respective performance entry. A higher value might increase match frequency at
|
|
130
130
|
* the cost of potential incorrect matches. Matching is performed based on request timing and url.
|
|
131
131
|
*
|
|
132
|
-
* @default
|
|
132
|
+
* @default 50
|
|
133
133
|
*/
|
|
134
134
|
maxToleranceForResourceTimingsMillis: number;
|
|
135
135
|
|
|
@@ -160,7 +160,7 @@ export const vars: Vars = {
|
|
|
160
160
|
wrapTimers: true,
|
|
161
161
|
propagateTraceHeadersCorsURLs: [],
|
|
162
162
|
maxWaitForResourceTimingsMillis: 10000,
|
|
163
|
-
maxToleranceForResourceTimingsMillis:
|
|
163
|
+
maxToleranceForResourceTimingsMillis: 50,
|
|
164
164
|
headersToCapture: [],
|
|
165
165
|
pageViewInstrumentation: {
|
|
166
166
|
trackVirtualPageViews: true,
|