fix: wrap timeseries rows in Druid-era envelope for UI consumers#5
Merged
Conversation
The ClickHouse timeseries adapter returned rows as {timestamp, count}
(or {timestamp, <dim1>, <dim2>, ...} when aggregation_dimensions are
set). Two consumers expect the Druid-era shape {timestamp, result: {...}}:
- osprey_ui Timeseries.tsx:108 reads point.result.count — currently
crashes with 'Cannot read properties of undefined (reading count)'
whenever the chart has data to render.
- views/entities.py:64 reads timeseries_result[0]['result'] — silently
KeyError or wrong-shape depending on context.
Both consumers reflect the TimeseriesResult type in
osprey_ui/src/types/QueryTypes.tsx, which declares:
result: { count: number; [key: string]: number }
— designed to carry either a plain count or the per-dimension
aggregation this query emits when aggregation_dimensions is populated.
Reshape the rows inside TimeseriesClickHouseQuery.execute() so both
consumers see the expected envelope. Transform verified against both
response cases (plain count, aggregation dimensions).
Member
Author
|
thanks @dcadenas, i keep pulling you in because this sits right at the intersection of T&S and devops, and you happen to sit at the intersection of devops and a lot of things. really appreciate the review bandwidth. |
dcadenas
approved these changes
Apr 22, 2026
dcadenas
left a comment
There was a problem hiding this comment.
Approve. The reshape matches the {timestamp, result: {...}} shape the UI and entities.py consumers expect, and the inline comment points at both call sites so future readers can verify.
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.
Summary
Fixes the long-standing Timeseries chart crash in Osprey UI. The ClickHouse adapter returned flat rows
{timestamp, count}(or{timestamp, <dim1>, <dim2>, ...}whenaggregation_dimensionsare set), but two consumers expect the Druid-era envelope{timestamp, result: {...}}:osprey_ui/src/components/timeseries/Timeseries.tsx:108readspoint.result.count. With the flat shape,point.resultisundefined, so reading.counton it crashes the component (observed:Uncaught TypeError: Cannot read properties of undefined (reading 'count')).osprey_worker/src/osprey/worker/ui_api/osprey/views/entities.py:64readstimeseries_result[0]['result']. With the flat shape, there is noresultkey.The TimeseriesResult TypeScript interface already declares the envelope:
which is designed to carry either a plain count or the per-dimension aggregations the query can emit.
Fix
Reshape rows inside
TimeseriesClickHouseQuery.execute()so both consumers see the expected envelope. Transform verified against both response cases:{timestamp, count: 84}{timestamp, result: {count: 84}}{timestamp, ns: 5, ai: 7}{timestamp, result: {ns: 5, ai: 7}}Reproduction (pre-fix)
osprey-ui:5002 andosprey-ui-api:5004 in staging.Kind > 0over Last Day).Uncaught TypeError: Cannot read properties of undefined (reading 'count')with a stack atTimeseries→QueryView→AppRouter. Chart shows 'No data available' overlay.Verification
Scope
Read-side only. No rule, schema, or enforcement-path changes. Matches the pattern flagged in prior osprey-staging notes as the remaining Druid→ClickHouse shape adapter gap.