Repository navigation
feat(core,cli): emit the canary decision reason alongside the assignment #3074
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -180,13 +180,22 @@ export function canaryDecisionsForStudio(): Record<string, CliCanaryDecision> { | |
|
|
||
| /** | ||
| * Canary assignments as PostHog flag properties — `$feature/canary-<name>` | ||
| * set to `"true"` / `"false"` for every registered canary. Spread onto every | ||
| * event so any metric can be broken down by cohort using PostHog's native | ||
| * flag tooling, with nothing configured server-side. See | ||
| * `canaryFeatureProperties` for why non-enrolled canaries are emitted too. | ||
| * set to `"true"` / `"false"` for every registered canary, each paired with a | ||
| * `canary_reason_<name>`. Spread onto every event so any metric can be broken | ||
| * down by cohort using PostHog's native flag tooling, with nothing configured | ||
| * server-side. See `canaryFeatureProperties` for why non-enrolled canaries are | ||
| * emitted too, and why the reason has to ride along. | ||
| * | ||
| * The reason is what makes a cohort flip attributable. `resolveCanary` has | ||
| * computed it all along and this function used to drop it, so an install | ||
| * reporting both values looked identical whether a developer had toggled | ||
| * `HF_CANARY_*` or the bucketer had genuinely disagreed with itself. | ||
| */ | ||
| export function canaryEventProperties(): Record<string, string> { | ||
| return canaryFeatureProperties( | ||
| CANARIES.map((c) => ({ name: c.name, enabled: resolveCanary(c.name).enabled })), | ||
| CANARIES.map((c) => { | ||
| const { enabled, reason } = resolveCanary(c.name); | ||
|
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. 🔴 The identical anti-pattern is still live in Studio. export function canaryEventProperties(): Record<string, string> {
return canaryFeatureProperties(
CANARIES.map((c) => ({ name: c.name, enabled: resolveCanary(c.name).enabled })),
);
}That is the exact shape this PR just fixed on the CLI side. Studio events emit
Fix here — the Studio change is the same three-line shape as the one below, and the tests parallel |
||
| return { name: c.name, enabled, reason }; | ||
| }), | ||
| ); | ||
| } | ||
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.
🟡 The
describe("reason reaches the event properties")block coversin_cohort(line 250),forced_on(260),excluded(267),telemetry_opt_out(274) — but notno_unit_id, which the PR body advertises as the second of "two values that pay for themselves immediately".resolveCanary("test-gamma")at line 217 already exercisesno_unit_idat the resolver layer (whenconfigState.bucketSeed = undefined), so the emission-layer test is one line: unsetbucketSeed, unset any override, thenexpect(canaryEventProperties()["canary_reason_test_gamma"]).toBe("no_unit_id"). Same shape as the four existing tests — closes the "advertised in body, not asserted in tests" gap for a value the body specifically names. — Rames D Jusso