Skip to content

feat(app): show GPU metrics in log side panel infrastructure section - #2897

Draft
MikeShi42 wants to merge 6 commits into
mainfrom
cursor/gpu-metrics-infra-panel-5abf
Draft

feat(app): show GPU metrics in log side panel infrastructure section#2897
MikeShi42 wants to merge 6 commits into
mainfrom
cursor/gpu-metrics-infra-panel-5abf

Conversation

@MikeShi42

@MikeShi42 MikeShi42 commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds GPU utilization and GPU memory utilization charts to the Infrastructure tab of the log/span side panel, using the OpenTelemetry hardware semantic conventions (hw.gpu.*).

Design

GPU registers as a descriptor in infraCorrelations.ts alongside Pod and Node — no separate component. InfraChartSpec supports:

  • groupBy — per-chart SQL expressions for multi-GPU series labeling
  • where — per-chart Lucene filter (ANDed with the correlation WHERE)
  • metricType — a real MetricsDataType, defaulting to Gauge

InfraCorrelation gains requiresMetricAvailability. A single InfraCorrelationGroup component renders every group (Pod / Node / GPU) and owns its own wrapper, so a group with nothing to show renders no DOM at all rather than an empty flex child.

Charts

Chart Metric Filter
GPU utilization hw.gpu.utilization hw.gpu.task:"general" OR NOT hw.gpu.task:*
GPU memory utilization hw.gpu.memory.utilization

Correlated at node level via k8s.node.name. Series are labeled by concat(hw.id, hw.name, hw.model) so multi-GPU nodes show identifiable per-device lines.

Metric existence check

useAvailableMetricNames asks which of a given candidate list exist for the correlated resource. It queries only the candidate names rather than enumerating every distinct MetricName on the host — the metadata layer aggregates with groupUniqArray(limit) even when disableRowLimit is set, so an open-ended lookup can silently drop the name being looked for on a metric-heavy host and hide a chart that does have data. Bounding the universe to the candidates and sizing the limit to match makes truncation impossible, and replaces an unanchored ILIKE scan with exact equality. Cached 5 min.

Direct v2 chart configs

Infra charts no longer go through convertV1ChartConfigToV2. For metrics that layer was a lossy round trip: a 'name - Gauge' string split and re-parsed into an enum, a table: 'metrics' discriminator that only selects a branch, a seriesReturnType that is accepted and silently dropped, a groupBy array joined into a string via a startsWith('k8s') rewrite, and a valueExpression the renderer overwrites. buildChartConfig now emits BuilderChartConfigWithDateRange directly and calls getMetricNameSql itself, so the k8s cpu.utilizationcpu.usage rename still matches both names — pinned by a test.

Graceful degradation

  • Section fully hidden when no GPU metrics exist — no empty state, no layout gap
  • Partial availability renders only the charts with data
  • Non-GPU users see exactly what they saw before

Out of scope (follow-up)

The hw.gpu.memory.usage / hw.gpu.memory.limit fallback is deferred. It needs ratio-over-Sum support, which is broken in three independent places (seriesReturnType dropped for metrics in convertV1ChartConfigToV2; the second select silently discarded in renderChartConfig; counter-increase semantics applied to non-monotonic UpDownCounters). Tracked on HDX-5102.

Screenshots or video

N/A — GPU metrics require an OTel-semconv-compliant GPU collector; the preview demo has no GPU data, so the section stays hidden by design.

How to test on Vercel preview

N/A — no user-visible change without hw.gpu.* metrics.

References

Linear Issue: HDX-5102

Open in Web Open in Cursor 

Add GPU utilization and GPU memory utilization charts to the Infrastructure
tab of the log/span side panel, using OTel hardware semantic conventions
(hw.gpu.*).

- Add useGpuMetricsAvailability hook for cheap metric existence check
  (queries MetricName values from gauge table, cached 5 min)
- Add GpuInfraSection component with per-GPU series via hw.id groupBy
- Add getGpuCorrelationWhere to build resource correlation filter
  (prefers k8s.node.name, falls back to host.name)
- Section is fully hidden when no GPU metrics exist for the correlated
  resource; partial availability renders only available charts
- GPU utilization chart filters to hw.gpu.task:general (or unset) to
  avoid mixing encoder/decoder series

HDX-5102

Co-authored-by: Mike Shi <mike@hyperdx.io>
@changeset-bot

changeset-bot Bot commented Aug 12, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 6aa74d5

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@hyperdx/app Minor
@hyperdx/api Minor
@hyperdx/otel-collector Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Aug 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
hyperdx-oss Ready Ready Preview Aug 15, 2026 12:51pm
hyperdx-storybook Ready Ready Preview Aug 15, 2026 12:51pm

Request Review

@greptile-apps

greptile-apps Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR adds availability-gated GPU utilization charts to the log/span infrastructure panel while preserving the existing Pod and Node groups.

  • Adds GPU utilization and memory-utilization chart descriptors with per-device grouping.
  • Bounds metric discovery to the supported GPU metric names and sizes the distinct-value limit accordingly.
  • Hides unavailable charts and removes the entire GPU group when no supported metrics exist.
  • Replaces unsafe control-handler casts with narrowed union types.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
packages/app/src/components/DBInfraPanel.tsx Refactors infrastructure groups into a shared renderer and gates GPU charts using exact supported-metric availability.
packages/app/src/hooks/useAvailableMetricNames.ts Queries only candidate gauge metric names before bounded distinct-value aggregation, resolving the previously reported truncation and unsupported-metric cases.
packages/app/src/components/infraCorrelations.ts Adds the GPU correlation descriptor, chart filters, formatting, and per-device grouping configuration.
packages/app/src/components/tests/DBInfraPanel.buildChartConfig.test.ts Covers metric config construction, GPU filtering and grouping, source wiring, and renamed Kubernetes CPU metrics.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Row[Selected log or span] --> Node[k8s.node.name]
  Node --> Availability[Query supported GPU metric names]
  Availability -->|No supported names| Hidden[Render no GPU group]
  Availability -->|Utilization available| Util[GPU utilization chart]
  Availability -->|Memory utilization available| Memory[GPU memory utilization chart]
  Util --> Charts[DBTimeChart]
  Memory --> Charts
Loading

Reviews (6): Last reviewed commit: "refactor(app): build v2 chart configs di..." | Re-trigger Greptile

Comment thread packages/app/src/hooks/useGpuMetricsAvailability.ts Outdated
Comment thread packages/app/src/hooks/useGpuMetricsAvailability.ts Outdated
Comment thread packages/app/src/components/GpuInfraSection.tsx Outdated
Use specific type assertions instead of 'as any' to stay within the
max-warnings threshold. Fix import sort order in test file.

Co-authored-by: Mike Shi <mike@hyperdx.io>
@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

E2E Test Results

All tests passed • 282 passed • 1 skipped • 1069s

Status Count
✅ Passed 282
❌ Failed 0
⚠️ Flaky 0
⏭️ Skipped 1

Tests ran across 4 shards in parallel.

View full report →

Use the stable NOW constant from config instead of new Date() in the
GPU infra section's date range calculation, matching the project's
date hygiene rules.

Co-authored-by: Mike Shi <mike@hyperdx.io>
Structural:
- Extend InfraChartSpec with optional groupBy, where, metricType, and
  fallback fields so GPU registers as a descriptor rather than a
  separate component
- Delete GpuInfraSection.tsx; InfraSubpanelGroup now handles both k8s
  and GPU charts via the descriptor data
- Add requiresMetricAvailability flag to InfraCorrelation; gated groups
  only render when metric existence is confirmed
- Add AvailabilityGatedGroup wrapper that checks availability before
  rendering

Bug fixes:
- Fix _exists_ syntax (unsupported) → hw.gpu.task:* per query parser
- Push MetricName:hw.gpu.* prefix filter into the availability query
  so limit doesn't produce false negatives on metric-heavy nodes
- Check both gauge and sum tables for availability
- Drop host.name fallback (unreachable: tab requires k8s attributes)

Acceptance criteria:
- Series grouped by concat(hw.id, hw.name, hw.model) for richer labels
- hw.gpu.memory.usage / hw.gpu.memory.limit fallback via ratio chart
  when hw.gpu.memory.utilization isn't emitted
- resolveChartAvailability tested for primary, fallback, none, and
  partial cases

Minor:
- Use live new Date() (eslint-disable) matching sibling InfraSubpanelGroup
- Move GPU_UTILIZATION_NUMBER_FORMAT to ChartUtils for consistency
- Remove empty select comment (now annotated in the hook)

HDX-5102

Co-authored-by: Mike Shi <mike@hyperdx.io>
Remove the hw.gpu.memory.usage / hw.gpu.memory.limit fallback:
convertV1ChartConfigToV2 drops seriesReturnType for metrics, the
renderer discards the second series, and Sum uses counter-increase
semantics on a non-monotonic UpDownCounter. All three failures are in
the renderer and out of scope for this PR.

Changes:
- Remove InfraChartFallback type and fallback field from InfraChartSpec
- Simplify resolveChartAvailability to return boolean (available / not)
- Remove sum-table query from useGpuMetricsAvailability (halves cost)
- Simplify buildChartConfig (no mode parameter)
- Fix 40px empty-div gap: return null from the correlation map entry
  when both metricsGroup and timeline render nothing, so no empty flex
  child is emitted into Stack

Follow-up: HDX-5102 — support ratio charts over Sum metrics for GPU
memory fallback (requires changes to convertV1ChartConfigToV2,
renderChartConfig metric select handling, and Sum aggFn projection).

HDX-5102

Co-authored-by: Mike Shi <mike@hyperdx.io>
Comment thread packages/app/src/hooks/useGpuMetricsAvailability.ts Outdated
Greptile findings:
- Metric-name cap could hide GPU charts. useGetKeyValues aggregates with
  groupUniqArray(limit) even when disableRowLimit is set, so an open-ended
  MetricName lookup can drop the name being looked for on a metric-heavy
  host. Now the query asks only about the candidate metric names (derived
  from the chart specs) and sizes the limit to match, so truncation is
  impossible. This also replaces the unanchored MetricName:hw.gpu.* ILIKE
  scan with exact equality.
- hasAny was true for any hw.gpu.* metric, so a host emitting only
  hw.gpu.io could render GPU controls over an empty grid. Asking only
  about chartable metrics removes the failure mode structurally; the
  separate hasAny flag is gone.

Drop convertV1ChartConfigToV2 for infra charts and build the v2
BuilderChartConfig directly. The v1 layer was a lossy round trip for
metrics: 'name - Gauge' string-split and re-parsed into an enum, a
table:'metrics' discriminator that only picks a branch, a
seriesReturnType that is silently dropped, a groupBy array joined to a
string via a startsWith('k8s') rewrite, and a valueExpression the
renderer overwrites. getMetricNameSql is now called directly so the k8s
cpu.utilization -> cpu.usage rename still matches both names; a test
pins that.

Also:
- Collapse AvailabilityGatedGroup and InfraSubpanelGroup into one
  InfraCorrelationGroup that owns its wrapper, so a group with nothing
  to show renders no DOM. The previous fix was ineffective: a React
  element is always truthy, so the empty-wrapper check never fired and
  the 40px Stack gap remained.
- Gate the availability loading state to gated groups only, so Pod/Node
  are not held back by a query they do not run.
- Preserve the pre-existing behavior of dropping a group whose correlate
  attribute is present but empty.
- Rename useGpuMetricsAvailability to useAvailableMetricNames; nothing
  in it is GPU-specific.
- Add DBInfraPanel.buildChartConfig tests asserting the produced config
  rather than an intermediate decision.

HDX-5102

Co-authored-by: Mike Shi <mike@hyperdx.io>
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.

2 participants