@zuplo/cli 7.4.4 → 7.4.6
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/common/settings.d.ts +1 -0
- package/dist/common/settings.d.ts.map +1 -1
- package/dist/common/settings.js +3 -0
- package/dist/common/settings.js.map +1 -1
- package/dist/deploy/classify-build-probe.d.ts +14 -0
- package/dist/deploy/classify-build-probe.d.ts.map +1 -0
- package/dist/deploy/classify-build-probe.js +35 -0
- package/dist/deploy/classify-build-probe.js.map +1 -0
- package/dist/deploy/classify-build-probe.test.d.ts +2 -0
- package/dist/deploy/classify-build-probe.test.d.ts.map +1 -0
- package/dist/deploy/classify-build-probe.test.js +51 -0
- package/dist/deploy/classify-build-probe.test.js.map +1 -0
- package/dist/deploy/handler.js +20 -5
- package/dist/deploy/handler.js.map +1 -1
- package/dist/deploy/poll-deployment.d.ts +8 -4
- package/dist/deploy/poll-deployment.d.ts.map +1 -1
- package/dist/deploy/poll-deployment.js +32 -4
- package/dist/deploy/poll-deployment.js.map +1 -1
- package/dist/deploy/poll-deployment.test.d.ts +2 -0
- package/dist/deploy/poll-deployment.test.d.ts.map +1 -0
- package/dist/deploy/poll-deployment.test.js +158 -0
- package/dist/deploy/poll-deployment.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/types/jwks/remote.d.ts +4 -4
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/types/jws/general/verify.d.ts +3 -3
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/types/jwt/encrypt.d.ts +8 -14
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/types/jwt/sign.d.ts +8 -14
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/types/jwt/unsecured.d.ts +9 -15
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/jwe/compact/encrypt.js +30 -8
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/jwe/flattened/decrypt.js +8 -4
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/jwe/flattened/encrypt.js +6 -13
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/jwe/general/decrypt.js +19 -19
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/jwe/general/encrypt.js +27 -20
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/jwk/embedded.js +15 -1
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/jwk/thumbprint.js +11 -5
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/jwks/local.js +45 -53
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/jwks/remote.js +82 -103
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/jws/compact/sign.js +10 -9
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/jws/flattened/sign.js +2 -1
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/jws/flattened/verify.js +8 -7
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/jws/general/sign.js +5 -3
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/jws/general/verify.js +51 -21
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/jwt/decrypt.js +7 -9
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/jwt/encrypt.js +21 -50
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/jwt/sign.js +8 -41
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/jwt/unsecured.js +21 -42
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/key/generate_key_pair.js +6 -2
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/key/generate_secret.js +7 -6
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/key/import.js +16 -12
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/lib/asn1.js +7 -2
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/lib/content_encryption.js +7 -15
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/lib/deflate.js +8 -0
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/lib/helpers.js +1 -1
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/lib/jwe_decrypt.js +85 -28
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/lib/jwe_encrypt.js +40 -12
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/lib/jwk_metadata.js +20 -0
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/lib/jws_sign.js +47 -36
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/lib/jws_verify.js +77 -45
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/lib/jwt_claims_set.js +82 -47
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/lib/key.js +24 -9
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/lib/key_management.js +10 -4
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/lib/key_options.js +6 -0
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/lib/options.js +26 -0
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/dist/webapi/lib/type_checks.js +11 -13
- package/node_modules/@modelcontextprotocol/client/node_modules/jose/package.json +1 -1
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/types/jwks/remote.d.ts +4 -4
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/types/jws/general/verify.d.ts +3 -3
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/types/jwt/encrypt.d.ts +8 -14
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/types/jwt/sign.d.ts +8 -14
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/types/jwt/unsecured.d.ts +9 -15
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwe/compact/encrypt.js +30 -8
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwe/flattened/decrypt.js +8 -4
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwe/flattened/encrypt.js +6 -13
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwe/general/decrypt.js +19 -19
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwe/general/encrypt.js +27 -20
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwk/embedded.js +15 -1
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwk/thumbprint.js +11 -5
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwks/local.js +45 -53
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwks/remote.js +82 -103
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jws/compact/sign.js +10 -9
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jws/flattened/sign.js +2 -1
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jws/flattened/verify.js +8 -7
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jws/general/sign.js +5 -3
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jws/general/verify.js +51 -21
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwt/decrypt.js +7 -9
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwt/encrypt.js +21 -50
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwt/sign.js +8 -41
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/jwt/unsecured.js +21 -42
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/key/generate_key_pair.js +6 -2
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/key/generate_secret.js +7 -6
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/key/import.js +16 -12
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/asn1.js +7 -2
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/content_encryption.js +7 -15
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/deflate.js +8 -0
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/helpers.js +1 -1
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jwe_decrypt.js +85 -28
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jwe_encrypt.js +40 -12
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jwk_metadata.js +20 -0
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jws_sign.js +47 -36
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jws_verify.js +77 -45
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/jwt_claims_set.js +82 -47
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/key.js +24 -9
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/key_management.js +10 -4
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/key_options.js +6 -0
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/options.js +26 -0
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/dist/webapi/lib/type_checks.js +11 -13
- package/node_modules/@modelcontextprotocol/sdk/node_modules/jose/package.json +1 -1
- package/node_modules/@posthog/core/dist/logs/index.js +1 -1
- package/node_modules/@posthog/core/dist/logs/index.mjs +1 -1
- package/node_modules/@posthog/core/dist/logs/logs-utils.d.ts +4 -13
- package/node_modules/@posthog/core/dist/logs/logs-utils.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/logs/logs-utils.js +160 -26
- package/node_modules/@posthog/core/dist/logs/logs-utils.mjs +160 -26
- package/node_modules/@posthog/core/dist/metrics/index.js +1 -1
- package/node_modules/@posthog/core/dist/metrics/index.mjs +1 -1
- package/node_modules/@posthog/core/dist/posthog-core-stateless.d.ts +12 -18
- package/node_modules/@posthog/core/dist/posthog-core-stateless.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/posthog-core-stateless.js +15 -47
- package/node_modules/@posthog/core/dist/posthog-core-stateless.mjs +15 -47
- package/node_modules/@posthog/core/dist/posthog-core.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/posthog-core.js +12 -7
- package/node_modules/@posthog/core/dist/posthog-core.mjs +12 -7
- package/node_modules/@posthog/core/dist/types.d.ts +4 -1
- package/node_modules/@posthog/core/dist/types.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/utils/index.d.ts +1 -1
- package/node_modules/@posthog/core/dist/utils/index.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/utils/index.js +14 -24
- package/node_modules/@posthog/core/dist/utils/index.mjs +2 -2
- package/node_modules/@posthog/core/dist/utils/json-utils.d.ts +15 -0
- package/node_modules/@posthog/core/dist/utils/json-utils.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/utils/json-utils.js +24 -0
- package/node_modules/@posthog/core/dist/utils/json-utils.mjs +1 -1
- package/node_modules/@posthog/core/package.json +2 -2
- package/node_modules/@posthog/core/src/logs/index.spec.ts +77 -0
- package/node_modules/@posthog/core/src/logs/index.ts +2 -2
- package/node_modules/@posthog/core/src/logs/logs-utils.spec.ts +314 -9
- package/node_modules/@posthog/core/src/logs/logs-utils.ts +215 -27
- package/node_modules/@posthog/core/src/metrics/index.spec.ts +15 -1
- package/node_modules/@posthog/core/src/metrics/index.ts +1 -1
- package/node_modules/@posthog/core/src/posthog-core-stateless.ts +40 -65
- package/node_modules/@posthog/core/src/posthog-core.ts +19 -12
- package/node_modules/@posthog/core/src/types.ts +3 -1
- package/node_modules/@posthog/core/src/utils/index.ts +3 -1
- package/node_modules/@posthog/core/src/utils/json-utils.ts +15 -8
- package/node_modules/@posthog/types/dist/capture-log.d.ts +10 -1
- package/node_modules/@posthog/types/dist/capture-log.d.ts.map +1 -1
- package/node_modules/@posthog/types/dist/index.d.ts +1 -1
- package/node_modules/@posthog/types/dist/index.d.ts.map +1 -1
- package/node_modules/@posthog/types/dist/posthog-config.d.ts +20 -5
- package/node_modules/@posthog/types/dist/posthog-config.d.ts.map +1 -1
- package/node_modules/@posthog/types/package.json +1 -1
- package/node_modules/@posthog/types/src/capture-log.ts +8 -1
- package/node_modules/@posthog/types/src/index.ts +1 -0
- package/node_modules/@posthog/types/src/posthog-config.ts +21 -5
- package/node_modules/@zuplo/core/customer.cli.minified.js +1 -1
- package/node_modules/@zuplo/core/index.minified.js +1 -1
- package/node_modules/@zuplo/core/package.json +1 -1
- package/node_modules/@zuplo/graphql/package.json +1 -1
- package/node_modules/@zuplo/openapi-tools/package.json +1 -1
- package/node_modules/@zuplo/otel/package.json +1 -1
- package/node_modules/@zuplo/runtime/out/esm/{chunk-IZE65N7D.js → chunk-CUK3VROF.js} +2 -2
- package/node_modules/@zuplo/runtime/out/esm/{chunk-4CDML74A.js → chunk-K4TBJG47.js} +2 -2
- package/node_modules/@zuplo/runtime/out/esm/{chunk-4VE55TG3.js → chunk-S4EBLGSU.js} +2 -2
- package/node_modules/@zuplo/runtime/out/esm/{chunk-4POCC75H.js → chunk-XF3IIUDX.js} +4 -4
- package/node_modules/@zuplo/runtime/out/esm/{chunk-4POCC75H.js.map → chunk-XF3IIUDX.js.map} +1 -1
- package/node_modules/@zuplo/runtime/out/esm/chunk-ZPOD3IK4.js +403 -0
- package/node_modules/@zuplo/runtime/out/esm/chunk-ZPOD3IK4.js.map +1 -0
- package/node_modules/@zuplo/runtime/out/esm/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/esm/internal/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/esm/mocks/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/esm/sdks/aws/index.js +1 -1
- package/node_modules/@zuplo/runtime/package.json +1 -1
- package/node_modules/fast-uri/index.js +201 -48
- package/node_modules/fast-uri/lib/schemes.js +9 -4
- package/node_modules/fast-uri/lib/utils.js +388 -91
- package/node_modules/fast-uri/package.json +1 -1
- package/node_modules/fast-uri/test/component-safe-serialization.test.js +105 -0
- package/node_modules/fast-uri/test/equal.test.js +31 -3
- package/node_modules/fast-uri/test/fixtures/uri-js-parse.json +2 -0
- package/node_modules/fast-uri/test/ipv6-canonical.test.js +34 -0
- package/node_modules/fast-uri/test/ipv6-validation.test.js +90 -0
- package/node_modules/fast-uri/test/malformed-percent.test.js +77 -0
- package/node_modules/fast-uri/test/malformed-urn.test.js +61 -0
- package/node_modules/fast-uri/test/parse.test.js +7 -3
- package/node_modules/fast-uri/test/query-fragment-normalization.test.js +33 -0
- package/node_modules/fast-uri/test/reserved-path-normalization.test.js +109 -0
- package/node_modules/fast-uri/test/scheme-validation.test.js +124 -0
- package/node_modules/fast-uri/test/security-normalization.test.js +101 -0
- package/node_modules/fast-uri/test/security.test.js +75 -3
- package/node_modules/fast-uri/test/urn-full-input.test.js +29 -0
- package/node_modules/fast-uri/test/websocket-query-preservation.test.js +24 -0
- package/node_modules/hono/dist/cjs/client/client.js +25 -11
- package/node_modules/hono/dist/cjs/client/utils.js +3 -0
- package/node_modules/hono/dist/cjs/helper/accepts/accepts.js +36 -2
- package/node_modules/hono/dist/cjs/jsx/dom/render.js +2 -0
- package/node_modules/hono/dist/cjs/middleware/etag/index.js +1 -1
- package/node_modules/hono/dist/cjs/request.js +8 -4
- package/node_modules/hono/dist/cjs/router/reg-exp-router/node.js +10 -3
- package/node_modules/hono/dist/cjs/router/reg-exp-router/router.js +47 -83
- package/node_modules/hono/dist/cjs/router/reg-exp-router/trie.js +2 -1
- package/node_modules/hono/dist/cjs/router/trie-router/node.js +4 -3
- package/node_modules/hono/dist/cjs/router/utils.js +27 -0
- package/node_modules/hono/dist/cjs/utils/cookie.js +1 -1
- package/node_modules/hono/dist/cjs/utils/stream.js +7 -1
- package/node_modules/hono/dist/client/client.js +25 -11
- package/node_modules/hono/dist/client/utils.js +3 -0
- package/node_modules/hono/dist/helper/accepts/accepts.js +36 -2
- package/node_modules/hono/dist/jsx/dom/render.js +2 -0
- package/node_modules/hono/dist/middleware/etag/index.js +1 -1
- package/node_modules/hono/dist/request.js +8 -4
- package/node_modules/hono/dist/router/reg-exp-router/node.js +6 -2
- package/node_modules/hono/dist/router/reg-exp-router/router.js +53 -84
- package/node_modules/hono/dist/router/reg-exp-router/trie.js +2 -1
- package/node_modules/hono/dist/router/trie-router/node.js +4 -3
- package/node_modules/hono/dist/router/utils.js +5 -0
- package/node_modules/hono/dist/types/router/reg-exp-router/node.d.ts +3 -0
- package/node_modules/hono/dist/types/router/utils.d.ts +1 -0
- package/node_modules/hono/dist/utils/cookie.js +1 -1
- package/node_modules/hono/dist/utils/stream.js +7 -1
- package/node_modules/hono/package.json +1 -1
- package/package.json +11 -11
- package/node_modules/@zuplo/runtime/out/esm/chunk-4SX4HBWT.js +0 -409
- package/node_modules/@zuplo/runtime/out/esm/chunk-4SX4HBWT.js.map +0 -1
- /package/node_modules/@zuplo/runtime/out/esm/{chunk-IZE65N7D.js.map → chunk-CUK3VROF.js.map} +0 -0
- /package/node_modules/@zuplo/runtime/out/esm/{chunk-4CDML74A.js.map → chunk-K4TBJG47.js.map} +0 -0
- /package/node_modules/@zuplo/runtime/out/esm/{chunk-4VE55TG3.js.map → chunk-S4EBLGSU.js.map} +0 -0
- /package/node_modules/@zuplo/runtime/out/esm/{chunk-4POCC75H.js.LEGAL.txt → chunk-XF3IIUDX.js.LEGAL.txt} +0 -0
- /package/node_modules/@zuplo/runtime/out/esm/{chunk-4SX4HBWT.js.LEGAL.txt → chunk-ZPOD3IK4.js.LEGAL.txt} +0 -0
|
@@ -9,8 +9,19 @@ import type {
|
|
|
9
9
|
OtlpSeverityEntry,
|
|
10
10
|
OtlpSeverityText,
|
|
11
11
|
} from '@posthog/types'
|
|
12
|
+
import type { Logger } from '../types'
|
|
12
13
|
import type { LogSdkContext, ResolvedPostHogLogsConfig } from './types'
|
|
13
14
|
import { isArray, isBoolean, isNull, isNullish, isUndefined } from '../utils'
|
|
15
|
+
import {
|
|
16
|
+
CIRCULAR_VALUE,
|
|
17
|
+
FUNCTION_VALUE,
|
|
18
|
+
MAX_JSON_SAFE_VALUE_DEPTH,
|
|
19
|
+
MAX_JSON_SAFE_VALUE_ITEMS,
|
|
20
|
+
MAX_JSON_SAFE_VALUE_NODES,
|
|
21
|
+
sanitizeString,
|
|
22
|
+
TRUNCATED_VALUE,
|
|
23
|
+
UNSERIALIZABLE_VALUE,
|
|
24
|
+
} from '../utils/json-utils'
|
|
14
25
|
|
|
15
26
|
// ============================================================================
|
|
16
27
|
// Severity mapping
|
|
@@ -39,49 +50,192 @@ export function getOtlpSeverityNumber(level: LogSeverityLevel): number {
|
|
|
39
50
|
// OTLP AnyValue conversion
|
|
40
51
|
// ============================================================================
|
|
41
52
|
|
|
42
|
-
|
|
53
|
+
// 2^63 — one past int64 max.
|
|
54
|
+
const INT64_RANGE_LIMIT = 9223372036854775808
|
|
55
|
+
|
|
56
|
+
const propertyIsEnumerable = Object.prototype.propertyIsEnumerable
|
|
57
|
+
|
|
58
|
+
interface EncodeState {
|
|
59
|
+
/** Containers on the current path, so a back-reference becomes a marker. */
|
|
60
|
+
ancestors: WeakSet<object>
|
|
61
|
+
remainingNodes: number
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function newState(): EncodeState {
|
|
65
|
+
return { ancestors: new WeakSet(), remainingNodes: MAX_JSON_SAFE_VALUE_NODES }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function toOtlpAnyValue(value: LogAttributeValue, logger?: Logger): OtlpAnyValue {
|
|
69
|
+
try {
|
|
70
|
+
return encodeAnyValue(value, logger, newState(), 0)
|
|
71
|
+
} catch {
|
|
72
|
+
// Runs inside `captureLog` and the metrics flush: an error escaping here
|
|
73
|
+
// surfaces in the caller's own code.
|
|
74
|
+
return { stringValue: UNSERIALIZABLE_VALUE }
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function toOtlpKeyValueList(attrs: Record<string, LogAttributeValue>, logger?: Logger): OtlpKeyValue[] {
|
|
79
|
+
try {
|
|
80
|
+
return encodeKeyValueList(attrs, logger, newState(), 0)
|
|
81
|
+
} catch {
|
|
82
|
+
return []
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function encodeAnyValue(
|
|
87
|
+
value: LogAttributeValue,
|
|
88
|
+
logger: Logger | undefined,
|
|
89
|
+
state: EncodeState,
|
|
90
|
+
depth: number
|
|
91
|
+
): OtlpAnyValue {
|
|
92
|
+
if (state.remainingNodes <= 0) {
|
|
93
|
+
return { stringValue: TRUNCATED_VALUE }
|
|
94
|
+
}
|
|
95
|
+
state.remainingNodes--
|
|
96
|
+
|
|
43
97
|
if (isBoolean(value)) {
|
|
44
98
|
return { boolValue: value }
|
|
45
99
|
}
|
|
46
|
-
//
|
|
47
|
-
//
|
|
48
|
-
// route NaN through the JSON.stringify branch below — JSON has no
|
|
49
|
-
// representation for non-finite floats and JSON.stringify turns them into
|
|
50
|
-
// `null`, losing the value server-side. proto3 JSON mapping (which OTLP/HTTP
|
|
51
|
-
// rides) requires the literal strings; we encode them as stringValue to keep
|
|
52
|
-
// the human-readable signal regardless of which downstream parser sees them.
|
|
100
|
+
// typeof, not core's isNumber, which excludes NaN — proto3 JSON distinguishes
|
|
101
|
+
// a non-finite float from an ordinary string.
|
|
53
102
|
if (typeof value === 'number') {
|
|
54
103
|
if (!Number.isFinite(value)) {
|
|
55
104
|
return { stringValue: String(value) }
|
|
56
105
|
}
|
|
57
106
|
if (Number.isInteger(value)) {
|
|
58
|
-
|
|
107
|
+
if (Number.isSafeInteger(value)) {
|
|
108
|
+
return { intValue: String(value) }
|
|
109
|
+
}
|
|
110
|
+
// Past MAX_SAFE_INTEGER only BigInt gives the double's exact decimal:
|
|
111
|
+
// `String(-(2**63))` lands 192 below int64 min, outside the field it is
|
|
112
|
+
// about to be parsed into. Without BigInt the value rides as a string,
|
|
113
|
+
// which is never range-checked.
|
|
114
|
+
if (typeof BigInt === 'undefined') {
|
|
115
|
+
return { stringValue: String(value) }
|
|
116
|
+
}
|
|
117
|
+
const decimal = BigInt(value).toString()
|
|
118
|
+
if (value >= INT64_RANGE_LIMIT || value < -INT64_RANGE_LIMIT) {
|
|
119
|
+
// An out-of-range intValue 400s the whole logs request; on the metrics
|
|
120
|
+
// path it is swallowed server-side and the metric just disappears.
|
|
121
|
+
logger?.debug(`Attribute ${decimal} is outside the int64 range; encoding it as a string`)
|
|
122
|
+
return { stringValue: decimal }
|
|
123
|
+
}
|
|
124
|
+
return { intValue: decimal }
|
|
59
125
|
}
|
|
60
126
|
return { doubleValue: value }
|
|
61
127
|
}
|
|
62
128
|
if (typeof value === 'string') {
|
|
63
|
-
return { stringValue: value }
|
|
129
|
+
return { stringValue: sanitizeString(value) }
|
|
64
130
|
}
|
|
65
|
-
|
|
66
|
-
|
|
131
|
+
// `String(value)` would put a function's source text on the wire.
|
|
132
|
+
if (typeof value === 'function') {
|
|
133
|
+
return { stringValue: FUNCTION_VALUE }
|
|
67
134
|
}
|
|
68
|
-
|
|
69
|
-
// stays flat for simplicity.
|
|
70
|
-
try {
|
|
71
|
-
return { stringValue: JSON.stringify(value) }
|
|
72
|
-
} catch {
|
|
135
|
+
if (typeof value === 'symbol') {
|
|
73
136
|
return { stringValue: String(value) }
|
|
74
137
|
}
|
|
138
|
+
if (typeof value === 'object' && value !== null) {
|
|
139
|
+
if (state.ancestors.has(value)) {
|
|
140
|
+
return { stringValue: CIRCULAR_VALUE }
|
|
141
|
+
}
|
|
142
|
+
if (depth >= MAX_JSON_SAFE_VALUE_DEPTH) {
|
|
143
|
+
return { stringValue: TRUNCATED_VALUE }
|
|
144
|
+
}
|
|
145
|
+
if (value instanceof Date) {
|
|
146
|
+
const time = value.getTime()
|
|
147
|
+
const iso = Number.isFinite(time) ? value.toISOString() : String(value)
|
|
148
|
+
// An overridden toISOString can return a non-string, which the server
|
|
149
|
+
// refuses for the whole request.
|
|
150
|
+
return { stringValue: typeof iso === 'string' ? sanitizeString(iso) : String(iso) }
|
|
151
|
+
}
|
|
152
|
+
// Registered before the toJSON probe: a toJSON returning a structure that
|
|
153
|
+
// references its own object is a cycle like any other.
|
|
154
|
+
state.ancestors.add(value)
|
|
155
|
+
try {
|
|
156
|
+
// The representation a value defines for itself — dayjs, Decimal, an ORM
|
|
157
|
+
// document, and a cross-realm Date that fails the `instanceof` above.
|
|
158
|
+
try {
|
|
159
|
+
const toJSON = (value as { toJSON?: unknown }).toJSON
|
|
160
|
+
if (typeof toJSON === 'function') {
|
|
161
|
+
return encodeAnyValue(toJSON.call(value) as LogAttributeValue, logger, state, depth + 1)
|
|
162
|
+
}
|
|
163
|
+
} catch {
|
|
164
|
+
// A throwing toJSON falls through to the plain walk.
|
|
165
|
+
}
|
|
166
|
+
if (isArray(value)) {
|
|
167
|
+
return { arrayValue: { values: encodeArrayValues(value, logger, state, depth + 1) } }
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
kvlistValue: {
|
|
171
|
+
values: encodeKeyValueList(value as Record<string, LogAttributeValue>, logger, state, depth + 1),
|
|
172
|
+
},
|
|
173
|
+
}
|
|
174
|
+
} finally {
|
|
175
|
+
// Siblings that reference the same object are duplication, not a cycle.
|
|
176
|
+
state.ancestors.delete(value)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return { stringValue: sanitizeString(String(value)) }
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function encodeArrayValues(
|
|
183
|
+
values: unknown[],
|
|
184
|
+
logger: Logger | undefined,
|
|
185
|
+
state: EncodeState,
|
|
186
|
+
depth: number
|
|
187
|
+
): OtlpAnyValue[] {
|
|
188
|
+
const result: OtlpAnyValue[] = []
|
|
189
|
+
const itemCount = Math.min(values.length, MAX_JSON_SAFE_VALUE_ITEMS)
|
|
190
|
+
let index = 0
|
|
191
|
+
for (; index < itemCount && state.remainingNodes > 0; index++) {
|
|
192
|
+
try {
|
|
193
|
+
const element = index in values ? values[index] : undefined
|
|
194
|
+
// Dropped, as iOS and Android do: proto3 JSON has no null AnyValue, and
|
|
195
|
+
// both `null` and `{}` here are rejected for the whole request.
|
|
196
|
+
if (isNullish(element)) {
|
|
197
|
+
continue
|
|
198
|
+
}
|
|
199
|
+
result.push(encodeAnyValue(element as LogAttributeValue, logger, state, depth))
|
|
200
|
+
} catch {
|
|
201
|
+
result.push({ stringValue: UNSERIALIZABLE_VALUE })
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (values.length > index) {
|
|
205
|
+
result.push({ stringValue: TRUNCATED_VALUE })
|
|
206
|
+
}
|
|
207
|
+
return result
|
|
75
208
|
}
|
|
76
209
|
|
|
77
|
-
|
|
210
|
+
function encodeKeyValueList(
|
|
211
|
+
attrs: Record<string, LogAttributeValue>,
|
|
212
|
+
logger: Logger | undefined,
|
|
213
|
+
state: EncodeState,
|
|
214
|
+
depth: number
|
|
215
|
+
): OtlpKeyValue[] {
|
|
78
216
|
const result: OtlpKeyValue[] = []
|
|
79
217
|
for (const key in attrs) {
|
|
80
|
-
|
|
81
|
-
|
|
218
|
+
// for...in walks the prototype chain once own keys are exhausted. Skipped
|
|
219
|
+
// rather than broken out of: a proxy can yield keys in any order.
|
|
220
|
+
if (!propertyIsEnumerable.call(attrs, key)) {
|
|
82
221
|
continue
|
|
83
222
|
}
|
|
84
|
-
result.
|
|
223
|
+
if (result.length >= MAX_JSON_SAFE_VALUE_ITEMS || state.remainingNodes <= 0) {
|
|
224
|
+
// Reported rather than written into the attributes: a synthetic key would
|
|
225
|
+
// land in the user's own namespace and could collide with a real one.
|
|
226
|
+
logger?.debug('Attributes truncated: the value exceeds the OTLP encoder budget')
|
|
227
|
+
break
|
|
228
|
+
}
|
|
229
|
+
try {
|
|
230
|
+
const value = attrs[key]
|
|
231
|
+
if (isNull(value) || isUndefined(value)) {
|
|
232
|
+
continue
|
|
233
|
+
}
|
|
234
|
+
result.push({ key: sanitizeString(key), value: encodeAnyValue(value, logger, state, depth) })
|
|
235
|
+
} catch {
|
|
236
|
+
// A getter that throws costs its own key, not the whole record.
|
|
237
|
+
result.push({ key: sanitizeString(key), value: { stringValue: UNSERIALIZABLE_VALUE } })
|
|
238
|
+
}
|
|
85
239
|
}
|
|
86
240
|
return result
|
|
87
241
|
}
|
|
@@ -111,7 +265,22 @@ function timestampToUnixNano(): string {
|
|
|
111
265
|
*
|
|
112
266
|
* User-provided `options.attributes` always wins on conflicts.
|
|
113
267
|
*/
|
|
114
|
-
|
|
268
|
+
// `body` is only typed as a string. An untyped caller — or a `beforeSend` that
|
|
269
|
+
// rewrites it — can pass anything, and `String()` throws on a value whose
|
|
270
|
+
// `toString` does, or on a null-prototype object.
|
|
271
|
+
function encodeBody(body: string): string {
|
|
272
|
+
try {
|
|
273
|
+
return sanitizeString(String(body))
|
|
274
|
+
} catch {
|
|
275
|
+
return UNSERIALIZABLE_VALUE
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export function buildOtlpLogRecord(
|
|
280
|
+
options: CaptureLogOptions,
|
|
281
|
+
sdkContext: LogSdkContext,
|
|
282
|
+
logger?: Logger
|
|
283
|
+
): OtlpLogRecord {
|
|
115
284
|
const level: LogSeverityLevel = options.level || 'info'
|
|
116
285
|
const { text: severityText, number: severityNumber } = OTLP_SEVERITY_MAP[level] || DEFAULT_OTLP_SEVERITY
|
|
117
286
|
const now = timestampToUnixNano()
|
|
@@ -146,9 +315,28 @@ export function buildOtlpLogRecord(options: CaptureLogOptions, sdkContext: LogSd
|
|
|
146
315
|
autoAttributes.feature_flags = sdkContext.activeFeatureFlags
|
|
147
316
|
}
|
|
148
317
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
318
|
+
// Read key by key rather than spreading: a getter over a disposed store or a
|
|
319
|
+
// revoked proxy throws on the read itself, before the encoder's guards see it.
|
|
320
|
+
const mergedAttributes: Record<string, LogAttributeValue> = { ...autoAttributes }
|
|
321
|
+
const userAttributes = options.attributes
|
|
322
|
+
if (userAttributes) {
|
|
323
|
+
let keys: string[] = []
|
|
324
|
+
try {
|
|
325
|
+
keys = Object.keys(userAttributes)
|
|
326
|
+
} catch {
|
|
327
|
+
keys = []
|
|
328
|
+
}
|
|
329
|
+
for (const key of keys) {
|
|
330
|
+
let value: LogAttributeValue
|
|
331
|
+
try {
|
|
332
|
+
value = userAttributes[key]
|
|
333
|
+
} catch {
|
|
334
|
+
value = UNSERIALIZABLE_VALUE
|
|
335
|
+
}
|
|
336
|
+
// defineProperty, not assignment: `attributes['__proto__'] = v` hits the
|
|
337
|
+
// prototype setter and the attribute vanishes.
|
|
338
|
+
Object.defineProperty(mergedAttributes, key, { value, enumerable: true, writable: true, configurable: true })
|
|
339
|
+
}
|
|
152
340
|
}
|
|
153
341
|
|
|
154
342
|
const record: OtlpLogRecord = {
|
|
@@ -156,8 +344,8 @@ export function buildOtlpLogRecord(options: CaptureLogOptions, sdkContext: LogSd
|
|
|
156
344
|
observedTimeUnixNano: now,
|
|
157
345
|
severityNumber,
|
|
158
346
|
severityText,
|
|
159
|
-
body: { stringValue: options.body },
|
|
160
|
-
attributes: toOtlpKeyValueList(mergedAttributes),
|
|
347
|
+
body: { stringValue: encodeBody(options.body) },
|
|
348
|
+
attributes: toOtlpKeyValueList(mergedAttributes, logger),
|
|
161
349
|
}
|
|
162
350
|
|
|
163
351
|
if (options.trace_id) {
|
|
@@ -169,10 +169,24 @@ describe('PostHogMetrics', () => {
|
|
|
169
169
|
|
|
170
170
|
const attrs = sentMetrics()[0].sum!.dataPoints[0].attributes
|
|
171
171
|
expect(attrs).toContainEqual({ key: 'route', value: { stringValue: '/home' } })
|
|
172
|
-
expect(attrs).toContainEqual({ key: 'retries', value: { intValue: 2 } })
|
|
172
|
+
expect(attrs).toContainEqual({ key: 'retries', value: { intValue: '2' } })
|
|
173
173
|
expect(attrs).toContainEqual({ key: 'cached', value: { boolValue: true } })
|
|
174
174
|
})
|
|
175
175
|
|
|
176
|
+
// The encoder is shared with logs, so the debug line it emits on the
|
|
177
|
+
// out-of-range path only reaches anyone if metrics passes its logger down.
|
|
178
|
+
it('encodes an out-of-int64 attribute as a string and reports it through the logger', async () => {
|
|
179
|
+
const metrics = createMetrics()
|
|
180
|
+
metrics.count('api_calls', 1, { attributes: { huge: 2 ** 63 } as any })
|
|
181
|
+
await metrics.flush()
|
|
182
|
+
|
|
183
|
+
const attrs = sentMetrics()[0].sum!.dataPoints[0].attributes
|
|
184
|
+
expect(attrs).toContainEqual({ key: 'huge', value: { stringValue: '9223372036854775808' } })
|
|
185
|
+
expect((logger.debug as jest.Mock).mock.calls.some((c) => String(c[0]).includes('outside the int64 range'))).toBe(
|
|
186
|
+
true
|
|
187
|
+
)
|
|
188
|
+
})
|
|
189
|
+
|
|
176
190
|
it('stamps delta data points with a window: startTimeUnixNano <= timeUnixNano, both nano strings', async () => {
|
|
177
191
|
const metrics = createMetrics()
|
|
178
192
|
metrics.count('orders_created', 1)
|
|
@@ -374,7 +374,7 @@ export class PostHogMetrics {
|
|
|
374
374
|
byMetric.set(metricKey, metric)
|
|
375
375
|
}
|
|
376
376
|
|
|
377
|
-
const attributes = toOtlpKeyValueList(state.attributes ?? {})
|
|
377
|
+
const attributes = toOtlpKeyValueList(state.attributes ?? {}, this._logger)
|
|
378
378
|
const startNano = msToUnixNano(state.windowStartMs)
|
|
379
379
|
|
|
380
380
|
if (state.type === 'count') {
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
FeatureFlagDetail,
|
|
18
18
|
SurveyResponse,
|
|
19
19
|
PostHogFetchResponse,
|
|
20
|
+
PostHogFetchBodyBytes,
|
|
20
21
|
PostHogFetchOptions,
|
|
21
22
|
PostHogPersistedProperty,
|
|
22
23
|
PostHogQueueItem,
|
|
@@ -221,13 +222,12 @@ function isPostHogEventProperties(value: JsonType | undefined): value is PostHog
|
|
|
221
222
|
}
|
|
222
223
|
|
|
223
224
|
/**
|
|
224
|
-
* Outcome of a logs batch send. Keeps HTTP error classification inside core
|
|
225
|
-
* (single source of truth — same policy events already use in `_flush()`) so
|
|
225
|
+
* Outcome of a logs batch send. Keeps HTTP error classification inside core so
|
|
226
226
|
* PostHogLogs doesn't need to know about specific error types.
|
|
227
227
|
*
|
|
228
228
|
* - ok → records are accepted; drop them from the queue
|
|
229
229
|
* - too-large → 413; caller should halve batch size and retry same records
|
|
230
|
-
* - retry-later → network error; caller keeps records and retries next cycle
|
|
230
|
+
* - retry-later → retryable network or HTTP error; caller keeps records and retries next cycle
|
|
231
231
|
* - fatal → anything else (auth, malformed, etc.); caller drops the
|
|
232
232
|
* batch and surfaces the error
|
|
233
233
|
*/
|
|
@@ -237,6 +237,17 @@ export type SendLogsBatchOutcome =
|
|
|
237
237
|
| { kind: 'retry-later'; error: unknown }
|
|
238
238
|
| { kind: 'fatal'; error: unknown }
|
|
239
239
|
|
|
240
|
+
/**
|
|
241
|
+
* Each signal keeps its own exported outcome type because each belongs to a
|
|
242
|
+
* separate host contract. The wrappers return this value directly, so one
|
|
243
|
+
* drifting out of shape fails to compile.
|
|
244
|
+
*/
|
|
245
|
+
type SendOtlpBatchOutcome =
|
|
246
|
+
| { kind: 'ok' }
|
|
247
|
+
| { kind: 'too-large' }
|
|
248
|
+
| { kind: 'retry-later'; error: unknown }
|
|
249
|
+
| { kind: 'fatal'; error: unknown }
|
|
250
|
+
|
|
240
251
|
export enum QuotaLimitedFeature {
|
|
241
252
|
FeatureFlags = 'feature_flags',
|
|
242
253
|
Recordings = 'recordings',
|
|
@@ -1447,7 +1458,7 @@ export abstract class PostHogCoreStateless {
|
|
|
1447
1458
|
* Compresses an outgoing payload. Runtime-specific clients can override this
|
|
1448
1459
|
* to avoid using the Web Streams compression implementation.
|
|
1449
1460
|
*/
|
|
1450
|
-
protected compressPayload(payload: string): Promise<Blob | null> {
|
|
1461
|
+
protected compressPayload(payload: string): Promise<Blob | PostHogFetchBodyBytes | null> {
|
|
1451
1462
|
return gzipCompress(payload, this.isDebug)
|
|
1452
1463
|
}
|
|
1453
1464
|
|
|
@@ -1632,22 +1643,28 @@ export abstract class PostHogCoreStateless {
|
|
|
1632
1643
|
}
|
|
1633
1644
|
|
|
1634
1645
|
/**
|
|
1635
|
-
*
|
|
1636
|
-
* outcome instead of throwing so
|
|
1637
|
-
* core's error class hierarchy.
|
|
1638
|
-
* source of truth, same policy the events `_flush()` uses for its own
|
|
1639
|
-
* 413 / network / fatal handling).
|
|
1646
|
+
* Shared implementation behind the OTLP senders, which differ only in path.
|
|
1647
|
+
* Returns a tagged outcome instead of throwing so the queue owners don't
|
|
1648
|
+
* have to know the core's error class hierarchy.
|
|
1640
1649
|
*
|
|
1641
|
-
*
|
|
1642
|
-
*
|
|
1650
|
+
* Exhausted 408/429/5xx stay `retry-later`, unlike the events `_flush()`
|
|
1651
|
+
* which drops anything that isn't a network error: every OTLP queue is
|
|
1652
|
+
* bounded and retried with backoff, so holding a batch through an outage can
|
|
1653
|
+
* neither grow without limit nor spin.
|
|
1643
1654
|
*/
|
|
1644
|
-
async
|
|
1655
|
+
private async _sendOtlpBatch({
|
|
1656
|
+
path,
|
|
1657
|
+
payload,
|
|
1658
|
+
}: {
|
|
1659
|
+
path: 'logs' | 'metrics'
|
|
1660
|
+
payload: OtlpLogsPayload | OtlpMetricsPayload
|
|
1661
|
+
}): Promise<SendOtlpBatchOutcome> {
|
|
1645
1662
|
if (this.disabled) {
|
|
1646
1663
|
return { kind: 'fatal', error: new Error('The client is disabled') }
|
|
1647
1664
|
}
|
|
1648
1665
|
|
|
1649
1666
|
const serialized = JSON.stringify(payload)
|
|
1650
|
-
const url = `${this.host}/i/v1
|
|
1667
|
+
const url = `${this.host}/i/v1/${path}?token=${encodeURIComponent(this.apiKey)}`
|
|
1651
1668
|
|
|
1652
1669
|
const gzippedPayload = !this.disableCompression ? await this.compressPayload(serialized) : null
|
|
1653
1670
|
const fetchOptions: PostHogFetchOptions = {
|
|
@@ -1679,65 +1696,19 @@ export abstract class PostHogCoreStateless {
|
|
|
1679
1696
|
if (isPostHogFetchContentTooLargeError(err)) {
|
|
1680
1697
|
return { kind: 'too-large' }
|
|
1681
1698
|
}
|
|
1682
|
-
if (err
|
|
1699
|
+
if (isPostHogFetchRetryableError(err)) {
|
|
1683
1700
|
return { kind: 'retry-later', error: err }
|
|
1684
1701
|
}
|
|
1685
1702
|
return { kind: 'fatal', error: err }
|
|
1686
1703
|
}
|
|
1687
1704
|
}
|
|
1688
1705
|
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
* the `MetricsHost._sendMetricsBatch` implementation, so `PostHogMetrics`
|
|
1693
|
-
* can use any core-based SDK as its host.
|
|
1694
|
-
*/
|
|
1695
|
-
async _sendMetricsBatch(payload: OtlpMetricsPayload): Promise<SendMetricsBatchOutcome> {
|
|
1696
|
-
if (this.disabled) {
|
|
1697
|
-
return { kind: 'fatal', error: new Error('The client is disabled') }
|
|
1698
|
-
}
|
|
1699
|
-
|
|
1700
|
-
const serialized = JSON.stringify(payload)
|
|
1701
|
-
const url = `${this.host}/i/v1/metrics?token=${encodeURIComponent(this.apiKey)}`
|
|
1702
|
-
|
|
1703
|
-
const gzippedPayload = !this.disableCompression ? await this.compressPayload(serialized) : null
|
|
1704
|
-
const fetchOptions: PostHogFetchOptions = {
|
|
1705
|
-
method: 'POST',
|
|
1706
|
-
headers: {
|
|
1707
|
-
...this.getCustomHeaders(),
|
|
1708
|
-
'Content-Type': 'application/json',
|
|
1709
|
-
...(gzippedPayload !== null && { 'Content-Encoding': 'gzip' }),
|
|
1710
|
-
},
|
|
1711
|
-
body: gzippedPayload || serialized,
|
|
1712
|
-
}
|
|
1706
|
+
async _sendLogsBatch(payload: OtlpLogsPayload): Promise<SendLogsBatchOutcome> {
|
|
1707
|
+
return this._sendOtlpBatch({ path: 'logs', payload })
|
|
1708
|
+
}
|
|
1713
1709
|
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
url,
|
|
1717
|
-
fetchOptions,
|
|
1718
|
-
{ type: 'successful-write' },
|
|
1719
|
-
{
|
|
1720
|
-
retryCheck: (err) => {
|
|
1721
|
-
if (isPostHogFetchContentTooLargeError(err)) {
|
|
1722
|
-
return false
|
|
1723
|
-
}
|
|
1724
|
-
return isPostHogFetchRetryableError(err)
|
|
1725
|
-
},
|
|
1726
|
-
}
|
|
1727
|
-
)
|
|
1728
|
-
return { kind: 'ok' }
|
|
1729
|
-
} catch (err) {
|
|
1730
|
-
if (isPostHogFetchContentTooLargeError(err)) {
|
|
1731
|
-
return { kind: 'too-large' }
|
|
1732
|
-
}
|
|
1733
|
-
// Exhausted retries on a retryable failure (network error, 408/429/5xx)
|
|
1734
|
-
// still classify as retry-later so the window rides the next flush; only
|
|
1735
|
-
// non-retryable HTTP errors (and 413 above) drop the batch.
|
|
1736
|
-
if (isPostHogFetchRetryableError(err)) {
|
|
1737
|
-
return { kind: 'retry-later', error: err }
|
|
1738
|
-
}
|
|
1739
|
-
return { kind: 'fatal', error: err }
|
|
1740
|
-
}
|
|
1710
|
+
async _sendMetricsBatch(payload: OtlpMetricsPayload): Promise<SendMetricsBatchOutcome> {
|
|
1711
|
+
return this._sendOtlpBatch({ path: 'metrics', payload })
|
|
1741
1712
|
}
|
|
1742
1713
|
|
|
1743
1714
|
private fetchWithRetry<T>(
|
|
@@ -1766,12 +1737,16 @@ export abstract class PostHogCoreStateless {
|
|
|
1766
1737
|
try {
|
|
1767
1738
|
if (body instanceof Blob) {
|
|
1768
1739
|
reqByteLength = body.size
|
|
1740
|
+
} else if (body instanceof Uint8Array) {
|
|
1741
|
+
reqByteLength = body.byteLength
|
|
1769
1742
|
} else {
|
|
1770
1743
|
reqByteLength = Buffer.byteLength(body, STRING_FORMAT)
|
|
1771
1744
|
}
|
|
1772
1745
|
} catch {
|
|
1773
1746
|
if (body instanceof Blob) {
|
|
1774
1747
|
reqByteLength = body.size
|
|
1748
|
+
} else if (body instanceof Uint8Array) {
|
|
1749
|
+
reqByteLength = body.byteLength
|
|
1775
1750
|
} else {
|
|
1776
1751
|
const encoded = new TextEncoder().encode(body)
|
|
1777
1752
|
reqByteLength = encoded.length
|
|
@@ -53,8 +53,11 @@ interface FlagsAsyncOptions {
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
interface PendingFlagsRequest extends FlagsAsyncOptions {
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
// every caller displaced from this slot, so none is settled against a request it did not make
|
|
57
|
+
waiters: {
|
|
58
|
+
resolve: (value: PostHogFeatureFlagsResponse | undefined) => void
|
|
59
|
+
reject: (reason?: unknown) => void
|
|
60
|
+
}[]
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
export abstract class PostHogCore extends PostHogCoreStateless {
|
|
@@ -651,16 +654,20 @@ export abstract class PostHogCore extends PostHogCoreStateless {
|
|
|
651
654
|
return undefined
|
|
652
655
|
}
|
|
653
656
|
if (this._flagsResponsePromise) {
|
|
654
|
-
// Queue
|
|
655
|
-
//
|
|
657
|
+
// Queue rather than drop, so an identity-changing reload still reaches the server. Displaced
|
|
658
|
+
// callers are carried over rather than settled against the in-flight request: that request
|
|
659
|
+
// was issued before their context changed, so it cannot reflect it. Options are merged so
|
|
660
|
+
// the single queued request satisfies every caller behind it — one caller asking for the
|
|
661
|
+
// remote config or for $anon_distinct_id is enough for the re-issued request to carry it.
|
|
656
662
|
this._logger.info('Feature flags are being loaded already, queuing reload.')
|
|
657
|
-
|
|
658
|
-
if (this._pendingFlagsRequest) {
|
|
659
|
-
this._flagsResponsePromise.then(this._pendingFlagsRequest.resolve).catch(this._pendingFlagsRequest.reject)
|
|
660
|
-
}
|
|
661
|
-
// Return a promise that resolves when the pending request completes
|
|
663
|
+
const pending = this._pendingFlagsRequest
|
|
662
664
|
return new Promise((resolve, reject) => {
|
|
663
|
-
this._pendingFlagsRequest = {
|
|
665
|
+
this._pendingFlagsRequest = {
|
|
666
|
+
sendAnonDistinctId: sendAnonDistinctId || !!pending?.sendAnonDistinctId,
|
|
667
|
+
fetchConfig: fetchConfig || !!pending?.fetchConfig,
|
|
668
|
+
triggerOnRemoteConfig: triggerOnRemoteConfig || !!pending?.triggerOnRemoteConfig,
|
|
669
|
+
waiters: [...(pending?.waiters ?? []), { resolve, reject }],
|
|
670
|
+
}
|
|
664
671
|
})
|
|
665
672
|
}
|
|
666
673
|
return this._flagsAsync({ sendAnonDistinctId, fetchConfig, triggerOnRemoteConfig })
|
|
@@ -911,8 +918,8 @@ export abstract class PostHogCore extends PostHogCoreStateless {
|
|
|
911
918
|
fetchConfig: pendingRequest.fetchConfig,
|
|
912
919
|
triggerOnRemoteConfig: pendingRequest.triggerOnRemoteConfig,
|
|
913
920
|
})
|
|
914
|
-
.then(pendingRequest.resolve)
|
|
915
|
-
.catch(pendingRequest.reject)
|
|
921
|
+
.then((res) => pendingRequest.waiters.forEach((w) => w.resolve(res)))
|
|
922
|
+
.catch((e) => pendingRequest.waiters.forEach((w) => w.reject(e)))
|
|
916
923
|
}
|
|
917
924
|
})
|
|
918
925
|
return this._flagsResponsePromise
|
|
@@ -299,12 +299,14 @@ export enum PostHogPersistedProperty {
|
|
|
299
299
|
DeviceId = 'device_id', // only used by posthog-react-native
|
|
300
300
|
}
|
|
301
301
|
|
|
302
|
+
export type PostHogFetchBodyBytes = Uint8Array & { buffer: ArrayBuffer }
|
|
303
|
+
|
|
302
304
|
export type PostHogFetchOptions = {
|
|
303
305
|
method: 'GET' | 'POST' | 'PUT' | 'PATCH'
|
|
304
306
|
mode?: 'no-cors'
|
|
305
307
|
credentials?: 'omit'
|
|
306
308
|
headers: { [key: string]: string }
|
|
307
|
-
body?: string | Blob
|
|
309
|
+
body?: string | Blob | PostHogFetchBodyBytes
|
|
308
310
|
signal?: AbortSignal
|
|
309
311
|
}
|
|
310
312
|
|
|
@@ -3,7 +3,9 @@ import { FetchLike } from '../types'
|
|
|
3
3
|
export * from './bot-detection'
|
|
4
4
|
export * from './browser-utils'
|
|
5
5
|
export * from './bucketed-rate-limiter'
|
|
6
|
-
export
|
|
6
|
+
// Named rather than `export *`: the budgets, markers and `sanitizeString` are
|
|
7
|
+
// shared with the OTLP encoder but are not public API.
|
|
8
|
+
export { toJsonSafeValue } from './json-utils'
|
|
7
9
|
export * from './number-utils'
|
|
8
10
|
export * from './string-utils'
|
|
9
11
|
export * from './type-utils'
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
1
|
+
/** Traversal budgets and markers, shared with the OTLP attribute encoder. Not
|
|
2
|
+
* public API — `utils/index.ts` re-exports `toJsonSafeValue` only. */
|
|
3
|
+
export const MAX_JSON_SAFE_VALUE_DEPTH = 20
|
|
4
|
+
export const MAX_JSON_SAFE_VALUE_ITEMS = 1_000
|
|
5
|
+
export const MAX_JSON_SAFE_VALUE_NODES = 10_000
|
|
6
|
+
export const CIRCULAR_VALUE = '[Circular]'
|
|
7
|
+
export const TRUNCATED_VALUE = '[Truncated]'
|
|
8
|
+
export const UNSERIALIZABLE_VALUE = '[Unserializable]'
|
|
9
|
+
export const FUNCTION_VALUE = '[Function]'
|
|
8
10
|
|
|
9
11
|
const dateGetTime = Date.prototype.getTime
|
|
10
12
|
const dateToISOString = Date.prototype.toISOString
|
|
@@ -15,7 +17,12 @@ interface JsonSafeValueConversionState {
|
|
|
15
17
|
remainingNodes: number
|
|
16
18
|
}
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Replaces unpaired surrogates with U+FFFD. A lone surrogate survives
|
|
22
|
+
* `JSON.stringify` as a `\uD800`-style escape, which strict JSON parsers
|
|
23
|
+
* reject — for OTLP that means the whole request is refused.
|
|
24
|
+
*/
|
|
25
|
+
export function sanitizeString(value: string): string {
|
|
19
26
|
let output = ''
|
|
20
27
|
for (let index = 0; index < value.length; index++) {
|
|
21
28
|
const codeUnit = value.charCodeAt(index)
|
|
@@ -66,12 +66,21 @@ export interface Logger {
|
|
|
66
66
|
}
|
|
67
67
|
export interface OtlpAnyValue {
|
|
68
68
|
stringValue?: string;
|
|
69
|
-
|
|
69
|
+
/**
|
|
70
|
+
* proto3 JSON maps int64 to a string, which is the form the SDK emits.
|
|
71
|
+
* `number` stays valid because encoded records persist in the logs queue:
|
|
72
|
+
* one written by an earlier version rehydrates in the numeric form and is
|
|
73
|
+
* re-sent unchanged. The wire format accepts both.
|
|
74
|
+
*/
|
|
75
|
+
intValue?: string | number;
|
|
70
76
|
doubleValue?: number;
|
|
71
77
|
boolValue?: boolean;
|
|
72
78
|
arrayValue?: {
|
|
73
79
|
values: OtlpAnyValue[];
|
|
74
80
|
};
|
|
81
|
+
kvlistValue?: {
|
|
82
|
+
values: OtlpKeyValue[];
|
|
83
|
+
};
|
|
75
84
|
}
|
|
76
85
|
export interface OtlpKeyValue {
|
|
77
86
|
key: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capture-log.d.ts","sourceRoot":"","sources":["../src/capture-log.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAA;AAEtF,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAA;AAEtF,MAAM,WAAW,iBAAiB;IAC9B,IAAI,EAAE,gBAAgB,CAAA;IACtB,MAAM,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAElH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;AAE7D,MAAM,WAAW,iBAAiB;IAC9B,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAA;IACZ,2CAA2C;IAC3C,KAAK,CAAC,EAAE,gBAAgB,CAAA;IACxB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,mCAAmC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,aAAa,CAAA;CAC7B;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,iBAAiB,KAAK,iBAAiB,GAAG,IAAI,CAAA;AAErF;;;;;;;;;;GAUG;AACH,MAAM,WAAW,MAAM;IACnB,sDAAsD;IACtD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,aAAa,GAAG,IAAI,CAAA;IACrD,iEAAiE;IACjE,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,aAAa,GAAG,IAAI,CAAA;IACrD,wDAAwD;IACxD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,aAAa,GAAG,IAAI,CAAA;IACpD,mDAAmD;IACnD,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,aAAa,GAAG,IAAI,CAAA;IACpD,qDAAqD;IACrD,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,aAAa,GAAG,IAAI,CAAA;IACrD,+DAA+D;IAC/D,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,aAAa,GAAG,IAAI,CAAA;CACxD;AAMD,MAAM,WAAW,YAAY;IACzB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"capture-log.d.ts","sourceRoot":"","sources":["../src/capture-log.ts"],"names":[],"mappings":"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"}
|