Skip to content

feat(local-ui): metrics/services/errors views + promote shared chrome into @maple/ui#248

Merged
Makisuo merged 1 commit into
mainfrom
feat/local-ui-parity-shared-chrome
Jul 22, 2026
Merged

feat(local-ui): metrics/services/errors views + promote shared chrome into @maple/ui#248
Makisuo merged 1 commit into
mainfrom
feat/local-ui-parity-shared-chrome

Conversation

@Makisuo

@Makisuo Makisuo commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

What

Brings the local-mode UI (apps/local-ui) closer to feature/UI parity with the web app, and kills the duplicated chrome by promoting it into @maple/ui.

Shared-chrome promotion (dedup)

Promoted into packages/ui/src — web files become re-export shims (zero consumer edits), local copies deleted:

  • components/filters/filter-section.tsx — web's superset (option icons, serviceColorMap, SingleCheckboxFilter); local gains service color swatches
  • components/filters/filter-sidebar.tsx — width-agnostic frame + header/body/loading; FilterSidebarError stays in web (binds the app's ErrorState)
  • components/filters/duration-range-filter.tsx — web's onRangeChange API + local's flush-on-blur/Enter, debounceMs prop (web 400ms default, local passes 300ms)
  • components/toolbar.tsx — generic Toolbar/ToolbarSearch/ToolbarStat/TimeRangeSelect/RefreshButton, data-agnostic so @maple/ui gains no react-query dep; local keeps a tiny wrapper binding the ["local"] invalidation. Web toolbar adoption deliberately deferred (router/effect-atom wired).
  • components/metrics/metric-type-badge.tsx (+ METRIC_TYPE_COLORS)
  • lib/replay-format.ts — pure formatters only; replayPartitionWindow stays in web because @maple/ui must not depend on @maple/query-engine
  • span-detail-panel / log-detail-sheet stay intentionally divergent (web's are effect-atom/infra-coupled); header comments now document that

New local views (parity)

All backed by MVs that already exist in local-schema.sql and existing @maple/query-engine CH queries — no CLI/schema changes. All 15 queries smoke-tested against a live chDB binary first, including the windowed metricsTimeseriesRateQuery.

  • Metrics #/metrics + #/metrics/:name — sparkline preview grid with type/service facets; detail plots true per-second rate for monotonic counters and avg for gauges/histograms via the shared QueryBuilderLineChart, plus per-service breakdown
  • Services #/services + #/services/:name — dense table (spans/errors/error rate/p50/p95/logs) with env/ns facets; detail has golden-signal cards, throughput-by-operation chart, top-operations table deep-linking into filtered traces
  • Errors #/errors — summary stats, fingerprint-grouped cards with service/env facets, expandable to recent affected traces linking to the trace waterfall

Why

The local UI had drifted: it hand-copied web chrome (each copy tagged "mirrors the web app's …") and exposed only traces/logs/sessions while the local chDB schema already materializes everything metrics/services/errors need.

Verification

  • Repo-wide bun typecheck passes; @maple/local-ui tests pass; all 730 web tests pass (route tests cover the filter-sidebar consumers)
  • Browser walkthrough against a live dev binary with seeded OTLP data: all new tabs render, filters persist across tabs, error → trace cross-link lands on the shared waterfall
  • Web spot-check at web.localhost/traces: filter sidebar unchanged on the promoted components
  • Embedded SPA bundle now ~485 kB gz JS (recharts enters with the charts — expected)

Reviewer notes

  • Only intended behavioral delta on web: the duration filter now also commits on blur/Enter (it already debounced at 400ms)
  • bucketSecondsForRange gives ~60 buckets per range; long ranges over short data windows legitimately show "not enough datapoints" previews

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

… into @maple/ui

Promote the filter chrome the local UI had hand-copied from apps/web into
packages/ui so both apps render from one source: filter-section (web's
superset with serviceColorMap/option icons), filter-sidebar (width-agnostic
frame), duration-range-filter (web's onRangeChange API + configurable
debounceMs and flush on blur/Enter), the generic toolbar family (data-
agnostic: RefreshButton takes onRefresh, TimeRangeSelect takes ranges, so
@maple/ui gains no react-query dep), metric-type-badge, and the pure
replay-format formatters (the warehouse partition-window helper stays in
web — @maple/ui must not depend on @maple/query-engine). Web paths become
re-export shims so no consumers change; local copies are deleted.

Close most of the local-mode feature gap with three new views backed by
MVs that already exist in the local chDB schema and existing CH queries
(all 15 smoke-tested against a live chDB binary, incl. the windowed
metricsTimeseriesRateQuery):

- #/metrics + #/metrics/:name — sparkline preview grid with type/service
  facets; detail plots true per-second rate for monotonic counters and
  avg for gauges/histograms via the shared QueryBuilderLineChart, plus a
  per-service breakdown table
- #/services + #/services/:name — dense table (spans/errors/error rate/
  p50/p95/logs) with env/ns facets; detail shows golden-signal cards,
  throughput-by-operation chart, and a top-operations table deep-linking
  into filtered traces
- #/errors — summary stats, fingerprint-grouped error cards with service/
  environment facets, expandable to recent affected traces linking to the
  trace waterfall

span-detail-panel/log-detail-sheet stay intentionally divergent (web's are
effect-atom/infra-coupled); their headers now document that instead of
claiming to mirror web.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@pullfrog

pullfrog Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Your Pullfrog Router balance is exhausted.

You have a card on file but auto-reload is disabled, so runs paused once your balance went past the overdraft buffer.

Top up balance → · Enable auto-reload →

Pullfrog  | ⚠️ this action is pinned to a commit SHA, which freezes the cleanup step — switch to @v0 or keep the SHA fresh with Dependabot | Rerun failed job ➔View workflow run | via Pullfrog | Using Claude Opus𝕏

@Makisuo
Makisuo merged commit 701af0c into main Jul 22, 2026
8 checks passed
@Makisuo
Makisuo deleted the feat/local-ui-parity-shared-chrome branch July 22, 2026 13:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant