Skip to content

feat: add "View logs" menu item to customer, team, and virtual key tables - #4073

Merged
akshaydeo merged 2 commits into
devfrom
06-05-feat_allow_viewing_filtered_logs_for_governance_entities
Jun 5, 2026
Merged

feat: add "View logs" menu item to customer, team, and virtual key tables#4073
akshaydeo merged 2 commits into
devfrom
06-05-feat_allow_viewing_filtered_logs_for_governance_entities

Conversation

@impoiler

@impoiler impoiler commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a "View logs" action to the dropdown menus in the Customers, Teams, and Virtual Keys tables. This allows users to quickly navigate to the logs page pre-filtered by the selected customer, team, or virtual key without having to manually configure filters.

Changes

  • Added a "View logs" DropdownMenuItem to the CustomerActionsMenu that links to /workspace/logs with customer_ids pre-populated as a search param
  • Added a "View logs" DropdownMenuItem to the TeamActionsMenu that links to /workspace/logs with team_ids pre-populated as a search param
  • Added a "View logs" DropdownMenuItem to the VKActionsMenu that links to /workspace/logs with virtual_key_ids pre-populated as a search param
  • Used Link from @tanstack/react-router rendered via asChild to ensure proper client-side navigation while maintaining dropdown item styling
  • Added ScrollText icon from lucide-react to visually distinguish the new action

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Documentation
  • Chore/CI

Affected areas

  • Core (Go)
  • Transports (HTTP)
  • Providers/Integrations
  • Plugins
  • UI (React)
  • Docs

How to test

  1. Navigate to the Customers, Teams, or Virtual Keys table in the workspace
  2. Open the actions dropdown (...) for any row
  3. Click "View logs"
  4. Verify you are redirected to /workspace/logs with the appropriate filter (customer_ids, team_ids, or virtual_key_ids) pre-applied for the selected entity
cd ui
pnpm i || npm i
pnpm build || npm run build

Screenshots/Recordings

Add before/after screenshots showing the new "View logs" option in the dropdown menus.

Breaking changes

  • Yes
  • No

Related issues

Security considerations

None. This change only adds navigation links using existing route and search param patterns. No new data is exposed.

Checklist

  • I read docs/contributing/README.md and followed the guidelines
  • I added/updated tests where appropriate
  • I updated documentation where needed
  • I verified builds succeed (Go and UI)
  • I verified the CI pipeline passes locally if applicable

Summary by CodeRabbit

  • New Features

    • Added "View logs" quick-access action to customer, team, and virtual key management tables. Users can navigate directly to activity logs with relevant filters pre-populated from the selected entity, streamlining audit trail access and investigations.
  • Chores

    • Improved URL query/search handling to make filter and search parameter serialization more consistent when navigating and sharing links.

@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2ccd6703-8791-40a8-a57d-e8207f9c13cd

📥 Commits

Reviewing files that changed from the base of the PR and between e9ef1b2 and 390d19e.

📒 Files selected for processing (4)
  • ui/app/main.tsx
  • ui/app/workspace/governance/views/customerTable.tsx
  • ui/app/workspace/governance/views/teamsTable.tsx
  • ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx

📝 Walkthrough

Walkthrough

Router adds a custom stringifySearch that serializes arrays as comma-separated values; customer, team, and virtual-key action menus add "View logs" links to /workspace/logs that pass the selected entity IDs as search params and close the dropdown on click.

Changes

Logs Navigation and Query Serialization

Layer / File(s) Summary
Router search serialization for array query params
ui/app/main.tsx
Adds stringifySearchValue and configures stringifySearch: stringifySearchWith(stringifySearchValue) alongside parseSearch: parseSearchWith(safeJsonParse) to serialize arrays as CSV and other values appropriately.
View logs dropdown items in customer, team, and virtual key tables
ui/app/workspace/governance/views/customerTable.tsx, ui/app/workspace/governance/views/teamsTable.tsx, ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
Each table's actions menu gains a DropdownMenuItem rendering a routed Link to /workspace/logs with customer_ids, team_ids, or virtual_key_ids in the search params; imports updated to include Link and the ScrollText icon; clicks stop propagation and close the dropdown.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • maximhq/bifrost#3487: Related refactor that introduced the per-row action dropdowns used by the current "View logs" additions.
  • maximhq/bifrost#3650: Related work on URL-driven multi-value log/dashboard filters and query-state parsing/serialization.
  • maximhq/bifrost#3602: Related edits to the virtual-keys row actions dropdown behavior; touches the same component this PR extends.

Suggested reviewers

  • akshaydeo
  • danpiths

Poem

🐰 I hopped through routes with a little twitch,
Turning arrays to CSV without a hitch.
Customers, teams, keys—logs now in sight,
One click, one link, and the filters take flight.
CSV carrots crunch—navigation delight! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main feature: adding a 'View logs' menu item to three tables, which matches the actual changes across customerTable, teamsTable, and virtualKeysTable components.
Description check ✅ Passed The description comprehensively covers the PR objectives, changes across all three components, design approach, testing steps, and security considerations, closely following the template structure.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 06-05-feat_allow_viewing_filtered_logs_for_governance_entities

Comment @coderabbitai help to get the list of available commands and usage tips.

impoiler commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

@impoiler
impoiler force-pushed the 06-05-feat_allow_viewing_filtered_logs_for_governance_entities branch from debe6b1 to e9ef1b2 Compare June 5, 2026 07:25
@roroghost17
roroghost17 marked this pull request as ready for review June 5, 2026 09:50
@greptile-apps

greptile-apps Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

Safe to merge; all three new View logs links pass array-typed IDs correctly and the global stringify change is consistent with how nuqs reads params elsewhere in the codebase.

The serialization logic is correct: arrays become comma-joined strings that nuqs parseAsArrayOf(parseAsString) can read, while numbers, booleans, and plain strings are unchanged from the router perspective. The same [id] array pattern already existed in logDetailView.tsx, so no new contract is introduced. No auth, data, or critical path is touched.

No files require special attention.

Important Files Changed

Filename Overview
ui/app/main.tsx Adds a custom stringifySearchValue function and wires it into the router stringifySearch; correctly handles primitive strings, numbers, booleans (raw), arrays (comma-joined), and objects (JSON).
ui/app/workspace/governance/views/customerTable.tsx Adds View logs DropdownMenuItem using asChild + Link with customer_ids: [customer.id] array. Consistent with the approach used in logDetailView.tsx.
ui/app/workspace/governance/views/teamsTable.tsx Adds View logs DropdownMenuItem with team_ids: [team.id] array. Correct param shape.
ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx Adds View logs DropdownMenuItem with virtual_key_ids: [vk.id] array. Correct param shape.

Reviews (4): Last reviewed commit: "feat: allow viewing filtered logs for Go..." | Re-trigger Greptile

Comment thread ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx Outdated
Comment thread ui/app/main.tsx
Comment thread ui/app/workspace/governance/views/customerTable.tsx
Comment thread ui/app/workspace/governance/views/teamsTable.tsx Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ui/app/main.tsx`:
- Around line 26-31: The current stringifySearchValue uses JSON.stringify which
wraps primitive strings in quotes; change it so primitives are not quoted: in
stringifySearchValue, keep the Array.isArray branch, and for non-arrays return
String(value) for primitives (and handle null/undefined), but if value is a
non-null object keep JSON.stringify(value) so complex values remain
JSON-encoded; update the function stringifySearchValue accordingly to avoid
producing quoted string query params.

In `@ui/app/workspace/governance/views/customerTable.tsx`:
- Around line 82-95: The search prop passed to the Link in the DropdownMenuItem
uses search={{ customer_ids: customer.id }} but the logs route declares
customer_ids as an array; change this to pass an array (e.g., search={{
customer_ids: [customer.id] }}) so the contract matches. Update the Link where
to="/workspace/logs" and keep the existing onClick/onPointerDown handlers and
setIsOpen(false) behavior intact.

In `@ui/app/workspace/governance/views/teamsTable.tsx`:
- Around line 83-88: The Link currently passes team_ids as a single value;
change it to pass an array to match the downstream contract by wrapping the ID
in an array (e.g., pass search={{ team_ids: [team.id] }}). Update the Link
inside DropdownMenuItem (the element using team.name, team.id and calling
setIsOpen on click) so the logs page receives team_ids as an array of strings.

In `@ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx`:
- Around line 220-229: The Link inside DropdownMenuItem currently passes
search={{ virtual_key_ids: vk.id }} but the logs route expects virtual_key_ids
to be an array; update the Link to pass the id wrapped in an array (e.g.,
virtual_key_ids: [vk.id]) so the contract (parseAsArrayOf(parseAsString)) is
satisfied—locate the Link within virtualKeysTable.tsx (the DropdownMenuItem /
Link block referencing vk.id) and change the search prop accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5278b6f9-edb6-4cec-96a7-8df4bfffcf32

📥 Commits

Reviewing files that changed from the base of the PR and between 46aada1 and e9ef1b2.

📒 Files selected for processing (4)
  • ui/app/main.tsx
  • ui/app/workspace/governance/views/customerTable.tsx
  • ui/app/workspace/governance/views/teamsTable.tsx
  • ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx

Comment thread ui/app/main.tsx
Comment thread ui/app/workspace/governance/views/customerTable.tsx
Comment thread ui/app/workspace/governance/views/teamsTable.tsx
Comment thread ui/app/workspace/virtual-keys/views/virtualKeysTable.tsx
@impoiler impoiler self-assigned this Jun 5, 2026
@impoiler
impoiler force-pushed the 06-05-feat_allow_viewing_filtered_logs_for_governance_entities branch from e9ef1b2 to 5138e35 Compare June 5, 2026 12:51
@impoiler
impoiler force-pushed the 06-04-chore_uniform_view_of_budget_and_limits_for_virtual_keys_table branch from 46aada1 to de5a5c7 Compare June 5, 2026 13:48
@impoiler
impoiler force-pushed the 06-05-feat_allow_viewing_filtered_logs_for_governance_entities branch from 5138e35 to 97fbee9 Compare June 5, 2026 13:48
@impoiler
impoiler force-pushed the 06-04-chore_uniform_view_of_budget_and_limits_for_virtual_keys_table branch from de5a5c7 to 7084c24 Compare June 5, 2026 13:51
@impoiler
impoiler force-pushed the 06-05-feat_allow_viewing_filtered_logs_for_governance_entities branch from 97fbee9 to 5c1a600 Compare June 5, 2026 13:51
@CLAassistant

CLAassistant commented Jun 5, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@impoiler
impoiler force-pushed the 06-04-chore_uniform_view_of_budget_and_limits_for_virtual_keys_table branch from 7084c24 to 880609d Compare June 5, 2026 13:53
@impoiler
impoiler force-pushed the 06-05-feat_allow_viewing_filtered_logs_for_governance_entities branch from 5c1a600 to 186956b Compare June 5, 2026 13:53

akshaydeo commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Merge activity

  • Jun 5, 2:00 PM UTC: A user started a stack merge that includes this pull request via Graphite.
  • Jun 5, 2:17 PM UTC: Graphite rebased this pull request as part of a merge.
  • Jun 5, 2:18 PM UTC: @akshaydeo merged this pull request with Graphite.

@akshaydeo
akshaydeo changed the base branch from 06-04-chore_uniform_view_of_budget_and_limits_for_virtual_keys_table to graphite-base/4073 June 5, 2026 14:15
@akshaydeo
akshaydeo changed the base branch from graphite-base/4073 to dev June 5, 2026 14:15
@akshaydeo
akshaydeo force-pushed the 06-05-feat_allow_viewing_filtered_logs_for_governance_entities branch from 186956b to 390d19e Compare June 5, 2026 14:16
@akshaydeo
akshaydeo merged commit 8ec9355 into dev Jun 5, 2026
13 of 15 checks passed
@akshaydeo
akshaydeo deleted the 06-05-feat_allow_viewing_filtered_logs_for_governance_entities branch June 5, 2026 14:18
@akshaydeo akshaydeo mentioned this pull request Jun 7, 2026
akshaydeo pushed a commit that referenced this pull request Jun 7, 2026
…bles (#4073)

## Summary

Adds a "View logs" action to the dropdown menus in the Customers, Teams, and Virtual Keys tables. This allows users to quickly navigate to the logs page pre-filtered by the selected customer, team, or virtual key without having to manually configure filters.

## Changes

- Added a "View logs" `DropdownMenuItem` to the `CustomerActionsMenu` that links to `/workspace/logs` with `customer_ids` pre-populated as a search param
- Added a "View logs" `DropdownMenuItem` to the `TeamActionsMenu` that links to `/workspace/logs` with `team_ids` pre-populated as a search param
- Added a "View logs" `DropdownMenuItem` to the `VKActionsMenu` that links to `/workspace/logs` with `virtual_key_ids` pre-populated as a search param
- Used `Link` from `@tanstack/react-router` rendered via `asChild` to ensure proper client-side navigation while maintaining dropdown item styling
- Added `ScrollText` icon from `lucide-react` to visually distinguish the new action

## Type of change

- [ ] Bug fix
- [x] Feature
- [ ] Refactor
- [ ] Documentation
- [ ] Chore/CI

## Affected areas

- [ ] Core (Go)
- [ ] Transports (HTTP)
- [ ] Providers/Integrations
- [ ] Plugins
- [x] UI (React)
- [ ] Docs

## How to test

1. Navigate to the Customers, Teams, or Virtual Keys table in the workspace
2. Open the actions dropdown (`...`) for any row
3. Click "View logs"
4. Verify you are redirected to `/workspace/logs` with the appropriate filter (`customer_ids`, `team_ids`, or `virtual_key_ids`) pre-applied for the selected entity

```sh
cd ui
pnpm i || npm i
pnpm build || npm run build
```

## Screenshots/Recordings

_Add before/after screenshots showing the new "View logs" option in the dropdown menus._

## Breaking changes

- [ ] Yes
- [x] No

## Related issues

## Security considerations

None. This change only adds navigation links using existing route and search param patterns. No new data is exposed.

## Checklist

- [ ] I read `docs/contributing/README.md` and followed the guidelines
- [ ] I added/updated tests where appropriate
- [ ] I updated documentation where needed
- [ ] I verified builds succeed (Go and UI)
- [ ] I verified the CI pipeline passes locally if applicable

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

* **New Features**
  * Added "View logs" quick-access action to customer, team, and virtual key management tables. Users can navigate directly to activity logs with relevant filters pre-populated from the selected entity, streamlining audit trail access and investigations.

* **Chores**
  * Improved URL query/search handling to make filter and search parameter serialization more consistent when navigating and sharing links.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
akshaydeo added a commit that referenced this pull request Jun 7, 2026
## ✨ Features

- **OpenAI Compaction** — Added OpenAI conversation compaction support
across core, framework, logging, and the API surface (#4053)
- **Multi-Customer & Org Hierarchy** — Logs and usage tracking now
support multiple customers, teams, and business units, including
business unit CRUD, team assignment, and governance endpoints in the
OpenAPI spec (#4066, #4041, #4082)
- **Provider-Level Governance** — Budgets & limits are now scope-aware
and can be applied at the virtual-key top level and per provider, wired
from the model configs table, with UI filters for scope and providers
(#3938, #3937, #3939, #3981, #3962)
- **Customer Budgets** — Customers support multiple budgets and
`calendar_aligned` budget windows (#3998, #3997)
- **Virtual Key Attribution & Controls** — Added a `created_by` user
attribution column and a `blacklisted_models` column for virtual key
provider configs (#3672, #3653)
- **Request Header Capture** — OTel and Maxim observability plugins
capture `request_headers` by pattern, with wildcard support (e.g.
`x-custom-*`); logging gained the same wildcard header capture (#4012,
#3958)
- **OTel Content Controls & Collectors** — New `disable_content_logging`
option drops message/tool content from exported spans, plus support for
multiple OTel collectors (#4064, #3894)
- **xAI x_search** — Added xAI `x_search` tool support (#3976)
- **URL Validation** — Added fetch URL validation with private-network
configuration and link-local blocking (#3947, #3991)
- **File Scheme Pricing URLs** — Pricing source URLs now accept the
`file://` scheme for air-gapped and self-hosted deployments (#4045)
- **Paginated Virtual Keys** — Virtual key fetching is paginated to
handle deployments with very large numbers of keys (#3957)
- **Client IP Resolution** — Resolve client IP from
`X-Forwarded-For`/`X-Real-IP` headers
- **SCIM Provisioning** — Added `attributeType`/`attributeValue` SCIM
provisioning fields
- **Helm/Config Schema** — Added `roles` RBAC governance config and
`per_user_oauth` MCP auth to the Helm chart and config schema (#4004,
#4009)
- **Log Navigation UI** — Added a "View logs" menu item to customer,
team, and virtual key tables, clickable links in log detail views, a
customer detail sheet, and a reusable `BudgetDisplay` component (#4073,
#4054, #4026, #4055)
- **Faster First Paint** — Added an inline loading shell to `#root`
before React mounts (#4063)
- **Materialized View Alias** — Added an `alias` column to the
materialized view with filter support (#4078)

## 🐞 Fixed

- **Fetch URL IP Checks** — Hardened fetch URL IP checks against SSRF
(#4092)
- **Mantle Model Matching** — Broadened Mantle model matching to all
`gpt` variants (#4091)
- **Empty Thinking Blocks** — Strip thinking blocks when the signature
is empty (#4079)
- **OpenAI Stream Usage** — Removed usage from the `responses.created`
event in the OpenAI stream (#4080)
- **Prompt Cache Key** — Set the prompt cache key from the Anthropic
integration (#4086)
- **Upstream Failure Status** — Map upstream connection failures to 502
instead of 400 (#3929) (thanks
[@chris-colinsky](https://github.com/chris-colinsky)!)
- **Gemini Schema Constraints** — Accept numeric schema integer
constraints for Gemini (#3994) (thanks
[@yanhao98](https://github.com/yanhao98)!)
- **Files Provider Param** — Accept the `?provider=` query param on `GET
/v1/files` (#3971) (thanks [@alexef](https://github.com/alexef)!)
- **Optional Batch Model** — Made the `model` field optional on `POST
/v1/batches` (#3973) (thanks [@alexef](https://github.com/alexef)!)
- **Helm Azure Config** — Added missing `azure_key_config` fields to the
Helm schema (#3996) (thanks
[@axelray-dev](https://github.com/axelray-dev)!)
- **Text Completion Chunk Model** — Added the missing `Model` field to
`TextCompletionChunkResponse` (#3970) (thanks
[@kuishou68](https://github.com/kuishou68)!)
- **MCP Inline stdio Env** — MCP stdio server configs accept inline
environment variable assignments (#3861) (thanks
[@Shushmitaaaa](https://github.com/Shushmitaaaa)!)
- **Orphaned Tool Results** — Orphaned tool results in the OpenAI to
Anthropic conversion flow are no longer rejected by the Anthropic API
(#3919)
- **Node Usage Reconciliation** — Added a monotonic `inc_number` log
cursor so node usage reconciliation does not skip late async log writes
(#3664)
- **Bedrock Output Assessments** — Corrected the type of
`outputAssessments` in Bedrock responses (#4028)
- **Model Pool Pricing Reloads** — Preserve non-pricing model pool
entries across pricing reloads (#3999)
- **Ghost Node Reconciliation** — Replicate the VK hierarchy flow for
ghost node reconciliation (#4088)
- **VK Double Usage Counting** — Fixed double usage counting when
creating a virtual key (#4070)
- **Model Config Lifecycle** — Cascade deletes for model configs and
removal of stale in-memory model configs (#4051, #4043)
- **FTS Index Cap** — Reduced the FTS index `left()` cap from 800k to
250k chars to stay within the tsvector limit (#4057)
- **Sync Worker Drift** — Reduced the sync worker ticker period to 5m to
prevent threshold drift (#4023)
- **Passthrough** — Fixed passthrough budgets, gated passthrough models
per VK, model extraction for Azure passthrough, and restricted
fallbacks/provider selection to the VK boundary (#3941, #3988, #3983,
#3924)
- **Provider Response Headers** — Strip provider response headers and
add a content-type filter (#3955, #4024)
- **Stream Handling** — Drain non-SSE stream readers and retry stale
connections (#3956, #3967)
- **Azure Claude** — Strip Azure diagnostic property for Claude models
(#3925)
- **Compat max_tokens** — Preserve chat `max_tokens` during param
filtering (#3992)
- **Raw Request Flag** — Removed the raw request flag from providers
that don't support it (#4058)
- **UI Fixes** — Standardized page container layout, virtual key model
configs UI, and dashboard chart tooltips (#4046, #4052, #4044)

## 🔧 Maintenance

- **Dependency Upgrades** — Bumped transitive `golang.org/x`
dependencies (crypto, net, sys, text) for Docker Scout CVE remediation
and `recharts` to 3.8.1; cascaded version bumps across all modules
(#3900, #4003)
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.

4 participants