@posthog/browser-common 0.9.2 → 0.9.4
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/dist/client.d.ts +4 -2
- package/dist/config.js +1 -1
- package/dist/config.mjs +1 -1
- package/dist/console-logs.d.ts +15 -0
- package/dist/console-logs.js +317 -0
- package/dist/console-logs.mjs +276 -0
- package/dist/constants.d.ts +16 -0
- package/dist/constants.js +64 -0
- package/dist/constants.mjs +17 -1
- package/dist/extension-tokens.d.ts +4 -0
- package/dist/extension-tokens.js +40 -0
- package/dist/extension-tokens.mjs +2 -0
- package/dist/extension.d.ts +4 -0
- package/dist/feature-flags-config.d.ts +23 -0
- package/dist/feature-flags-config.js +18 -0
- package/dist/feature-flags-config.mjs +1 -0
- package/dist/feature-flags.d.ts +329 -0
- package/dist/feature-flags.js +1222 -0
- package/dist/feature-flags.mjs +1172 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +15 -7
- package/dist/index.mjs +1 -0
- package/dist/logs-config.d.ts +24 -0
- package/dist/logs-config.js +80 -0
- package/dist/logs-config.mjs +42 -0
- package/dist/logs-types.d.ts +31 -0
- package/dist/logs-types.js +46 -0
- package/dist/logs-types.mjs +8 -0
- package/dist/logs.d.ts +85 -0
- package/dist/logs.js +469 -0
- package/dist/logs.mjs +428 -0
- package/dist/token.d.ts +1 -1
- package/dist/types/feature-flags.d.ts +18 -0
- package/dist/types/feature-flags.js +18 -0
- package/dist/types/feature-flags.mjs +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +7 -0
- package/dist/types/index.mjs +1 -0
- package/dist/utils/console-original.d.ts +6 -0
- package/dist/utils/console-original.js +43 -0
- package/dist/utils/console-original.mjs +5 -0
- package/dist/utils/event-utils.d.ts +1 -1
- package/dist/utils/event-utils.js +3 -9
- package/dist/utils/event-utils.mjs +1 -7
- package/dist/utils/logger.js +8 -3
- package/dist/utils/logger.mjs +8 -3
- package/dist/utils/patch.d.ts +3 -0
- package/dist/utils/patch.js +90 -0
- package/dist/utils/patch.mjs +52 -0
- package/dist/utils/request-reachability.d.ts +2 -0
- package/dist/utils/request-reachability.js +61 -0
- package/dist/utils/request-reachability.mjs +20 -0
- package/dist/utils/request-utils.d.ts +1 -2
- package/dist/utils/request-utils.js +3 -14
- package/dist/utils/request-utils.mjs +3 -14
- package/dist/utils/sanitize-url.d.ts +11 -0
- package/dist/utils/sanitize-url.js +55 -0
- package/dist/utils/sanitize-url.mjs +17 -0
- package/dist/utils/timezone.d.ts +1 -0
- package/dist/utils/timezone.js +46 -0
- package/dist/utils/timezone.mjs +8 -0
- package/package.json +59 -3
package/dist/logs.mjs
ADDED
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
import { PostHogLogs, PostHogPersistedProperty, buildOtlpLogsPayload, buildResourceAttributes, isNullish } from "@posthog/core";
|
|
2
|
+
import { continueWith } from "./utils/promise-utils.mjs";
|
|
3
|
+
import { addEventListener } from "./utils/general-utils.mjs";
|
|
4
|
+
import { createLogger } from "./utils/logger.mjs";
|
|
5
|
+
import { resolveLogsConfig } from "./logs-config.mjs";
|
|
6
|
+
import { BUFFERED_CONSOLE_LEVELS } from "./logs-types.mjs";
|
|
7
|
+
import { patch } from "./utils/patch.mjs";
|
|
8
|
+
import { originalConsoleMethod } from "./utils/console-original.mjs";
|
|
9
|
+
import { isStatusZeroFailureCircuitBreakerTripped, updateStatusZeroFailureCount } from "./utils/request-reachability.mjs";
|
|
10
|
+
const RECORDER_MAX_AGE_MS = 30000;
|
|
11
|
+
const CONSOLE_SCOPE_NAME = 'console';
|
|
12
|
+
const LOGS_SEND_TIMEOUT_MS = 90000;
|
|
13
|
+
const MAX_CONSECUTIVE_STATUS_ZERO_FAILURES = 3;
|
|
14
|
+
const HANDLED_LOGS_REQUEST_ERROR = '__posthogHandledLogsRequestError';
|
|
15
|
+
const markLogsRequestErrorAsHandled = (error, fallbackMessage)=>{
|
|
16
|
+
const handledError = error instanceof Error ? error : new Error(fallbackMessage);
|
|
17
|
+
handledError[HANDLED_LOGS_REQUEST_ERROR] = true;
|
|
18
|
+
return handledError;
|
|
19
|
+
};
|
|
20
|
+
const isHandledLogsRequestError = (error)=>!!error && 'object' == typeof error && true === error[HANDLED_LOGS_REQUEST_ERROR];
|
|
21
|
+
class logs_PostHogLogs {
|
|
22
|
+
get _coreLogger() {
|
|
23
|
+
return {
|
|
24
|
+
...this._logger,
|
|
25
|
+
error: (...args)=>{
|
|
26
|
+
if (!args.some(isHandledLogsRequestError)) this._logger.error(...args);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
constructor(_configSource, _getSdkContext){
|
|
31
|
+
this._configSource = _configSource;
|
|
32
|
+
this._getSdkContext = _getSdkContext;
|
|
33
|
+
this.name = 'logs';
|
|
34
|
+
this._isLogsEnabled = false;
|
|
35
|
+
this._isLoaded = false;
|
|
36
|
+
this._isLoading = false;
|
|
37
|
+
this._logger = createLogger('[logs]');
|
|
38
|
+
this._queue = [];
|
|
39
|
+
this._consoleQueue = [];
|
|
40
|
+
this._consecutiveStatusZeroFailures = 0;
|
|
41
|
+
this._setupStarted = false;
|
|
42
|
+
this._disposed = false;
|
|
43
|
+
this._consoleBuffer = [];
|
|
44
|
+
this._consoleRecorderUnpatchers = [];
|
|
45
|
+
this._isRecordingConsole = false;
|
|
46
|
+
this._isRecordingConsoleEntry = false;
|
|
47
|
+
this._listeningForReconnect = false;
|
|
48
|
+
this._onReconnect = ()=>{
|
|
49
|
+
if (this._disposed) return;
|
|
50
|
+
this._consecutiveStatusZeroFailures = 0;
|
|
51
|
+
this._core?.onReconnect();
|
|
52
|
+
this._consoleCore?.onReconnect();
|
|
53
|
+
};
|
|
54
|
+
this._isLogsEnabled = !!_configSource.get()?.captureConsoleLogs;
|
|
55
|
+
}
|
|
56
|
+
get _isRequestReady() {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
_getConsoleLoader() {}
|
|
60
|
+
_listenForReconnect() {
|
|
61
|
+
if (this._listeningForReconnect) return;
|
|
62
|
+
try {
|
|
63
|
+
this._window = "u" < typeof window ? void 0 : window;
|
|
64
|
+
} catch {
|
|
65
|
+
this._window = void 0;
|
|
66
|
+
}
|
|
67
|
+
if (this._window) {
|
|
68
|
+
addEventListener(this._window, 'online', this._onReconnect);
|
|
69
|
+
this._listeningForReconnect = true;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
_buildCore(getQueue, setQueue, opts, scopeName) {
|
|
73
|
+
this._listenForReconnect();
|
|
74
|
+
const config = resolveLogsConfig(this._configSource.get(), opts);
|
|
75
|
+
const core = new PostHogLogs(this._createHost(getQueue, setQueue), config, this._coreLogger, ()=>this._getSdkContext(), (fn)=>fn(), void 0, scopeName);
|
|
76
|
+
return [
|
|
77
|
+
core,
|
|
78
|
+
config
|
|
79
|
+
];
|
|
80
|
+
}
|
|
81
|
+
_getCore() {
|
|
82
|
+
const logsConfig = this._configSource.get();
|
|
83
|
+
if (!this._core || this._resolvedFrom !== logsConfig) {
|
|
84
|
+
this._core?.reset();
|
|
85
|
+
this._resolvedFrom = logsConfig;
|
|
86
|
+
[this._core, this._resolvedConfig] = this._buildCore(()=>this._queue, (q)=>{
|
|
87
|
+
this._queue = q;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return this._core;
|
|
91
|
+
}
|
|
92
|
+
_getConsoleCore() {
|
|
93
|
+
const logsConfig = this._configSource.get();
|
|
94
|
+
if (!this._consoleCore || this._consoleResolvedFrom !== logsConfig) {
|
|
95
|
+
this._consoleCore?.reset();
|
|
96
|
+
this._consoleResolvedFrom = logsConfig;
|
|
97
|
+
[this._consoleCore, this._consoleResolvedConfig] = this._buildCore(()=>this._consoleQueue, (q)=>{
|
|
98
|
+
this._consoleQueue = q;
|
|
99
|
+
}, {
|
|
100
|
+
serviceNameDefault: 'posthog-browser-logs',
|
|
101
|
+
consoleCapture: true
|
|
102
|
+
}, CONSOLE_SCOPE_NAME);
|
|
103
|
+
}
|
|
104
|
+
return this._consoleCore;
|
|
105
|
+
}
|
|
106
|
+
setup(client) {
|
|
107
|
+
if (this._disposed || this._setupStarted) return;
|
|
108
|
+
this._setupStarted = true;
|
|
109
|
+
this._client = client;
|
|
110
|
+
this._logger = client.logger.createLogger('[logs]');
|
|
111
|
+
return continueWith(client.kv.initialize(), ()=>{
|
|
112
|
+
if (!this._disposed) this._finishSetup(client);
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
_finishSetup(client) {
|
|
116
|
+
this._listenForReconnect();
|
|
117
|
+
if (this._configSource.get()?.captureConsoleLogs) this._isLogsEnabled = true;
|
|
118
|
+
if (this._isLogsEnabled || this._configSource.remoteConfigWillArrive && client.kv.get(this._configSource.captureHintKey)) this._startConsoleRecorder();
|
|
119
|
+
let replayedEnabledConfig = false;
|
|
120
|
+
const subscription = client.onRemoteConfig((result)=>{
|
|
121
|
+
replayedEnabledConfig = result.ok && result.config.logs?.captureConsoleLogs === true;
|
|
122
|
+
this.onRemoteConfig(result);
|
|
123
|
+
});
|
|
124
|
+
if (this._disposed) return void subscription.dispose();
|
|
125
|
+
this._remoteConfigSubscription = subscription;
|
|
126
|
+
if (!replayedEnabledConfig) this.loadIfEnabled();
|
|
127
|
+
}
|
|
128
|
+
dispose() {
|
|
129
|
+
if (this._disposed) return;
|
|
130
|
+
this._disposed = true;
|
|
131
|
+
this._stopConsoleRecorder();
|
|
132
|
+
this._remoteConfigSubscription?.dispose();
|
|
133
|
+
this._remoteConfigSubscription = void 0;
|
|
134
|
+
this._client = void 0;
|
|
135
|
+
this._isLoading = false;
|
|
136
|
+
this._window?.removeEventListener('online', this._onReconnect);
|
|
137
|
+
this._consoleLogsDispose?.();
|
|
138
|
+
this._consoleLogsDispose = void 0;
|
|
139
|
+
this._core?.clearQueue();
|
|
140
|
+
this._consoleCore?.clearQueue();
|
|
141
|
+
this._core?.reset();
|
|
142
|
+
this._consoleCore?.reset();
|
|
143
|
+
}
|
|
144
|
+
onRemoteConfig(result) {
|
|
145
|
+
if (this._disposed) return;
|
|
146
|
+
const logCapture = result.ok ? result.config.logs?.captureConsoleLogs : void 0;
|
|
147
|
+
if (isNullish(logCapture)) return void this._stopRecorderStartedByPersistedHint();
|
|
148
|
+
this._client?.kv.set(this._configSource.captureHintKey, !!logCapture);
|
|
149
|
+
if (!logCapture) return void this._stopRecorderStartedByPersistedHint();
|
|
150
|
+
this._isLogsEnabled = true;
|
|
151
|
+
if (!this._isLoaded) this._startConsoleRecorder();
|
|
152
|
+
this.loadIfEnabled();
|
|
153
|
+
}
|
|
154
|
+
reset() {
|
|
155
|
+
this._stopConsoleRecorder();
|
|
156
|
+
this._core?.clearQueue();
|
|
157
|
+
this._queue = [];
|
|
158
|
+
this._core?.reset();
|
|
159
|
+
this._consoleCore?.clearQueue();
|
|
160
|
+
this._consoleQueue = [];
|
|
161
|
+
this._consoleCore?.reset();
|
|
162
|
+
this._consecutiveStatusZeroFailures = 0;
|
|
163
|
+
}
|
|
164
|
+
captureLog(options) {
|
|
165
|
+
if (!this._disposed && this._client) this._getCore().captureLog(options);
|
|
166
|
+
}
|
|
167
|
+
captureConsoleLog(options) {
|
|
168
|
+
if (!this._disposed && this._client) this._getConsoleCore().captureLog(options);
|
|
169
|
+
}
|
|
170
|
+
captureBufferedConsoleLog(options, context, occurredAtMs) {
|
|
171
|
+
if (!this._disposed && this._client) this._getConsoleCore().captureLog(options, {
|
|
172
|
+
context,
|
|
173
|
+
occurredAtMs
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
_onOptOut() {
|
|
177
|
+
this._stopConsoleRecorder();
|
|
178
|
+
this._consoleCore?.clearQueue();
|
|
179
|
+
this._consoleQueue = [];
|
|
180
|
+
}
|
|
181
|
+
_stopRecorderStartedByPersistedHint() {
|
|
182
|
+
if (this._isLogsEnabled) return;
|
|
183
|
+
this._stopConsoleRecorder();
|
|
184
|
+
}
|
|
185
|
+
_startConsoleRecorder() {
|
|
186
|
+
if (this._isRecordingConsole || !this._window?.console) return;
|
|
187
|
+
const maxBufferSize = resolveLogsConfig(this._configSource.get()).maxBufferSize;
|
|
188
|
+
let active = true;
|
|
189
|
+
this._consoleRecorderUnpatchers.push(()=>{
|
|
190
|
+
active = false;
|
|
191
|
+
});
|
|
192
|
+
for (const level of BUFFERED_CONSOLE_LEVELS){
|
|
193
|
+
let trueOriginal;
|
|
194
|
+
try {
|
|
195
|
+
trueOriginal = originalConsoleMethod(this._window.console[level]);
|
|
196
|
+
} catch {
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
if (trueOriginal) this._consoleRecorderUnpatchers.push(patch(this._window.console, level, (next)=>{
|
|
200
|
+
const wrapped = (...args)=>{
|
|
201
|
+
try {
|
|
202
|
+
if (active) this._recordConsoleEntry(level, args, maxBufferSize);
|
|
203
|
+
} catch {}
|
|
204
|
+
return next.apply(this._window.console, args);
|
|
205
|
+
};
|
|
206
|
+
wrapped.__rrweb_original__ = trueOriginal;
|
|
207
|
+
return wrapped;
|
|
208
|
+
}));
|
|
209
|
+
}
|
|
210
|
+
this._isRecordingConsole = true;
|
|
211
|
+
this._consoleRecorderTimeout = setTimeout(()=>{
|
|
212
|
+
this._stopConsoleRecorder();
|
|
213
|
+
}, RECORDER_MAX_AGE_MS);
|
|
214
|
+
}
|
|
215
|
+
_recordConsoleEntry(level, args, maxBufferSize) {
|
|
216
|
+
if (!this._isRecordingConsole || this._isRecordingConsoleEntry || 0 === args.length) return;
|
|
217
|
+
if (!this._client?.canCapture) return void this._stopConsoleRecorder();
|
|
218
|
+
if (this._consoleBuffer.length >= maxBufferSize) return;
|
|
219
|
+
this._isRecordingConsoleEntry = true;
|
|
220
|
+
try {
|
|
221
|
+
this._consoleBuffer.push({
|
|
222
|
+
level,
|
|
223
|
+
args,
|
|
224
|
+
occurredAtMs: Date.now(),
|
|
225
|
+
context: this._getSdkContext()
|
|
226
|
+
});
|
|
227
|
+
} finally{
|
|
228
|
+
this._isRecordingConsoleEntry = false;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
_stopConsoleRecorder() {
|
|
232
|
+
this._consoleBuffer = [];
|
|
233
|
+
if (!this._isRecordingConsole) return;
|
|
234
|
+
this._isRecordingConsole = false;
|
|
235
|
+
if (this._consoleRecorderTimeout) {
|
|
236
|
+
clearTimeout(this._consoleRecorderTimeout);
|
|
237
|
+
this._consoleRecorderTimeout = void 0;
|
|
238
|
+
}
|
|
239
|
+
for (const unpatch of this._consoleRecorderUnpatchers)unpatch();
|
|
240
|
+
this._consoleRecorderUnpatchers = [];
|
|
241
|
+
}
|
|
242
|
+
_takeConsoleBuffer() {
|
|
243
|
+
const buffered = this._consoleBuffer;
|
|
244
|
+
this._stopConsoleRecorder();
|
|
245
|
+
return buffered;
|
|
246
|
+
}
|
|
247
|
+
get logger() {
|
|
248
|
+
if (!this._capture_logger) this._capture_logger = {
|
|
249
|
+
trace: (body, attributes)=>this.captureLog({
|
|
250
|
+
body,
|
|
251
|
+
level: 'trace',
|
|
252
|
+
attributes
|
|
253
|
+
}),
|
|
254
|
+
debug: (body, attributes)=>this.captureLog({
|
|
255
|
+
body,
|
|
256
|
+
level: 'debug',
|
|
257
|
+
attributes
|
|
258
|
+
}),
|
|
259
|
+
info: (body, attributes)=>this.captureLog({
|
|
260
|
+
body,
|
|
261
|
+
level: 'info',
|
|
262
|
+
attributes
|
|
263
|
+
}),
|
|
264
|
+
warn: (body, attributes)=>this.captureLog({
|
|
265
|
+
body,
|
|
266
|
+
level: 'warn',
|
|
267
|
+
attributes
|
|
268
|
+
}),
|
|
269
|
+
error: (body, attributes)=>this.captureLog({
|
|
270
|
+
body,
|
|
271
|
+
level: 'error',
|
|
272
|
+
attributes
|
|
273
|
+
}),
|
|
274
|
+
fatal: (body, attributes)=>this.captureLog({
|
|
275
|
+
body,
|
|
276
|
+
level: 'fatal',
|
|
277
|
+
attributes
|
|
278
|
+
})
|
|
279
|
+
};
|
|
280
|
+
return this._capture_logger;
|
|
281
|
+
}
|
|
282
|
+
flushLogs(transport) {
|
|
283
|
+
if (!this._client) return;
|
|
284
|
+
if (transport) return void this._flushViaTransport(transport);
|
|
285
|
+
if (this._core) this._core.flush().catch((err)=>this._logFlushError(err));
|
|
286
|
+
if (this._consoleCore) this._consoleCore.flush().catch((err)=>this._logFlushError(err));
|
|
287
|
+
}
|
|
288
|
+
async flush() {
|
|
289
|
+
const programmatic = this._core?.flush().catch((error)=>this._logFlushError(error));
|
|
290
|
+
const console = this._consoleCore?.flush().catch((error)=>this._logFlushError(error));
|
|
291
|
+
await programmatic;
|
|
292
|
+
await console;
|
|
293
|
+
}
|
|
294
|
+
_logFlushError(error) {
|
|
295
|
+
if (!isHandledLogsRequestError(error)) this._logger.error('PostHog logs flush failed:', error);
|
|
296
|
+
}
|
|
297
|
+
loadIfEnabled() {
|
|
298
|
+
if (this._disposed || !this._isLogsEnabled || this._isLoaded || this._isLoading) return;
|
|
299
|
+
const loadConsole = this._getConsoleLoader();
|
|
300
|
+
if (!loadConsole) return void this._stopConsoleRecorder();
|
|
301
|
+
this._isLoading = true;
|
|
302
|
+
try {
|
|
303
|
+
loadConsole((err, logsExtension)=>{
|
|
304
|
+
this._isLoading = false;
|
|
305
|
+
if (this._disposed || !this._isLogsEnabled) return;
|
|
306
|
+
if (err || !logsExtension) {
|
|
307
|
+
this._logger.error("Could not load logs script", err);
|
|
308
|
+
this._stopConsoleRecorder();
|
|
309
|
+
} else {
|
|
310
|
+
const buffered = this._takeConsoleBuffer();
|
|
311
|
+
this._consoleLogsDispose = logsExtension.initialize(this._client);
|
|
312
|
+
this._isLoaded = true;
|
|
313
|
+
if (buffered.length > 0) logsExtension.replay(this._client, buffered);
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
} catch (error) {
|
|
317
|
+
this._isLoading = false;
|
|
318
|
+
throw error;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
_createHost(getQueue, setQueue) {
|
|
322
|
+
const client = this._client;
|
|
323
|
+
return {
|
|
324
|
+
get isDisabled () {
|
|
325
|
+
return false;
|
|
326
|
+
},
|
|
327
|
+
get optedOut () {
|
|
328
|
+
return !client.canCapture;
|
|
329
|
+
},
|
|
330
|
+
getPersistedProperty: (key)=>key === PostHogPersistedProperty.LogsQueue ? getQueue() : void 0,
|
|
331
|
+
setPersistedProperty: (key, value)=>{
|
|
332
|
+
if (key === PostHogPersistedProperty.LogsQueue) setQueue(value ?? []);
|
|
333
|
+
},
|
|
334
|
+
_sendLogsBatch: (payload)=>this._sendLogsBatch(payload),
|
|
335
|
+
getLibraryId: ()=>client.library.name,
|
|
336
|
+
getLibraryVersion: ()=>client.library.version
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
_sendLogsBatch(payload) {
|
|
340
|
+
return new Promise((resolve)=>{
|
|
341
|
+
if (isStatusZeroFailureCircuitBreakerTripped(this._consecutiveStatusZeroFailures, MAX_CONSECUTIVE_STATUS_ZERO_FAILURES)) return void resolve({
|
|
342
|
+
kind: 'fatal',
|
|
343
|
+
error: markLogsRequestErrorAsHandled(void 0, 'logs endpoint is unreachable, dropping batch')
|
|
344
|
+
});
|
|
345
|
+
let settled = false;
|
|
346
|
+
const settle = (outcome)=>{
|
|
347
|
+
if (settled) return;
|
|
348
|
+
settled = true;
|
|
349
|
+
clearTimeout(timer);
|
|
350
|
+
resolve(outcome);
|
|
351
|
+
};
|
|
352
|
+
const timer = setTimeout(()=>{
|
|
353
|
+
this._logger.warn('Logs request timed out before receiving a response');
|
|
354
|
+
settle({
|
|
355
|
+
kind: 'retry-later',
|
|
356
|
+
error: markLogsRequestErrorAsHandled(void 0, 'logs request timed out')
|
|
357
|
+
});
|
|
358
|
+
}, LOGS_SEND_TIMEOUT_MS);
|
|
359
|
+
const isRequestReady = this._isRequestReady;
|
|
360
|
+
this._client.sendRequest('/i/v1/logs', {
|
|
361
|
+
method: 'POST',
|
|
362
|
+
query: {
|
|
363
|
+
token: this._client.projectToken
|
|
364
|
+
},
|
|
365
|
+
body: payload,
|
|
366
|
+
compression: 'best-available',
|
|
367
|
+
timeoutMs: 60000
|
|
368
|
+
}).then((response)=>{
|
|
369
|
+
const status = response.statusCode;
|
|
370
|
+
this._trackEndpointReachability(status, isRequestReady);
|
|
371
|
+
if (status >= 200 && status < 300) settle({
|
|
372
|
+
kind: 'ok'
|
|
373
|
+
});
|
|
374
|
+
else if (413 === status) settle({
|
|
375
|
+
kind: 'too-large'
|
|
376
|
+
});
|
|
377
|
+
else if (0 === status || 408 === status || 429 === status || status >= 500) if (0 === status) {
|
|
378
|
+
if (!response.error) this._logger.warn('Logs request failed before receiving an HTTP response');
|
|
379
|
+
settle({
|
|
380
|
+
kind: 'retry-later',
|
|
381
|
+
error: markLogsRequestErrorAsHandled(response.error, 'logs request failed before receiving an HTTP response')
|
|
382
|
+
});
|
|
383
|
+
} else settle({
|
|
384
|
+
kind: 'retry-later',
|
|
385
|
+
error: response.error ?? new Error(`logs request failed with status ${status}`)
|
|
386
|
+
});
|
|
387
|
+
else settle({
|
|
388
|
+
kind: 'fatal',
|
|
389
|
+
error: new Error(`logs request failed with status ${status}`)
|
|
390
|
+
});
|
|
391
|
+
}, (error)=>{
|
|
392
|
+
settle({
|
|
393
|
+
kind: 'retry-later',
|
|
394
|
+
error
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
_trackEndpointReachability(statusCode, isRequestReady) {
|
|
400
|
+
if (0 === statusCode && !isRequestReady) return;
|
|
401
|
+
this._consecutiveStatusZeroFailures = updateStatusZeroFailureCount(statusCode, this._consecutiveStatusZeroFailures, MAX_CONSECUTIVE_STATUS_ZERO_FAILURES, ()=>this._logger.warn('Log requests are failing before receiving an HTTP response; this can happen due to network issues, CORS, browser blocking, or ad blockers. Stopped sending logs; will try again when connectivity changes.'));
|
|
402
|
+
}
|
|
403
|
+
_flushViaTransport(transport) {
|
|
404
|
+
if (this._queue.length > 0) this._drainQueueViaTransport(transport, this._queue, this._resolvedConfig, this._client.library.name, (q)=>{
|
|
405
|
+
this._queue = q;
|
|
406
|
+
});
|
|
407
|
+
if (this._consoleQueue.length > 0) this._drainQueueViaTransport(transport, this._consoleQueue, this._consoleResolvedConfig, CONSOLE_SCOPE_NAME, (q)=>{
|
|
408
|
+
this._consoleQueue = q;
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
_drainQueueViaTransport(transport, queue, config, scopeName, setQueue) {
|
|
412
|
+
if (0 === queue.length) return;
|
|
413
|
+
const records = queue.map((e)=>e.record);
|
|
414
|
+
setQueue([]);
|
|
415
|
+
const payload = buildOtlpLogsPayload(records, buildResourceAttributes(config, this._client.library.name, this._client.library.version), scopeName, this._client.library.version);
|
|
416
|
+
this._client.sendRequest('/i/v1/logs', {
|
|
417
|
+
method: 'POST',
|
|
418
|
+
query: {
|
|
419
|
+
token: this._client.projectToken
|
|
420
|
+
},
|
|
421
|
+
body: payload,
|
|
422
|
+
compression: 'best-available',
|
|
423
|
+
transport,
|
|
424
|
+
timeoutMs: 60000
|
|
425
|
+
}).catch((error)=>this._logFlushError(error));
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
export { RECORDER_MAX_AGE_MS, logs_PostHogLogs as PostHogLogs };
|
package/dist/token.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ declare const extensionTokenType: unique symbol;
|
|
|
6
6
|
* Tokens are plain strings at runtime, so independently compiled scripts can
|
|
7
7
|
* share them without a registry or object-identity contract. The generic brand
|
|
8
8
|
* lets `Client.getExtension` infer the extension type. A token's string
|
|
9
|
-
* value must
|
|
9
|
+
* value must match an installed extension's stable `name` or one of its `bindings` keys.
|
|
10
10
|
*/
|
|
11
11
|
export type ExtensionToken<T> = string & {
|
|
12
12
|
readonly [extensionTokenType]: T;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { FeatureFlagDetail, JsonType } from '@posthog/types';
|
|
2
|
+
import type { RemoteConfig } from './remote-config';
|
|
3
|
+
/**
|
|
4
|
+
* Flags returns feature flags and their payloads
|
|
5
|
+
*/
|
|
6
|
+
export interface FlagsResponse extends RemoteConfig {
|
|
7
|
+
featureFlags: Record<string, string | boolean>;
|
|
8
|
+
featureFlagPayloads: Record<string, JsonType>;
|
|
9
|
+
errorsWhileComputingFlags: boolean;
|
|
10
|
+
requestId?: string;
|
|
11
|
+
flags: Record<string, FeatureFlagDetail>;
|
|
12
|
+
evaluatedAt?: number;
|
|
13
|
+
/**
|
|
14
|
+
* Server-controlled gate for minimal `$feature_flag_called` events. `true` only when the
|
|
15
|
+
* project opted in; omitted otherwise. Absence always means full events.
|
|
16
|
+
*/
|
|
17
|
+
minimalFlagCalledEvents?: boolean;
|
|
18
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.r = (exports1)=>{
|
|
5
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
6
|
+
value: 'Module'
|
|
7
|
+
});
|
|
8
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
9
|
+
value: true
|
|
10
|
+
});
|
|
11
|
+
};
|
|
12
|
+
})();
|
|
13
|
+
var __webpack_exports__ = {};
|
|
14
|
+
__webpack_require__.r(__webpack_exports__);
|
|
15
|
+
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
16
|
+
Object.defineProperty(exports, '__esModule', {
|
|
17
|
+
value: true
|
|
18
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
package/dist/types/index.d.ts
CHANGED
package/dist/types/index.js
CHANGED
|
@@ -3,6 +3,9 @@ var __webpack_modules__ = {
|
|
|
3
3
|
"./compression" (module) {
|
|
4
4
|
module.exports = require("./compression.js");
|
|
5
5
|
},
|
|
6
|
+
"./feature-flags" (module) {
|
|
7
|
+
module.exports = require("./feature-flags.js");
|
|
8
|
+
},
|
|
6
9
|
"./network-recording" (module) {
|
|
7
10
|
module.exports = require("./network-recording.js");
|
|
8
11
|
},
|
|
@@ -76,6 +79,10 @@ var __webpack_exports__ = {};
|
|
|
76
79
|
var __rspack_reexport = {};
|
|
77
80
|
for(const __rspack_import_key in _surveys__rspack_import_3)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_surveys__rspack_import_3[__rspack_import_key];
|
|
78
81
|
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
82
|
+
var _feature_flags__rspack_import_4 = __webpack_require__("./feature-flags");
|
|
83
|
+
var __rspack_reexport = {};
|
|
84
|
+
for(const __rspack_import_key in _feature_flags__rspack_import_4)if ("default" !== __rspack_import_key) __rspack_reexport[__rspack_import_key] = ()=>_feature_flags__rspack_import_4[__rspack_import_key];
|
|
85
|
+
__webpack_require__.d(__webpack_exports__, __rspack_reexport);
|
|
79
86
|
})();
|
|
80
87
|
for(var __rspack_i in __webpack_exports__)exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
81
88
|
Object.defineProperty(exports, '__esModule', {
|
package/dist/types/index.mjs
CHANGED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walks the `__rrweb_original__` markers console plugins leave behind to reach the
|
|
3
|
+
* real console method. Shared by the main bundle's recorder and the logs entrypoint
|
|
4
|
+
* so a change to the marker protocol can't be applied to only one of them.
|
|
5
|
+
*/
|
|
6
|
+
export declare const originalConsoleMethod: (method: any) => any;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
3
|
+
(()=>{
|
|
4
|
+
__webpack_require__.d = (exports1, getters, values)=>{
|
|
5
|
+
var define = (defs, kind)=>{
|
|
6
|
+
for(var key in defs)if (__webpack_require__.o(defs, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
[kind]: defs[key]
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
define(getters, "get");
|
|
12
|
+
define(values, "value");
|
|
13
|
+
};
|
|
14
|
+
})();
|
|
15
|
+
(()=>{
|
|
16
|
+
__webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
|
|
17
|
+
})();
|
|
18
|
+
(()=>{
|
|
19
|
+
__webpack_require__.r = (exports1)=>{
|
|
20
|
+
if ("u" > typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
|
|
21
|
+
value: 'Module'
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(exports1, '__esModule', {
|
|
24
|
+
value: true
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
})();
|
|
28
|
+
var __webpack_exports__ = {};
|
|
29
|
+
__webpack_require__.r(__webpack_exports__);
|
|
30
|
+
const originalConsoleMethod = (method)=>{
|
|
31
|
+
while(method?.__rrweb_original__)method = method.__rrweb_original__;
|
|
32
|
+
return method;
|
|
33
|
+
};
|
|
34
|
+
__webpack_require__.d(__webpack_exports__, {}, {
|
|
35
|
+
originalConsoleMethod: originalConsoleMethod
|
|
36
|
+
});
|
|
37
|
+
exports.originalConsoleMethod = __webpack_exports__.originalConsoleMethod;
|
|
38
|
+
for(var __rspack_i in __webpack_exports__)if (-1 === [
|
|
39
|
+
"originalConsoleMethod"
|
|
40
|
+
].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];
|
|
41
|
+
Object.defineProperty(exports, '__esModule', {
|
|
42
|
+
value: true
|
|
43
|
+
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { getTimezone } from './timezone';
|
|
1
2
|
import type { Properties } from '@posthog/types';
|
|
2
3
|
import type { BrowserDetectionHints } from '@posthog/core';
|
|
3
4
|
export declare const PERSONAL_DATA_CAMPAIGN_PARAMS: string[];
|
|
@@ -18,7 +19,6 @@ export declare function getPersonInfo(maskPersonalDataProperties?: boolean, cust
|
|
|
18
19
|
};
|
|
19
20
|
export declare function getPersonPropsFromInfo(info: Record<string, any>, disableCaptureUrlHashes?: boolean): Record<string, any>;
|
|
20
21
|
export declare function getInitialPersonPropsFromInfo(info: Record<string, any>, disableCaptureUrlHashes?: boolean): Record<string, any>;
|
|
21
|
-
export declare function getTimezone(): string | undefined;
|
|
22
22
|
export declare function getTimezoneOffset(): number | undefined;
|
|
23
23
|
export declare function getBrowserDetectionHints(): BrowserDetectionHints;
|
|
24
24
|
export declare function getEventProperties(maskPersonalDataProperties?: boolean, customPersonalDataProperties?: string[], detectGoogleSearchApp?: boolean, disableCaptureUrlHashes?: boolean): Properties;
|
|
@@ -54,9 +54,10 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
54
54
|
getReferrerInfo: ()=>getReferrerInfo,
|
|
55
55
|
getReferringDomain: ()=>getReferringDomain,
|
|
56
56
|
getSearchInfo: ()=>getSearchInfo,
|
|
57
|
-
getTimezone: ()=>getTimezone,
|
|
57
|
+
getTimezone: ()=>external_timezone_js_namespaceObject.getTimezone,
|
|
58
58
|
getTimezoneOffset: ()=>getTimezoneOffset
|
|
59
59
|
});
|
|
60
|
+
const external_timezone_js_namespaceObject = require("./timezone.js");
|
|
60
61
|
const external_request_utils_js_namespaceObject = require("./request-utils.js");
|
|
61
62
|
const core_namespaceObject = require("@posthog/core");
|
|
62
63
|
const external_config_js_namespaceObject = require("../config.js");
|
|
@@ -235,13 +236,6 @@ function getInitialPersonPropsFromInfo(info, disableCaptureUrlHashes = false) {
|
|
|
235
236
|
});
|
|
236
237
|
return props;
|
|
237
238
|
}
|
|
238
|
-
function getTimezone() {
|
|
239
|
-
try {
|
|
240
|
-
return Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
241
|
-
} catch {
|
|
242
|
-
return;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
239
|
function getTimezoneOffset() {
|
|
246
240
|
try {
|
|
247
241
|
return new Date().getTimezoneOffset();
|
|
@@ -285,7 +279,7 @@ function getEventProperties(maskPersonalDataProperties, customPersonalDataProper
|
|
|
285
279
|
$webview_app_version: webviewAppVersion,
|
|
286
280
|
$device: (0, core_namespaceObject.detectDevice)(external_globals_js_namespaceObject.userAgent),
|
|
287
281
|
$device_type: (0, core_namespaceObject.detectDeviceType)(external_globals_js_namespaceObject.userAgent, deviceOptions),
|
|
288
|
-
$timezone: getTimezone(),
|
|
282
|
+
$timezone: (0, external_timezone_js_namespaceObject.getTimezone)(),
|
|
289
283
|
$timezone_offset: getTimezoneOffset()
|
|
290
284
|
}), {
|
|
291
285
|
$current_url: (0, external_request_utils_js_namespaceObject.maskQueryParams)(disableCaptureUrlHashes ? (0, core_namespaceObject.stripUrlHash)(external_globals_js_namespaceObject.location?.href) : external_globals_js_namespaceObject.location?.href, paramsToMask, MASKED),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getTimezone } from "./timezone.mjs";
|
|
1
2
|
import { convertToURL, getQueryParam, maskQueryParams } from "./request-utils.mjs";
|
|
2
3
|
import { detectBrowser, detectBrowserVersion, detectDevice, detectDeviceType, detectOS, detectWebviewApp, isNull, isUndefined, stripLeadingDollar, stripUrlHash } from "@posthog/core";
|
|
3
4
|
import config from "../config.mjs";
|
|
@@ -175,13 +176,6 @@ function getInitialPersonPropsFromInfo(info, disableCaptureUrlHashes = false) {
|
|
|
175
176
|
});
|
|
176
177
|
return props;
|
|
177
178
|
}
|
|
178
|
-
function getTimezone() {
|
|
179
|
-
try {
|
|
180
|
-
return Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
181
|
-
} catch {
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
179
|
function getTimezoneOffset() {
|
|
186
180
|
try {
|
|
187
181
|
return new Date().getTimezoneOffset();
|
package/dist/utils/logger.js
CHANGED
|
@@ -43,12 +43,17 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
43
43
|
const external_config_js_namespaceObject = require("../config.js");
|
|
44
44
|
var external_config_js_default = /*#__PURE__*/ __webpack_require__.n(external_config_js_namespaceObject);
|
|
45
45
|
const core_namespaceObject = require("@posthog/core");
|
|
46
|
-
const external_globals_js_namespaceObject = require("./globals.js");
|
|
47
46
|
const _createLogger = (prefix, { debugEnabled } = {})=>{
|
|
48
47
|
const logger = {
|
|
49
48
|
_log: (level, ...args)=>{
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
let browserWindow;
|
|
50
|
+
try {
|
|
51
|
+
browserWindow = "u" < typeof window ? void 0 : window;
|
|
52
|
+
} catch {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (browserWindow && (external_config_js_default().DEBUG || browserWindow.POSTHOG_DEBUG || debugEnabled) && !(0, core_namespaceObject.isUndefined)(browserWindow.console) && browserWindow.console) {
|
|
56
|
+
const consoleLog = '__rrweb_original__' in browserWindow.console[level] ? browserWindow.console[level]['__rrweb_original__'] : browserWindow.console[level];
|
|
52
57
|
consoleLog(prefix, ...args);
|
|
53
58
|
}
|
|
54
59
|
},
|