2025-04-01 10:38:02 +09:00

52 lines
1.7 KiB
TypeScript

// Consider any sequence of characters not permitted for metric names as a sepratator
const splitSeparator = /[^a-z0-9_:]+/;
export function deriveSearchTermsFromInput(whiteSpaceSeparatedTerms?: string) {
return (
whiteSpaceSeparatedTerms
?.toLowerCase()
.split(splitSeparator)
.filter((term) => term.length > 0) || []
);
}
export function createJSRegExpFromSearchTerms(searchQuery?: string) {
const searchParts = deriveSearchTermsFromInput(searchQuery).map((part) => `(?=(.*${part.toLowerCase()}.*))`);
if (searchParts.length === 0) {
return null;
}
const regex = searchParts.join('');
// (?=(.*expr1.*)(?=(.*expr2.*))...
// The ?=(...) lookahead allows us to match these in any order.
return new RegExp(regex, 'igy');
}
export function createPromRegExp(searchQuery?: string) {
const searchParts = getUniqueTerms(deriveSearchTermsFromInput(searchQuery))
.filter((term) => term.length > 0)
.map((term) => `(.*${term.toLowerCase()}.*)`);
const count = searchParts.length;
if (searchParts.length === 0) {
// avoid match[] must contain at least one non-empty matcher
return null; //'..*';
}
const regex = `(?i:${searchParts.join('|')}){${count}}`;
// (?i:(.*expr_1.*)|.*expr_2.*)|...|.*expr_n.*){n}
// ?i: to ignore case
// {n} to ensure that it matches n times, one match per term
// - This isn't ideal, since it doesn't enforce that each unique term is matched,
// but it's the best we can do with the Prometheus / Go stdlib implementation of regex.
return regex;
}
function getUniqueTerms(terms: string[] = []) {
const set = new Set(terms.map((term) => term.toLowerCase().trim()));
return Array.from(set);
}