Repository navigation
feat(flags): count projects tab evaluations from flag_evaluations - #110148
Conversation
Organizations on FLAG_EVALUATIONS_ONLY read the 7-day per-project eval counts from flag_evaluations. Every other mode keeps reading events. The cache key names the source table, so a mode change cannot serve a count read from the other table. Claude-Session: https://claude.ai/code/session_01Hqgf9Fx7M77d5BMEKbxQBG
|
😎 Merged successfully - details. |
🤖 CI report
|
| File | Comment lines | Added lines |
|---|---|---|
products/feature_flags/backend/facade/enums.py |
4 | 4 |
products/feature_flags/backend/flag_analytics.py |
2 | 35 |
posthog/test/base.py |
1 | 26 |
This check does not block merging. It updates on every push and clears when the share drops.
|
[Medium risk] Changes how the projects tab counts flag evaluations. The PR appears safe to merge; no outstanding finding or new actionable issue remains. Reviews (2) · Last reviewed commit: "chore(flags): explain why read_flag_eval..." |
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
Source selection, cache isolation, tenant scoping, and regression coverage are consistent and complete.
Review effort: Balanced
Findings: None
What changed in this PR
Updates cross-project feature flag evaluation counts for FLAG_EVALUATIONS_ONLY organizations.
Changes:
- Selects the appropriate ClickHouse source by organization mode.
- Separates caches by source table.
- Adds query, endpoint, and cache-transition coverage.
| File | Description |
|---|---|
products/feature_flags/backend/flag_analytics.py |
Selects and caches counts by source table. |
products/feature_flags/backend/api/organization_feature_flag.py |
Passes organization context to count selection. |
products/feature_flags/backend/api/test/test_organization_feature_flag.py |
Tests mode-dependent endpoint counts. |
products/feature_flags/backend/api/test/__snapshots__/test_organization_feature_flag.ambr |
Records the added mode lookup. |
posthog/test/test_feature_flag_analytics.py |
Tests both sources and cache transitions. |
posthog/test/base.py |
Adds a flag-evaluation fixture helper. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. 📝 WalkthroughWalkthroughSeven-day cross-project evaluation counts can now come from either Priority: ➖ Normal Merge Risk: 🔵 Low · up to The source selection and cache behavior are covered, but switching an organization before every team has ingestion coverage can undercount Projects tab evaluations. Merge with explicit ownership of that prerequisite and keep uncovered organizations on EVENTS. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to Access remains limited to projects the user may view, and the inspected changes show no access-control bypass. Remaining uncertainty concerns rollout sequencing and the completeness of evaluation data when organizations switch modes. Retained concerns Security review detailsSecurity Blast Radius
Security Findings and Attack Paths
Trust Boundaries and Controls
Resilience and Maintainability Implications
🚥 Pre-merge checks | ✅ 1✅ Passed checks (1 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Note
Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.
🟡 Other comments (1)
products/feature_flags/backend/flag_analytics.py-360-362 (1)
360-362: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick winGate
FLAG_EVALUATIONS_ONLYon ingestion coverage.
FLAG_EVALUATIONS_ONLYmakes this query readflag_evaluationsfor every team in the organization. Ingestion uses separate team, lane, topic, and exclusion settings. If any team is not covered by the activedual_writefork, recent evaluations can be missing and the zero-filled result can undercount that team. Keep the organization onEVENTSuntil ingestion covers every team.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository: PostHog/posthog/.coderabbit.yaml
Review profile: QUIET
Plan: Enterprise
Run ID: e06e9400-ce0e-47b1-8f61-f9fa4cdb42f1
📒 Files selected for processing (2)
products/feature_flags/backend/facade/enums.pyproducts/feature_flags/backend/flag_analytics.py
Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 7 remain after this review.
|
Risk: No findings This change makes the organization flag Projects tab count evaluations from the Sentinel reviewed |
There was a problem hiding this comment.
Approved.
Contained read-path change for the Projects tab. It only affects organizations explicitly set to the flag-evaluations-only mode, and the owning-team author included tests for each mode and for cache isolation. The CodeRabbit ingestion-coverage note is a rollout concern, because no organization gets this mode without an explicit change.
- Author wrote 0% of the modified lines and has 42 merged PRs in these paths (familiarity MODERATE).
- coderabbitai[bot] reviewed the current head.
Gate mechanics and policy version
| Gate | Result | |
|---|---|---|
| prerequisites | ✓ | all clear |
| deny-list | ✓ | no deny categories matched |
| size | ✓ | 53L, 3F substantive, 167L/7F incl. docs/generated/snapshots — within ceiling |
| tier | ✓ | T1-agent / T1c-medium (167L, 7F, two-areas, feat) |
| stamphog 2.3.1 | .stamphog/policy.yml @ 027dbce · reviewed head 027dbce |

Problem
$feature_flag_calledrows inevents.FLAG_EVALUATIONS_ONLY, where ingestion stops writing those rows toevents.Changes
flag_evaluationswhen the organization is onFLAG_EVALUATIONS_ONLY.events, so organizations onEVENTSsee no change. That covers self-hosted and hobby installs.team_id,flag_keyandtimestamp, which are the first three columns of theflag_evaluationssort key.READ_FLAG_EVALUATIONSstays onevents, unlike the Usage tab. The rollout keeps existing organizations unchanged, so only organizations whoseeventswrites will stop switch tables.FLAG_EVALUATIONS_ONLYreader changes land.EVENTSandREAD_FLAG_EVALUATIONSshare entries.get_cached_evaluations_7d_by_teamtakes the organization id. One call never spans organizations, because the view passes only that organization's teams._create_flag_evaluationstest helper inposthog/test/base.py.How did you test this code?
Test rationale:
test_counts_flag_calls_by_team_from_the_selected_tableextendstest_counts_events_by_team. It fails if theflag_evaluationsquery counts other flag keys or rows older than 7 days, or reads the wrong table.test_evaluation_counts_come_from_the_table_the_mode_selectsextendstest_evaluation_counts_match_eventsover all three modes. It fails if the view stops passing the organization, or ifREAD_FLAG_EVALUATIONSmoves offevents.test_mode_change_does_not_serve_the_result_cached_under_the_previous_modeis new. It fails if the cache key stops naming the source table, which no other test catches.posthog/test/test_feature_flag_analytics.pyandproducts/feature_flags/backend/api/test/test_organization_feature_flag.py.flag_evaluationsdata. NoEXPLAINwas run.eventstable with raw SQL, not through HogQL, and that path is unchanged.👉 Stay up-to-date with PostHog coding conventions for a smoother review.
Release status
The organization's stored flag evaluations mode selects the table. No organization reaches
FLAG_EVALUATIONS_ONLYwithout an explicit mode change.Automatic notifications
Docs update
None. No doc under
docs/covers this tab.🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Agent: Claude Code, Claude Opus 5.5 (
claude-opus-5-5)/gopipeline. The plan asked for decisions to be recorded here rather than raised as questions./writing-tests,/writing-code-comments,/improving-drf-endpoints(no serializer or schema change was needed),/simplify,/reviewing-with-coderabbit,/writing-pr-descriptions.--deep, because the diff adds raw ClickHouse SQL that filters by team. It returned 0 findings.https://claude.ai/code/session_01Hqgf9Fx7M77d5BMEKbxQBG