feat(customer-analytics): Add sparkline visualization for usage metrics#54349
feat(customer-analytics): Add sparkline visualization for usage metrics#54349arthurdedeus wants to merge 12 commits intographite-base/54349from
Conversation
|
Hey @arthurdedeus! 👋\nThis pull request seems to contain no description. Please add useful context, rationale, and/or any other information that will help make sense of this change now and in the distant Mars-based future. |
|
Size Change: +2.19 kB (0%) Total Size: 129 MB ℹ️ View Unchanged
|
Prompt To Fix All With AIThis is a comment left during a code review.
Path: products/customer_analytics/frontend/components/UsageMetricCard.tsx
Line: 57-59
Comment:
**Redundant null check in `TrendIndicator`**
`getTrendFromPercentageChange` already returns `undefined` when given `null`, so `!trend` covers the `null` case entirely — the second condition is dead code.
```suggestion
if (!trend) {
```
How can I resolve this? If you propose a fix, please make it concise.
---
This is a comment left during a code review.
Path: products/customer_analytics/backend/hogql_queries/test/test_usage_metrics_query_runner.py
Line: 749-750
Comment:
**Magic number obscures test intent**
The `5` isn't self-documenting. With an interval of 7 and events on exactly 2 days, the expected zero count is `interval - 2`. Deriving it from the test parameters would make the relationship explicit, and using `assertEqual` rather than `assertGreaterEqual` would make the assertion tighter.
```suggestion
self.assertEqual(zero_count, 7 - 2) # interval=7, events on 2 distinct days
```
How can I resolve this? If you propose a fix, please make it concise.Reviews (1): Last reviewed commit: "fix(customer-analytics): Fix cache inval..." | Re-trigger Greptile |
🔍 Migration Risk AnalysisWe've analyzed your migrations for potential risks. Summary: 1 Safe | 0 Needs Review | 0 Blocked ✅ SafeBrief or no lock, backwards compatible 📚 How to Deploy These Changes SafelyAddField: This operation acquires a brief lock but doesn't rewrite the table. Deployment uses lock timeouts with automatic retries, so lock contention will cause retries rather than connection pile-up. Last updated: 2026-04-13 21:24 UTC (dd744ff) |
|
🎭 Playwright report · View test results →
These issues are not necessarily caused by your changes. |
…egation Generated-By: PostHog Code Task-Id: 887010a6-d3c0-4a87-b260-bdbc5cb48df1
…d API types Generated-By: PostHog Code Task-Id: 887010a6-d3c0-4a87-b260-bdbc5cb48df1
Generated-By: PostHog Code Task-Id: 887010a6-d3c0-4a87-b260-bdbc5cb48df1
Generated-By: PostHog Code Task-Id: 887010a6-d3c0-4a87-b260-bdbc5cb48df1
Generated-By: PostHog Code Task-Id: 887010a6-d3c0-4a87-b260-bdbc5cb48df1
…erval grouping Generated-By: PostHog Code Task-Id: 9ad27541-d11a-40b3-89f1-4424f193f8d0
…ry runner Generated-By: PostHog Code Task-Id: 59552aa7-0856-47b1-86c6-034bb0a4ac82
Generated-By: PostHog Code Task-Id: 9ad27541-d11a-40b3-89f1-4424f193f8d0
… and sparkline alignment Generated-By: PostHog Code Task-Id: 9ad27541-d11a-40b3-89f1-4424f193f8d0
Generated-By: PostHog Code Task-Id: e1dc5244-8330-4dbf-b60b-43c8ef5d882d
dd744ff to
95d8395
Compare
Prompt To Fix All With AIThis is a comment left during a code review.
Path: products/customer_analytics/backend/hogql_queries/usage_metrics_query_runner.py
Line: 289-296
Comment:
**Extra DB query on every request**
`get_cache_payload` calls `_get_usage_metrics()` (a DB query), and so does `_calculate` on every cache miss. Both calls fetch the same rows from the same table. On a cache miss, that's two identical queries in one request cycle.
A simple fix is to memoize the result at the instance level:
```python
@functools.cached_property
def _metrics(self) -> list[GroupUsageMetric]:
return list(
GroupUsageMetric.objects.filter(team=self.team).only(
"id", "name", "format", "interval", "display", "filters", "math", "math_property"
)
)
```
Then both `get_cache_payload` and `_calculate` can call `self._metrics` instead of going through `_get_usage_metrics`.
How can I resolve this? If you propose a fix, please make it concise.Reviews (2): Last reviewed commit: "chore(customer-analytics): Address PR re..." | Re-trigger Greptile |
There was a problem hiding this comment.
@arthurdedeus approving to unblock, I would like to run this one locally but just to make sure the Sparkline keeps working on all other places.
sounds good! the sparkline component didn't change, though. I'm just reusing it |
Riiiight, I misread the PR description, sorry! I will have a brain again next week |

Problem
Usage metrics only displayed scalar number cards with no visual trend representation. Additionally, changing a metric's display type (e.g. number → sparkline) didn't invalidate the query cache, returning stale results.
Changes
timeseriesandtimeseries_labelsfields to theUsageMetricschema — populated with daily values whendisplay=sparklineSparklinecomponent, with compact value + trend indicator belowHow did you test this code?
New test cases for sparkline timeseries, gap-filling, and mixed display types added. Full suite passes:
hogli test products/customer_analytics/backend/hogql_queries/test/test_usage_metrics_query_runner.py— 25 tests.Publish to changelog?
No
Docs update
🤖 LLM context
Authored by PostHog Code (Claude Code).
Created with PostHog Code