Skip to content

Keep ALB logs in the URL, count filters across the window, and fix local sign-in - #1807

Merged
mattdjenkinson merged 6 commits into
mainfrom
feat/alb-logs-url-state
Nov 10, 2026
Merged

mattdjenkinson merged 6 commits into
mainfrom
feat/alb-logs-url-state

Conversation

@mattdjenkinson

@mattdjenkinson mattdjenkinson commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

ALB logs now keep their view in the URL and show filter counts for the whole time window. This also fixes the local sign-in 500, a toolbar that jumped while the metrics page loaded, and logs pages that scrolled past the bottom.

Merge after production has milo-os/telemetry#267. The counts and the window-wide filter options use queryapi features from that PR. It is live on staging, but production pins o11y v0.6.8, which is older. Without it, counts are left off, but the filter options would list values from every ALB in the project instead of this one.

What changed

  1. Logs view in the URL. The time range, filters, search, live mode and the open row live in the query string, so a refresh or a shared link reopens the same view. Refresh slides a preset window like "last 30 minutes" up to now. This uses useLogsUrlState from datum-ui.
  2. Filters for the whole window, with counts.
    • Options: come from label values for the whole window, not just the 500 loaded rows. Ticking one option no longer hides the others.
    • Counts: each option shows how many lines match the other ticked filters, from one sum by (…) (count_over_time(…)) query per filter. So ticking GET still shows how many POSTs there are.
    • When counts hide: search and Host are applied in the browser, so counts hide while you search. Method and Status code counts also hide while a Host is ticked.
  3. Host shows the host each row shows. The Host filter used every host label on a row, including authority, which the proxy rewrites to the backend's name. So httpbin.org was an option even though no row showed it. Host now uses the same order as the Host column (host, SNI, x_forwarded_host, then authority), and empty - values are skipped.
  4. No loading flash on filter clicks. Earlier rows and filters stay on screen while the next request runs, using datum-ui 3.11's isFetching state: dimmed rows, a spinning Refresh and a thin progress bar. Filter groups start open.
  5. Sign-in 500 on Node 26 (fix(server)).
    • The error: Node 26 throws "Illegal invocation" when undici copies @hono/node-server's lightweight Request, which remix-auth does in login, reauth and the OAuth callback.
    • Why production was fine: the forwarded-proto middleware happens to rebuild every request behind the gateway. Locally nothing did.
    • The fix: a global middleware now converts each request once, before anything else reads it.
  6. Metrics toolbar (fix(metrics)).
    • No reflow on load: the Step and Auto-refresh selects render their label on the server. Radix otherwise fills it in on hydration and the toolbar jumped.
    • Refresh corners: the button squares its own right corners, because datum-ui's Tooltip wrapper stops ButtonGroup from reaching it.
    • Alignment: filter multi-selects use datum-ui's MultiSelect so they line up with the other controls.
  7. Full-height pages (fix(layout)). SubLayout's content was h-full of the whole layout, title and tabs included, so logs ran past the bottom. It now takes the remaining space with flex-1.
  8. datum-ui 3.11.0 (chore(deps)). Brings in isFetching, filter groups open by default, and the picker clear button that no longer sits inside the trigger button.

Testing

  • npm run typecheck, eslint and the pre-commit hook pass.
  • The app/resources/o11y-logs, app/features/edge and app/server tests pass (403 tests). New tests cover:
    • building the count queries
    • when counts are shown
    • one host per row
    • reading the count response
    • native requests
  • Run locally against staging: sign-in works, and the ALB logs page showed the right counts per filter (GET 9, 200 9, one host with 9).

The compute plugin's logs get the same changes in datum-cloud/compute#634.

Node 26 throws "Illegal invocation" when undici copies @hono/node-server's
lightweight Request, which remix-auth does in login, reauth and the OAuth
callback. Production only worked because the forwarded-proto middleware
happens to rebuild every request behind the gateway; locally nothing did,
so sign-in 500ed. A global middleware now converts the request once, before
anything else reads it.
- Step and auto-refresh selects render their label on the server, so the
  toolbar no longer reflows when Radix fills it in on hydration.
- The refresh button squares its right corners itself: Tooltip's wrapper
  stops ButtonGroup from reaching it.
- Filter multi-selects use datum-ui's MultiSelect so they line up with the
  other toolbar controls.
The content wrapper was h-full of the whole sub layout, title and tabs
included, so full-height pages such as logs ran past the bottom by their
height. It now takes the remaining space with flex-1.
… window

- Time range, filters, search, live and the open row live in the query
  string, so a refresh or shared link reopens the same view. Refresh slides
  a preset window to now.
- Filter options come from label values for the whole window, so ticking
  one never hides the others, and each option shows how many lines match
  the other ticked filters (queryapi's sum by count_over_time).
- Host lists the host each row shows, not every host label on it, so a
  rewritten backend authority (e.g. httpbin.org) is no longer an option.
- Earlier rows and filters stay on screen while the next request runs, with
  datum-ui's isFetching state instead of skeletons.
@mattdjenkinson mattdjenkinson added the enhancement New feature or request label Nov 10, 2026
@mattdjenkinson mattdjenkinson self-assigned this Nov 10, 2026
@mattdjenkinson
mattdjenkinson requested a review from a team November 10, 2026 11:09
@github-actions

Copy link
Copy Markdown

🧪 Test Summary

Job Status
E2E Regression (0) ✅ success
E2E Regression (1) ✅ success
E2E Regression (2) ✅ success
E2E Regression (3) ✅ success
E2E Smoke ✅ success
Unit Tests ❌ failure
Vitest Unit Tests ✅ success

View workflow run

Need another run? Use Re-run failed jobs: one shard costs a few minutes, the whole workflow about 26.

The ALB explorer's component test expected the rewritten authority in the
Host filter and clicked Host open, which now collapses it since datum-ui
3.11 opens every group.
@github-actions

Copy link
Copy Markdown

🧪 Test Summary

Job Status
E2E Regression (0) ✅ success
E2E Regression (1) ✅ success
E2E Regression (2) ✅ success
E2E Regression (3) ✅ success
E2E Smoke ✅ success
Unit Tests ✅ success
Vitest Unit Tests ✅ success

View workflow run

Need another run? Use Re-run failed jobs: one shard costs a few minutes, the whole workflow about 26.

@mattdjenkinson
mattdjenkinson merged commit 0218bdc into main Nov 10, 2026
17 checks passed
@mattdjenkinson
mattdjenkinson deleted the feat/alb-logs-url-state branch November 10, 2026 12:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants