chore(experiments): extract metric value and predicate semantics#60787
Merged
Conversation
Contributor
|
🎭 Playwright report · View test results →
These issues are not necessarily caused by your changes. |
7b6791d to
1c27829
Compare
Move conversion-window, metric-predicate, value, and value-aggregation helpers out of ExperimentQueryBuilder into experiment_metric_values.py as module-level functions with explicit inputs. The builder keeps delegating wrappers of the same name and signature, so all callers (including the funnel actors subclass) are unchanged. Pure mechanical move, no SQL change.
57e897c to
653d88f
Compare
Contributor
Prompt To Fix All With AIFix the following 3 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 3
posthog/hogql_queries/experiments/experiment_metric_values.py:150-156
These docstrings were copied verbatim from the class methods and still say "uses `self.metric.source` by default" — but this module-level function has no `self` and requires `source` as an explicit argument. Any new reader of this file will be confused about whether the function falls back to something automatically.
```suggestion
def build_value_expr(source: MetricSource, apply_coalesce: bool = True) -> ast.Expr:
"""
Extracts the value expression from the metric source configuration.
For ratio metrics, pass the specific source (numerator or denominator).
For mean metrics, pass the resolved metric source explicitly.
Args:
```
### Issue 2 of 3
posthog/hogql_queries/experiments/experiment_metric_values.py:199-202
Same stale `self.metric.source` reference in the docstring for `build_value_aggregation_expr`. The function requires `source` explicitly; the "uses self.metric.source by default" text is left over from the class context and no longer applies here.
```suggestion
"""
Returns the value aggregation expression based on math type.
For ratio metrics, pass the specific source (numerator or denominator) and events_alias.
For mean metrics, pass the resolved metric source explicitly with "metric_events" alias.
```
### Issue 3 of 3
posthog/hogql_queries/experiments/experiment_metric_values.py:106-110
Same stale `self.metric.source` reference in `build_metric_predicate`'s docstring — no `self` here either.
```suggestion
"""
Builds the metric predicate as an AST expression.
For ratio metrics, pass the specific source (numerator or denominator) and table_alias.
For mean metrics, pass the resolved metric source explicitly with "events" alias.
"""
```
Reviews (1): Last reviewed commit: "chore(experiments): extract metric value..." | Re-trigger Greptile |
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
mp-hog
approved these changes
Jun 2, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Problem
This is PR 3 of an 8-PR stacked, behavior-preserving refactor that breaks the ~3000-line
experiment_query_builder.pygod class into cohesive modules, following the team's hybrid refactor plan. It isolates the metric value and predicate semantics — conversion-window predicates, the metric predicate, the value expression, and the value-aggregation expression (sum/avg/min/max/unique-sessions/DAU/unique-groups/HogQL-aggregation/nullable/winsorization) — into a dedicated module so the builder no longer owns this self-contained slice of SQL-construction logic.Changes
posthog/hogql_queries/experiments/experiment_metric_values.pywith seven module-level functions taking fully explicit inputs (team,source,date_range_query,conversion_window_seconds,table_alias,events_alias,column_name,value_expr, etc.):get_conversion_window_seconds,build_conversion_window_predicate,build_session_conversion_window_predicate,build_conversion_window_predicate_for_events,build_metric_predicate,build_value_expr, andbuild_value_aggregation_expr.ExperimentQueryBuilderkeeps a thin delegating wrapper of the same name and signature for each of the seven methods, so every caller — the mean/ratio/funnel/retention builders, internal callers inexperiment_query_runner.py, and theExperimentFunnelActorsQueryBuildersubclass — is unchanged.experiment_query_builder.py(get_source_value_expr, thehogql_aggregation_utilsblock, andExperimentMetricMathType) that now live only in the new module..ambrdiffs); no SQL or logic was edited; all comments preserved verbatim.How did you test this code?
Authored by an AI agent (Claude Code) in an automated multi-agent workflow — no manual testing was performed. The following automated tests were run locally and pass, with no snapshot (
.ambr) changes:posthog/hogql_queries/experiments/test/experiment_query_runner/test_mean_metric.pyposthog/hogql_queries/experiments/test/experiment_query_runner/test_ratio_metric.py(48 passed, 1 pre-existing skip, 47 snapshots passed; no
.ambrfiles changed.)Automatic notifications
Docs update
Add the
skip-inkeep-docslabel — internal refactor with no user-facing docs impact.🤖 Agent context
Authored by Claude Code via a stacked-PR refactor workflow; PR 3 of 8, stacked on
refactor/exp-qb-2-exposure. Mechanical, behavior-preserving extraction — generated SQL is unchanged (experiment snapshot tests pass with no.ambrdiffs) and delegating wrappers were kept onExperimentQueryBuildersoExperimentFunnelActorsQueryBuilderand internal callers keep working. The seven extracted functions take fully explicit args; the builder wrappers retain thesource=Noneresolution and theExperimentMeanMetric/metric is requiredasserts since some callers invoke them externally. PR 2 used a class-based exposure builder; per this phase's plan the metric-value helpers are module-level functions. Agent-authored and requires human review — do not self-merge or auto-approve.