Compare commits

...

6 Commits

Author SHA1 Message Date
Tushar Vats
89d90710a3 fix: improve readability 2026-05-08 15:22:49 +05:30
Tushar Vats
a1bb4c1645 fix: removed comment 2026-04-21 00:53:31 +05:30
Tushar Vats
892443fbd5 fix: new logic 2026-04-21 00:40:59 +05:30
Tushar Vats
4b95f84bfb fix: improve filter key suggestions 2026-04-20 23:56:32 +05:30
Tushar Vats
9d7bce0f2e Merge branch 'main' into tvats-improve-key-suggestions 2026-04-20 15:35:52 +05:30
Tushar Vats
2973598246 fix: improved key suggestions 2026-04-16 05:37:54 +05:30
3 changed files with 32 additions and 19 deletions

View File

@@ -216,9 +216,10 @@ function QuerySearch({
[key: string]: QueryKeyDataSuggestionsProps[];
}): any[] =>
Object.values(keys).flatMap((items: QueryKeyDataSuggestionsProps[]) =>
items.map(({ name, fieldDataType }) => ({
items.map(({ name, fieldDataType, fieldContext }) => ({
label: name,
type: fieldDataType === 'string' ? 'keyword' : fieldDataType,
fieldContext,
info: '',
details: '',
})),
@@ -276,17 +277,21 @@ function QuerySearch({
if (response.data.data) {
const { keys } = response.data.data;
const options = generateOptions(keys);
// Use a Map to deduplicate by label and preserve order: new options take precedence
// Dedup by `label::fieldContext` so the same name in different contexts
// (e.g. attribute.foo vs resource.foo) is preserved as two entries.
const dedupKey = (opt: QueryKeyDataSuggestionsProps): string =>
`${opt.label}::${opt.fieldContext ?? ''}`;
const merged = new Map<string, QueryKeyDataSuggestionsProps>();
options.forEach((opt) => merged.set(opt.label, opt));
options.forEach((opt) => merged.set(dedupKey(opt), opt));
if (searchText && lastKeyRef.current !== searchText) {
(keySuggestions || []).forEach((opt) => {
if (!merged.has(opt.label)) {
merged.set(opt.label, opt);
const k = dedupKey(opt);
if (!merged.has(k)) {
merged.set(k, opt);
}
});
}
setKeySuggestions(Array.from(merged.values()));
setKeySuggestions([...merged.values()]);
// Force reopen the completion if editor is available and focused
if (editorRef.current) {
@@ -886,25 +891,32 @@ function QuerySearch({
};
}
if (queryContext.isInKey) {
const searchText = word?.text.toLowerCase().trim() ?? '';
const rawSearchText = word?.text.toLowerCase().trim() ?? '';
options = (keySuggestions || []).filter((option) =>
option.label.toLowerCase().includes(searchText),
);
if (options.length === 0 && lastFetchedKeyRef.current !== searchText) {
debouncedFetchKeySuggestions(searchText);
if (queryContext.isInKey || rawSearchText.includes('.')) {
if (lastFetchedKeyRef.current !== rawSearchText) {
debouncedFetchKeySuggestions(rawSearchText);
}
// Bare names matched by `contains`; `<context>.<name>` form by prefix.
const list = keySuggestions ?? [];
const bareMatches = list.filter((opt) =>
opt.label.toLowerCase().includes(rawSearchText),
);
const prefixedMatches = list
.filter((opt) => !!opt.fieldContext)
.map((opt) => ({ ...opt, label: `${opt.fieldContext}.${opt.label}` }))
.filter((opt) => opt.label.toLowerCase().startsWith(rawSearchText));
options = [...bareMatches, ...prefixedMatches];
// If we have previous pairs, we can prioritize keys that haven't been used yet
if (queryContext.queryPairs && queryContext.queryPairs.length > 0) {
const usedKeys = queryContext.queryPairs.map((pair) => pair.key);
const usedKeys = new Set(queryContext.queryPairs.map((pair) => pair.key));
// Add boost to unused keys to prioritize them
options = options.map((option) => ({
...option,
boost: usedKeys.includes(option.label) ? -10 : 10,
boost: usedKeys.has(option.label) ? -10 : 10,
}));
}
@@ -913,7 +925,7 @@ function QuerySearch({
...option,
boost:
(option.boost || 0) +
(option.label.toLowerCase() === searchText ? 100 : 0),
(option.label.toLowerCase() === rawSearchText ? 100 : 0),
}));
// Add space after selection for keys

View File

@@ -6,7 +6,7 @@ export interface QueryKeyDataSuggestionsProps {
info?: string;
apply?: string;
detail?: string;
fieldContext?: 'resource' | 'scope' | 'attribute' | 'span';
fieldContext?: 'resource' | 'scope' | 'attribute' | 'span' | 'log' | 'body';
fieldDataType?: QUERY_BUILDER_KEY_TYPES;
name: string;
signal: 'traces' | 'logs' | 'metrics';
@@ -25,7 +25,7 @@ export interface QueryKeySuggestionsResponseProps {
export interface QueryKeyRequestProps {
signal: 'traces' | 'logs' | 'metrics';
searchText: string;
fieldContext?: 'resource' | 'scope' | 'attribute' | 'span';
fieldContext?: 'resource' | 'scope' | 'attribute' | 'span' | 'log' | 'body';
fieldDataType?: QUERY_BUILDER_KEY_TYPES;
metricName?: string;
signalSource?: 'meter' | '';

View File

@@ -46,6 +46,7 @@ export type FieldContext =
| 'scope'
| 'attribute'
| 'event'
| 'body'
| '';
export type FieldDataType =