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(),