@posthog/core 1.49.2 → 1.50.1

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.
Files changed (41) hide show
  1. package/dist/featureFlagLocalEvaluation.d.ts +1 -1
  2. package/dist/featureFlagLocalEvaluation.d.ts.map +1 -1
  3. package/dist/featureFlagLocalEvaluation.js +149 -10
  4. package/dist/featureFlagLocalEvaluation.mjs +149 -10
  5. package/dist/index.d.ts +3 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +48 -31
  8. package/dist/index.mjs +4 -2
  9. package/dist/logs/logs-utils.d.ts +1 -3
  10. package/dist/logs/logs-utils.d.ts.map +1 -1
  11. package/dist/logs/logs-utils.js +7 -170
  12. package/dist/logs/logs-utils.mjs +6 -163
  13. package/dist/metrics/index.js +2 -2
  14. package/dist/metrics/index.mjs +1 -1
  15. package/dist/metrics/metrics-utils.d.ts.map +1 -1
  16. package/dist/metrics/metrics-utils.js +4 -14
  17. package/dist/metrics/metrics-utils.mjs +3 -13
  18. package/dist/utils/otlp-any-value.d.ts +5 -0
  19. package/dist/utils/otlp-any-value.d.ts.map +1 -0
  20. package/dist/utils/otlp-any-value.js +203 -0
  21. package/dist/utils/otlp-any-value.mjs +166 -0
  22. package/dist/utils/otlp-resource.d.ts +38 -0
  23. package/dist/utils/otlp-resource.d.ts.map +1 -0
  24. package/dist/utils/otlp-resource.js +81 -0
  25. package/dist/utils/otlp-resource.mjs +41 -0
  26. package/dist/utils/user-agent-utils.d.ts +4 -4
  27. package/dist/utils/user-agent-utils.d.ts.map +1 -1
  28. package/dist/utils/user-agent-utils.js +16 -0
  29. package/dist/utils/user-agent-utils.mjs +16 -0
  30. package/package.json +1 -1
  31. package/src/featureFlagLocalEvaluation.ts +199 -12
  32. package/src/index.ts +2 -2
  33. package/src/logs/logs-utils.spec.ts +2 -350
  34. package/src/logs/logs-utils.ts +5 -215
  35. package/src/metrics/index.ts +1 -1
  36. package/src/metrics/metrics-utils.ts +3 -9
  37. package/src/utils/otlp-any-value.spec.ts +361 -0
  38. package/src/utils/otlp-any-value.ts +225 -0
  39. package/src/utils/otlp-resource.spec.ts +125 -0
  40. package/src/utils/otlp-resource.ts +89 -0
  41. package/src/utils/user-agent-utils.ts +22 -6
@@ -0,0 +1,203 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ toOtlpKeyValueList: ()=>toOtlpKeyValueList,
28
+ toOtlpAnyValue: ()=>toOtlpAnyValue
29
+ });
30
+ const external_type_utils_js_namespaceObject = require("./type-utils.js");
31
+ const external_json_utils_js_namespaceObject = require("./json-utils.js");
32
+ const INT64_RANGE_LIMIT = 9223372036854775808;
33
+ const INT64_RANGE_LIMIT_DECIMAL = '9223372036854775808';
34
+ const propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
35
+ function newState() {
36
+ return {
37
+ ancestors: new WeakSet(),
38
+ remainingNodes: external_json_utils_js_namespaceObject.MAX_JSON_SAFE_VALUE_NODES
39
+ };
40
+ }
41
+ function toOtlpAnyValue(value, logger) {
42
+ try {
43
+ return encodeAnyValue(value, logger, newState(), 0);
44
+ } catch {
45
+ return {
46
+ stringValue: external_json_utils_js_namespaceObject.UNSERIALIZABLE_VALUE
47
+ };
48
+ }
49
+ }
50
+ function toOtlpKeyValueList(attrs, logger) {
51
+ try {
52
+ return encodeKeyValueList(attrs, logger, newState(), 0);
53
+ } catch {
54
+ return [];
55
+ }
56
+ }
57
+ function encodeBigInt(value, logger) {
58
+ const decimal = value.toString();
59
+ const limit = BigInt(INT64_RANGE_LIMIT_DECIMAL);
60
+ if (value >= limit || value < -limit) {
61
+ logger?.debug(`Attribute ${decimal} is outside the int64 range; encoding it as a string`);
62
+ return {
63
+ stringValue: decimal
64
+ };
65
+ }
66
+ return {
67
+ intValue: decimal
68
+ };
69
+ }
70
+ function encodeAnyValue(value, logger, state, depth) {
71
+ if (state.remainingNodes <= 0) return {
72
+ stringValue: external_json_utils_js_namespaceObject.TRUNCATED_VALUE
73
+ };
74
+ state.remainingNodes--;
75
+ if ((0, external_type_utils_js_namespaceObject.isBoolean)(value)) return {
76
+ boolValue: value
77
+ };
78
+ if ('bigint' == typeof value) return encodeBigInt(value, logger);
79
+ if ('number' == typeof value) {
80
+ if (!Number.isFinite(value)) return {
81
+ stringValue: String(value)
82
+ };
83
+ if (Number.isInteger(value)) {
84
+ if (Number.isSafeInteger(value)) return {
85
+ intValue: String(value)
86
+ };
87
+ if ('undefined' == typeof BigInt) return {
88
+ stringValue: String(value)
89
+ };
90
+ const decimal = BigInt(value).toString();
91
+ if (value >= INT64_RANGE_LIMIT || value < -INT64_RANGE_LIMIT) {
92
+ logger?.debug(`Attribute ${decimal} is outside the int64 range; encoding it as a string`);
93
+ return {
94
+ stringValue: decimal
95
+ };
96
+ }
97
+ return {
98
+ intValue: decimal
99
+ };
100
+ }
101
+ return {
102
+ doubleValue: value
103
+ };
104
+ }
105
+ if ('string' == typeof value) return {
106
+ stringValue: (0, external_json_utils_js_namespaceObject.sanitizeString)(value)
107
+ };
108
+ if ('function' == typeof value) return {
109
+ stringValue: external_json_utils_js_namespaceObject.FUNCTION_VALUE
110
+ };
111
+ if ('symbol' == typeof value) return {
112
+ stringValue: String(value)
113
+ };
114
+ if ('object' == typeof value && null !== value) {
115
+ if (state.ancestors.has(value)) return {
116
+ stringValue: external_json_utils_js_namespaceObject.CIRCULAR_VALUE
117
+ };
118
+ if (depth >= external_json_utils_js_namespaceObject.MAX_JSON_SAFE_VALUE_DEPTH) return {
119
+ stringValue: external_json_utils_js_namespaceObject.TRUNCATED_VALUE
120
+ };
121
+ if (value instanceof Date) {
122
+ const time = value.getTime();
123
+ const iso = Number.isFinite(time) ? value.toISOString() : String(value);
124
+ return {
125
+ stringValue: 'string' == typeof iso ? (0, external_json_utils_js_namespaceObject.sanitizeString)(iso) : String(iso)
126
+ };
127
+ }
128
+ state.ancestors.add(value);
129
+ try {
130
+ try {
131
+ const toJSON = value.toJSON;
132
+ if ('function' == typeof toJSON) return encodeAnyValue(toJSON.call(value), logger, state, depth + 1);
133
+ } catch {}
134
+ if ((0, external_type_utils_js_namespaceObject.isArray)(value)) return {
135
+ arrayValue: {
136
+ values: encodeArrayValues(value, logger, state, depth + 1)
137
+ }
138
+ };
139
+ return {
140
+ kvlistValue: {
141
+ values: encodeKeyValueList(value, logger, state, depth + 1)
142
+ }
143
+ };
144
+ } finally{
145
+ state.ancestors.delete(value);
146
+ }
147
+ }
148
+ return {
149
+ stringValue: (0, external_json_utils_js_namespaceObject.sanitizeString)(String(value))
150
+ };
151
+ }
152
+ function encodeArrayValues(values, logger, state, depth) {
153
+ const result = [];
154
+ const itemCount = Math.min(values.length, external_json_utils_js_namespaceObject.MAX_JSON_SAFE_VALUE_ITEMS);
155
+ let index = 0;
156
+ for(; index < itemCount && state.remainingNodes > 0; index++)try {
157
+ const element = index in values ? values[index] : void 0;
158
+ if ((0, external_type_utils_js_namespaceObject.isNullish)(element)) continue;
159
+ result.push(encodeAnyValue(element, logger, state, depth));
160
+ } catch {
161
+ result.push({
162
+ stringValue: external_json_utils_js_namespaceObject.UNSERIALIZABLE_VALUE
163
+ });
164
+ }
165
+ if (values.length > index) result.push({
166
+ stringValue: external_json_utils_js_namespaceObject.TRUNCATED_VALUE
167
+ });
168
+ return result;
169
+ }
170
+ function encodeKeyValueList(attrs, logger, state, depth) {
171
+ const result = [];
172
+ for(const key in attrs)if (propertyIsEnumerable.call(attrs, key)) {
173
+ if (result.length >= external_json_utils_js_namespaceObject.MAX_JSON_SAFE_VALUE_ITEMS || state.remainingNodes <= 0) {
174
+ logger?.debug('Attributes truncated: the value exceeds the OTLP encoder budget');
175
+ break;
176
+ }
177
+ try {
178
+ const value = attrs[key];
179
+ if ((0, external_type_utils_js_namespaceObject.isNull)(value) || (0, external_type_utils_js_namespaceObject.isUndefined)(value)) continue;
180
+ result.push({
181
+ key: (0, external_json_utils_js_namespaceObject.sanitizeString)(key),
182
+ value: encodeAnyValue(value, logger, state, depth)
183
+ });
184
+ } catch {
185
+ result.push({
186
+ key: (0, external_json_utils_js_namespaceObject.sanitizeString)(key),
187
+ value: {
188
+ stringValue: external_json_utils_js_namespaceObject.UNSERIALIZABLE_VALUE
189
+ }
190
+ });
191
+ }
192
+ }
193
+ return result;
194
+ }
195
+ exports.toOtlpAnyValue = __webpack_exports__.toOtlpAnyValue;
196
+ exports.toOtlpKeyValueList = __webpack_exports__.toOtlpKeyValueList;
197
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
198
+ "toOtlpAnyValue",
199
+ "toOtlpKeyValueList"
200
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
201
+ Object.defineProperty(exports, '__esModule', {
202
+ value: true
203
+ });
@@ -0,0 +1,166 @@
1
+ import { isArray, isBoolean, isNull, isNullish, isUndefined } from "./type-utils.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 "./json-utils.mjs";
3
+ const INT64_RANGE_LIMIT = 9223372036854775808;
4
+ const INT64_RANGE_LIMIT_DECIMAL = '9223372036854775808';
5
+ const propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
6
+ function newState() {
7
+ return {
8
+ ancestors: new WeakSet(),
9
+ remainingNodes: MAX_JSON_SAFE_VALUE_NODES
10
+ };
11
+ }
12
+ function toOtlpAnyValue(value, logger) {
13
+ try {
14
+ return encodeAnyValue(value, logger, newState(), 0);
15
+ } catch {
16
+ return {
17
+ stringValue: UNSERIALIZABLE_VALUE
18
+ };
19
+ }
20
+ }
21
+ function toOtlpKeyValueList(attrs, logger) {
22
+ try {
23
+ return encodeKeyValueList(attrs, logger, newState(), 0);
24
+ } catch {
25
+ return [];
26
+ }
27
+ }
28
+ function encodeBigInt(value, logger) {
29
+ const decimal = value.toString();
30
+ const limit = BigInt(INT64_RANGE_LIMIT_DECIMAL);
31
+ if (value >= limit || value < -limit) {
32
+ logger?.debug(`Attribute ${decimal} is outside the int64 range; encoding it as a string`);
33
+ return {
34
+ stringValue: decimal
35
+ };
36
+ }
37
+ return {
38
+ intValue: decimal
39
+ };
40
+ }
41
+ function encodeAnyValue(value, logger, state, depth) {
42
+ if (state.remainingNodes <= 0) return {
43
+ stringValue: TRUNCATED_VALUE
44
+ };
45
+ state.remainingNodes--;
46
+ if (isBoolean(value)) return {
47
+ boolValue: value
48
+ };
49
+ if ('bigint' == typeof value) return encodeBigInt(value, logger);
50
+ if ('number' == typeof value) {
51
+ if (!Number.isFinite(value)) return {
52
+ stringValue: String(value)
53
+ };
54
+ if (Number.isInteger(value)) {
55
+ if (Number.isSafeInteger(value)) return {
56
+ intValue: String(value)
57
+ };
58
+ if ('undefined' == typeof BigInt) return {
59
+ stringValue: String(value)
60
+ };
61
+ const decimal = BigInt(value).toString();
62
+ if (value >= INT64_RANGE_LIMIT || value < -INT64_RANGE_LIMIT) {
63
+ logger?.debug(`Attribute ${decimal} is outside the int64 range; encoding it as a string`);
64
+ return {
65
+ stringValue: decimal
66
+ };
67
+ }
68
+ return {
69
+ intValue: decimal
70
+ };
71
+ }
72
+ return {
73
+ doubleValue: value
74
+ };
75
+ }
76
+ if ('string' == typeof value) return {
77
+ stringValue: sanitizeString(value)
78
+ };
79
+ if ('function' == typeof value) return {
80
+ stringValue: FUNCTION_VALUE
81
+ };
82
+ if ('symbol' == typeof value) return {
83
+ stringValue: String(value)
84
+ };
85
+ if ('object' == typeof value && null !== value) {
86
+ if (state.ancestors.has(value)) return {
87
+ stringValue: CIRCULAR_VALUE
88
+ };
89
+ if (depth >= MAX_JSON_SAFE_VALUE_DEPTH) return {
90
+ stringValue: TRUNCATED_VALUE
91
+ };
92
+ if (value instanceof Date) {
93
+ const time = value.getTime();
94
+ const iso = Number.isFinite(time) ? value.toISOString() : String(value);
95
+ return {
96
+ stringValue: 'string' == typeof iso ? sanitizeString(iso) : String(iso)
97
+ };
98
+ }
99
+ state.ancestors.add(value);
100
+ try {
101
+ try {
102
+ const toJSON = value.toJSON;
103
+ if ('function' == typeof toJSON) return encodeAnyValue(toJSON.call(value), logger, state, depth + 1);
104
+ } catch {}
105
+ if (isArray(value)) return {
106
+ arrayValue: {
107
+ values: encodeArrayValues(value, logger, state, depth + 1)
108
+ }
109
+ };
110
+ return {
111
+ kvlistValue: {
112
+ values: encodeKeyValueList(value, logger, state, depth + 1)
113
+ }
114
+ };
115
+ } finally{
116
+ state.ancestors.delete(value);
117
+ }
118
+ }
119
+ return {
120
+ stringValue: sanitizeString(String(value))
121
+ };
122
+ }
123
+ function encodeArrayValues(values, logger, state, depth) {
124
+ const result = [];
125
+ const itemCount = Math.min(values.length, MAX_JSON_SAFE_VALUE_ITEMS);
126
+ let index = 0;
127
+ for(; index < itemCount && state.remainingNodes > 0; index++)try {
128
+ const element = index in values ? values[index] : void 0;
129
+ if (isNullish(element)) continue;
130
+ result.push(encodeAnyValue(element, logger, state, depth));
131
+ } catch {
132
+ result.push({
133
+ stringValue: UNSERIALIZABLE_VALUE
134
+ });
135
+ }
136
+ if (values.length > index) result.push({
137
+ stringValue: TRUNCATED_VALUE
138
+ });
139
+ return result;
140
+ }
141
+ function encodeKeyValueList(attrs, logger, state, depth) {
142
+ const result = [];
143
+ for(const key in attrs)if (propertyIsEnumerable.call(attrs, key)) {
144
+ if (result.length >= MAX_JSON_SAFE_VALUE_ITEMS || state.remainingNodes <= 0) {
145
+ logger?.debug('Attributes truncated: the value exceeds the OTLP encoder budget');
146
+ break;
147
+ }
148
+ try {
149
+ const value = attrs[key];
150
+ if (isNull(value) || isUndefined(value)) continue;
151
+ result.push({
152
+ key: sanitizeString(key),
153
+ value: encodeAnyValue(value, logger, state, depth)
154
+ });
155
+ } catch {
156
+ result.push({
157
+ key: sanitizeString(key),
158
+ value: {
159
+ stringValue: UNSERIALIZABLE_VALUE
160
+ }
161
+ });
162
+ }
163
+ }
164
+ return result;
165
+ }
166
+ export { toOtlpAnyValue, toOtlpKeyValueList };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Shape the logs and metrics resolved configs share for resource
3
+ * attribution. Generic over the attribute value type so each signal keeps its
4
+ * own value union.
5
+ */
6
+ export interface OtlpResourceConfig<TAttributeValue> {
7
+ serviceName?: string;
8
+ serviceVersion?: string;
9
+ environment?: string;
10
+ resourceAttributes?: Record<string, TAttributeValue>;
11
+ }
12
+ /**
13
+ * OTLP resource attributes shared by the logs and metrics envelopes.
14
+ *
15
+ * User `resourceAttributes` are spread first, then SDK-controlled keys on top so
16
+ * a stray user key can't clobber the ingestion-attribution ones; the dedicated
17
+ * `serviceName` / `environment` / `serviceVersion` fields are how you override
18
+ * those three.
19
+ *
20
+ * @internal Shared within this SDK; not part of the stable public API.
21
+ */
22
+ export declare function buildOtlpResourceAttributes<TAttributeValue>(config: OtlpResourceConfig<TAttributeValue>, sdkName: string, sdkVersion: string): Record<string, TAttributeValue | string>;
23
+ /**
24
+ * Normalizes a natively-detected OS name against the table above.
25
+ * Unrecognized names pass through: a wrong-looking value beats dropping an OS
26
+ * we have not mapped yet.
27
+ *
28
+ * @internal Shared within this SDK; not part of the stable public API.
29
+ */
30
+ export declare function normalizeOsName(name: string | undefined): string | undefined;
31
+ /**
32
+ * The `os.name` / `os.version` resource attribute pair, with either key omitted
33
+ * rather than emitted empty when the host cannot determine it.
34
+ *
35
+ * @internal Exposed for cross-package use within this SDK; not part of the stable public API.
36
+ */
37
+ export declare function osResourceAttributes(name: string | undefined, version: string | undefined): Record<string, string>;
38
+ //# sourceMappingURL=otlp-resource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otlp-resource.d.ts","sourceRoot":"","sources":["../../src/utils/otlp-resource.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,kBAAkB,CAAC,eAAe;IACjD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;CACrD;AAED;;;;;;;;;GASG;AACH,wBAAgB,2BAA2B,CAAC,eAAe,EACzD,MAAM,EAAE,kBAAkB,CAAC,eAAe,CAAC,EAC3C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAAC,CAS1C;AA2BD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAK5E;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAMlH"}
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ var __webpack_require__ = {};
3
+ (()=>{
4
+ __webpack_require__.d = (exports1, definition)=>{
5
+ for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
6
+ enumerable: true,
7
+ get: definition[key]
8
+ });
9
+ };
10
+ })();
11
+ (()=>{
12
+ __webpack_require__.o = (obj, prop)=>Object.prototype.hasOwnProperty.call(obj, prop);
13
+ })();
14
+ (()=>{
15
+ __webpack_require__.r = (exports1)=>{
16
+ if ('undefined' != typeof Symbol && Symbol.toStringTag) Object.defineProperty(exports1, Symbol.toStringTag, {
17
+ value: 'Module'
18
+ });
19
+ Object.defineProperty(exports1, '__esModule', {
20
+ value: true
21
+ });
22
+ };
23
+ })();
24
+ var __webpack_exports__ = {};
25
+ __webpack_require__.r(__webpack_exports__);
26
+ __webpack_require__.d(__webpack_exports__, {
27
+ buildOtlpResourceAttributes: ()=>buildOtlpResourceAttributes,
28
+ normalizeOsName: ()=>normalizeOsName,
29
+ osResourceAttributes: ()=>osResourceAttributes
30
+ });
31
+ function buildOtlpResourceAttributes(config, sdkName, sdkVersion) {
32
+ return {
33
+ ...config.resourceAttributes,
34
+ 'service.name': config.serviceName || 'unknown_service',
35
+ ...config.environment && {
36
+ 'deployment.environment': config.environment
37
+ },
38
+ ...config.serviceVersion && {
39
+ 'service.version': config.serviceVersion
40
+ },
41
+ 'telemetry.sdk.name': sdkName,
42
+ 'telemetry.sdk.version': sdkVersion
43
+ };
44
+ }
45
+ const OS_NAMES = {
46
+ darwin: 'macOS',
47
+ win32: 'Windows',
48
+ linux: 'Linux',
49
+ android: 'Android',
50
+ freebsd: 'FreeBSD',
51
+ openbsd: 'OpenBSD',
52
+ sunos: 'SunOS',
53
+ aix: 'AIX',
54
+ 'Mac OS X': 'macOS'
55
+ };
56
+ function normalizeOsName(name) {
57
+ if (!name) return;
58
+ return Object.prototype.hasOwnProperty.call(OS_NAMES, name) ? OS_NAMES[name] : name;
59
+ }
60
+ function osResourceAttributes(name, version) {
61
+ const osName = normalizeOsName(name);
62
+ return {
63
+ ...osName ? {
64
+ 'os.name': osName
65
+ } : {},
66
+ ...version ? {
67
+ 'os.version': version
68
+ } : {}
69
+ };
70
+ }
71
+ exports.buildOtlpResourceAttributes = __webpack_exports__.buildOtlpResourceAttributes;
72
+ exports.normalizeOsName = __webpack_exports__.normalizeOsName;
73
+ exports.osResourceAttributes = __webpack_exports__.osResourceAttributes;
74
+ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
75
+ "buildOtlpResourceAttributes",
76
+ "normalizeOsName",
77
+ "osResourceAttributes"
78
+ ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
79
+ Object.defineProperty(exports, '__esModule', {
80
+ value: true
81
+ });
@@ -0,0 +1,41 @@
1
+ function buildOtlpResourceAttributes(config, sdkName, sdkVersion) {
2
+ return {
3
+ ...config.resourceAttributes,
4
+ 'service.name': config.serviceName || 'unknown_service',
5
+ ...config.environment && {
6
+ 'deployment.environment': config.environment
7
+ },
8
+ ...config.serviceVersion && {
9
+ 'service.version': config.serviceVersion
10
+ },
11
+ 'telemetry.sdk.name': sdkName,
12
+ 'telemetry.sdk.version': sdkVersion
13
+ };
14
+ }
15
+ const OS_NAMES = {
16
+ darwin: 'macOS',
17
+ win32: 'Windows',
18
+ linux: 'Linux',
19
+ android: 'Android',
20
+ freebsd: 'FreeBSD',
21
+ openbsd: 'OpenBSD',
22
+ sunos: 'SunOS',
23
+ aix: 'AIX',
24
+ 'Mac OS X': 'macOS'
25
+ };
26
+ function normalizeOsName(name) {
27
+ if (!name) return;
28
+ return Object.prototype.hasOwnProperty.call(OS_NAMES, name) ? OS_NAMES[name] : name;
29
+ }
30
+ function osResourceAttributes(name, version) {
31
+ const osName = normalizeOsName(name);
32
+ return {
33
+ ...osName ? {
34
+ 'os.name': osName
35
+ } : {},
36
+ ...version ? {
37
+ 'os.version': version
38
+ } : {}
39
+ };
40
+ }
41
+ export { buildOtlpResourceAttributes, normalizeOsName, osResourceAttributes };
@@ -8,10 +8,10 @@ export interface BrowserDetectionHints {
8
8
  brave?: boolean;
9
9
  }
10
10
  /**
11
- * Opt-in tweaks to UA-string detection. These change how existing traffic is
12
- * attributed, so the host SDK gates them (behind its `2026-05-30` config
13
- * defaults) rather than enabling them unconditionally turning one on
14
- * reattributes browsers that were previously reported as something else.
11
+ * Opt-in tweaks to UA-string detection. Turning one on reattributes browsers
12
+ * that were previously reported as something else, so the host SDK gates
13
+ * shifts big enough to move users' metrics behind its `2026-05-30` config
14
+ * defaults. Smaller reattributions ship unconditionally in `detectBrowser`.
15
15
  */
16
16
  export interface BrowserDetectionOptions {
17
17
  detectGoogleSearchApp?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"user-agent-utils.d.ts","sourceRoot":"","sources":["../../src/utils/user-agent-utils.ts"],"names":[],"mappings":"AAgEA;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IAGpC,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AASD;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IAGtC,qBAAqB,CAAC,EAAE,OAAO,CAAA;CAChC;AAgCD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,GACxB,YAAY,MAAM,EAClB,QAAQ,MAAM,GAAG,SAAS,EAC1B,QAAQ,qBAAqB,EAC7B,UAAU,uBAAuB,KAChC,MA2FF,CAAA;AAmCD;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,GAC/B,WAAW,MAAM,EACjB,QAAQ,MAAM,GAAG,SAAS,EAC1B,QAAQ,qBAAqB,EAC7B,UAAU,uBAAuB,KAChC,MAAM,GAAG,IAmBX,CAAA;AA0FD,eAAO,MAAM,QAAQ,GAAa,YAAY,MAAM,KAAG,CAAC,MAAM,EAAE,MAAM,CAUrE,CAAA;AAED,eAAO,MAAM,YAAY,GAAa,YAAY,MAAM,KAAG,MAuD1D,CAAA;AAED,eAAO,MAAM,gBAAgB,GAC3B,YAAY,MAAM,EAClB,UAAU;IACR,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B,KACA,MA4BF,CAAA"}
1
+ {"version":3,"file":"user-agent-utils.d.ts","sourceRoot":"","sources":["../../src/utils/user-agent-utils.ts"],"names":[],"mappings":"AAsEA;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IAGpC,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AASD;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IAGtC,qBAAqB,CAAC,EAAE,OAAO,CAAA;CAChC;AAgCD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,GACxB,YAAY,MAAM,EAClB,QAAQ,MAAM,GAAG,SAAS,EAC1B,QAAQ,qBAAqB,EAC7B,UAAU,uBAAuB,KAChC,MAkGF,CAAA;AAsCD;;;;;;;GAOG;AACH,eAAO,MAAM,oBAAoB,GAC/B,WAAW,MAAM,EACjB,QAAQ,MAAM,GAAG,SAAS,EAC1B,QAAQ,qBAAqB,EAC7B,UAAU,uBAAuB,KAChC,MAAM,GAAG,IAmBX,CAAA;AA0FD,eAAO,MAAM,QAAQ,GAAa,YAAY,MAAM,KAAG,CAAC,MAAM,EAAE,MAAM,CAUrE,CAAA;AAED,eAAO,MAAM,YAAY,GAAa,YAAY,MAAM,KAAG,MAuD1D,CAAA;AAED,eAAO,MAAM,gBAAgB,GAC3B,YAAY,MAAM,EAClB,UAAU;IACR,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B,KACA,MA4BF,CAAA"}
@@ -78,9 +78,13 @@ const DUCKDUCKGO = 'DuckDuckGo';
78
78
  const PALE_MOON = 'Pale Moon';
79
79
  const WATERFOX = 'Waterfox';
80
80
  const BRAVE = 'Brave';
81
+ const CLAUDE = 'Claude';
82
+ const CODEX = 'Codex';
83
+ const CHATGPT = 'ChatGPT';
81
84
  const GOOGLE_SEARCH_APP = 'Google Search App';
82
85
  const BROWSER_VERSION_REGEX_SUFFIX = '(\\d+(\\.\\d+)?)';
83
86
  const DEFAULT_BROWSER_VERSION_REGEX = new RegExp('Version/' + BROWSER_VERSION_REGEX_SUFFIX);
87
+ const AI_APP_VERSION_REGEX = new RegExp('(' + CLAUDE + '|' + CODEX + '|' + CHATGPT + ')\\/' + BROWSER_VERSION_REGEX_SUFFIX);
84
88
  function browserFromHints(hints) {
85
89
  if (hints?.brave) return BRAVE;
86
90
  return null;
@@ -122,6 +126,9 @@ const detectBrowser = function(user_agent, vendor, hints, options) {
122
126
  else if ((0, external_string_utils_js_namespaceObject.includes)(user_agent, 'YaBrowser/')) return YANDEX;
123
127
  else if ((0, external_string_utils_js_namespaceObject.includes)(user_agent, WHALE + '/')) return WHALE;
124
128
  else if ((0, external_string_utils_js_namespaceObject.includes)(user_agent, DUCKDUCKGO + '/') || (0, external_string_utils_js_namespaceObject.includes)(user_agent, 'Ddg/')) return DUCKDUCKGO;
129
+ else if ((0, external_string_utils_js_namespaceObject.includes)(user_agent, CLAUDE + '/')) return CLAUDE;
130
+ else if ((0, external_string_utils_js_namespaceObject.includes)(user_agent, CODEX + '/')) return CODEX;
131
+ else if ((0, external_string_utils_js_namespaceObject.includes)(user_agent, CHATGPT + '/')) return CHATGPT;
125
132
  else if ((0, external_string_utils_js_namespaceObject.includes)(user_agent, 'FBIOS')) return FACEBOOK + ' ' + MOBILE;
126
133
  else if ((0, external_string_utils_js_namespaceObject.includes)(user_agent, 'UCWEB') || (0, external_string_utils_js_namespaceObject.includes)(user_agent, 'UCBrowser')) return 'UC Browser';
127
134
  else if ((0, external_string_utils_js_namespaceObject.includes)(user_agent, 'CriOS')) return CHROME_IOS;
@@ -198,6 +205,15 @@ const versionRegexes = {
198
205
  [BRAVE]: [
199
206
  new RegExp(BRAVE + '\\/' + BROWSER_VERSION_REGEX_SUFFIX)
200
207
  ],
208
+ [CLAUDE]: [
209
+ AI_APP_VERSION_REGEX
210
+ ],
211
+ [CODEX]: [
212
+ AI_APP_VERSION_REGEX
213
+ ],
214
+ [CHATGPT]: [
215
+ AI_APP_VERSION_REGEX
216
+ ],
201
217
  [DUCKDUCKGO]: [
202
218
  new RegExp('(DuckDuckGo|Ddg)\\/' + BROWSER_VERSION_REGEX_SUFFIX)
203
219
  ],
@@ -46,9 +46,13 @@ const DUCKDUCKGO = 'DuckDuckGo';
46
46
  const PALE_MOON = 'Pale Moon';
47
47
  const WATERFOX = 'Waterfox';
48
48
  const BRAVE = 'Brave';
49
+ const CLAUDE = 'Claude';
50
+ const CODEX = 'Codex';
51
+ const CHATGPT = 'ChatGPT';
49
52
  const GOOGLE_SEARCH_APP = 'Google Search App';
50
53
  const BROWSER_VERSION_REGEX_SUFFIX = '(\\d+(\\.\\d+)?)';
51
54
  const DEFAULT_BROWSER_VERSION_REGEX = new RegExp('Version/' + BROWSER_VERSION_REGEX_SUFFIX);
55
+ const AI_APP_VERSION_REGEX = new RegExp('(' + CLAUDE + '|' + CODEX + '|' + CHATGPT + ')\\/' + BROWSER_VERSION_REGEX_SUFFIX);
52
56
  function browserFromHints(hints) {
53
57
  if (hints?.brave) return BRAVE;
54
58
  return null;
@@ -90,6 +94,9 @@ const detectBrowser = function(user_agent, vendor, hints, options) {
90
94
  else if (includes(user_agent, 'YaBrowser/')) return YANDEX;
91
95
  else if (includes(user_agent, WHALE + '/')) return WHALE;
92
96
  else if (includes(user_agent, DUCKDUCKGO + '/') || includes(user_agent, 'Ddg/')) return DUCKDUCKGO;
97
+ else if (includes(user_agent, CLAUDE + '/')) return CLAUDE;
98
+ else if (includes(user_agent, CODEX + '/')) return CODEX;
99
+ else if (includes(user_agent, CHATGPT + '/')) return CHATGPT;
93
100
  else if (includes(user_agent, 'FBIOS')) return FACEBOOK + ' ' + MOBILE;
94
101
  else if (includes(user_agent, 'UCWEB') || includes(user_agent, 'UCBrowser')) return 'UC Browser';
95
102
  else if (includes(user_agent, 'CriOS')) return CHROME_IOS;
@@ -166,6 +173,15 @@ const versionRegexes = {
166
173
  [BRAVE]: [
167
174
  new RegExp(BRAVE + '\\/' + BROWSER_VERSION_REGEX_SUFFIX)
168
175
  ],
176
+ [CLAUDE]: [
177
+ AI_APP_VERSION_REGEX
178
+ ],
179
+ [CODEX]: [
180
+ AI_APP_VERSION_REGEX
181
+ ],
182
+ [CHATGPT]: [
183
+ AI_APP_VERSION_REGEX
184
+ ],
169
185
  [DUCKDUCKGO]: [
170
186
  new RegExp('(DuckDuckGo|Ddg)\\/' + BROWSER_VERSION_REGEX_SUFFIX)
171
187
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@posthog/core",
3
- "version": "1.49.2",
3
+ "version": "1.50.1",
4
4
  "bugs": {
5
5
  "url": "https://github.com/PostHog/posthog-js/issues"
6
6
  },