@kubesense/kubesense-browser-core 1.3.0 → 1.5.0
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 +40 -15
- package/cjs/boot/init.js +1 -1
- package/cjs/domain/configuration/endpointBuilder.js +1 -1
- package/cjs/domain/configuration/index.d.ts +2 -0
- package/cjs/domain/configuration/index.js +14 -1
- package/cjs/domain/configuration/index.js.map +1 -1
- package/cjs/domain/configuration/remoteSdkConfig.d.ts +81 -0
- package/cjs/domain/configuration/remoteSdkConfig.js +185 -0
- package/cjs/domain/configuration/remoteSdkConfig.js.map +1 -0
- package/cjs/domain/contexts/userContext.d.ts +1 -0
- package/cjs/domain/contexts/userContext.js +4 -0
- package/cjs/domain/contexts/userContext.js.map +1 -1
- package/cjs/domain/tags.js +1 -1
- package/cjs/domain/telemetry/telemetry.js +1 -1
- package/cjs/index.d.ts +2 -1
- package/cjs/index.js +15 -3
- package/cjs/index.js.map +1 -1
- package/esm/boot/init.js +1 -1
- package/esm/domain/configuration/endpointBuilder.js +1 -1
- package/esm/domain/configuration/index.d.ts +2 -0
- package/esm/domain/configuration/index.js +1 -0
- package/esm/domain/configuration/index.js.map +1 -1
- package/esm/domain/configuration/remoteSdkConfig.d.ts +81 -0
- package/esm/domain/configuration/remoteSdkConfig.js +172 -0
- package/esm/domain/configuration/remoteSdkConfig.js.map +1 -0
- package/esm/domain/contexts/userContext.d.ts +1 -0
- package/esm/domain/contexts/userContext.js +4 -0
- package/esm/domain/contexts/userContext.js.map +1 -1
- package/esm/domain/tags.js +1 -1
- package/esm/domain/telemetry/telemetry.js +1 -1
- package/esm/index.d.ts +2 -1
- package/esm/index.js +1 -1
- package/esm/index.js.map +1 -1
- package/package.json +13 -2
- package/src/domain/configuration/index.ts +15 -0
- package/src/domain/configuration/remoteSdkConfig.ts +213 -0
- package/src/domain/contexts/userContext.ts +5 -0
- package/src/index.ts +13 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { InitConfiguration } from './configuration';
|
|
2
|
+
/**
|
|
3
|
+
* Dashboard-managed SDK settings, served by the Kubesense collector.
|
|
4
|
+
*
|
|
5
|
+
* The document is fetched asynchronously *after* the SDK has started and cached in local
|
|
6
|
+
* storage, so it costs nothing on the initialization path. Cached values are applied on the
|
|
7
|
+
* next page load — SDK configuration is frozen at `init()` time by design.
|
|
8
|
+
*/
|
|
9
|
+
export declare const SDK_CONFIG_CACHE_KEY = "_kubesense_sdk_config";
|
|
10
|
+
export declare const SDK_CONFIG_PATH = "/rum/api/v1/sdk-config";
|
|
11
|
+
/** Give up rather than let a hung request keep a page-load handle alive. */
|
|
12
|
+
export declare const SDK_CONFIG_FETCH_TIMEOUT = 10000;
|
|
13
|
+
/**
|
|
14
|
+
* A remote configuration document. Every field is optional: a missing (or invalid) field means
|
|
15
|
+
* "leave the SDK default alone", so a malformed document can never take an application away
|
|
16
|
+
* from its defaults.
|
|
17
|
+
*/
|
|
18
|
+
export interface RemoteSdkConfig {
|
|
19
|
+
/** Free-form number for dashboard bookkeeping. Not interpreted by the SDK. */
|
|
20
|
+
version?: number;
|
|
21
|
+
features?: RemoteSdkConfigFeatures;
|
|
22
|
+
rum?: {
|
|
23
|
+
[key: string]: unknown;
|
|
24
|
+
};
|
|
25
|
+
sessionReplay?: {
|
|
26
|
+
[key: string]: unknown;
|
|
27
|
+
};
|
|
28
|
+
profiling?: {
|
|
29
|
+
[key: string]: unknown;
|
|
30
|
+
};
|
|
31
|
+
logs?: {
|
|
32
|
+
[key: string]: unknown;
|
|
33
|
+
};
|
|
34
|
+
[key: string]: unknown;
|
|
35
|
+
}
|
|
36
|
+
export interface RemoteSdkConfigFeatures {
|
|
37
|
+
rum?: boolean;
|
|
38
|
+
sessionReplay?: boolean;
|
|
39
|
+
profiling?: boolean;
|
|
40
|
+
logs?: boolean;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Read the cached document. Synchronous, never touches the network, and never throws: a
|
|
44
|
+
* corrupted or unavailable cache resolves to `undefined` (pure SDK defaults).
|
|
45
|
+
*/
|
|
46
|
+
export declare function getCachedSdkConfig(): RemoteSdkConfig | undefined;
|
|
47
|
+
export declare function setCachedSdkConfig(rawConfig: string): void;
|
|
48
|
+
export declare function clearCachedSdkConfig(): void;
|
|
49
|
+
/**
|
|
50
|
+
* A document is only usable if it is a JSON object. Anything else (array, primitive, invalid
|
|
51
|
+
* JSON) is rejected wholesale.
|
|
52
|
+
*/
|
|
53
|
+
export declare function parseSdkConfig(raw: string): RemoteSdkConfig | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* The config endpoint deliberately carries the same query parameters as the intake, for two
|
|
56
|
+
* reasons: it authenticates without a custom header (which would force a CORS preflight), and
|
|
57
|
+
* it makes `isIntakeUrl()` return true, so the SDK never reports its own configuration request
|
|
58
|
+
* as a resource or a network error.
|
|
59
|
+
*/
|
|
60
|
+
export declare function buildSdkConfigEndpoint(initConfiguration: InitConfiguration, applicationId?: string): string;
|
|
61
|
+
/**
|
|
62
|
+
* Fetch the document and refresh the cache for the *next* page load. Fire-and-forget: any
|
|
63
|
+
* failure (offline, 404 because the collector has no config file, 401, timeout, malformed
|
|
64
|
+
* body) leaves the existing cache untouched.
|
|
65
|
+
*
|
|
66
|
+
* The response is validated before it overwrites the cache, so a half-written document on the
|
|
67
|
+
* collector can never poison a client.
|
|
68
|
+
*/
|
|
69
|
+
export declare function refreshSdkConfig(initConfiguration: InitConfiguration, applicationId?: string): Promise<void>;
|
|
70
|
+
export declare function readBoolean(source: {
|
|
71
|
+
[key: string]: unknown;
|
|
72
|
+
} | undefined, key: string): boolean | undefined;
|
|
73
|
+
export declare function readSampleRate(source: {
|
|
74
|
+
[key: string]: unknown;
|
|
75
|
+
} | undefined, key: string): number | undefined;
|
|
76
|
+
export declare function readString(source: {
|
|
77
|
+
[key: string]: unknown;
|
|
78
|
+
} | undefined, key: string): string | undefined;
|
|
79
|
+
export declare function readEnum<T extends string>(source: {
|
|
80
|
+
[key: string]: unknown;
|
|
81
|
+
} | undefined, key: string, allowedValues: readonly T[]): T | undefined;
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { generateUUID } from '../../tools/utils/stringUtils';
|
|
2
|
+
import { display } from '../../tools/display';
|
|
3
|
+
import { monitorError } from '../../tools/monitor';
|
|
4
|
+
import { buildEndpointHost } from './endpointBuilder';
|
|
5
|
+
/**
|
|
6
|
+
* Dashboard-managed SDK settings, served by the Kubesense collector.
|
|
7
|
+
*
|
|
8
|
+
* The document is fetched asynchronously *after* the SDK has started and cached in local
|
|
9
|
+
* storage, so it costs nothing on the initialization path. Cached values are applied on the
|
|
10
|
+
* next page load — SDK configuration is frozen at `init()` time by design.
|
|
11
|
+
*/
|
|
12
|
+
export const SDK_CONFIG_CACHE_KEY = '_kubesense_sdk_config';
|
|
13
|
+
export const SDK_CONFIG_PATH = '/rum/api/v1/sdk-config';
|
|
14
|
+
/** Give up rather than let a hung request keep a page-load handle alive. */
|
|
15
|
+
export const SDK_CONFIG_FETCH_TIMEOUT = 10000;
|
|
16
|
+
/**
|
|
17
|
+
* Read the cached document. Synchronous, never touches the network, and never throws: a
|
|
18
|
+
* corrupted or unavailable cache resolves to `undefined` (pure SDK defaults).
|
|
19
|
+
*/
|
|
20
|
+
export function getCachedSdkConfig() {
|
|
21
|
+
let raw;
|
|
22
|
+
try {
|
|
23
|
+
raw = localStorage.getItem(SDK_CONFIG_CACHE_KEY);
|
|
24
|
+
}
|
|
25
|
+
catch (_a) {
|
|
26
|
+
// Local storage can be unavailable (disabled, quota, sandboxed iframe).
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
if (!raw) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
const config = parseSdkConfig(raw);
|
|
33
|
+
if (!config) {
|
|
34
|
+
// Drop a document we can no longer read so we stop paying for it on every page load.
|
|
35
|
+
clearCachedSdkConfig();
|
|
36
|
+
}
|
|
37
|
+
return config;
|
|
38
|
+
}
|
|
39
|
+
export function setCachedSdkConfig(rawConfig) {
|
|
40
|
+
try {
|
|
41
|
+
localStorage.setItem(SDK_CONFIG_CACHE_KEY, rawConfig);
|
|
42
|
+
}
|
|
43
|
+
catch (_a) {
|
|
44
|
+
// Ignore: caching is an optimization, not a requirement.
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export function clearCachedSdkConfig() {
|
|
48
|
+
try {
|
|
49
|
+
localStorage.removeItem(SDK_CONFIG_CACHE_KEY);
|
|
50
|
+
}
|
|
51
|
+
catch (_a) {
|
|
52
|
+
// Ignore.
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* A document is only usable if it is a JSON object. Anything else (array, primitive, invalid
|
|
57
|
+
* JSON) is rejected wholesale.
|
|
58
|
+
*/
|
|
59
|
+
export function parseSdkConfig(raw) {
|
|
60
|
+
try {
|
|
61
|
+
const parsed = JSON.parse(raw);
|
|
62
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
return parsed;
|
|
66
|
+
}
|
|
67
|
+
catch (_a) {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The config endpoint deliberately carries the same query parameters as the intake, for two
|
|
73
|
+
* reasons: it authenticates without a custom header (which would force a CORS preflight), and
|
|
74
|
+
* it makes `isIntakeUrl()` return true, so the SDK never reports its own configuration request
|
|
75
|
+
* as a resource or a network error.
|
|
76
|
+
*/
|
|
77
|
+
export function buildSdkConfigEndpoint(initConfiguration, applicationId) {
|
|
78
|
+
const host = buildEndpointHost('rum', initConfiguration);
|
|
79
|
+
const parameters = [
|
|
80
|
+
'ksource=browser',
|
|
81
|
+
`kubesense-api-key=${encodeURIComponent(initConfiguration.clientToken)}`,
|
|
82
|
+
`kubesense-request-id=${generateUUID()}`,
|
|
83
|
+
];
|
|
84
|
+
if (applicationId) {
|
|
85
|
+
// The collector resolves the application from this parameter first, falling back to the
|
|
86
|
+
// token -> application mapping. Sending it makes per-application configuration explicit.
|
|
87
|
+
parameters.push(`application_id=${encodeURIComponent(applicationId)}`);
|
|
88
|
+
}
|
|
89
|
+
return `https://${host}${SDK_CONFIG_PATH}?${parameters.join('&')}`;
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Fetch the document and refresh the cache for the *next* page load. Fire-and-forget: any
|
|
93
|
+
* failure (offline, 404 because the collector has no config file, 401, timeout, malformed
|
|
94
|
+
* body) leaves the existing cache untouched.
|
|
95
|
+
*
|
|
96
|
+
* The response is validated before it overwrites the cache, so a half-written document on the
|
|
97
|
+
* collector can never poison a client.
|
|
98
|
+
*/
|
|
99
|
+
export function refreshSdkConfig(initConfiguration, applicationId) {
|
|
100
|
+
if (typeof fetch !== 'function') {
|
|
101
|
+
return Promise.resolve();
|
|
102
|
+
}
|
|
103
|
+
let endpoint;
|
|
104
|
+
try {
|
|
105
|
+
endpoint = buildSdkConfigEndpoint(initConfiguration, applicationId);
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
monitorError(error);
|
|
109
|
+
return Promise.resolve();
|
|
110
|
+
}
|
|
111
|
+
return fetch(endpoint, {
|
|
112
|
+
method: 'GET',
|
|
113
|
+
// Configuration is not user data: never attach cookies to it.
|
|
114
|
+
credentials: 'omit',
|
|
115
|
+
mode: 'cors',
|
|
116
|
+
// Always ask the collector, never a proxy cache — dashboard edits must propagate.
|
|
117
|
+
cache: 'no-store',
|
|
118
|
+
signal: createTimeoutSignal(SDK_CONFIG_FETCH_TIMEOUT),
|
|
119
|
+
})
|
|
120
|
+
.then((response) => {
|
|
121
|
+
if (!response.ok) {
|
|
122
|
+
// 404 simply means "no configuration published"; keep whatever we already had.
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
return response.text();
|
|
126
|
+
})
|
|
127
|
+
.then((rawConfig) => {
|
|
128
|
+
if (rawConfig === undefined) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
if (!parseSdkConfig(rawConfig)) {
|
|
132
|
+
display.warn('Remote SDK configuration is not a valid JSON object, ignoring it.');
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
setCachedSdkConfig(rawConfig);
|
|
136
|
+
})
|
|
137
|
+
.catch(() => {
|
|
138
|
+
// Network failures are expected and must stay silent: the SDK keeps running on the
|
|
139
|
+
// cached configuration, or on its defaults.
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
function createTimeoutSignal(timeout) {
|
|
143
|
+
// AbortSignal.timeout is not available on all supported browsers; without it the fetch
|
|
144
|
+
// simply runs to completion, which is acceptable for a fire-and-forget request.
|
|
145
|
+
if (typeof AbortSignal !== 'undefined' && typeof AbortSignal.timeout === 'function') {
|
|
146
|
+
return AbortSignal.timeout(timeout);
|
|
147
|
+
}
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
/* ------------------------------------------------------------------------------------------
|
|
151
|
+
* Defensive readers
|
|
152
|
+
*
|
|
153
|
+
* Each returns `undefined` when the value is missing or unusable, which callers translate into
|
|
154
|
+
* "do not override the SDK default".
|
|
155
|
+
* ---------------------------------------------------------------------------------------- */
|
|
156
|
+
export function readBoolean(source, key) {
|
|
157
|
+
const value = source === null || source === void 0 ? void 0 : source[key];
|
|
158
|
+
return typeof value === 'boolean' ? value : undefined;
|
|
159
|
+
}
|
|
160
|
+
export function readSampleRate(source, key) {
|
|
161
|
+
const value = source === null || source === void 0 ? void 0 : source[key];
|
|
162
|
+
return typeof value === 'number' && isFinite(value) && value >= 0 && value <= 100 ? value : undefined;
|
|
163
|
+
}
|
|
164
|
+
export function readString(source, key) {
|
|
165
|
+
const value = source === null || source === void 0 ? void 0 : source[key];
|
|
166
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined;
|
|
167
|
+
}
|
|
168
|
+
export function readEnum(source, key, allowedValues) {
|
|
169
|
+
const value = source === null || source === void 0 ? void 0 : source[key];
|
|
170
|
+
return typeof value === 'string' && allowedValues.includes(value) ? value : undefined;
|
|
171
|
+
}
|
|
172
|
+
//# sourceMappingURL=remoteSdkConfig.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remoteSdkConfig.js","sourceRoot":"","sources":["../../../src/domain/configuration/remoteSdkConfig.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,7 @@ export interface User {
|
|
|
6
6
|
id?: string | undefined;
|
|
7
7
|
email?: string | undefined;
|
|
8
8
|
name?: string | undefined;
|
|
9
|
+
mobile?: string | undefined;
|
|
9
10
|
[key: string]: unknown;
|
|
10
11
|
}
|
|
11
12
|
export declare function startUserContext(hooks: AbstractHooks, configuration: Configuration, sessionManager: {
|
|
@@ -110,6 +110,10 @@ export function buildUserContextManager() {
|
|
|
110
110
|
id: { type: 'string' },
|
|
111
111
|
name: { type: 'string' },
|
|
112
112
|
email: { type: 'string' },
|
|
113
|
+
// Coerced to string like the other identity fields: phone numbers are
|
|
114
|
+
// routinely passed as JS numbers, and the collector unmarshals
|
|
115
|
+
// usr.mobile into a string column.
|
|
116
|
+
mobile: { type: 'string' },
|
|
113
117
|
},
|
|
114
118
|
});
|
|
115
119
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"userContext.js","sourceRoot":"","sources":["../../../src/domain/contexts/userContext.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,EAAa,OAAO,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAEhE,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAA;AAE7D,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAA;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAA;AAEjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;
|
|
1
|
+
{"version":3,"file":"userContext.js","sourceRoot":"","sources":["../../../src/domain/contexts/userContext.ts"],"names":[],"mappings":"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"}
|
package/esm/domain/tags.js
CHANGED
|
@@ -2,7 +2,7 @@ import { DOCS_ORIGIN, MORE_DETAILS, display } from '../tools/display';
|
|
|
2
2
|
export const TAG_SIZE_LIMIT = 200;
|
|
3
3
|
export function buildTags(configuration) {
|
|
4
4
|
const { env, service, version, datacenter, sdkVersion, variant } = configuration;
|
|
5
|
-
const tags = [buildTag('sdk_version', sdkVersion !== null && sdkVersion !== void 0 ? sdkVersion : "1.
|
|
5
|
+
const tags = [buildTag('sdk_version', sdkVersion !== null && sdkVersion !== void 0 ? sdkVersion : "1.5.0")];
|
|
6
6
|
if (env) {
|
|
7
7
|
tags.push(buildTag('env', env));
|
|
8
8
|
}
|
|
@@ -96,7 +96,7 @@ export function startTelemetryCollection(telemetryService, configuration, hooks,
|
|
|
96
96
|
type: 'telemetry',
|
|
97
97
|
date: clockNow.timeStamp,
|
|
98
98
|
service: telemetryService,
|
|
99
|
-
version: "1.
|
|
99
|
+
version: "1.5.0",
|
|
100
100
|
source: 'browser',
|
|
101
101
|
_kubesense: {
|
|
102
102
|
format_version: 2,
|
package/esm/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export type { Configuration, InitConfiguration, EndpointBuilder, ProxyFn } from './domain/configuration';
|
|
2
|
-
export {
|
|
2
|
+
export type { RemoteSdkConfig, RemoteSdkConfigFeatures } from './domain/configuration';
|
|
3
|
+
export { validateAndBuildConfiguration, DefaultPrivacyLevel, TraceContextInjection, serializeConfiguration, isSampleRate, buildEndpointHost, INTAKE_URL_PARAMETERS, INTAKE_SITE_PROD, INTAKE_SITE_STAGING, isIntakeUrl, SDK_CONFIG_CACHE_KEY, SDK_CONFIG_PATH, buildSdkConfigEndpoint, clearCachedSdkConfig, getCachedSdkConfig, parseSdkConfig, readBoolean, readEnum, readSampleRate, readString, refreshSdkConfig, setCachedSdkConfig, } from './domain/configuration';
|
|
3
4
|
export * from './domain/intakeSites';
|
|
4
5
|
export type { TrackingConsentState } from './domain/trackingConsent';
|
|
5
6
|
export { TrackingConsent, createTrackingConsentState } from './domain/trackingConsent';
|
package/esm/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { validateAndBuildConfiguration, DefaultPrivacyLevel, TraceContextInjection, serializeConfiguration, isSampleRate, buildEndpointHost, INTAKE_URL_PARAMETERS, INTAKE_SITE_PROD, INTAKE_SITE_STAGING, isIntakeUrl, } from './domain/configuration';
|
|
1
|
+
export { validateAndBuildConfiguration, DefaultPrivacyLevel, TraceContextInjection, serializeConfiguration, isSampleRate, buildEndpointHost, INTAKE_URL_PARAMETERS, INTAKE_SITE_PROD, INTAKE_SITE_STAGING, isIntakeUrl, SDK_CONFIG_CACHE_KEY, SDK_CONFIG_PATH, buildSdkConfigEndpoint, clearCachedSdkConfig, getCachedSdkConfig, parseSdkConfig, readBoolean, readEnum, readSampleRate, readString, refreshSdkConfig, setCachedSdkConfig, } from './domain/configuration';
|
|
2
2
|
export * from './domain/intakeSites';
|
|
3
3
|
export { TrackingConsent, createTrackingConsentState } from './domain/trackingConsent';
|
|
4
4
|
export { isExperimentalFeatureEnabled, addExperimentalFeatures, resetExperimentalFeatures, getExperimentalFeatures, initFeatureFlags, ExperimentalFeature, } from './tools/experimentalFeatures';
|
package/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubesense/kubesense-browser-core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
|
+
"description": "Core utilities shared across the Kubesense Browser SDK (session management, transport, configuration, and context).",
|
|
4
5
|
"license": "Apache-2.0",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"kubesense",
|
|
8
|
+
"browser",
|
|
9
|
+
"sdk",
|
|
10
|
+
"monitoring",
|
|
11
|
+
"observability",
|
|
12
|
+
"telemetry",
|
|
13
|
+
"rum",
|
|
14
|
+
"core"
|
|
15
|
+
],
|
|
5
16
|
"main": "cjs/index.js",
|
|
6
17
|
"module": "esm/index.js",
|
|
7
18
|
"types": "cjs/index.d.ts",
|
|
@@ -24,5 +35,5 @@
|
|
|
24
35
|
"publishConfig": {
|
|
25
36
|
"access": "public"
|
|
26
37
|
},
|
|
27
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "01223bc403c9f02d866e98a88e891388014ea471"
|
|
28
39
|
}
|
|
@@ -8,5 +8,20 @@ export {
|
|
|
8
8
|
} from './configuration'
|
|
9
9
|
export type { EndpointBuilder, TrackType } from './endpointBuilder'
|
|
10
10
|
export { createEndpointBuilder, buildEndpointHost } from './endpointBuilder'
|
|
11
|
+
export type { RemoteSdkConfig, RemoteSdkConfigFeatures } from './remoteSdkConfig'
|
|
12
|
+
export {
|
|
13
|
+
SDK_CONFIG_CACHE_KEY,
|
|
14
|
+
SDK_CONFIG_PATH,
|
|
15
|
+
buildSdkConfigEndpoint,
|
|
16
|
+
clearCachedSdkConfig,
|
|
17
|
+
getCachedSdkConfig,
|
|
18
|
+
parseSdkConfig,
|
|
19
|
+
readBoolean,
|
|
20
|
+
readEnum,
|
|
21
|
+
readSampleRate,
|
|
22
|
+
readString,
|
|
23
|
+
refreshSdkConfig,
|
|
24
|
+
setCachedSdkConfig,
|
|
25
|
+
} from './remoteSdkConfig'
|
|
11
26
|
export * from '../intakeSites'
|
|
12
27
|
export { computeTransportConfiguration, isIntakeUrl } from './transportConfiguration'
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { generateUUID } from '../../tools/utils/stringUtils'
|
|
2
|
+
import { display } from '../../tools/display'
|
|
3
|
+
import { monitorError } from '../../tools/monitor'
|
|
4
|
+
import type { InitConfiguration } from './configuration'
|
|
5
|
+
import { buildEndpointHost } from './endpointBuilder'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Dashboard-managed SDK settings, served by the Kubesense collector.
|
|
9
|
+
*
|
|
10
|
+
* The document is fetched asynchronously *after* the SDK has started and cached in local
|
|
11
|
+
* storage, so it costs nothing on the initialization path. Cached values are applied on the
|
|
12
|
+
* next page load — SDK configuration is frozen at `init()` time by design.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export const SDK_CONFIG_CACHE_KEY = '_kubesense_sdk_config'
|
|
16
|
+
export const SDK_CONFIG_PATH = '/rum/api/v1/sdk-config'
|
|
17
|
+
|
|
18
|
+
/** Give up rather than let a hung request keep a page-load handle alive. */
|
|
19
|
+
export const SDK_CONFIG_FETCH_TIMEOUT = 10_000
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* A remote configuration document. Every field is optional: a missing (or invalid) field means
|
|
23
|
+
* "leave the SDK default alone", so a malformed document can never take an application away
|
|
24
|
+
* from its defaults.
|
|
25
|
+
*/
|
|
26
|
+
export interface RemoteSdkConfig {
|
|
27
|
+
/** Free-form number for dashboard bookkeeping. Not interpreted by the SDK. */
|
|
28
|
+
version?: number
|
|
29
|
+
features?: RemoteSdkConfigFeatures
|
|
30
|
+
rum?: { [key: string]: unknown }
|
|
31
|
+
sessionReplay?: { [key: string]: unknown }
|
|
32
|
+
profiling?: { [key: string]: unknown }
|
|
33
|
+
logs?: { [key: string]: unknown }
|
|
34
|
+
[key: string]: unknown
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface RemoteSdkConfigFeatures {
|
|
38
|
+
rum?: boolean
|
|
39
|
+
sessionReplay?: boolean
|
|
40
|
+
profiling?: boolean
|
|
41
|
+
logs?: boolean
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Read the cached document. Synchronous, never touches the network, and never throws: a
|
|
46
|
+
* corrupted or unavailable cache resolves to `undefined` (pure SDK defaults).
|
|
47
|
+
*/
|
|
48
|
+
export function getCachedSdkConfig(): RemoteSdkConfig | undefined {
|
|
49
|
+
let raw: string | null
|
|
50
|
+
try {
|
|
51
|
+
raw = localStorage.getItem(SDK_CONFIG_CACHE_KEY)
|
|
52
|
+
} catch {
|
|
53
|
+
// Local storage can be unavailable (disabled, quota, sandboxed iframe).
|
|
54
|
+
return undefined
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!raw) {
|
|
58
|
+
return undefined
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const config = parseSdkConfig(raw)
|
|
62
|
+
if (!config) {
|
|
63
|
+
// Drop a document we can no longer read so we stop paying for it on every page load.
|
|
64
|
+
clearCachedSdkConfig()
|
|
65
|
+
}
|
|
66
|
+
return config
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function setCachedSdkConfig(rawConfig: string) {
|
|
70
|
+
try {
|
|
71
|
+
localStorage.setItem(SDK_CONFIG_CACHE_KEY, rawConfig)
|
|
72
|
+
} catch {
|
|
73
|
+
// Ignore: caching is an optimization, not a requirement.
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function clearCachedSdkConfig() {
|
|
78
|
+
try {
|
|
79
|
+
localStorage.removeItem(SDK_CONFIG_CACHE_KEY)
|
|
80
|
+
} catch {
|
|
81
|
+
// Ignore.
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* A document is only usable if it is a JSON object. Anything else (array, primitive, invalid
|
|
87
|
+
* JSON) is rejected wholesale.
|
|
88
|
+
*/
|
|
89
|
+
export function parseSdkConfig(raw: string): RemoteSdkConfig | undefined {
|
|
90
|
+
try {
|
|
91
|
+
const parsed: unknown = JSON.parse(raw)
|
|
92
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
93
|
+
return undefined
|
|
94
|
+
}
|
|
95
|
+
return parsed as RemoteSdkConfig
|
|
96
|
+
} catch {
|
|
97
|
+
return undefined
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* The config endpoint deliberately carries the same query parameters as the intake, for two
|
|
103
|
+
* reasons: it authenticates without a custom header (which would force a CORS preflight), and
|
|
104
|
+
* it makes `isIntakeUrl()` return true, so the SDK never reports its own configuration request
|
|
105
|
+
* as a resource or a network error.
|
|
106
|
+
*/
|
|
107
|
+
export function buildSdkConfigEndpoint(initConfiguration: InitConfiguration, applicationId?: string): string {
|
|
108
|
+
const host = buildEndpointHost('rum', initConfiguration)
|
|
109
|
+
const parameters = [
|
|
110
|
+
'ksource=browser',
|
|
111
|
+
`kubesense-api-key=${encodeURIComponent(initConfiguration.clientToken)}`,
|
|
112
|
+
`kubesense-request-id=${generateUUID()}`,
|
|
113
|
+
]
|
|
114
|
+
if (applicationId) {
|
|
115
|
+
// The collector resolves the application from this parameter first, falling back to the
|
|
116
|
+
// token -> application mapping. Sending it makes per-application configuration explicit.
|
|
117
|
+
parameters.push(`application_id=${encodeURIComponent(applicationId)}`)
|
|
118
|
+
}
|
|
119
|
+
return `https://${host}${SDK_CONFIG_PATH}?${parameters.join('&')}`
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Fetch the document and refresh the cache for the *next* page load. Fire-and-forget: any
|
|
124
|
+
* failure (offline, 404 because the collector has no config file, 401, timeout, malformed
|
|
125
|
+
* body) leaves the existing cache untouched.
|
|
126
|
+
*
|
|
127
|
+
* The response is validated before it overwrites the cache, so a half-written document on the
|
|
128
|
+
* collector can never poison a client.
|
|
129
|
+
*/
|
|
130
|
+
export function refreshSdkConfig(initConfiguration: InitConfiguration, applicationId?: string): Promise<void> {
|
|
131
|
+
if (typeof fetch !== 'function') {
|
|
132
|
+
return Promise.resolve()
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
let endpoint: string
|
|
136
|
+
try {
|
|
137
|
+
endpoint = buildSdkConfigEndpoint(initConfiguration, applicationId)
|
|
138
|
+
} catch (error) {
|
|
139
|
+
monitorError(error)
|
|
140
|
+
return Promise.resolve()
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return fetch(endpoint, {
|
|
144
|
+
method: 'GET',
|
|
145
|
+
// Configuration is not user data: never attach cookies to it.
|
|
146
|
+
credentials: 'omit',
|
|
147
|
+
mode: 'cors',
|
|
148
|
+
// Always ask the collector, never a proxy cache — dashboard edits must propagate.
|
|
149
|
+
cache: 'no-store',
|
|
150
|
+
signal: createTimeoutSignal(SDK_CONFIG_FETCH_TIMEOUT),
|
|
151
|
+
})
|
|
152
|
+
.then((response) => {
|
|
153
|
+
if (!response.ok) {
|
|
154
|
+
// 404 simply means "no configuration published"; keep whatever we already had.
|
|
155
|
+
return undefined
|
|
156
|
+
}
|
|
157
|
+
return response.text()
|
|
158
|
+
})
|
|
159
|
+
.then((rawConfig) => {
|
|
160
|
+
if (rawConfig === undefined) {
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
if (!parseSdkConfig(rawConfig)) {
|
|
164
|
+
display.warn('Remote SDK configuration is not a valid JSON object, ignoring it.')
|
|
165
|
+
return
|
|
166
|
+
}
|
|
167
|
+
setCachedSdkConfig(rawConfig)
|
|
168
|
+
})
|
|
169
|
+
.catch(() => {
|
|
170
|
+
// Network failures are expected and must stay silent: the SDK keeps running on the
|
|
171
|
+
// cached configuration, or on its defaults.
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function createTimeoutSignal(timeout: number): AbortSignal | undefined {
|
|
176
|
+
// AbortSignal.timeout is not available on all supported browsers; without it the fetch
|
|
177
|
+
// simply runs to completion, which is acceptable for a fire-and-forget request.
|
|
178
|
+
if (typeof AbortSignal !== 'undefined' && typeof AbortSignal.timeout === 'function') {
|
|
179
|
+
return AbortSignal.timeout(timeout)
|
|
180
|
+
}
|
|
181
|
+
return undefined
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/* ------------------------------------------------------------------------------------------
|
|
185
|
+
* Defensive readers
|
|
186
|
+
*
|
|
187
|
+
* Each returns `undefined` when the value is missing or unusable, which callers translate into
|
|
188
|
+
* "do not override the SDK default".
|
|
189
|
+
* ---------------------------------------------------------------------------------------- */
|
|
190
|
+
|
|
191
|
+
export function readBoolean(source: { [key: string]: unknown } | undefined, key: string): boolean | undefined {
|
|
192
|
+
const value = source?.[key]
|
|
193
|
+
return typeof value === 'boolean' ? value : undefined
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export function readSampleRate(source: { [key: string]: unknown } | undefined, key: string): number | undefined {
|
|
197
|
+
const value = source?.[key]
|
|
198
|
+
return typeof value === 'number' && isFinite(value) && value >= 0 && value <= 100 ? value : undefined
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export function readString(source: { [key: string]: unknown } | undefined, key: string): string | undefined {
|
|
202
|
+
const value = source?.[key]
|
|
203
|
+
return typeof value === 'string' && value.length > 0 ? value : undefined
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function readEnum<T extends string>(
|
|
207
|
+
source: { [key: string]: unknown } | undefined,
|
|
208
|
+
key: string,
|
|
209
|
+
allowedValues: readonly T[]
|
|
210
|
+
): T | undefined {
|
|
211
|
+
const value = source?.[key]
|
|
212
|
+
return typeof value === 'string' && (allowedValues as readonly string[]).includes(value) ? (value as T) : undefined
|
|
213
|
+
}
|
|
@@ -16,6 +16,7 @@ export interface User {
|
|
|
16
16
|
id?: string | undefined
|
|
17
17
|
email?: string | undefined
|
|
18
18
|
name?: string | undefined
|
|
19
|
+
mobile?: string | undefined
|
|
19
20
|
[key: string]: unknown
|
|
20
21
|
}
|
|
21
22
|
|
|
@@ -143,6 +144,10 @@ export function buildUserContextManager() {
|
|
|
143
144
|
id: { type: 'string' },
|
|
144
145
|
name: { type: 'string' },
|
|
145
146
|
email: { type: 'string' },
|
|
147
|
+
// Coerced to string like the other identity fields: phone numbers are
|
|
148
|
+
// routinely passed as JS numbers, and the collector unmarshals
|
|
149
|
+
// usr.mobile into a string column.
|
|
150
|
+
mobile: { type: 'string' },
|
|
146
151
|
},
|
|
147
152
|
})
|
|
148
153
|
}
|