107 lines
2.7 KiB
TypeScript
107 lines
2.7 KiB
TypeScript
import { cloneDeep, merge } from 'lodash';
|
|
import { useEffect, useMemo, useState } from 'react';
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
|
|
import { InterpolateFunction } from '@grafana/data';
|
|
|
|
import { filterSpans, TraceSpan } from './components';
|
|
|
|
export interface SearchProps {
|
|
serviceName?: string;
|
|
serviceNameOperator: string;
|
|
spanName?: string;
|
|
spanNameOperator: string;
|
|
from?: string;
|
|
fromOperator: string;
|
|
to?: string;
|
|
toOperator: string;
|
|
tags: Tag[];
|
|
query?: string;
|
|
matchesOnly: boolean;
|
|
criticalPathOnly: boolean;
|
|
}
|
|
|
|
export interface Tag {
|
|
id: string;
|
|
key?: string;
|
|
operator: string;
|
|
value?: string;
|
|
}
|
|
|
|
export const randomId = () => uuidv4().slice(0, 12);
|
|
|
|
export const defaultTagFilter = {
|
|
id: randomId(),
|
|
operator: '=',
|
|
};
|
|
|
|
export const defaultFilters = {
|
|
spanNameOperator: '=',
|
|
serviceNameOperator: '=',
|
|
fromOperator: '>',
|
|
toOperator: '<',
|
|
tags: [defaultTagFilter],
|
|
matchesOnly: false,
|
|
criticalPathOnly: false,
|
|
};
|
|
|
|
/**
|
|
* Controls the state of search input that highlights spans if they match the search string.
|
|
* @param spans
|
|
*/
|
|
export function useSearch(spans?: TraceSpan[], initialFilters?: SearchProps) {
|
|
const [search, setSearch] = useState<SearchProps>(merge(cloneDeep(defaultFilters), initialFilters ?? {}));
|
|
|
|
useEffect(() => {
|
|
if (initialFilters) {
|
|
setSearch(merge(cloneDeep(defaultFilters), initialFilters));
|
|
}
|
|
}, [initialFilters]);
|
|
|
|
const spanFilterMatches: Set<string> | undefined = useMemo(() => {
|
|
return spans && filterSpans(search, spans);
|
|
}, [search, spans]);
|
|
|
|
return { search, setSearch, spanFilterMatches };
|
|
}
|
|
|
|
export function replaceSearchVariables(replaceVariables: InterpolateFunction, search?: SearchProps) {
|
|
if (!search) {
|
|
return search;
|
|
}
|
|
|
|
const newSearch = { ...search };
|
|
if (newSearch.query) {
|
|
newSearch.query = replaceVariables(newSearch.query);
|
|
}
|
|
if (newSearch.serviceNameOperator) {
|
|
newSearch.serviceNameOperator = replaceVariables(newSearch.serviceNameOperator);
|
|
}
|
|
if (newSearch.serviceName) {
|
|
newSearch.serviceName = replaceVariables(newSearch.serviceName);
|
|
}
|
|
if (newSearch.spanNameOperator) {
|
|
newSearch.spanNameOperator = replaceVariables(newSearch.spanNameOperator);
|
|
}
|
|
if (newSearch.spanName) {
|
|
newSearch.spanName = replaceVariables(newSearch.spanName);
|
|
}
|
|
if (newSearch.from) {
|
|
newSearch.from = replaceVariables(newSearch.from);
|
|
}
|
|
if (newSearch.to) {
|
|
newSearch.to = replaceVariables(newSearch.to);
|
|
}
|
|
if (newSearch.tags) {
|
|
newSearch.tags = newSearch.tags.map((tag) => {
|
|
return {
|
|
...tag,
|
|
key: replaceVariables(tag.key ?? ''),
|
|
value: replaceVariables(tag.value ?? ''),
|
|
};
|
|
});
|
|
}
|
|
|
|
return newSearch;
|
|
}
|