diff --git a/.changeset/android-v4-major.md b/.changeset/android-v4-major.md index 84bcc13c4..f7772aa54 100644 --- a/.changeset/android-v4-major.md +++ b/.changeset/android-v4-major.md @@ -20,7 +20,7 @@ - **Breaking:** rename `PostHogConfig.maxRetries` to `pushNotificationSubscriptionMaxRetries`, because it only limits push-notification subscription retries - **Breaking:** set `$lib` and `$lib_version` from the `PostHog-Sdk-Info` request header; a value set in properties, super properties or `beforeSend` is removed before sending - **Breaking:** send `$session_id` and `$window_id` as top-level `session_id` and `window_id` fields; a non-string value is dropped with a warning -- **Breaking:** disable the SDK at setup when `projectToken` is a personal API key (`phx_...`), as for an empty token +- **Breaking:** disable the SDK at setup when `projectToken` is a personal API key (`phx_...`), as for an empty token, and print a warning for both even when `debug` is off - **Breaking:** add an `options` argument to `capture`, `screen`, `identify`, `setPersonProperties`, `alias`, `group` and `captureException` for per-event capture options such as `cookieless_mode`, sent apart from the properties and editable in `beforeSend` through `PostHogEvent.options`; Java callers pass the trailing argument or `null`, and classes that implement `PostHogInterface` add the parameter - **Breaking:** move `identify(distinctId, userProperties, userPropertiesSetOnce)` from `PostHogCoreInterface` to `PostHogStatelessInterface`; `PostHogInterface` declares `identify` with the trailing `options` parameter - **Breaking:** registered super properties now override the properties the SDK sets itself, such as `$os_name`; super and event properties also override `$is_identified`, `$process_person_profile` and the session replay debug properties, which the SDK no longer re-applies after the caller's values @@ -30,7 +30,7 @@ - use the current distinct ID when the `distinctId` argument to `capture` is empty or whitespace-only, instead of dropping the event - **Breaking:** skip deep link query parameters whose name starts with `$` in the `Deep Link Opened` event, so a link can't set a PostHog property such as `$process_person_profile` - stop storing or matching the person-properties deduplication hash for a `$set` sent with `process_person_profile: false` -- debug logs for capture requests name the event count and the response status instead of printing the request and response bodies, and count the events PostHog drops, the duplicate copies it drops and the events it asks to retry, in one line per batch +- debug logs for capture requests name the event count and the response status instead of printing the request and response bodies, and count the events PostHog drops, the duplicate copies it drops and the events it asks to retry, in one line per batch, and log the status when PostHog rejects a whole batch - **Breaking:** drop an event whose name is empty before sending it, including one `beforeSend` renames to `""` - **Breaking:** let `userProperties`, `userPropertiesSetOnce` and `groups` win key by key over `$set`, `$set_once` and `$groups` maps passed in the same call's properties, instead of being replaced by them, and merge a `$groups` map in properties into the groups set with `group()` - add `captureAiCompression`, `captureAiMaxQueueSize`, `captureAiTimeout` and `captureAiMaxEventBytes` to `PostHogConfig` to tune AI requests separately from other events; the defaults are gzip, 100 queued events (and at most 50 MiB), 60 seconds and 8 MiB + 64 KiB per serialized event diff --git a/posthog/src/main/java/com/posthog/PostHog.kt b/posthog/src/main/java/com/posthog/PostHog.kt index 516309305..d4398bffe 100644 --- a/posthog/src/main/java/com/posthog/PostHog.kt +++ b/posthog/src/main/java/com/posthog/PostHog.kt @@ -223,14 +223,14 @@ public class PostHog private constructor( if (config.logger is PostHogNoOpLogger) PostHogPrintLogger(config) else config.logger if (config.projectToken.isEmpty()) { - config.logger.log( + config.logger.logWarning( "PostHog SDK is disabled because the project token is required and was empty after trimming whitespace.", ) return } if (config.projectToken.startsWith("phx_")) { - config.logger.log( + config.logger.logWarning( "PostHog SDK is disabled because the project token is a personal API key (phx_...), " + "use your project token (phc_...).", ) diff --git a/posthog/src/main/java/com/posthog/PostHogStateless.kt b/posthog/src/main/java/com/posthog/PostHogStateless.kt index deb9b0ad2..6458181dd 100644 --- a/posthog/src/main/java/com/posthog/PostHogStateless.kt +++ b/posthog/src/main/java/com/posthog/PostHogStateless.kt @@ -62,14 +62,14 @@ public open class PostHogStateless protected constructor( if (config.logger is PostHogNoOpLogger) PostHogPrintLogger(config) else config.logger if (config.projectToken.isEmpty()) { - config.logger.log( + config.logger.logWarning( "PostHog SDK is disabled because the project token is required and was empty after trimming whitespace.", ) return } if (config.projectToken.startsWith("phx_")) { - config.logger.log( + config.logger.logWarning( "PostHog SDK is disabled because the project token is a personal API key (phx_...), " + "use your project token (phc_...).", ) diff --git a/posthog/src/main/java/com/posthog/internal/PostHogQueue.kt b/posthog/src/main/java/com/posthog/internal/PostHogQueue.kt index fd1213473..63832acbf 100644 --- a/posthog/src/main/java/com/posthog/internal/PostHogQueue.kt +++ b/posthog/src/main/java/com/posthog/internal/PostHogQueue.kt @@ -751,5 +751,6 @@ internal fun deleteFilesIfAPIError( return false } + logger.log("Flushing failed with ${e.statusCode}, dropping $actualBatchSize records.") return true } diff --git a/posthog/src/test/java/com/posthog/PostHogStatelessTest.kt b/posthog/src/test/java/com/posthog/PostHogStatelessTest.kt index b2b0cd2fe..95e6c1198 100644 --- a/posthog/src/test/java/com/posthog/PostHogStatelessTest.kt +++ b/posthog/src/test/java/com/posthog/PostHogStatelessTest.kt @@ -277,7 +277,7 @@ internal class PostHogStatelessTest { sut.setup(config) assertFalse(sut.isEnabledPublic()) - assertTrue(mockLogger.messages.any { it.contains("PostHog SDK is disabled because the project token is required") }) + assertTrue(mockLogger.warnings.any { it.contains("PostHog SDK is disabled because the project token is required") }) } @Test @@ -289,7 +289,7 @@ internal class PostHogStatelessTest { sut.setup(config) assertFalse(sut.isEnabledPublic()) - assertTrue(mockLogger.messages.any { it.contains("PostHog SDK is disabled because the project token is a personal API key") }) + assertTrue(mockLogger.warnings.any { it.contains("PostHog SDK is disabled because the project token is a personal API key") }) } @Test diff --git a/posthog/src/test/java/com/posthog/PostHogTest.kt b/posthog/src/test/java/com/posthog/PostHogTest.kt index 36cddafd5..9a1d4a03f 100644 --- a/posthog/src/test/java/com/posthog/PostHogTest.kt +++ b/posthog/src/test/java/com/posthog/PostHogTest.kt @@ -276,7 +276,7 @@ internal class PostHogTest { ) assertTrue(sut.isOptOut()) - assertTrue(logger.messages.any { it.contains("PostHog SDK is disabled because the project token is required") }) + assertTrue(logger.warnings.any { it.contains("PostHog SDK is disabled because the project token is required") }) sut.close() } @@ -297,7 +297,7 @@ internal class PostHogTest { ) assertTrue(sut.isOptOut()) - assertTrue(logger.messages.any { it.contains("PostHog SDK is disabled because the project token is a personal API key") }) + assertTrue(logger.warnings.any { it.contains("PostHog SDK is disabled because the project token is a personal API key") }) sut.close() } diff --git a/posthog/src/test/java/com/posthog/internal/PostHogQueueTest.kt b/posthog/src/test/java/com/posthog/internal/PostHogQueueTest.kt index 670f95e88..73d06cc38 100644 --- a/posthog/src/test/java/com/posthog/internal/PostHogQueueTest.kt +++ b/posthog/src/test/java/com/posthog/internal/PostHogQueueTest.kt @@ -5,6 +5,7 @@ import com.posthog.PostHogConfig import com.posthog.PostHogEvent import com.posthog.PostHogEventName import com.posthog.TestHttpServers +import com.posthog.TestLogger import com.posthog.awaitExecution import com.posthog.generateEvent import com.posthog.internal.errortracking.ThrowableCoercer @@ -958,8 +959,10 @@ internal class PostHogQueueTest { val e = PostHogApiError(400, "", null) val config = PostHogConfig(PROJECT_TOKEN) val limits = initialBatchLimits(config) + val logger = TestLogger() - assertTrue(deleteFilesIfAPIError(e, limits, actualBatchSize = limits.cap, logger = config.logger)) + assertTrue(deleteFilesIfAPIError(e, limits, actualBatchSize = limits.cap, logger = logger)) + assertEquals(listOf("Flushing failed with 400, dropping ${limits.cap} records."), logger.messages) } @Test