diff --git a/package.json b/package.json index 19f72ffc..08c6645b 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,7 @@ "app:dev": "npx concurrently -k -n 'API,APP,ALERTS-TASK,COMMON-UTILS' -c 'green.bold,blue.bold,yellow.bold,magenta' 'nx run @hyperdx/api:dev' 'nx run @hyperdx/app:dev' 'nx run @hyperdx/api:dev-task check-alerts' 'nx run @hyperdx/common-utils:dev'", "app:lint": "nx run @hyperdx/app:ci:lint", "dev": "docker compose -f docker-compose.dev.yml up -d && yarn app:dev && docker compose -f docker-compose.dev.yml down", + "dev:down": "docker compose -f docker-compose.dev.yml down", "lint": "npx nx run-many -t ci:lint", "version": "make version", "release": "npx nx run-many --target=build --projects=@hyperdx/common-utils && npx changeset tag && npx changeset publish" diff --git a/packages/app/src/AppNav.tsx b/packages/app/src/AppNav.tsx index f828a4ad..1e06c79a 100644 --- a/packages/app/src/AppNav.tsx +++ b/packages/app/src/AppNav.tsx @@ -779,7 +779,7 @@ export default function AppNav({ fixed = false }: { fixed?: boolean }) { pathname.startsWith('/clickhouse'), })} > - Clickhouse + ClickHouse - {isRegister ? 'Register' : 'Login'} + {config.IS_OSS && isRegister + ? 'Create' + : isRegister + ? 'Register' + : 'Login'} diff --git a/packages/app/src/TeamPage.tsx b/packages/app/src/TeamPage.tsx index f704e57a..75daf09a 100644 --- a/packages/app/src/TeamPage.tsx +++ b/packages/app/src/TeamPage.tsx @@ -12,7 +12,7 @@ import { SubmitHandler, useForm } from 'react-hook-form'; import { json, jsonParseLinter } from '@codemirror/lang-json'; import { linter } from '@codemirror/lint'; import { EditorView, ViewUpdate } from '@codemirror/view'; -import { WebhookService } from '@hyperdx/common-utils/dist/types'; +import { SourceKind, WebhookService } from '@hyperdx/common-utils/dist/types'; import { Alert, Badge, @@ -198,6 +198,7 @@ function ConnectionsSection() { } function SourcesSection() { + const { data: connections } = useConnections(); const { data: sources } = useSources(); const [editedSourceId, setEditedSourceId] = useState(null); @@ -216,13 +217,22 @@ function SourcesSection() {
{s.name} - + {capitalizeFirstLetter(s.kind)} + + + {connections?.find(c => c.id === s.connection)?.name} + {s.from && ( <> - {' '} - · - {s.from.databaseName}.{s.from.tableName} + + {s.from.databaseName} + { + s.kind === SourceKind.Metric + ? '' + : '.' /** Metrics dont have table names */ + } + {s.from.tableName} )} diff --git a/packages/app/src/components/DBRowOverviewPanel.tsx b/packages/app/src/components/DBRowOverviewPanel.tsx index cf28c788..c3df89c2 100644 --- a/packages/app/src/components/DBRowOverviewPanel.tsx +++ b/packages/app/src/components/DBRowOverviewPanel.tsx @@ -1,5 +1,6 @@ import { useCallback, useContext, useMemo } from 'react'; -import { isString, pickBy } from 'lodash'; +import isString from 'lodash/isString'; +import pickBy from 'lodash/pickBy'; import { SourceKind, TSource } from '@hyperdx/common-utils/dist/types'; import { Accordion, Box, Divider, Flex, Text } from '@mantine/core'; @@ -37,6 +38,32 @@ export function RowOverviewPanel({ return firstRow; }, [data]); + // TODO: Use source config to select these in SQL, but we'll just + // assume OTel column names for now + const topLevelAttributeKeys = [ + 'ServiceName', + 'SpanName', + 'Duration', + 'SeverityText', + 'StatusCode', + 'StatusMessage', + 'SpanKind', + 'TraceId', + 'SpanId', + 'ParentSpanId', + 'ScopeName', + 'ScopeVersion', + ]; + const topLevelAttributes = pickBy(firstRow, (value, key) => { + if (value === '') { + return false; + } + if (topLevelAttributeKeys.includes(key)) { + return true; + } + return false; + }); + const resourceAttributes = firstRow?.__hdx_resource_attributes ?? EMPTY_OBJ; const eventAttributes = firstRow?.__hdx_event_attributes ?? EMPTY_OBJ; const dataAttributes = @@ -138,6 +165,7 @@ export function RowOverviewPanel({ 'network', 'resourceAttributes', 'eventAttributes', + 'topLevelAttributes', ]} multiple > @@ -181,6 +209,21 @@ export function RowOverviewPanel({ )} + {Object.keys(topLevelAttributes).length > 0 && ( + + + + Top Level Attributes + + + + + + + + + )} + diff --git a/packages/app/src/components/DBTracePanel.tsx b/packages/app/src/components/DBTracePanel.tsx index deb2389c..d7485f7f 100644 --- a/packages/app/src/components/DBTracePanel.tsx +++ b/packages/app/src/components/DBTracePanel.tsx @@ -35,8 +35,8 @@ export default function DBTracePanel({ focusDate, parentSourceId, }: { - parentSourceId?: string; - childSourceId?: string; + parentSourceId?: string | null; + childSourceId?: string | null; traceId: string; dateRange: [Date, Date]; focusDate: Date; diff --git a/packages/app/src/source.ts b/packages/app/src/source.ts index 3882d6ef..a79cadd3 100644 --- a/packages/app/src/source.ts +++ b/packages/app/src/source.ts @@ -268,7 +268,7 @@ export async function inferTableSourceConfig({ ...(isOtelLogSchema ? { defaultTableSelectExpression: - 'Timestamp, ServiceName, SeverityText, Body', + 'Timestamp, ServiceName as service, SeverityText as level, Body', serviceNameExpression: 'ServiceName', bodyExpression: 'Body', @@ -288,7 +288,7 @@ export async function inferTableSourceConfig({ implicitColumnExpression: 'SpanName', bodyExpression: 'SpanName', defaultTableSelectExpression: - 'Timestamp, ServiceName, StatusCode, round(Duration / 1e6), SpanName', + 'Timestamp, ServiceName as service, StatusCode as level, round(Duration / 1e6) as duration, SpanName', eventAttributesExpression: 'SpanAttributes', serviceNameExpression: 'ServiceName', resourceAttributesExpression: 'ResourceAttributes', diff --git a/packages/common-utils/src/types.ts b/packages/common-utils/src/types.ts index a75d265a..509bb380 100644 --- a/packages/common-utils/src/types.ts +++ b/packages/common-utils/src/types.ts @@ -516,7 +516,7 @@ export const SourceSchema = z.object({ spanKindExpression: z.string().optional(), statusCodeExpression: z.string().optional(), statusMessageExpression: z.string().optional(), - logSourceId: z.string().optional(), + logSourceId: z.string().optional().nullable(), // OTEL Metrics metricTables: MetricTableSchema.optional(),