feat: introduce session table model form (#606)

<img width="699" alt="Screenshot 2025-02-11 at 10 24 35 AM" src="https://github.com/user-attachments/assets/8df05bf1-f542-4f50-ba56-f57b2e82e819" />
This commit is contained in:
Warren 2025-02-11 11:59:12 -08:00 committed by GitHub
parent 3fb3169f43
commit 459267a1f8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 114 additions and 5 deletions

View file

@ -0,0 +1,5 @@
---
"@hyperdx/app": patch
---
feat: introduce session table model form

View file

@ -32,6 +32,7 @@ import { useConnections } from './connection';
import { withAppNav } from './layout';
import { useSources } from './source';
import { useConfirm } from './useConfirm';
import { capitalizeFirstLetter } from './utils';
import styles from '../styles/TeamPage.module.scss';
@ -193,7 +194,7 @@ function SourcesSection() {
<div>
<Text>{s.name}</Text>
<Text size="xxs" c="dimmed">
{s.kind === 'log' ? 'Logs' : 'Metrics'}
{capitalizeFirstLetter(s.kind)}
{s.from && (
<>
{' '}

View file

@ -28,7 +28,7 @@ import { useDebouncedCallback } from '@mantine/hooks';
import { notifications } from '@mantine/notifications';
import { SourceSelectControlled } from '@/components/SourceSelect';
import { IS_SESSIONS_ENABLED } from '@/config';
import { IS_METRICS_ENABLED, IS_SESSIONS_ENABLED } from '@/config';
import { useConnections } from '@/connection';
import {
inferTableSourceConfig,
@ -537,6 +537,100 @@ export function TraceTableModelForm({
);
}
export function SessionTableModelForm({
control,
watch,
setValue,
}: {
control: Control<TSource>;
watch: UseFormWatch<TSource>;
setValue: UseFormSetValue<TSource>;
}) {
const databaseName = watch(`from.databaseName`, DEFAULT_DATABASE);
const tableName = watch(`from.tableName`);
const connectionId = watch(`connection`);
const [showOptionalFields, setShowOptionalFields] = useState(false);
return (
<>
<Stack gap="sm">
<FormRow label={'Server Connection'}>
<ConnectionSelectControlled control={control} name={`connection`} />
</FormRow>
<FormRow label={'Database'}>
<DatabaseSelectControlled
control={control}
name={`from.databaseName`}
connectionId={connectionId}
/>
</FormRow>
<FormRow label={'Table'}>
<DBTableSelectControlled
database={databaseName}
control={control}
name={`from.tableName`}
connectionId={connectionId}
rules={{ required: 'Table is required' }}
/>
</FormRow>
<FormRow
label={'Timestamp Column'}
helpText="DateTime column or expression that is part of your table's primary key."
>
<SQLInlineEditorControlled
database={databaseName}
table={tableName}
control={control}
name="timestampValueExpression"
disableKeywordAutocomplete
connectionId={connectionId}
/>
</FormRow>
<FormRow label={'Log Attributes Expression'}>
<SQLInlineEditorControlled
database={databaseName}
table={tableName}
control={control}
name="eventAttributesExpression"
placeholder="LogAttributes"
connectionId={connectionId}
/>
</FormRow>
<FormRow label={'Resource Attributes Expression'}>
<SQLInlineEditorControlled
database={databaseName}
table={tableName}
control={control}
name="resourceAttributesExpression"
placeholder="ResourceAttributes"
connectionId={connectionId}
/>
</FormRow>
<FormRow
label={'Correlated Trace Source'}
helpText="HyperDX Source for traces associated with sessions. Required"
>
<SourceSelectControlled control={control} name="traceSourceId" />
</FormRow>
<FormRow
label={'Implicit Column Expression'}
helpText="Column used for full text search if no property is specified in a Lucene-based search. Typically the message body of a log."
>
<SQLInlineEditorControlled
database={databaseName}
table={tableName}
control={control}
name="implicitColumnExpression"
placeholder="Body"
connectionId={connectionId}
/>
</FormRow>
</Stack>
</>
);
}
export function MetricTableModelForm({
control,
watch,
@ -746,7 +840,6 @@ function TableModelForm({
}) {
switch (kind) {
case SourceKind.Log:
case SourceKind.Session:
return (
<LogTableModelForm
control={control}
@ -762,6 +855,14 @@ function TableModelForm({
setValue={setValue}
/>
);
case SourceKind.Session:
return (
<SessionTableModelForm
control={control}
watch={watch}
setValue={setValue}
/>
);
case SourceKind.Metric:
return (
<MetricTableModelForm
@ -974,7 +1075,9 @@ export function TableSourceForm({
<Group>
<Radio value={SourceKind.Log} label="Log" />
<Radio value={SourceKind.Trace} label="Trace" />
<Radio value={SourceKind.Metric} label="Metric" />
{IS_METRICS_ENABLED && (
<Radio value={SourceKind.Metric} label="Metric" />
)}
{IS_SESSIONS_ENABLED && (
<Radio value={SourceKind.Session} label="Session" />
)}

View file

@ -26,6 +26,6 @@ export const IS_LOCAL_MODE = //true;
(process.env.NEXT_PUBLIC_IS_LOCAL_MODE ?? 'false') === 'true';
// Features in development
export const IS_METRICS_ENABLED = false || IS_DEV;
export const IS_MTVIEWS_ENABLED = false;
export const IS_SESSIONS_ENABLED = false || IS_DEV;