@posthog/core 1.48.6 → 1.48.7
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/logs/index.js +1 -1
- package/dist/logs/index.mjs +1 -1
- package/dist/logs/logs-utils.d.ts +4 -13
- package/dist/logs/logs-utils.d.ts.map +1 -1
- package/dist/logs/logs-utils.js +160 -26
- package/dist/logs/logs-utils.mjs +160 -26
- package/dist/metrics/index.js +1 -1
- package/dist/metrics/index.mjs +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +14 -24
- package/dist/utils/index.mjs +2 -2
- package/dist/utils/json-utils.d.ts +15 -0
- package/dist/utils/json-utils.d.ts.map +1 -1
- package/dist/utils/json-utils.js +24 -0
- package/dist/utils/json-utils.mjs +1 -1
- package/package.json +2 -2
- package/src/logs/index.ts +1 -1
- package/src/logs/logs-utils.spec.ts +314 -9
- package/src/logs/logs-utils.ts +215 -27
- package/src/metrics/index.spec.ts +15 -1
- package/src/metrics/index.ts +1 -1
- package/src/utils/index.ts +3 -1
- package/src/utils/json-utils.ts +15 -8
package/dist/logs/index.js
CHANGED
|
@@ -74,7 +74,7 @@ class PostHogLogs {
|
|
|
74
74
|
if (null === filtered) return;
|
|
75
75
|
if (!filtered.body) return void this._logger.info("Log was rejected in beforeSend function");
|
|
76
76
|
if (!this._checkRateLimit()) return;
|
|
77
|
-
const record = (0, external_logs_utils_js_namespaceObject.buildOtlpLogRecord)(filtered, this._getContext());
|
|
77
|
+
const record = (0, external_logs_utils_js_namespaceObject.buildOtlpLogRecord)(filtered, this._getContext(), this._logger);
|
|
78
78
|
const entry = {
|
|
79
79
|
record
|
|
80
80
|
};
|
package/dist/logs/index.mjs
CHANGED
|
@@ -46,7 +46,7 @@ class PostHogLogs {
|
|
|
46
46
|
if (null === filtered) return;
|
|
47
47
|
if (!filtered.body) return void this._logger.info("Log was rejected in beforeSend function");
|
|
48
48
|
if (!this._checkRateLimit()) return;
|
|
49
|
-
const record = buildOtlpLogRecord(filtered, this._getContext());
|
|
49
|
+
const record = buildOtlpLogRecord(filtered, this._getContext(), this._logger);
|
|
50
50
|
const entry = {
|
|
51
51
|
record
|
|
52
52
|
};
|
|
@@ -1,20 +1,11 @@
|
|
|
1
1
|
import type { CaptureLogOptions, LogAttributeValue, LogSeverityLevel, OtlpAnyValue, OtlpKeyValue, OtlpLogRecord, OtlpLogsPayload, OtlpSeverityText } from '@posthog/types';
|
|
2
|
+
import type { Logger } from '../types';
|
|
2
3
|
import type { LogSdkContext, ResolvedPostHogLogsConfig } from './types';
|
|
3
4
|
export declare function getOtlpSeverityText(level: LogSeverityLevel): OtlpSeverityText;
|
|
4
5
|
export declare function getOtlpSeverityNumber(level: LogSeverityLevel): number;
|
|
5
|
-
export declare function toOtlpAnyValue(value: LogAttributeValue): OtlpAnyValue;
|
|
6
|
-
export declare function toOtlpKeyValueList(attrs: Record<string, LogAttributeValue
|
|
7
|
-
|
|
8
|
-
* Builds a single OTLP log record.
|
|
9
|
-
*
|
|
10
|
-
* Auto-attribute population is shape-driven: any field present on `sdkContext`
|
|
11
|
-
* is emitted as the corresponding attribute. Each SDK populates only the
|
|
12
|
-
* fields that apply to it (browser fills `currentUrl`; mobile fills
|
|
13
|
-
* `screenName` / `appState`), so a missing field never adds a stray attribute.
|
|
14
|
-
*
|
|
15
|
-
* User-provided `options.attributes` always wins on conflicts.
|
|
16
|
-
*/
|
|
17
|
-
export declare function buildOtlpLogRecord(options: CaptureLogOptions, sdkContext: LogSdkContext): OtlpLogRecord;
|
|
6
|
+
export declare function toOtlpAnyValue(value: LogAttributeValue, logger?: Logger): OtlpAnyValue;
|
|
7
|
+
export declare function toOtlpKeyValueList(attrs: Record<string, LogAttributeValue>, logger?: Logger): OtlpKeyValue[];
|
|
8
|
+
export declare function buildOtlpLogRecord(options: CaptureLogOptions, sdkContext: LogSdkContext, logger?: Logger): OtlpLogRecord;
|
|
18
9
|
/**
|
|
19
10
|
* OTLP resource attributes for every batch, shared by the core flush path and
|
|
20
11
|
* SDK-specific paths that bypass it (e.g. the browser's synchronous sendBeacon
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"logs-utils.d.ts","sourceRoot":"","sources":["../../src/logs/logs-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,eAAe,EAEf,gBAAgB,EACjB,MAAM,gBAAgB,CAAA;AACvB,OAAO,KAAK,EAAE,aAAa,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"logs-utils.d.ts","sourceRoot":"","sources":["../../src/logs/logs-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,eAAe,EAEf,gBAAgB,EACjB,MAAM,gBAAgB,CAAA;AACvB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAA;AACtC,OAAO,KAAK,EAAE,aAAa,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAA;AA4BvE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,gBAAgB,GAAG,gBAAgB,CAE7E;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAErE;AAqBD,wBAAgB,cAAc,CAAC,KAAK,EAAE,iBAAiB,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,CAQtF;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,YAAY,EAAE,CAM5G;AAmMD,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,iBAAiB,EAC1B,UAAU,EAAE,aAAa,EACzB,MAAM,CAAC,EAAE,MAAM,GACd,aAAa,CA+Ef;AAMD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,yBAAyB,EACjC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CASnC;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,aAAa,EAAE,EAC3B,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,EACrD,SAAS,EAAE,MAAM,EACjB,YAAY,EAAE,MAAM,GACnB,eAAe,CAcjB"}
|
package/dist/logs/logs-utils.js
CHANGED
|
@@ -33,6 +33,7 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
33
33
|
toOtlpAnyValue: ()=>toOtlpAnyValue
|
|
34
34
|
});
|
|
35
35
|
const index_js_namespaceObject = require("../utils/index.js");
|
|
36
|
+
const json_utils_js_namespaceObject = require("../utils/json-utils.js");
|
|
36
37
|
const OTLP_SEVERITY_MAP = {
|
|
37
38
|
trace: {
|
|
38
39
|
text: 'TRACE',
|
|
@@ -66,7 +67,35 @@ function getOtlpSeverityText(level) {
|
|
|
66
67
|
function getOtlpSeverityNumber(level) {
|
|
67
68
|
return (OTLP_SEVERITY_MAP[level] || DEFAULT_OTLP_SEVERITY).number;
|
|
68
69
|
}
|
|
69
|
-
|
|
70
|
+
const INT64_RANGE_LIMIT = 9223372036854775808;
|
|
71
|
+
const propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
|
|
72
|
+
function newState() {
|
|
73
|
+
return {
|
|
74
|
+
ancestors: new WeakSet(),
|
|
75
|
+
remainingNodes: json_utils_js_namespaceObject.MAX_JSON_SAFE_VALUE_NODES
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function toOtlpAnyValue(value, logger) {
|
|
79
|
+
try {
|
|
80
|
+
return encodeAnyValue(value, logger, newState(), 0);
|
|
81
|
+
} catch {
|
|
82
|
+
return {
|
|
83
|
+
stringValue: json_utils_js_namespaceObject.UNSERIALIZABLE_VALUE
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function toOtlpKeyValueList(attrs, logger) {
|
|
88
|
+
try {
|
|
89
|
+
return encodeKeyValueList(attrs, logger, newState(), 0);
|
|
90
|
+
} catch {
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
function encodeAnyValue(value, logger, state, depth) {
|
|
95
|
+
if (state.remainingNodes <= 0) return {
|
|
96
|
+
stringValue: json_utils_js_namespaceObject.TRUNCATED_VALUE
|
|
97
|
+
};
|
|
98
|
+
state.remainingNodes--;
|
|
70
99
|
if ((0, index_js_namespaceObject.isBoolean)(value)) return {
|
|
71
100
|
boolValue: value
|
|
72
101
|
};
|
|
@@ -74,46 +103,129 @@ function toOtlpAnyValue(value) {
|
|
|
74
103
|
if (!Number.isFinite(value)) return {
|
|
75
104
|
stringValue: String(value)
|
|
76
105
|
};
|
|
77
|
-
if (Number.isInteger(value))
|
|
78
|
-
|
|
79
|
-
|
|
106
|
+
if (Number.isInteger(value)) {
|
|
107
|
+
if (Number.isSafeInteger(value)) return {
|
|
108
|
+
intValue: String(value)
|
|
109
|
+
};
|
|
110
|
+
if ('undefined' == typeof BigInt) return {
|
|
111
|
+
stringValue: String(value)
|
|
112
|
+
};
|
|
113
|
+
const decimal = BigInt(value).toString();
|
|
114
|
+
if (value >= INT64_RANGE_LIMIT || value < -INT64_RANGE_LIMIT) {
|
|
115
|
+
logger?.debug(`Attribute ${decimal} is outside the int64 range; encoding it as a string`);
|
|
116
|
+
return {
|
|
117
|
+
stringValue: decimal
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
intValue: decimal
|
|
122
|
+
};
|
|
123
|
+
}
|
|
80
124
|
return {
|
|
81
125
|
doubleValue: value
|
|
82
126
|
};
|
|
83
127
|
}
|
|
84
128
|
if ('string' == typeof value) return {
|
|
85
|
-
stringValue: value
|
|
129
|
+
stringValue: (0, json_utils_js_namespaceObject.sanitizeString)(value)
|
|
86
130
|
};
|
|
87
|
-
if (
|
|
88
|
-
|
|
89
|
-
values: value.map((v)=>toOtlpAnyValue(v))
|
|
90
|
-
}
|
|
131
|
+
if ('function' == typeof value) return {
|
|
132
|
+
stringValue: json_utils_js_namespaceObject.FUNCTION_VALUE
|
|
91
133
|
};
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
134
|
+
if ('symbol' == typeof value) return {
|
|
135
|
+
stringValue: String(value)
|
|
136
|
+
};
|
|
137
|
+
if ('object' == typeof value && null !== value) {
|
|
138
|
+
if (state.ancestors.has(value)) return {
|
|
139
|
+
stringValue: json_utils_js_namespaceObject.CIRCULAR_VALUE
|
|
95
140
|
};
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
stringValue: String(value)
|
|
141
|
+
if (depth >= json_utils_js_namespaceObject.MAX_JSON_SAFE_VALUE_DEPTH) return {
|
|
142
|
+
stringValue: json_utils_js_namespaceObject.TRUNCATED_VALUE
|
|
99
143
|
};
|
|
144
|
+
if (value instanceof Date) {
|
|
145
|
+
const time = value.getTime();
|
|
146
|
+
const iso = Number.isFinite(time) ? value.toISOString() : String(value);
|
|
147
|
+
return {
|
|
148
|
+
stringValue: 'string' == typeof iso ? (0, json_utils_js_namespaceObject.sanitizeString)(iso) : String(iso)
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
state.ancestors.add(value);
|
|
152
|
+
try {
|
|
153
|
+
try {
|
|
154
|
+
const toJSON = value.toJSON;
|
|
155
|
+
if ('function' == typeof toJSON) return encodeAnyValue(toJSON.call(value), logger, state, depth + 1);
|
|
156
|
+
} catch {}
|
|
157
|
+
if ((0, index_js_namespaceObject.isArray)(value)) return {
|
|
158
|
+
arrayValue: {
|
|
159
|
+
values: encodeArrayValues(value, logger, state, depth + 1)
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
return {
|
|
163
|
+
kvlistValue: {
|
|
164
|
+
values: encodeKeyValueList(value, logger, state, depth + 1)
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
} finally{
|
|
168
|
+
state.ancestors.delete(value);
|
|
169
|
+
}
|
|
100
170
|
}
|
|
171
|
+
return {
|
|
172
|
+
stringValue: (0, json_utils_js_namespaceObject.sanitizeString)(String(value))
|
|
173
|
+
};
|
|
101
174
|
}
|
|
102
|
-
function
|
|
175
|
+
function encodeArrayValues(values, logger, state, depth) {
|
|
103
176
|
const result = [];
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
177
|
+
const itemCount = Math.min(values.length, json_utils_js_namespaceObject.MAX_JSON_SAFE_VALUE_ITEMS);
|
|
178
|
+
let index = 0;
|
|
179
|
+
for(; index < itemCount && state.remainingNodes > 0; index++)try {
|
|
180
|
+
const element = index in values ? values[index] : void 0;
|
|
181
|
+
if ((0, index_js_namespaceObject.isNullish)(element)) continue;
|
|
182
|
+
result.push(encodeAnyValue(element, logger, state, depth));
|
|
183
|
+
} catch {
|
|
184
|
+
result.push({
|
|
185
|
+
stringValue: json_utils_js_namespaceObject.UNSERIALIZABLE_VALUE
|
|
109
186
|
});
|
|
110
187
|
}
|
|
188
|
+
if (values.length > index) result.push({
|
|
189
|
+
stringValue: json_utils_js_namespaceObject.TRUNCATED_VALUE
|
|
190
|
+
});
|
|
191
|
+
return result;
|
|
192
|
+
}
|
|
193
|
+
function encodeKeyValueList(attrs, logger, state, depth) {
|
|
194
|
+
const result = [];
|
|
195
|
+
for(const key in attrs)if (propertyIsEnumerable.call(attrs, key)) {
|
|
196
|
+
if (result.length >= json_utils_js_namespaceObject.MAX_JSON_SAFE_VALUE_ITEMS || state.remainingNodes <= 0) {
|
|
197
|
+
logger?.debug('Attributes truncated: the value exceeds the OTLP encoder budget');
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
try {
|
|
201
|
+
const value = attrs[key];
|
|
202
|
+
if ((0, index_js_namespaceObject.isNull)(value) || (0, index_js_namespaceObject.isUndefined)(value)) continue;
|
|
203
|
+
result.push({
|
|
204
|
+
key: (0, json_utils_js_namespaceObject.sanitizeString)(key),
|
|
205
|
+
value: encodeAnyValue(value, logger, state, depth)
|
|
206
|
+
});
|
|
207
|
+
} catch {
|
|
208
|
+
result.push({
|
|
209
|
+
key: (0, json_utils_js_namespaceObject.sanitizeString)(key),
|
|
210
|
+
value: {
|
|
211
|
+
stringValue: json_utils_js_namespaceObject.UNSERIALIZABLE_VALUE
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
111
216
|
return result;
|
|
112
217
|
}
|
|
113
218
|
function timestampToUnixNano() {
|
|
114
219
|
return String(Date.now()) + '000000';
|
|
115
220
|
}
|
|
116
|
-
function
|
|
221
|
+
function encodeBody(body) {
|
|
222
|
+
try {
|
|
223
|
+
return (0, json_utils_js_namespaceObject.sanitizeString)(String(body));
|
|
224
|
+
} catch {
|
|
225
|
+
return json_utils_js_namespaceObject.UNSERIALIZABLE_VALUE;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
function buildOtlpLogRecord(options, sdkContext, logger) {
|
|
117
229
|
const level = options.level || 'info';
|
|
118
230
|
const { text: severityText, number: severityNumber } = OTLP_SEVERITY_MAP[level] || DEFAULT_OTLP_SEVERITY;
|
|
119
231
|
const now = timestampToUnixNano();
|
|
@@ -128,18 +240,40 @@ function buildOtlpLogRecord(options, sdkContext) {
|
|
|
128
240
|
if (sdkContext.appState) autoAttributes['app.state'] = sdkContext.appState;
|
|
129
241
|
if (sdkContext.activeFeatureFlags && sdkContext.activeFeatureFlags.length > 0) autoAttributes.feature_flags = sdkContext.activeFeatureFlags;
|
|
130
242
|
const mergedAttributes = {
|
|
131
|
-
...autoAttributes
|
|
132
|
-
...options.attributes || {}
|
|
243
|
+
...autoAttributes
|
|
133
244
|
};
|
|
245
|
+
const userAttributes = options.attributes;
|
|
246
|
+
if (userAttributes) {
|
|
247
|
+
let keys = [];
|
|
248
|
+
try {
|
|
249
|
+
keys = Object.keys(userAttributes);
|
|
250
|
+
} catch {
|
|
251
|
+
keys = [];
|
|
252
|
+
}
|
|
253
|
+
for (const key of keys){
|
|
254
|
+
let value;
|
|
255
|
+
try {
|
|
256
|
+
value = userAttributes[key];
|
|
257
|
+
} catch {
|
|
258
|
+
value = json_utils_js_namespaceObject.UNSERIALIZABLE_VALUE;
|
|
259
|
+
}
|
|
260
|
+
Object.defineProperty(mergedAttributes, key, {
|
|
261
|
+
value,
|
|
262
|
+
enumerable: true,
|
|
263
|
+
writable: true,
|
|
264
|
+
configurable: true
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
}
|
|
134
268
|
const record = {
|
|
135
269
|
timeUnixNano: now,
|
|
136
270
|
observedTimeUnixNano: now,
|
|
137
271
|
severityNumber,
|
|
138
272
|
severityText,
|
|
139
273
|
body: {
|
|
140
|
-
stringValue: options.body
|
|
274
|
+
stringValue: encodeBody(options.body)
|
|
141
275
|
},
|
|
142
|
-
attributes: toOtlpKeyValueList(mergedAttributes)
|
|
276
|
+
attributes: toOtlpKeyValueList(mergedAttributes, logger)
|
|
143
277
|
};
|
|
144
278
|
if (options.trace_id) record.traceId = options.trace_id;
|
|
145
279
|
if (options.span_id) record.spanId = options.span_id;
|
package/dist/logs/logs-utils.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isArray, isBoolean, isNull, isNullish, isUndefined } from "../utils/index.mjs";
|
|
2
|
+
import { CIRCULAR_VALUE, FUNCTION_VALUE, MAX_JSON_SAFE_VALUE_DEPTH, MAX_JSON_SAFE_VALUE_ITEMS, MAX_JSON_SAFE_VALUE_NODES, TRUNCATED_VALUE, UNSERIALIZABLE_VALUE, sanitizeString } from "../utils/json-utils.mjs";
|
|
2
3
|
const OTLP_SEVERITY_MAP = {
|
|
3
4
|
trace: {
|
|
4
5
|
text: 'TRACE',
|
|
@@ -32,7 +33,35 @@ function getOtlpSeverityText(level) {
|
|
|
32
33
|
function getOtlpSeverityNumber(level) {
|
|
33
34
|
return (OTLP_SEVERITY_MAP[level] || DEFAULT_OTLP_SEVERITY).number;
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
+
const INT64_RANGE_LIMIT = 9223372036854775808;
|
|
37
|
+
const propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
|
|
38
|
+
function newState() {
|
|
39
|
+
return {
|
|
40
|
+
ancestors: new WeakSet(),
|
|
41
|
+
remainingNodes: MAX_JSON_SAFE_VALUE_NODES
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function toOtlpAnyValue(value, logger) {
|
|
45
|
+
try {
|
|
46
|
+
return encodeAnyValue(value, logger, newState(), 0);
|
|
47
|
+
} catch {
|
|
48
|
+
return {
|
|
49
|
+
stringValue: UNSERIALIZABLE_VALUE
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function toOtlpKeyValueList(attrs, logger) {
|
|
54
|
+
try {
|
|
55
|
+
return encodeKeyValueList(attrs, logger, newState(), 0);
|
|
56
|
+
} catch {
|
|
57
|
+
return [];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function encodeAnyValue(value, logger, state, depth) {
|
|
61
|
+
if (state.remainingNodes <= 0) return {
|
|
62
|
+
stringValue: TRUNCATED_VALUE
|
|
63
|
+
};
|
|
64
|
+
state.remainingNodes--;
|
|
36
65
|
if (isBoolean(value)) return {
|
|
37
66
|
boolValue: value
|
|
38
67
|
};
|
|
@@ -40,46 +69,129 @@ function toOtlpAnyValue(value) {
|
|
|
40
69
|
if (!Number.isFinite(value)) return {
|
|
41
70
|
stringValue: String(value)
|
|
42
71
|
};
|
|
43
|
-
if (Number.isInteger(value))
|
|
44
|
-
|
|
45
|
-
|
|
72
|
+
if (Number.isInteger(value)) {
|
|
73
|
+
if (Number.isSafeInteger(value)) return {
|
|
74
|
+
intValue: String(value)
|
|
75
|
+
};
|
|
76
|
+
if ('undefined' == typeof BigInt) return {
|
|
77
|
+
stringValue: String(value)
|
|
78
|
+
};
|
|
79
|
+
const decimal = BigInt(value).toString();
|
|
80
|
+
if (value >= INT64_RANGE_LIMIT || value < -INT64_RANGE_LIMIT) {
|
|
81
|
+
logger?.debug(`Attribute ${decimal} is outside the int64 range; encoding it as a string`);
|
|
82
|
+
return {
|
|
83
|
+
stringValue: decimal
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
intValue: decimal
|
|
88
|
+
};
|
|
89
|
+
}
|
|
46
90
|
return {
|
|
47
91
|
doubleValue: value
|
|
48
92
|
};
|
|
49
93
|
}
|
|
50
94
|
if ('string' == typeof value) return {
|
|
51
|
-
stringValue: value
|
|
95
|
+
stringValue: sanitizeString(value)
|
|
52
96
|
};
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
values: value.map((v)=>toOtlpAnyValue(v))
|
|
56
|
-
}
|
|
97
|
+
if ('function' == typeof value) return {
|
|
98
|
+
stringValue: FUNCTION_VALUE
|
|
57
99
|
};
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
100
|
+
if ('symbol' == typeof value) return {
|
|
101
|
+
stringValue: String(value)
|
|
102
|
+
};
|
|
103
|
+
if ('object' == typeof value && null !== value) {
|
|
104
|
+
if (state.ancestors.has(value)) return {
|
|
105
|
+
stringValue: CIRCULAR_VALUE
|
|
61
106
|
};
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
stringValue: String(value)
|
|
107
|
+
if (depth >= MAX_JSON_SAFE_VALUE_DEPTH) return {
|
|
108
|
+
stringValue: TRUNCATED_VALUE
|
|
65
109
|
};
|
|
110
|
+
if (value instanceof Date) {
|
|
111
|
+
const time = value.getTime();
|
|
112
|
+
const iso = Number.isFinite(time) ? value.toISOString() : String(value);
|
|
113
|
+
return {
|
|
114
|
+
stringValue: 'string' == typeof iso ? sanitizeString(iso) : String(iso)
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
state.ancestors.add(value);
|
|
118
|
+
try {
|
|
119
|
+
try {
|
|
120
|
+
const toJSON = value.toJSON;
|
|
121
|
+
if ('function' == typeof toJSON) return encodeAnyValue(toJSON.call(value), logger, state, depth + 1);
|
|
122
|
+
} catch {}
|
|
123
|
+
if (isArray(value)) return {
|
|
124
|
+
arrayValue: {
|
|
125
|
+
values: encodeArrayValues(value, logger, state, depth + 1)
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
return {
|
|
129
|
+
kvlistValue: {
|
|
130
|
+
values: encodeKeyValueList(value, logger, state, depth + 1)
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
} finally{
|
|
134
|
+
state.ancestors.delete(value);
|
|
135
|
+
}
|
|
66
136
|
}
|
|
137
|
+
return {
|
|
138
|
+
stringValue: sanitizeString(String(value))
|
|
139
|
+
};
|
|
67
140
|
}
|
|
68
|
-
function
|
|
141
|
+
function encodeArrayValues(values, logger, state, depth) {
|
|
69
142
|
const result = [];
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
143
|
+
const itemCount = Math.min(values.length, MAX_JSON_SAFE_VALUE_ITEMS);
|
|
144
|
+
let index = 0;
|
|
145
|
+
for(; index < itemCount && state.remainingNodes > 0; index++)try {
|
|
146
|
+
const element = index in values ? values[index] : void 0;
|
|
147
|
+
if (isNullish(element)) continue;
|
|
148
|
+
result.push(encodeAnyValue(element, logger, state, depth));
|
|
149
|
+
} catch {
|
|
150
|
+
result.push({
|
|
151
|
+
stringValue: UNSERIALIZABLE_VALUE
|
|
75
152
|
});
|
|
76
153
|
}
|
|
154
|
+
if (values.length > index) result.push({
|
|
155
|
+
stringValue: TRUNCATED_VALUE
|
|
156
|
+
});
|
|
157
|
+
return result;
|
|
158
|
+
}
|
|
159
|
+
function encodeKeyValueList(attrs, logger, state, depth) {
|
|
160
|
+
const result = [];
|
|
161
|
+
for(const key in attrs)if (propertyIsEnumerable.call(attrs, key)) {
|
|
162
|
+
if (result.length >= MAX_JSON_SAFE_VALUE_ITEMS || state.remainingNodes <= 0) {
|
|
163
|
+
logger?.debug('Attributes truncated: the value exceeds the OTLP encoder budget');
|
|
164
|
+
break;
|
|
165
|
+
}
|
|
166
|
+
try {
|
|
167
|
+
const value = attrs[key];
|
|
168
|
+
if (isNull(value) || isUndefined(value)) continue;
|
|
169
|
+
result.push({
|
|
170
|
+
key: sanitizeString(key),
|
|
171
|
+
value: encodeAnyValue(value, logger, state, depth)
|
|
172
|
+
});
|
|
173
|
+
} catch {
|
|
174
|
+
result.push({
|
|
175
|
+
key: sanitizeString(key),
|
|
176
|
+
value: {
|
|
177
|
+
stringValue: UNSERIALIZABLE_VALUE
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
77
182
|
return result;
|
|
78
183
|
}
|
|
79
184
|
function timestampToUnixNano() {
|
|
80
185
|
return String(Date.now()) + '000000';
|
|
81
186
|
}
|
|
82
|
-
function
|
|
187
|
+
function encodeBody(body) {
|
|
188
|
+
try {
|
|
189
|
+
return sanitizeString(String(body));
|
|
190
|
+
} catch {
|
|
191
|
+
return UNSERIALIZABLE_VALUE;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function buildOtlpLogRecord(options, sdkContext, logger) {
|
|
83
195
|
const level = options.level || 'info';
|
|
84
196
|
const { text: severityText, number: severityNumber } = OTLP_SEVERITY_MAP[level] || DEFAULT_OTLP_SEVERITY;
|
|
85
197
|
const now = timestampToUnixNano();
|
|
@@ -94,18 +206,40 @@ function buildOtlpLogRecord(options, sdkContext) {
|
|
|
94
206
|
if (sdkContext.appState) autoAttributes['app.state'] = sdkContext.appState;
|
|
95
207
|
if (sdkContext.activeFeatureFlags && sdkContext.activeFeatureFlags.length > 0) autoAttributes.feature_flags = sdkContext.activeFeatureFlags;
|
|
96
208
|
const mergedAttributes = {
|
|
97
|
-
...autoAttributes
|
|
98
|
-
...options.attributes || {}
|
|
209
|
+
...autoAttributes
|
|
99
210
|
};
|
|
211
|
+
const userAttributes = options.attributes;
|
|
212
|
+
if (userAttributes) {
|
|
213
|
+
let keys = [];
|
|
214
|
+
try {
|
|
215
|
+
keys = Object.keys(userAttributes);
|
|
216
|
+
} catch {
|
|
217
|
+
keys = [];
|
|
218
|
+
}
|
|
219
|
+
for (const key of keys){
|
|
220
|
+
let value;
|
|
221
|
+
try {
|
|
222
|
+
value = userAttributes[key];
|
|
223
|
+
} catch {
|
|
224
|
+
value = UNSERIALIZABLE_VALUE;
|
|
225
|
+
}
|
|
226
|
+
Object.defineProperty(mergedAttributes, key, {
|
|
227
|
+
value,
|
|
228
|
+
enumerable: true,
|
|
229
|
+
writable: true,
|
|
230
|
+
configurable: true
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
100
234
|
const record = {
|
|
101
235
|
timeUnixNano: now,
|
|
102
236
|
observedTimeUnixNano: now,
|
|
103
237
|
severityNumber,
|
|
104
238
|
severityText,
|
|
105
239
|
body: {
|
|
106
|
-
stringValue: options.body
|
|
240
|
+
stringValue: encodeBody(options.body)
|
|
107
241
|
},
|
|
108
|
-
attributes: toOtlpKeyValueList(mergedAttributes)
|
|
242
|
+
attributes: toOtlpKeyValueList(mergedAttributes, logger)
|
|
109
243
|
};
|
|
110
244
|
if (options.trace_id) record.traceId = options.trace_id;
|
|
111
245
|
if (options.span_id) record.spanId = options.span_id;
|
package/dist/metrics/index.js
CHANGED
|
@@ -268,7 +268,7 @@ class PostHogMetrics {
|
|
|
268
268
|
};
|
|
269
269
|
byMetric.set(metricKey, metric);
|
|
270
270
|
}
|
|
271
|
-
const attributes = (0, logs_utils_js_namespaceObject.toOtlpKeyValueList)(state.attributes ?? {});
|
|
271
|
+
const attributes = (0, logs_utils_js_namespaceObject.toOtlpKeyValueList)(state.attributes ?? {}, this._logger);
|
|
272
272
|
const startNano = (0, external_metrics_utils_js_namespaceObject.msToUnixNano)(state.windowStartMs);
|
|
273
273
|
if ('count' === state.type) {
|
|
274
274
|
const dp = {
|
package/dist/metrics/index.mjs
CHANGED
|
@@ -236,7 +236,7 @@ class PostHogMetrics {
|
|
|
236
236
|
};
|
|
237
237
|
byMetric.set(metricKey, metric);
|
|
238
238
|
}
|
|
239
|
-
const attributes = toOtlpKeyValueList(state.attributes ?? {});
|
|
239
|
+
const attributes = toOtlpKeyValueList(state.attributes ?? {}, this._logger);
|
|
240
240
|
const startNano = msToUnixNano(state.windowStartMs);
|
|
241
241
|
if ('count' === state.type) {
|
|
242
242
|
const dp = {
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { FetchLike } from '../types';
|
|
|
2
2
|
export * from './bot-detection';
|
|
3
3
|
export * from './browser-utils';
|
|
4
4
|
export * from './bucketed-rate-limiter';
|
|
5
|
-
export
|
|
5
|
+
export { toJsonSafeValue } from './json-utils';
|
|
6
6
|
export * from './number-utils';
|
|
7
7
|
export * from './string-utils';
|
|
8
8
|
export * from './type-utils';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEpC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEpC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,yBAAyB,CAAA;AAGvC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAC9C,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,UAAU,CAAA;AACxB,cAAc,oBAAoB,CAAA;AAElC,eAAO,MAAM,aAAa,SAAS,CAAA;AAEnC,eAAO,MAAM,UAAU,QAAoE,CAAA;AAE3F,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAE3D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,MAAM,GAAG,MAAM,CAE9E;AAED,wBAAgB,MAAM,CAAC,WAAW,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAI9D;AASD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,GAAG,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,SAAS,MAAM,GAAG,MAAM,GAAG,SAAS,CAMxG;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAA;CACtC;AAED,wBAAsB,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,CAAC,CAAC,CAqB5F;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,GAAG,CAOnE;AAED,wBAAsB,eAAe,CAAC,CAAC,EACrC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,IAAI,GACrB,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAoBnB;AAGD,eAAO,MAAM,SAAS,GAAI,KAAK,GAAG,KAAG,GAAG,IAAI,OAAO,CAAC,GAAG,CAEtD,CAAA;AAED,wBAAgB,QAAQ,IAAI,SAAS,GAAG,SAAS,CAEhD;AAED,wBAAgB,UAAU,CAAC,CAAC,EAC1B,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC,EAAE,GAC1C,OAAO,CAAC,CAAC;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,GAAG,CAAA;CAAE,CAAC,EAAE,CAAC,CAStF"}
|