@posthog/core 1.34.0 → 1.35.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.
@@ -26,6 +26,7 @@ __webpack_require__.r(__webpack_exports__);
26
26
  __webpack_require__.d(__webpack_exports__, {
27
27
  toOtlpKeyValueList: ()=>toOtlpKeyValueList,
28
28
  getOtlpSeverityNumber: ()=>getOtlpSeverityNumber,
29
+ buildResourceAttributes: ()=>buildResourceAttributes,
29
30
  getOtlpSeverityText: ()=>getOtlpSeverityText,
30
31
  buildOtlpLogsPayload: ()=>buildOtlpLogsPayload,
31
32
  buildOtlpLogRecord: ()=>buildOtlpLogRecord,
@@ -142,6 +143,20 @@ function buildOtlpLogRecord(options, sdkContext) {
142
143
  if (!(0, index_js_namespaceObject.isUndefined)(options.trace_flags)) record.flags = options.trace_flags;
143
144
  return record;
144
145
  }
146
+ function buildResourceAttributes(config, scopeName, scopeVersion) {
147
+ return {
148
+ ...config.resourceAttributes,
149
+ 'service.name': config.serviceName || 'unknown_service',
150
+ ...config.environment && {
151
+ 'deployment.environment': config.environment
152
+ },
153
+ ...config.serviceVersion && {
154
+ 'service.version': config.serviceVersion
155
+ },
156
+ 'telemetry.sdk.name': scopeName,
157
+ 'telemetry.sdk.version': scopeVersion
158
+ };
159
+ }
145
160
  function buildOtlpLogsPayload(logRecords, resourceAttributes, scopeName, scopeVersion) {
146
161
  return {
147
162
  resourceLogs: [
@@ -164,6 +179,7 @@ function buildOtlpLogsPayload(logRecords, resourceAttributes, scopeName, scopeVe
164
179
  }
165
180
  exports.buildOtlpLogRecord = __webpack_exports__.buildOtlpLogRecord;
166
181
  exports.buildOtlpLogsPayload = __webpack_exports__.buildOtlpLogsPayload;
182
+ exports.buildResourceAttributes = __webpack_exports__.buildResourceAttributes;
167
183
  exports.getOtlpSeverityNumber = __webpack_exports__.getOtlpSeverityNumber;
168
184
  exports.getOtlpSeverityText = __webpack_exports__.getOtlpSeverityText;
169
185
  exports.toOtlpAnyValue = __webpack_exports__.toOtlpAnyValue;
@@ -171,6 +187,7 @@ exports.toOtlpKeyValueList = __webpack_exports__.toOtlpKeyValueList;
171
187
  for(var __webpack_i__ in __webpack_exports__)if (-1 === [
172
188
  "buildOtlpLogRecord",
173
189
  "buildOtlpLogsPayload",
190
+ "buildResourceAttributes",
174
191
  "getOtlpSeverityNumber",
175
192
  "getOtlpSeverityText",
176
193
  "toOtlpAnyValue",
@@ -109,6 +109,20 @@ function buildOtlpLogRecord(options, sdkContext) {
109
109
  if (!isUndefined(options.trace_flags)) record.flags = options.trace_flags;
110
110
  return record;
111
111
  }
112
+ function buildResourceAttributes(config, scopeName, scopeVersion) {
113
+ return {
114
+ ...config.resourceAttributes,
115
+ 'service.name': config.serviceName || 'unknown_service',
116
+ ...config.environment && {
117
+ 'deployment.environment': config.environment
118
+ },
119
+ ...config.serviceVersion && {
120
+ 'service.version': config.serviceVersion
121
+ },
122
+ 'telemetry.sdk.name': scopeName,
123
+ 'telemetry.sdk.version': scopeVersion
124
+ };
125
+ }
112
126
  function buildOtlpLogsPayload(logRecords, resourceAttributes, scopeName, scopeVersion) {
113
127
  return {
114
128
  resourceLogs: [
@@ -129,4 +143,4 @@ function buildOtlpLogsPayload(logRecords, resourceAttributes, scopeName, scopeVe
129
143
  ]
130
144
  };
131
145
  }
132
- export { buildOtlpLogRecord, buildOtlpLogsPayload, getOtlpSeverityNumber, getOtlpSeverityText, toOtlpAnyValue, toOtlpKeyValueList };
146
+ export { buildOtlpLogRecord, buildOtlpLogsPayload, buildResourceAttributes, getOtlpSeverityNumber, getOtlpSeverityText, toOtlpAnyValue, toOtlpKeyValueList };
@@ -1,4 +1,4 @@
1
- export type { LogSeverityLevel, OtlpSeverityText, OtlpSeverityEntry, LogAttributeValue, LogAttributes, CaptureLogOptions, OtlpAnyValue, OtlpKeyValue, OtlpLogRecord, OtlpLogsPayload, } from '@posthog/types';
1
+ export type { LogSeverityLevel, OtlpSeverityText, OtlpSeverityEntry, LogAttributeValue, LogAttributes, CaptureLogOptions, OtlpAnyValue, OtlpKeyValue, OtlpLogRecord, OtlpLogsPayload, BeforeSendLogFn, } from '@posthog/types';
2
2
  /**
3
3
  * SDK-internal context the host SDK passes to `buildOtlpLogRecord` at capture
4
4
  * time. Each SDK populates the fields that apply to it: browser fills
@@ -20,42 +20,26 @@ export interface LogSdkContext {
20
20
  }
21
21
  import type { Logger as CaptureLoggerType } from '@posthog/types';
22
22
  export type CaptureLogger = CaptureLoggerType;
23
- import type { LogAttributeValue, CaptureLogOptions, OtlpLogRecord } from '@posthog/types';
23
+ import type { LogAttributeValue, OtlpLogRecord, OtlpLogsPayload, BeforeSendLogFn } from '@posthog/types';
24
+ import type { PostHogPersistedProperty } from '../types';
25
+ import type { SendLogsBatchOutcome } from '../posthog-core-stateless';
24
26
  export interface BufferedLogEntry {
25
27
  record: OtlpLogRecord;
26
28
  }
27
29
  /**
28
- * Pre-send filter. Inspect, mutate, or drop a captured record before it
29
- * enters the rate-cap or the queue. Return the (possibly transformed) record
30
- * to keep it; return `null` to drop it.
31
- *
32
- * Configure as a single fn or an array. Arrays form a left-to-right chain:
33
- * each fn receives the previous fn's return value. A `null` from any link
34
- * short-circuits the chain and drops the record.
35
- *
36
- * Runs *before* the rate cap so dropped records don't consume the
37
- * per-interval budget. Throwing fns are logged and skipped — the chain
38
- * continues with the previous return value, so a buggy filter degrades to a
39
- * no-op rather than crashing `captureLog()`.
40
- *
41
- * @example Redact secrets from log bodies
42
- * ```ts
43
- * logs: {
44
- * beforeSend: (record) => ({
45
- * ...record,
46
- * body: record.body.replace(/api_key=\S+/g, 'api_key=[REDACTED]'),
47
- * }),
48
- * }
49
- * ```
50
- *
51
- * @example Drop noisy debug logs in production
52
- * ```ts
53
- * logs: {
54
- * beforeSend: (record) => (record.level === 'debug' ? null : record),
55
- * }
56
- * ```
30
+ * The minimal host surface `PostHogLogs` depends on. `PostHogCoreStateless`
31
+ * satisfies it structurally (mobile/node); the browser supplies an adapter
32
+ * backed by its own persistence and request layer.
57
33
  */
58
- export type BeforeSendLogFn = (record: CaptureLogOptions) => CaptureLogOptions | null;
34
+ export interface LogsHost {
35
+ readonly isDisabled: boolean;
36
+ readonly optedOut: boolean;
37
+ getPersistedProperty<T>(key: PostHogPersistedProperty): T | undefined;
38
+ setPersistedProperty<T>(key: PostHogPersistedProperty, value: T | null): void;
39
+ _sendLogsBatch(payload: OtlpLogsPayload): Promise<SendLogsBatchOutcome>;
40
+ getLibraryId(): string;
41
+ getLibraryVersion(): string;
42
+ }
59
43
  /**
60
44
  * Configuration for the logs feature on `new PostHog(key, { logs: ... })`.
61
45
  * All fields are optional; per-SDK defaults apply (mobile vs browser tune
@@ -65,7 +49,7 @@ export interface PostHogLogsConfig {
65
49
  /**
66
50
  * Service name attached to every record as the OTLP `service.name`
67
51
  * resource attribute. Used by the Logs UI for filtering / grouping.
68
- * Default: `'unknown_service'`.
52
+ * Defaults to `'unknown_service'` when unset.
69
53
  */
70
54
  serviceName?: string;
71
55
  /**
@@ -94,11 +78,11 @@ export interface PostHogLogsConfig {
94
78
  */
95
79
  flushIntervalMs?: number;
96
80
  /**
97
- * Max records held in memory before the queue evicts the oldest on push
98
- * (FIFO). Bounds memory footprint and on-disk-queue size. When the buffer
99
- * hits this size, an immediate flush is triggered to reclaim space; if
100
- * the flush hasn't completed before the next capture, the oldest record
101
- * is shifted out. Default: 100.
81
+ * Number of buffered records that triggers an immediate flush. Records also
82
+ * flush on the periodic interval and on `shutdown()`. The queue can grow past
83
+ * this while an async flush is in flight (e.g. during a synchronous burst); a
84
+ * separate, larger memory backstop evicts the oldest only once the queue
85
+ * exceeds the per-interval rate cap. Default: 100.
102
86
  */
103
87
  maxBufferSize?: number;
104
88
  /**
@@ -148,6 +132,7 @@ export interface PostHogLogsConfig {
148
132
  }
149
133
  export interface ResolvedPostHogLogsConfig extends Omit<PostHogLogsConfig, 'rateCap'> {
150
134
  maxBufferSize: number;
135
+ maxQueueSize?: number;
151
136
  flushIntervalMs: number;
152
137
  maxBatchRecordsPerPost: number;
153
138
  rateCapWindowMs: number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/logs/types.ts"],"names":[],"mappings":"AAEA,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,eAAe,GAChB,MAAM,gBAAgB,CAAA;AAEvB;;;;;;;GAOG;AACH,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,YAAY,GAAG,YAAY,CAAA;IACtC,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC9B;AAKD,OAAO,KAAK,EAAE,MAAM,IAAI,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AACjE,MAAM,MAAM,aAAa,GAAG,iBAAiB,CAAA;AAE7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEzF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,aAAa,CAAA;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,MAAM,EAAE,iBAAiB,KAAK,iBAAiB,GAAG,IAAI,CAAA;AAErF;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IAEvB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;IAEtD;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IAExB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB;;;;;;OAMG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAE/B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,OAAO,CAAC,EAAE;QACR;;WAEG;QACH,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB;;;WAGG;QACH,QAAQ,CAAC,EAAE,MAAM,CAAA;KAClB,CAAA;IAED;;;OAGG;IACH,UAAU,CAAC,EAAE,eAAe,GAAG,eAAe,EAAE,CAAA;CACjD;AAKD,MAAM,WAAW,yBAA0B,SAAQ,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAC;IACnF,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,MAAM,CAAA;IACvB,sBAAsB,EAAE,MAAM,CAAA;IAC9B,eAAe,EAAE,MAAM,CAAA;IACvB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,uBAAuB,EAAE,MAAM,CAAA;IAC/B,wBAAwB,EAAE,MAAM,CAAA;CACjC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/logs/types.ts"],"names":[],"mappings":"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"}
@@ -149,6 +149,9 @@ export declare abstract class PostHogCore extends PostHogCoreStateless {
149
149
  missingFlagBehavior?: 'getFeatureFlag' | 'getFeatureFlagPayload';
150
150
  }): FeatureFlagResult | undefined;
151
151
  getFeatureFlag(key: string): FeatureFlagValue | undefined;
152
+ /**
153
+ * @deprecated Use `getFeatureFlagResult()` instead, which returns the flag value and payload from a single evaluation.
154
+ */
152
155
  getFeatureFlagPayload(key: string): JsonType | undefined;
153
156
  getFeatureFlagPayloads(): PostHogFlagsResponse['featureFlagPayloads'] | undefined;
154
157
  getFeatureFlags(): PostHogFlagsResponse['featureFlags'] | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"posthog-core.d.ts","sourceRoot":"","sources":["../src/posthog-core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"posthog-core.d.ts","sourceRoot":"","sources":["../src/posthog-core.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@posthog/core",
3
- "version": "1.34.0",
3
+ "version": "1.35.1",
4
4
  "bugs": {
5
5
  "url": "https://github.com/PostHog/posthog-js/issues"
6
6
  },
@@ -70,7 +70,7 @@
70
70
  }
71
71
  },
72
72
  "dependencies": {
73
- "@posthog/types": "^1.387.0"
73
+ "@posthog/types": "^1.389.0"
74
74
  },
75
75
  "devDependencies": {
76
76
  "@rslib/core": "0.10.6",
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { getFeatureFlagValue } from './featureFlagUtils'
1
+ export { getFeatureFlagValue, getEnabledFromValue, getVariantFromValue, parsePayload } from './featureFlagUtils'
2
2
  export {
3
3
  gzipCompress,
4
4
  isGzipData,
@@ -12,6 +12,7 @@ export * as ErrorTracking from './error-tracking'
12
12
  export {
13
13
  buildOtlpLogRecord,
14
14
  buildOtlpLogsPayload,
15
+ buildResourceAttributes,
15
16
  getOtlpSeverityNumber,
16
17
  getOtlpSeverityText,
17
18
  toOtlpAnyValue,
@@ -256,6 +256,49 @@ describe('PostHogLogs', () => {
256
256
  expect(queue.map((e) => e.record.body.stringValue)).toEqual(['two', 'three', 'four'])
257
257
  })
258
258
 
259
+ it('holds a burst up to maxQueueSize, evicting only above it (flush trigger decoupled from eviction cap)', () => {
260
+ // maxBufferSize triggers a flush at 2, but the async drain can't run mid-burst,
261
+ // so the queue grows to the larger eviction cap (4) before the oldest is dropped.
262
+ const logs = new PostHogLogs(
263
+ mockInstance,
264
+ resolveForTest({ maxBufferSize: 2, maxQueueSize: 4 }),
265
+ logger,
266
+ getContextFor(mockInstance),
267
+ immediateOnReady
268
+ )
269
+
270
+ logs.captureLog({ body: 'one' })
271
+ logs.captureLog({ body: 'two' })
272
+ logs.captureLog({ body: 'three' })
273
+ logs.captureLog({ body: 'four' })
274
+ logs.captureLog({ body: 'five' })
275
+
276
+ const queue = readQueue(mockInstance)
277
+ // Grew past the flush trigger (2) to the eviction cap (4); only 'one' evicted.
278
+ expect(queue.map((e) => e.record.body.stringValue)).toEqual(['two', 'three', 'four', 'five'])
279
+ })
280
+
281
+ it('clamps a maxQueueSize below maxBufferSize up to maxBufferSize (flush trigger always reachable)', () => {
282
+ // A misconfigured eviction cap below the flush trigger would otherwise stop
283
+ // the size-based flush from ever firing; it collapses to single-knob instead.
284
+ const logs = new PostHogLogs(
285
+ mockInstance,
286
+ resolveForTest({ maxBufferSize: 3, maxQueueSize: 1 }),
287
+ logger,
288
+ getContextFor(mockInstance),
289
+ immediateOnReady
290
+ )
291
+
292
+ logs.captureLog({ body: 'one' })
293
+ logs.captureLog({ body: 'two' })
294
+ logs.captureLog({ body: 'three' })
295
+ logs.captureLog({ body: 'four' })
296
+
297
+ const queue = readQueue(mockInstance)
298
+ // Evicts at maxBufferSize (3), not the bogus maxQueueSize (1).
299
+ expect(queue.map((e) => e.record.body.stringValue)).toEqual(['two', 'three', 'four'])
300
+ })
301
+
259
302
  it('logs a diagnostic when evicting on overflow', () => {
260
303
  const logs = new PostHogLogs(
261
304
  mockInstance,
@@ -808,6 +851,140 @@ describe('PostHogLogs', () => {
808
851
  jest.advanceTimersByTime(5000)
809
852
  expect(mockInstance._sendLogsBatch).toHaveBeenCalledTimes(1)
810
853
  })
854
+
855
+ it('re-arms the timer after a failed flush so a retry happens without a new capture', async () => {
856
+ // First flush fails (retry-later keeps the records); the second succeeds.
857
+ mockInstance._sendLogsBatch = jest
858
+ .fn()
859
+ .mockResolvedValueOnce({ kind: 'retry-later', error: new Error('net') })
860
+ .mockResolvedValueOnce({ kind: 'ok' })
861
+
862
+ const logs = new PostHogLogs(
863
+ mockInstance,
864
+ resolveForTest({ flushIntervalMs: 5000 }),
865
+ logger,
866
+ getContextFor(mockInstance),
867
+ immediateOnReady
868
+ )
869
+ logs.captureLog({ body: 'retry-me' })
870
+
871
+ // First timer fires → flush #1 → retry-later → record retained, timer re-armed.
872
+ await jest.advanceTimersByTimeAsync(5000)
873
+ expect(mockInstance._sendLogsBatch).toHaveBeenCalledTimes(1)
874
+ expect(readQueue(mockInstance)).toHaveLength(1)
875
+
876
+ // No new capture: the re-armed timer alone fires the retry, which drains.
877
+ await jest.advanceTimersByTimeAsync(5000)
878
+ expect(mockInstance._sendLogsBatch).toHaveBeenCalledTimes(2)
879
+ expect(readQueue(mockInstance)).toHaveLength(0)
880
+ })
881
+
882
+ it('stops re-arming once the queue is empty', async () => {
883
+ const logs = new PostHogLogs(
884
+ mockInstance,
885
+ resolveForTest({ flushIntervalMs: 5000 }),
886
+ logger,
887
+ getContextFor(mockInstance),
888
+ immediateOnReady
889
+ )
890
+ logs.captureLog({ body: 'one' })
891
+
892
+ await jest.advanceTimersByTimeAsync(5000)
893
+ expect(mockInstance._sendLogsBatch).toHaveBeenCalledTimes(1)
894
+ expect(readQueue(mockInstance)).toHaveLength(0)
895
+
896
+ // Successful drain leaves nothing queued, so no further timer should fire.
897
+ await jest.advanceTimersByTimeAsync(20000)
898
+ expect(mockInstance._sendLogsBatch).toHaveBeenCalledTimes(1)
899
+ })
900
+
901
+ it('backs off exponentially across consecutive failed flushes', async () => {
902
+ // Every flush fails, so the record stays queued and the retry interval grows:
903
+ // base (initial), base (1st retry), 2x, 4x, ...
904
+ mockInstance._sendLogsBatch = jest.fn(() => Promise.resolve({ kind: 'retry-later', error: new Error('down') }))
905
+ const base = 1000
906
+ const logs = new PostHogLogs(
907
+ mockInstance,
908
+ resolveForTest({ flushIntervalMs: base }),
909
+ logger,
910
+ getContextFor(mockInstance),
911
+ immediateOnReady
912
+ )
913
+ logs.captureLog({ body: 'x' })
914
+
915
+ await jest.advanceTimersByTimeAsync(base) // initial timer → attempt #1
916
+ expect(mockInstance._sendLogsBatch).toHaveBeenCalledTimes(1)
917
+ await jest.advanceTimersByTimeAsync(base) // 1st retry still at base → attempt #2
918
+ expect(mockInstance._sendLogsBatch).toHaveBeenCalledTimes(2)
919
+
920
+ // Now backoff: next retry is 2x base — base alone must not fire it.
921
+ await jest.advanceTimersByTimeAsync(base)
922
+ expect(mockInstance._sendLogsBatch).toHaveBeenCalledTimes(2)
923
+ await jest.advanceTimersByTimeAsync(base) // 2x base elapsed → attempt #3
924
+ expect(mockInstance._sendLogsBatch).toHaveBeenCalledTimes(3)
925
+
926
+ // Next retry is 4x base.
927
+ await jest.advanceTimersByTimeAsync(2 * base)
928
+ expect(mockInstance._sendLogsBatch).toHaveBeenCalledTimes(3)
929
+ await jest.advanceTimersByTimeAsync(2 * base) // 4x base elapsed → attempt #4
930
+ expect(mockInstance._sendLogsBatch).toHaveBeenCalledTimes(4)
931
+ })
932
+
933
+ it('resets the backoff after a successful flush', async () => {
934
+ let shouldFail = true
935
+ mockInstance._sendLogsBatch = jest.fn(() =>
936
+ Promise.resolve(shouldFail ? { kind: 'retry-later', error: new Error('down') } : { kind: 'ok' })
937
+ )
938
+ const base = 1000
939
+ const logs = new PostHogLogs(
940
+ mockInstance,
941
+ resolveForTest({ flushIntervalMs: base }),
942
+ logger,
943
+ getContextFor(mockInstance),
944
+ immediateOnReady
945
+ )
946
+ logs.captureLog({ body: 'a' })
947
+
948
+ await jest.advanceTimersByTimeAsync(base) // attempt #1 fail (failures→1)
949
+ await jest.advanceTimersByTimeAsync(base) // attempt #2 fail (failures→2, next 2x)
950
+ await jest.advanceTimersByTimeAsync(2 * base) // attempt #3 fail (failures→3, next 4x)
951
+ shouldFail = false
952
+ await jest.advanceTimersByTimeAsync(4 * base) // attempt #4 succeeds → drains + resets
953
+ expect(readQueue(mockInstance)).toHaveLength(0)
954
+
955
+ // A new capture flushes at the base interval again, not the backed-off one.
956
+ ;(mockInstance._sendLogsBatch as jest.Mock).mockClear()
957
+ logs.captureLog({ body: 'b' })
958
+ await jest.advanceTimersByTimeAsync(base)
959
+ expect(mockInstance._sendLogsBatch).toHaveBeenCalledTimes(1)
960
+ })
961
+
962
+ it('onReconnect flushes immediately without waiting out the backoff', async () => {
963
+ let shouldFail = true
964
+ mockInstance._sendLogsBatch = jest.fn(() =>
965
+ Promise.resolve(shouldFail ? { kind: 'retry-later', error: new Error('down') } : { kind: 'ok' })
966
+ )
967
+ const base = 1000
968
+ const logs = new PostHogLogs(
969
+ mockInstance,
970
+ resolveForTest({ flushIntervalMs: base }),
971
+ logger,
972
+ getContextFor(mockInstance),
973
+ immediateOnReady
974
+ )
975
+ logs.captureLog({ body: 'x' })
976
+
977
+ await jest.advanceTimersByTimeAsync(base) // attempt #1 fails → record retained, backoff armed
978
+ expect(mockInstance._sendLogsBatch).toHaveBeenCalledTimes(1)
979
+ expect(readQueue(mockInstance)).toHaveLength(1)
980
+
981
+ // Reconnect drains now — no timer advance needed.
982
+ shouldFail = false
983
+ logs.onReconnect()
984
+ await jest.advanceTimersByTimeAsync(0)
985
+ expect(mockInstance._sendLogsBatch).toHaveBeenCalledTimes(2)
986
+ expect(readQueue(mockInstance)).toHaveLength(0)
987
+ })
811
988
  })
812
989
 
813
990
  describe('shutdown', () => {
@@ -1029,6 +1206,14 @@ describe('PostHogLogs', () => {
1029
1206
  expect(logger.info).toHaveBeenCalledWith('Log was rejected in beforeSend function')
1030
1207
  })
1031
1208
 
1209
+ it('logs the same info line when a fn empties the body', () => {
1210
+ // An emptied body is a drop too, so it surfaces the same diagnostic as a
1211
+ // null return rather than vanishing silently.
1212
+ const logs = makeLogs((r) => ({ ...r, body: '' }))
1213
+ logs.captureLog({ body: 'will-be-emptied' })
1214
+ expect(logger.info).toHaveBeenCalledWith('Log was rejected in beforeSend function')
1215
+ })
1216
+
1032
1217
  it('never crashes the caller when a fn throws — drops the record (fail closed) and logs', () => {
1033
1218
  const thrower = jest.fn(() => {
1034
1219
  throw new Error('bad filter')
@@ -1228,4 +1413,78 @@ describe('PostHogLogs', () => {
1228
1413
  expect(mockInstance._sendLogsBatch).toHaveBeenCalledTimes(2)
1229
1414
  })
1230
1415
  })
1416
+
1417
+ describe('queue advance under FIFO eviction', () => {
1418
+ it('keeps records captured during an in-flight flush at capacity', async () => {
1419
+ // Regression: the advance used to drop `consumed` records positionally,
1420
+ // but the FIFO cap evicts from the head while a batch is in flight, so a
1421
+ // positional drop discarded the records that arrived during the send.
1422
+ let resolveSend: (v: any) => void = () => {}
1423
+ const sendGate = new Promise((r) => {
1424
+ resolveSend = r
1425
+ })
1426
+ mockInstance._sendLogsBatch = jest.fn(() => sendGate)
1427
+
1428
+ const logs = new PostHogLogs(
1429
+ mockInstance,
1430
+ resolveForTest({ maxBufferSize: 3, maxBatchRecordsPerPost: 3 }),
1431
+ logger,
1432
+ getContextFor(mockInstance),
1433
+ immediateOnReady
1434
+ )
1435
+
1436
+ // Fill to capacity → triggers a background flush that awaits the gate.
1437
+ logs.captureLog({ body: 'a' })
1438
+ logs.captureLog({ body: 'b' })
1439
+ logs.captureLog({ body: 'c' })
1440
+ expect(mockInstance._sendLogsBatch).toHaveBeenCalledTimes(1)
1441
+
1442
+ // While the send is in flight, two captures arrive at capacity and evict
1443
+ // the (already-sent) head records a and b.
1444
+ logs.captureLog({ body: 'd' })
1445
+ logs.captureLog({ body: 'e' })
1446
+
1447
+ resolveSend({ kind: 'ok' })
1448
+ await logs.flush()
1449
+
1450
+ // The sent batch [a, b, c] leaves the queue; d and e survive for next flush.
1451
+ expect(readQueue(mockInstance).map((entry) => entry.record.body.stringValue)).toEqual(['d', 'e'])
1452
+ })
1453
+
1454
+ it('advances correctly across batches when eviction happens between iterations', async () => {
1455
+ // Regression: the eviction counter was reset once per flush, so an eviction
1456
+ // during the persist-await between batches got counted against the NEXT
1457
+ // batch's advance — under-dropping and re-sending an already-sent record.
1458
+ const entry = (body: string): any => ({ record: { body: { stringValue: body } } })
1459
+ mockInstance._store[PostHogPersistedProperty.LogsQueue] = [entry('a'), entry('b'), entry('c'), entry('d')]
1460
+ mockInstance._sendLogsBatch = jest.fn(() => Promise.resolve({ kind: 'ok' }))
1461
+
1462
+ let persistCalls = 0
1463
+ let logs: PostHogLogs
1464
+ // eslint-disable-next-line prefer-const
1465
+ logs = new PostHogLogs(
1466
+ mockInstance,
1467
+ resolveForTest({ maxBufferSize: 4, maxQueueSize: 4, maxBatchRecordsPerPost: 2 }),
1468
+ logger,
1469
+ getContextFor(mockInstance),
1470
+ immediateOnReady,
1471
+ () => {
1472
+ persistCalls++
1473
+ if (persistCalls === 1) {
1474
+ // After batch 1 [a,b] advances, captures arrive before batch 2 and
1475
+ // evict the head record 'c' at capacity.
1476
+ logs.captureLog({ body: 'e' })
1477
+ logs.captureLog({ body: 'f' })
1478
+ logs.captureLog({ body: 'g' })
1479
+ }
1480
+ return Promise.resolve()
1481
+ }
1482
+ )
1483
+
1484
+ await logs.flush()
1485
+
1486
+ // batch1 [a,b] dropped, 'c' evicted, batch2 [d,e] dropped — nothing sent twice.
1487
+ expect(readQueue(mockInstance).map((x) => x.record.body.stringValue)).toEqual(['f', 'g'])
1488
+ })
1489
+ })
1231
1490
  })