mirror of
https://github.com/hyperdxio/hyperdx
synced 2026-04-21 13:37:15 +00:00
fix: Show error on DBInfraPanel when correlated metric source is missing (#2049)
## Summary This PR adds an error message on the DB Infra Panel when the selected source is missing a correlated metric source. Previously, this case would have just resulted in an empty page, with no indication of what was wrong. ### Screenshots or video <img width="2038" height="367" alt="Screenshot 2026-04-03 at 8 28 22 AM" src="https://github.com/user-attachments/assets/4fde26c6-5ea8-4cf8-bdfa-9028ae48b15e" /> ### How to test locally or on Vercel This can be tested locally by creating a source that points to the demo dataset, without a correlated metric source (I suggest the demo dataset because it has K8s metrics). ### References - Linear Issue: - Related PRs:
This commit is contained in:
parent
d84237f98b
commit
df170d1e40
4 changed files with 102 additions and 1 deletions
5
.changeset/perfect-toys-draw.md
Normal file
5
.changeset/perfect-toys-draw.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@hyperdx/app": patch
|
||||
---
|
||||
|
||||
fix: Show error on DBInfraPanel when correlated metric source is missing
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import { useMemo, useState } from 'react';
|
||||
import Link from 'next/link';
|
||||
import { add, min, sub } from 'date-fns';
|
||||
import {
|
||||
convertDateRangeToGranularityString,
|
||||
|
|
@ -12,16 +13,23 @@ import {
|
|||
TSource,
|
||||
} from '@hyperdx/common-utils/dist/types';
|
||||
import {
|
||||
Alert,
|
||||
Anchor,
|
||||
Box,
|
||||
Card,
|
||||
Group,
|
||||
Modal,
|
||||
ScrollArea,
|
||||
SegmentedControl,
|
||||
SimpleGrid,
|
||||
Stack,
|
||||
Text,
|
||||
} from '@mantine/core';
|
||||
import { useDisclosure } from '@mantine/hooks';
|
||||
|
||||
import { convertV1ChartConfigToV2 } from '@/ChartUtils';
|
||||
import { TableSourceForm } from '@/components/Sources/SourceForm';
|
||||
import { IS_LOCAL_MODE } from '@/config';
|
||||
import { useSource } from '@/source';
|
||||
|
||||
import {
|
||||
|
|
@ -211,11 +219,14 @@ export default ({
|
|||
rowId: string | undefined | null;
|
||||
source: TSource;
|
||||
}) => {
|
||||
const [editModalOpened, { open: openEditModal, close: closeEditModal }] =
|
||||
useDisclosure(false);
|
||||
|
||||
const metricSourceId =
|
||||
isLogSource(source) || isTraceSource(source)
|
||||
? source.metricSourceId
|
||||
: undefined;
|
||||
const { data: metricSource } = useSource({
|
||||
const { data: metricSource, isLoading: isLoadingMetricSource } = useSource({
|
||||
id: metricSourceId,
|
||||
kinds: [SourceKind.Metric],
|
||||
});
|
||||
|
|
@ -227,6 +238,39 @@ export default ({
|
|||
|
||||
return (
|
||||
<Stack my="md" gap={40}>
|
||||
{!metricSource && !isLoadingMetricSource && (
|
||||
<>
|
||||
<Alert color="yellow" title="No correlated metric source">
|
||||
<Text size="sm">
|
||||
{metricSourceId
|
||||
? `The correlated metric source for "${source.name}" could not be found.`
|
||||
: `Source "${source.name}" does not have a correlated metric source.`}{' '}
|
||||
Infrastructure metrics can be displayed when a metric source is
|
||||
configured in{' '}
|
||||
{IS_LOCAL_MODE ? (
|
||||
<Anchor component="button" onClick={openEditModal}>
|
||||
Source Settings
|
||||
</Anchor>
|
||||
) : (
|
||||
<Anchor component={Link} href="/team">
|
||||
Team Settings
|
||||
</Anchor>
|
||||
)}
|
||||
.
|
||||
</Text>
|
||||
</Alert>
|
||||
{IS_LOCAL_MODE && (
|
||||
<Modal
|
||||
size="xl"
|
||||
opened={editModalOpened}
|
||||
onClose={closeEditModal}
|
||||
title="Edit Source"
|
||||
>
|
||||
<TableSourceForm sourceId={source.id} />
|
||||
</Modal>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{podUid && (
|
||||
<div>
|
||||
{metricSource && (
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
import { SearchPage } from '../page-objects/SearchPage';
|
||||
import { expect, test } from '../utils/base-test';
|
||||
|
||||
test.describe('Correlated Metric Source', { tag: ['@full-stack'] }, () => {
|
||||
let searchPage: SearchPage;
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
searchPage = new SearchPage(page);
|
||||
});
|
||||
|
||||
test('should show alert when no correlated metric source is configured', async ({
|
||||
page,
|
||||
}) => {
|
||||
// Navigate to search page
|
||||
await searchPage.goto();
|
||||
|
||||
// Select the source without metricSourceId
|
||||
await searchPage.selectSource('E2E K8s Logs No Metrics');
|
||||
|
||||
// Search for K8s events that have k8s.pod.uid resource attribute
|
||||
await searchPage.performSearch('ResourceAttributes.k8s.pod.uid:*');
|
||||
|
||||
// Click on first row to open side panel
|
||||
await searchPage.table.clickFirstRow();
|
||||
|
||||
// Click the Infrastructure tab
|
||||
await searchPage.sidePanel.clickTab('infrastructure');
|
||||
|
||||
// Assert the "No correlated metric source" alert is visible
|
||||
await expect(page.getByText('No correlated metric source')).toBeVisible();
|
||||
await expect(
|
||||
page.getByText('does not have a correlated metric source'),
|
||||
).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
|
@ -92,6 +92,23 @@
|
|||
"traceIdExpression": "TraceId",
|
||||
"spanIdExpression": "SpanId",
|
||||
"implicitColumnExpression": "Body"
|
||||
},
|
||||
{
|
||||
"id": "E2E K8s Logs No Metrics",
|
||||
"kind": "log",
|
||||
"name": "E2E K8s Logs No Metrics",
|
||||
"connection": "local",
|
||||
"from": { "databaseName": "default", "tableName": "e2e_otel_logs" },
|
||||
"timestampValueExpression": "TimestampTime",
|
||||
"defaultTableSelectExpression": "Timestamp, ServiceName, SeverityText, Body",
|
||||
"serviceNameExpression": "ServiceName",
|
||||
"severityTextExpression": "SeverityText",
|
||||
"eventAttributesExpression": "LogAttributes",
|
||||
"resourceAttributesExpression": "ResourceAttributes",
|
||||
"traceIdExpression": "TraceId",
|
||||
"spanIdExpression": "SpanId",
|
||||
"implicitColumnExpression": "Body",
|
||||
"displayedTimestampValueExpression": "Timestamp"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue