-
Notifications
You must be signed in to change notification settings - Fork 33
feat: SDK Compliance #362
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
jose-sequeira
wants to merge
13
commits into
main
Choose a base branch
from
jose-sequeira/sdk-compliance
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+792
−2
Open
feat: SDK Compliance #362
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
e7ca114
feat: SDK Compliance
jose-sequeira c21ed25
fix
jose-sequeira dd9e94b
fix
jose-sequeira 63fcedf
fix
jose-sequeira 1689478
Merge branch 'main' into jose-sequeira/sdk-compliance
jose-sequeira bda10dd
rename file
jose-sequeira cb02d27
fix wildcard imports
jose-sequeira ba65cc9
fix spotless
jose-sequeira a7616cb
more fixes
jose-sequeira 18415e4
more fixes
jose-sequeira c59d110
spottless apply
jose-sequeira 7982e38
update api
jose-sequeira 0ec0ddc
more fixes
jose-sequeira File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| name: SDK Compliance Tests | ||
|
|
||
| on: | ||
| push: | ||
| branches: [ main, master ] | ||
| paths: | ||
| - 'posthog/**' | ||
| - 'sdk_compliance_adapter/**' | ||
| - '.github/workflows/sdk-compliance-tests.yml' | ||
| pull_request: | ||
| branches: [ main, master ] | ||
| paths: | ||
| - 'posthog/**' | ||
| - 'sdk_compliance_adapter/**' | ||
| - '.github/workflows/sdk-compliance-tests.yml' | ||
| workflow_dispatch: | ||
|
|
||
| permissions: | ||
| contents: read | ||
| packages: read | ||
| pull-requests: write | ||
|
|
||
| jobs: | ||
| test-android-sdk: | ||
| uses: PostHog/posthog-sdk-test-harness/.github/workflows/test-sdk-action.yml@main | ||
| with: | ||
| adapter-dockerfile: sdk_compliance_adapter/Dockerfile | ||
| adapter-context: . | ||
| test-harness-version: latest | ||
| report-name: android-sdk-compliance-report | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -260,6 +260,21 @@ public open class PostHogConfig( | |||||
| */ | ||||||
| public var releaseIdentifier: String? = null, | ||||||
| ) { | ||||||
| /** | ||||||
| * Optional custom OkHttpClient for HTTP requests. | ||||||
| * | ||||||
| * When set, the SDK will use this client instead of creating its own. | ||||||
| * The provided client should be configured with any necessary interceptors, | ||||||
| * timeouts, and other settings required for your use case. | ||||||
| * | ||||||
| * Note: If both `proxy` and `httpClient` are set, the `httpClient` takes precedence | ||||||
| * and the `proxy` setting will be ignored. | ||||||
| * | ||||||
| * Default: `null` (SDK creates its own client). | ||||||
| */ | ||||||
| @PostHogInternal | ||||||
| public var httpClient: okhttp3.OkHttpClient? = null | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
then just import |
||||||
|
|
||||||
| @PostHogInternal | ||||||
| public var logger: PostHogLogger = PostHogNoOpLogger() | ||||||
|
|
||||||
|
|
||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -36,7 +36,7 @@ import java.io.IOException | |||||
| * This interceptor compresses the HTTP request body. Many webservers can't handle this! | ||||||
| * @property config The Config | ||||||
| */ | ||||||
| internal class GzipRequestInterceptor(private val config: PostHogConfig) : Interceptor { | ||||||
| public class GzipRequestInterceptor(private val config: PostHogConfig) : Interceptor { | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
we can revert this i assume? and run |
||||||
| @Throws(IOException::class) | ||||||
| override fun intercept(chain: Interceptor.Chain): Response { | ||||||
| val originalRequest = chain.request() | ||||||
|
|
||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| FROM --platform=linux/amd64 gradle:8.5-jdk17 AS builder | ||
|
|
||
| WORKDIR /app | ||
|
|
||
| COPY . . | ||
|
|
||
| RUN echo 'include(":sdk_compliance_adapter")' >> settings.gradle.kts && \ | ||
| sed -i '/^dependencyResolutionManagement/i plugins {\n id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"\n}' settings.gradle.kts && \ | ||
| mkdir -p /root/.gradle && \ | ||
| echo 'org.gradle.java.installations.auto-download=true' > /root/.gradle/gradle.properties && \ | ||
| gradle :sdk_compliance_adapter:installDist --no-daemon | ||
|
|
||
| FROM eclipse-temurin:11-jre | ||
|
|
||
| WORKDIR /app | ||
|
|
||
| COPY --from=builder /app/sdk_compliance_adapter/build/install/sdk_compliance_adapter /app | ||
|
|
||
| EXPOSE 8080 | ||
|
|
||
| CMD ["/app/bin/sdk_compliance_adapter"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,162 @@ | ||
| # PostHog Android SDK Compliance Adapter - Implementation Notes | ||
|
|
||
| ## Overview | ||
|
|
||
| This directory contains the compliance test adapter for the PostHog Android SDK. The adapter wraps the SDK and exposes a standardized HTTP API for automated compliance testing. | ||
|
|
||
| ## Architecture | ||
|
|
||
| ### Components | ||
|
|
||
| 1. **adapter.kt** - Ktor-based HTTP server that implements the compliance adapter API | ||
| 2. **TrackingInterceptor** - OkHttp interceptor that monitors HTTP requests made by the SDK | ||
| 3. **AdapterState** - Tracks captured events, sent events, retries, and request metadata | ||
| 4. **Docker** - Containerized build and runtime environment | ||
|
|
||
| ### Key Implementation Details | ||
|
|
||
| #### HTTP Request Tracking | ||
|
|
||
| The adapter uses a custom OkHttpClient with a `TrackingInterceptor` that: | ||
| - Intercepts all HTTP requests to the `/batch/` endpoint | ||
| - Parses request bodies to extract event UUIDs using regex | ||
| - Tracks request count, status codes, retry attempts, and event counts | ||
| - Updates adapter state with request metadata | ||
|
|
||
| #### Event UUID Tracking | ||
|
|
||
| Events are tracked using two mechanisms: | ||
| 1. **beforeSend hook** - Captures UUIDs as events are queued | ||
| 2. **HTTP interceptor** - Extracts UUIDs from outgoing HTTP requests | ||
|
|
||
| This dual approach ensures UUIDs are available immediately when events are captured AND verified when actually sent. | ||
|
|
||
| #### SDK Configuration | ||
|
|
||
| The adapter configures the PostHog SDK for optimal testing: | ||
| - `flushAt = 1` - Send events immediately (or as configured) | ||
| - `flushIntervalSeconds` - Fast flush intervals for tests | ||
| - `debug = true` - Enable logging | ||
| - `httpClient` - Custom OkHttpClient with tracking interceptor | ||
|
|
||
| ## SDK Modifications Required | ||
|
|
||
| To enable HTTP request tracking, the following changes were made to the core SDK: | ||
|
|
||
| ### PostHogConfig.kt | ||
|
|
||
| Added optional `httpClient` parameter: | ||
|
|
||
| ```kotlin | ||
| public var httpClient: okhttp3.OkHttpClient? = null | ||
| ``` | ||
|
|
||
| This allows test adapters to inject a custom OkHttpClient with interceptors. | ||
|
|
||
| ### PostHogApi.kt | ||
|
|
||
| Modified to use injected client if provided: | ||
|
|
||
| ```kotlin | ||
| private val client: OkHttpClient = | ||
| config.httpClient ?: OkHttpClient.Builder() | ||
| .proxy(config.proxy) | ||
| .addInterceptor(GzipRequestInterceptor(config)) | ||
| .build() | ||
| ``` | ||
|
|
||
| **These changes are backward compatible** - existing code works unchanged. | ||
|
|
||
| ## Building | ||
|
|
||
| ### Local Build (requires Java 8, 11, and 17) | ||
|
|
||
| ```bash | ||
| ./gradlew :sdk_compliance_adapter:build | ||
| ``` | ||
|
|
||
| ### Docker Build (recommended) | ||
|
|
||
| ```bash | ||
| docker build -f sdk_compliance_adapter/Dockerfile -t posthog-android-adapter . | ||
| ``` | ||
|
|
||
| The Dockerfile uses Gradle toolchain auto-download to fetch required Java versions. | ||
|
|
||
| ## Running Tests | ||
|
|
||
| ### With Docker Compose | ||
|
|
||
| ```bash | ||
| cd sdk_compliance_adapter | ||
| docker-compose up --build --abort-on-container-exit | ||
| ``` | ||
|
|
||
| This runs: | ||
| - **test-harness** - Compliance test runner | ||
| - **adapter** - This SDK adapter | ||
| - **mock-server** - Mock PostHog server | ||
|
|
||
| ### SDK Type | ||
|
|
||
| The Android SDK uses **server SDK format**: | ||
| - Endpoint: `/batch/` | ||
| - Format: `{api_key: "...", batch: [{event}, {event}], sent_at: "..."}` | ||
|
|
||
| Tests run with `--sdk-type server` flag. | ||
|
|
||
| ## API Endpoints | ||
|
|
||
| The adapter implements the standard compliance adapter API: | ||
|
|
||
| - `GET /health` - Health check with SDK version info | ||
| - `POST /init` - Initialize SDK with config | ||
| - `POST /capture` - Capture a single event | ||
| - `POST /flush` - Force flush all pending events | ||
| - `GET /state` - Get adapter state for assertions | ||
| - `POST /reset` - Reset SDK and adapter state | ||
|
|
||
| See [test-harness CONTRACT.yaml](https://github.com/PostHog/posthog-sdk-test-harness/blob/main/CONTRACT.yaml) for full API spec. | ||
|
|
||
| ## Testing Philosophy | ||
|
|
||
| The adapter tests the **core PostHog SDK** (`:posthog` module) which contains: | ||
| - All HTTP communication logic | ||
| - Retry behavior with exponential backoff | ||
| - Event batching and queueing | ||
| - Error handling | ||
|
|
||
| The `:posthog-android` module is a thin wrapper that adds Android-specific features (lifecycle tracking, etc.) but doesn't change the core compliance behavior. | ||
|
|
||
| ## Known Limitations | ||
|
|
||
| ### Java 8 on ARM64 | ||
|
|
||
| Java 8 is not available for ARM64 (Apple Silicon). The project requires Java 8 for the core module. Solutions: | ||
|
|
||
| 1. **Docker** (recommended) - Uses Gradle toolchain auto-download | ||
| 2. **CI/CD** - GitHub Actions provides Java 8 for Linux x64 | ||
| 3. **Modify core** - Upgrade to Java 11 (not recommended - breaks compatibility) | ||
|
|
||
| ### Flush Timing | ||
|
|
||
| The `/flush` endpoint includes a 2-second wait to account for: | ||
| - SDK's internal flush timer | ||
| - Network latency in Docker environment | ||
| - Mock server processing time | ||
|
|
||
| This may need adjustment based on test results. | ||
|
|
||
| ## Future Improvements | ||
|
|
||
| 1. **Reduce flush wait time** - Profile actual flush timing and optimize | ||
| 2. **Add compression support** - Currently the adapter doesn't test gzip compression | ||
| 3. **More detailed error tracking** - Capture and report SDK errors in state | ||
| 4. **Performance metrics** - Track request timing, payload sizes | ||
|
|
||
| ## References | ||
|
|
||
| - [Test Harness Repository](https://github.com/PostHog/posthog-sdk-test-harness) | ||
| - [Browser SDK Adapter](../../posthog-js/packages/browser/sdk_compliance_adapter/) - Reference implementation | ||
| - [Adapter Guide](https://github.com/PostHog/posthog-sdk-test-harness/blob/main/ADAPTER_GUIDE.md) | ||
| - [Contract Specification](https://github.com/PostHog/posthog-sdk-test-harness/blob/main/CONTRACT.yaml) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| # PostHog Android SDK Compliance Adapter | ||
|
|
||
| This compliance adapter wraps the PostHog Android SDK and exposes a standardized HTTP API for automated compliance testing using the [PostHog SDK Test Harness](https://github.com/PostHog/posthog-sdk-test-harness). | ||
|
|
||
| ## Quick Start | ||
|
|
||
| ### Running Tests in CI (Recommended) | ||
|
|
||
| Tests run automatically in GitHub Actions on: | ||
| - Push to `main`/`master` branch | ||
| - Pull requests | ||
| - Manual trigger via `workflow_dispatch` | ||
|
|
||
| See `.github/workflows/sdk-compliance-tests.yml` | ||
|
|
||
| ### Running Tests Locally | ||
|
|
||
| **Note:** Requires x86_64 architecture due to Java 8 dependency. On Apple Silicon, Docker will use emulation (slower but works). | ||
|
|
||
| ```bash | ||
| cd sdk_compliance_adapter | ||
| docker-compose up --build --abort-on-container-exit | ||
| ``` | ||
|
|
||
| ## Architecture | ||
|
|
||
| - **adapter.kt** - Ktor HTTP server implementing the compliance adapter API | ||
| - **TrackingInterceptor** - OkHttp interceptor for monitoring SDK HTTP requests | ||
| - **Dockerfile** - Multi-stage Docker build (requires x86_64 for Java 8) | ||
| - **docker-compose.yml** - Local test orchestration | ||
|
|
||
| ## SDK Modifications | ||
|
|
||
| To enable request tracking, we added an optional `httpClient` parameter to `PostHogConfig`: | ||
|
|
||
| ```kotlin | ||
| // PostHogConfig.kt | ||
| public var httpClient: okhttp3.OkHttpClient? = null | ||
| ``` | ||
|
|
||
| This allows the test adapter to inject a custom OkHttpClient with tracking interceptors. **This change is fully backward compatible** - existing code works unchanged. | ||
|
|
||
| ## Implementation Details | ||
|
|
||
| ### HTTP Request Tracking | ||
|
|
||
| The adapter injects a custom OkHttpClient that: | ||
| - Intercepts all `/batch/` requests | ||
| - Extracts event UUIDs from request bodies | ||
| - Tracks status codes, retry attempts, and event counts | ||
|
|
||
| ### Event Tracking | ||
|
|
||
| Events are tracked via: | ||
| 1. `beforeSend` hook - Captures UUIDs as events are queued | ||
| 2. HTTP interceptor - Verifies UUIDs in outgoing requests | ||
|
|
||
| ### SDK Type | ||
|
|
||
| The Android SDK uses **server SDK format**: | ||
| - Endpoint: `/batch/` | ||
| - Format: `{api_key, batch, sent_at}` | ||
|
|
||
| Tests run with `--sdk-type server`. | ||
|
|
||
| ## Files Created | ||
|
|
||
| ``` | ||
| sdk_compliance_adapter/ | ||
| ├── adapter.kt # Main adapter implementation | ||
| ├── build.gradle.kts # Gradle build configuration | ||
| ├── Dockerfile # Docker build (x86_64) | ||
| ├── docker-compose.yml # Local test setup | ||
| ├── README.md # This file | ||
| └── IMPLEMENTATION_NOTES.md # Detailed technical notes | ||
| ``` | ||
|
|
||
| ## Changes to Core SDK | ||
|
|
||
| ### posthog/src/main/java/com/posthog/PostHogConfig.kt | ||
| - Added `httpClient: OkHttpClient?` parameter | ||
|
|
||
| ### posthog/src/main/java/com/posthog/internal/PostHogApi.kt | ||
| - Modified to use injected `httpClient` if provided | ||
|
|
||
| ### settings.gradle.kts | ||
| - Added `:sdk_compliance_adapter` module | ||
|
|
||
| ### .github/workflows/sdk-compliance-tests.yml | ||
| - GitHub Actions workflow for automated testing | ||
|
|
||
| ## References | ||
|
|
||
| - [Test Harness Repository](https://github.com/PostHog/posthog-sdk-test-harness) | ||
| - [Adapter Guide](https://github.com/PostHog/posthog-sdk-test-harness/blob/main/ADAPTER_GUIDE.md) | ||
| - [Contract Specification](https://github.com/PostHog/posthog-sdk-test-harness/blob/main/CONTRACT.yaml) | ||
| - [Browser SDK Adapter](https://github.com/PostHog/posthog-js/tree/main/packages/browser/sdk_compliance_adapter) (Reference) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we dont have master