Compare commits

...

1 Commits

Author SHA1 Message Date
Cursor Agent
61d346f48e poc(ai-o11y): QuerySearch queryType + builder_ai_query serialization
Add optional queryType on QuerySearch (threaded through QueryBuilderV2)
so key/value suggestions send type=builder_ai_query. Extend ListViewOrderBy
with fieldContext + queryType. Serialize source:'ai' as builder_ai_query
in query-range. Demoed on Traces Explorer search bar and List order-by.

Co-authored-by: Gaurav Tewari <gauravtewari111@gmail.com>
2026-08-04 09:51:33 +00:00
15 changed files with 87 additions and 16 deletions

View File

@@ -23,6 +23,7 @@ export const getKeySuggestions = (
fieldDataType = '',
signalSource = '',
metricNamespace = '',
type = '',
} = props;
const encodedSignal = encodeURIComponent(signal);
@@ -32,8 +33,9 @@ export const getKeySuggestions = (
const encodedFieldDataType = encodeURIComponent(fieldDataType);
const encodedSource = encodeURIComponent(signalSource);
const encodedMetricNamespace = encodeURIComponent(metricNamespace);
const typeParam = type ? `&type=${encodeURIComponent(type)}` : '';
return axios.get(
`/fields/keys?signal=${encodedSignal}&searchText=${encodedSearchText}&metricName=${encodedMetricName}&fieldContext=${encodedFieldContext}&fieldDataType=${encodedFieldDataType}&source=${encodedSource}&metricNamespace=${encodedMetricNamespace}`,
`/fields/keys?signal=${encodedSignal}&searchText=${encodedSearchText}&metricName=${encodedMetricName}&fieldContext=${encodedFieldContext}&fieldDataType=${encodedFieldDataType}&source=${encodedSource}&metricNamespace=${encodedMetricNamespace}${typeParam}`,
);
};

View File

@@ -15,15 +15,16 @@ import {
export const getValueSuggestions = (
props: QueryKeyValueRequestProps,
): Promise<AxiosResponse<QueryKeyValueSuggestionsResponseProps>> => {
const { signal, key, searchText, signalSource, metricName } = props;
const { signal, key, searchText, signalSource, metricName, type } = props;
const encodedSignal = encodeURIComponent(signal);
const encodedKey = encodeURIComponent(key);
const encodedMetricName = encodeURIComponent(metricName || '');
const encodedSearchText = encodeURIComponent(searchText);
const encodedSource = encodeURIComponent(signalSource || '');
const typeParam = type ? `&type=${encodeURIComponent(type)}` : '';
return axios.get(
`/fields/values?signal=${encodedSignal}&name=${encodedKey}&searchText=${encodedSearchText}&metricName=${encodedMetricName}&source=${encodedSource}`,
`/fields/values?signal=${encodedSignal}&name=${encodedKey}&searchText=${encodedSearchText}&metricName=${encodedMetricName}&source=${encodedSource}${typeParam}`,
);
};

View File

@@ -364,7 +364,9 @@ export function convertBuilderQueriesToV5(
}
return {
type: 'builder_query' as QueryType,
type: (queryData.source === 'ai'
? 'builder_ai_query'
: 'builder_query') as QueryType,
spec,
};
},

View File

@@ -11,6 +11,16 @@ interface ListViewOrderByProps {
value: string;
onChange: (value: string) => void;
dataSource: DataSource;
/**
* POC / AI Trace View: scopes keys to trace aggregates
* (`fieldContext=trace` on /fields/keys).
*/
fieldContext?: 'resource' | 'scope' | 'attribute' | 'span' | 'trace';
/**
* POC / AI O11y: forwarded as `type` on /fields/keys
* (e.g. 'builder_ai_query').
*/
queryType?: string;
}
// Loader component for the dropdown when loading or no results
@@ -26,6 +36,8 @@ function ListViewOrderBy({
value,
onChange,
dataSource,
fieldContext,
queryType,
}: ListViewOrderByProps): JSX.Element {
const [searchInput, setSearchInput] = useState('');
const [debouncedInput, setDebouncedInput] = useState('');
@@ -36,11 +48,19 @@ function ListViewOrderBy({
// Fetch key suggestions based on debounced input
const { data, isLoading } = useQuery({
queryKey: ['orderByKeySuggestions', dataSource, debouncedInput],
queryKey: [
'orderByKeySuggestions',
dataSource,
debouncedInput,
fieldContext,
queryType,
],
queryFn: async () => {
const response = await getKeySuggestions({
signal: dataSource,
searchText: debouncedInput,
fieldContext,
type: queryType,
});
return response.data;
},

View File

@@ -26,6 +26,7 @@ export const QueryBuilderV2 = memo(function QueryBuilderV2({
onSignalSourceChange,
signalSourceChangeEnabled = false,
savePreviousQuery = false,
queryType,
}: QueryBuilderProps): JSX.Element {
const {
currentQuery,
@@ -214,6 +215,7 @@ export const QueryBuilderV2 = memo(function QueryBuilderV2({
signalSourceChangeEnabled={signalSourceChangeEnabled}
queriesCount={1}
savePreviousQuery={savePreviousQuery}
queryType={queryType}
/>
) : (
currentQuery.builder.queryData.map((query, index) => (
@@ -237,6 +239,7 @@ export const QueryBuilderV2 = memo(function QueryBuilderV2({
signalSourceChangeEnabled={signalSourceChangeEnabled}
queriesCount={currentQuery.builder.queryData.length}
savePreviousQuery={savePreviousQuery}
queryType={queryType}
/>
))
)}

View File

@@ -111,6 +111,11 @@ interface QuerySearchProps {
numberValues: number[];
complete: boolean;
}>;
/**
* POC / AI O11y: forwarded as `type` on /fields/keys and /fields/values
* (e.g. 'builder_ai_query'). Optional — existing callers unchanged.
*/
queryType?: string;
}
function QuerySearch({
@@ -125,6 +130,7 @@ function QuerySearch({
initialExpression,
metricNamespace,
valueSuggestionsOverride,
queryType,
}: QuerySearchProps): JSX.Element {
const isDarkMode = useIsDarkMode();
const [valueSuggestions, setValueSuggestions] = useState<any[]>([]);
@@ -326,6 +332,7 @@ function QuerySearch({
metricName: debouncedMetricName ?? undefined,
signalSource: signalSource as 'meter' | '',
metricNamespace,
type: queryType,
});
if (response.data.data) {
@@ -363,6 +370,7 @@ function QuerySearch({
hardcodedAttributeKeys,
showFilterSuggestionsWithoutMetric,
metricNamespace,
queryType,
],
);
@@ -502,6 +510,7 @@ function QuerySearch({
signal: dataSource,
signalSource: signalSource as 'meter' | '',
metricName: debouncedMetricName ?? undefined,
type: queryType,
}).then((response) => {
const responseData = response.data as any;
const data = responseData.data || {};
@@ -604,6 +613,7 @@ function QuerySearch({
signalSource,
toggleSuggestions,
valueSuggestionsOverride,
queryType,
],
);
@@ -1749,6 +1759,7 @@ QuerySearch.defaultProps = {
"Enter your filter query (e.g., http.status_code >= 500 AND service.name = 'frontend')",
showFilterSuggestionsWithoutMetric: false,
initialExpression: undefined,
queryType: undefined,
};
export default QuerySearch;

View File

@@ -43,6 +43,7 @@ export const QueryV2 = forwardRef(function QueryV2(
signalSourceChangeEnabled = false,
queriesCount = 1,
savePreviousQuery = false,
queryType,
}: QueryProps & {
onSignalSourceChange: (value: string) => void;
signalSourceChangeEnabled: boolean;
@@ -182,6 +183,7 @@ export const QueryV2 = forwardRef(function QueryV2(
queryData={query}
dataSource={dataSource}
signalSource={signalSource}
queryType={queryType}
/>
</div>
@@ -252,6 +254,7 @@ export const QueryV2 = forwardRef(function QueryV2(
queryData={query}
dataSource={dataSource}
signalSource={signalSource}
queryType={queryType}
/>
</div>

View File

@@ -38,6 +38,11 @@ export type QueryBuilderProps = {
onSignalSourceChange?: (value: string) => void;
signalSourceChangeEnabled?: boolean;
savePreviousQuery?: boolean;
/**
* POC / AI O11y: forwarded to QuerySearch for key/value suggestions
* (e.g. 'builder_ai_query'). Optional — existing callers unchanged.
*/
queryType?: string;
};
export enum TraceView {

View File

@@ -35,4 +35,9 @@ export type QueryProps = {
hasTraceOperator?: boolean;
signalSource?: string;
isMultiQueryAllowed?: boolean;
/**
* POC / AI O11y: forwarded to QuerySearch as suggestion `type`
* (e.g. 'builder_ai_query').
*/
queryType?: string;
} & Pick<QueryBuilderProps, 'filterConfigs' | 'queryComponents'>;

View File

@@ -250,6 +250,9 @@ function ListView({
value={orderBy}
onChange={handleOrderChange}
dataSource={DataSource.TRACES}
// POC: AI order-by — type=builder_ai_query&fieldContext=trace
fieldContext="trace"
queryType="builder_ai_query"
/>
</div>

View File

@@ -54,6 +54,8 @@ function QuerySection(): JSX.Element {
panelTypes === PANEL_TYPES.LIST || panelTypes === PANEL_TYPES.TRACE
}
version="v3" // setting this to v3 as we this is rendered in logs explorer
// POC: AI O11y — search bar key/value suggestions send type=builder_ai_query
queryType="builder_ai_query"
/>
);
}

View File

@@ -117,15 +117,24 @@ function TracesExplorer(): JSX.Element {
const [warning, setWarning] = useState<Warning | undefined>();
const [isOpen, setOpen] = useState<boolean>(true);
const defaultQuery = useMemo(
(): Query =>
updateAllQueriesOperators(
initialQueriesMap.traces,
PANEL_TYPES.LIST,
DataSource.TRACES,
),
[updateAllQueriesOperators],
);
const defaultQuery = useMemo((): Query => {
const query = updateAllQueriesOperators(
initialQueriesMap.traces,
PANEL_TYPES.LIST,
DataSource.TRACES,
);
// POC: tag queries source:'ai' so query-range serializes as builder_ai_query
return {
...query,
builder: {
...query.builder,
queryData: query.builder.queryData.map((qd) => ({
...qd,
source: 'ai' as const,
})),
},
};
}, [updateAllQueriesOperators]);
const { handleExplorerTabChange } = useHandleExplorerTabChange();
const { safeNavigate } = useSafeNavigate();

View File

@@ -89,7 +89,7 @@ export type IBuilderQuery = {
pageSize?: number;
offset?: number;
selectColumns?: BaseAutocompleteData[] | TelemetryFieldKey[];
source?: 'meter' | '';
source?: 'meter' | 'ai' | '';
};
export interface IClickHouseQuery {

View File

@@ -30,11 +30,13 @@ export interface QueryKeySuggestionsResponseProps {
export interface QueryKeyRequestProps {
signal: 'traces' | 'logs' | 'metrics';
searchText: string;
fieldContext?: 'resource' | 'scope' | 'attribute' | 'span';
fieldContext?: 'resource' | 'scope' | 'attribute' | 'span' | 'trace';
fieldDataType?: FieldDataType;
metricName?: string;
metricNamespace?: string;
signalSource?: 'meter' | '';
/** POC / AI O11y: e.g. 'builder_ai_query' — forwarded as `type` on /fields/keys */
type?: string;
}
export interface QueryKeyValueSuggestionsProps {
@@ -53,6 +55,8 @@ export interface QueryKeyValueRequestProps {
searchText: string;
signalSource?: 'meter' | '';
metricName?: string;
/** POC / AI O11y: e.g. 'builder_ai_query' — forwarded as `type` on /fields/values */
type?: string;
}
export type SignalType = 'traces' | 'logs' | 'metrics';

View File

@@ -16,6 +16,7 @@ export type RequestType =
export type QueryType =
| 'builder_query'
| 'builder_ai_query'
| 'builder_trace_operator'
| 'builder_formula'
| 'builder_sub_query'