Skip to content

feat!: v8.0 — decision history API + telemetry simplification#168

Merged
saurabhjain1592 merged 2 commits intomainfrom
feat/v8-telemetry-cleanup
May 8, 2026
Merged

feat!: v8.0 — decision history API + telemetry simplification#168
saurabhjain1592 merged 2 commits intomainfrom
feat/v8-telemetry-cleanup

Conversation

@saurabhjain1592
Copy link
Copy Markdown
Member

Summary

Combined major release for the Java SDK. Bundles a new decision-history client API surface (listDecisions + runnable explain example, both landed since v7.1.0) with a telemetry contract simplification that removes silent customer-side suppression paths.

After this lands:

  • AXONFLOW_TELEMETRY=off is the sole opt-out for SDK telemetry — same pattern as HashiCorp checkpoint, Docker, Datadog Agent.
  • Sandbox-mode clients now fire telemetry, tagged stream="sandbox" so they're distinguishable from production heartbeat in analytics.
  • AxonFlowConfig.Builder.telemetry(Boolean) + AxonFlowConfig.getTelemetry() are removed — the config-level kill switch is gone.

Why combined into a major

The telemetry contract had two redundant levers (env var + programmatic field) and one silent-suppression path (mode-based default-off). Cleanup is technically a breaking change, so it must ride a major version bump. We bundled the decision-history feature work (#166, #167) into the same major instead of releasing a v7.2.0 right before a v8.0.0 — fewer customer-facing version transitions.

Migration

// Before (v7.x)
AxonFlowConfig config = AxonFlowConfig.builder()
    .endpoint("...")
    .telemetry(false)   // ← removed in v8
    .build();

// After (v8.0)
AxonFlowConfig config = AxonFlowConfig.builder()
    .endpoint("...")
    .build();
// To disable telemetry: set AXONFLOW_TELEMETRY=off in the environment.

If you were calling config.getTelemetry(): drop the call site; AXONFLOW_TELEMETRY=off is the only telemetry knob.

Dependency note

This PR's runtime-e2e test (runtime-e2e/sandbox_telemetry_stream_tag/) depends on getaxonflow/axonflow-enterprise#2005 (server-side stream allowlist) being deployed. Pre-deploy the row will be tagged stream=heartbeat regardless of payload (server hardcodes), and the test's stream-tag assertion fails. The unit tests + behavioral correctness in this PR are independent and pass standalone.

Test plan

Unit + build

  • ./mvnw test — all 1236 tests pass on the v8 changes (unit + integration: heartbeat E2E, short-lived process regression, telemetry endpoint type, MCP, audit, plan, HITL, etc.).
  • ./mvnw -DskipTests compile clean.
  • bash -n runtime-e2e/sandbox_telemetry_stream_tag/test.sh clean.
  • scripts/lint-no-mocks-in-runtime-e2e.sh runtime-e2e/sandbox_telemetry_stream_tag/ clean (no forbidden mock patterns).

Runtime proof (3-rule DoD, HARD RULE #0)

The runtime-e2e file exists and satisfies the mechanical CI gate, but the test has not yet been executed against the deployed Lambda. Per HARD RULE #0, runtime proof is the rule, not the file's existence. The proof is gated on:

  • axonflow-enterprise#2005 (server-side stream allowlist) deployed via deploy-checkpoint.yml.
  • Then run runtime-e2e/sandbox_telemetry_stream_tag/test.sh against the live Lambda. Expected: an audit row tagged sdk=java/8 stream=sandbox lands in DynamoDB and CloudWatch within ~10s.

I will not request merge of this PR until those two items are checked. Pre-deploy I'm declaring "tests exist + unit-test parity is correct"; full runtime proof comes after #2005 deploys.

Release tagging (gated on user authorization)

  • Tag v8.0.0 on the merged commit.
  • Publish to Maven Central.

Per the project's release-approval rule, you authorize each release individually. DO NOT TAG OR PUBLISH is set on this PR until explicit approval.

Self-review

Hunk-by-hunk review on every modified file. Five-question protocol applied:

  1. pom.xml + examples/{explain-decision,list-decisions}/pom.xml — single <version>7.1.0</version><version>8.0.0</version>. Verified by grep that no other 7.1.0 literals remain in *.xml / *.java. README example deps bumped from 4.0.0 (already-stale install snippet) to 8.0.0.

  2. src/main/java/com/getaxonflow/sdk/AxonFlowConfig.java — three coordinated removals: field private final Boolean telemetry, accessor getTelemetry(), builder method telemetry(Boolean) + the matching Builder.telemetry field. Verified by grep that no production code references either symbol post-deletion.

  3. src/main/java/com/getaxonflow/sdk/telemetry/TelemetryReporter.java — class doc rewritten with v7→v8 history. isEnabled collapsed from (mode, configOverride, hasCredentials, axonflowTelemetry) four-arg shape to single-arg isEnabled(String axonflowTelemetry). sendPing overloads simplified — Boolean telemetryEnabled + boolean hasCredentials parameters dropped. buildPayload adds the stream="sandbox" field ONLY when mode.equals("sandbox") — production-mode payloads are byte-identical to v7.x because the field is omitted entirely (Jackson ObjectNode.put is only called in the sandbox branch). Verified by testPayloadFormat (asserts root.has("stream") == false for production) and testPayloadStreamTagSandbox (asserts stream="sandbox").

  4. src/main/java/com/getaxonflow/sdk/AxonFlow.java — single call-site update. invokeHeartbeat no longer derives hasCredentials (param removed from isEnabled) and no longer reads config.getTelemetry() (accessor removed). Down to: read AXONFLOW_TELEMETRY env, pass to isEnabled(String), pass result to HeartbeatState.maybeSendHeartbeat. Doc-comment retained around the heartbeat gate.

  5. src/test/java/com/getaxonflow/sdk/telemetry/TelemetryReporterTest.java — major refactor:

    • Removed: testTelemetryDefaultOffForSandbox, testTelemetryDefaultOnForProductionWithoutCredentials, testTelemetryDefaultOnForEnterpriseWithCredentials, testTelemetryConfigOverrideEnable, testTelemetryConfigOverrideDisable, testAxonflowTelemetryPrecedence, testSandboxModeDefaultOff, testSandboxModeExplicitEnable, testConfigDisableInProduction — all asserted v7.x mode-or-override semantics that no longer exist.
    • Added: testTelemetryOnByDefault (table-driven, asserts ON for null / "" / "on" / "anything-not-off"), testPayloadStreamTagSandbox (sandbox payload carries stream="sandbox"), testPayloadStreamTagProductionOmitted (production omits stream), testPayloadStreamTagOtherModesOmitted (enterprise/staging/empty/unknown omit stream), and the headline shouldFirePingWithStreamSandboxInSandboxMode covering both "ping fires" + "payload carries stream tag" via WireMock.
    • All remaining HTTP-integration tests have their sendPing calls updated to the new signature (mode, sdkEndpoint, debug, axonflowTelemetry, checkpointUrl).
  6. src/test/java/com/getaxonflow/sdk/telemetry/TelemetryReporterShortLivedTest.java — single signature update, dropped Boolean.TRUE + two boolean false arguments. Test still proves sendPing blocks until round-trip completes (≥150ms when mock has a 200ms fixed delay) — the synchronous-delivery contract is unchanged.

  7. runtime-e2e/sandbox_telemetry_stream_tag/ — new directory; test.sh + README.md. Real ping against deployed checkpoint Lambda, no mocks. Lint-clean per lint-no-mocks-in-runtime-e2e.sh. The bash script does mvn install -DskipTests of the local SDK to ~/.m2, then a tiny consumer pom + SandboxRuntimeProof.java resolving com.getaxonflow:axonflow-sdk:8.0.0, constructs Mode.SANDBOX against localhost:65530 (intentional-unreachable so we exercise heartbeat ping but no platform call), waits 2s, then aws logs filter-log-events for event_stored sdk=java/8 AND stream=sandbox.

  8. CHANGELOG.md — new v8.0.0 entry above v7.1.0. Headline names the feature theme (decision history API); telemetry change kept concise at the bottom under Removed. Migration guide walks through .telemetry(Boolean) builder removal + getTelemetry() accessor removal + TelemetryReporter testability-surface signature change.

  9. README.md — install snippet bumped from 4.0.0 to 8.0.0 (pre-existing stale documentation, fixed in this PR). Telemetry section gained a clarifying paragraph about AXONFLOW_TELEMETRY=off being the sole opt-out as of v8.0.

Risk

  • Breaking for any customer currently calling .telemetry(false) on the builder — the call site will fail to compile. Migration is a one-liner: delete the call, set AXONFLOW_TELEMETRY=off in the env if they wanted off. We have no telemetry on actual .telemetry() use; the audit found 0 production-code + 0 test-code in-tree usages of the builder method (cleanest of the four SDK migrations).
  • Sandbox-mode behavior changed — sandbox clients used to produce zero pings, now produce one ping per machine per 7 days (delivered-stamp gating from v7). CHANGELOG calls this out explicitly under Removed.

Linked

  • axonflow-enterprise#2005 — server-side stream allowlist (companion change; must be deployed for the runtime-e2e to fully succeed).
  • axonflow-enterprise#2006 — CloudWatch alarms (independent companion).
  • axonflow-enterprise#2004 — design discussion for platform-level startup ping (separate, future).
  • axonflow-sdk-go#160 — Go SDK reference v8 release shipped 2026-05-08; this Java PR is the symmetric translation.

Combined major release for the Java SDK. Bundles a new decision-history
client API surface (`listDecisions` + runnable explain example, both
landed since v7.1.0) with a telemetry contract simplification that
removes silent customer-side suppression paths.

After this lands:

- `AXONFLOW_TELEMETRY=off` is the SOLE opt-out for SDK telemetry — same
  pattern as HashiCorp checkpoint, Docker, Datadog Agent.
- Sandbox-mode clients now fire telemetry, tagged `stream="sandbox"` so
  they're distinguishable from production heartbeat in analytics.
- `AxonFlowConfig.Builder.telemetry(Boolean)` and
  `AxonFlowConfig.getTelemetry()` removed — the config-level kill switch
  is gone.

Why combined into a major: the telemetry contract had two redundant
levers (env var + programmatic field) and one silent-suppression path
(mode-based default-off). Cleanup is technically a breaking change, so
it must ride a major version bump. We bundled the decision-history
feature work (#166, #167) into the same major instead of releasing a
v7.2.0 right before a v8.0.0 — fewer customer-facing version transitions.

Signed-off-by: Saurabh Jain <saurabhjain1592@gmail.com>
Signed-off-by: Saurabh Jain <saurabhjain1592@gmail.com>
@saurabhjain1592 saurabhjain1592 merged commit b70806a into main May 8, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant