Loki: Fix label not being added to all subexpressions (#81360)

This commit is contained in:
Sven Grossmann 2024-01-26 14:03:24 +01:00 committed by GitHub
parent e90ea8a941
commit 9c728def38
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 38 additions and 13 deletions

View File

@ -98,6 +98,18 @@ describe('addLabelToQuery()', () => {
'{foo="bar"} | logfmt | forcedLabel=`value`'
);
});
it('should add label as labelFilter to multiple places if label is StructuredMetadata', () => {
expect(
addLabelToQuery(
'rate({foo="bar"} [$__auto]) / rate({foo="bar"} [$__auto])',
'forcedLabel',
'=',
'value',
LabelType.StructuredMetadata
)
).toEqual('rate({foo="bar"} | forcedLabel=`value` [$__auto]) / rate({foo="bar"} | forcedLabel=`value` [$__auto])');
});
});
describe('addParserToQuery', () => {

View File

@ -171,8 +171,13 @@ export function addLabelToQuery(
const filter = toLabelFilter(key, value, operator);
if (labelType === LabelType.Parsed || labelType === LabelType.StructuredMetadata) {
const positionToAdd = findLastPosition([...streamSelectorPositions, ...labelFilterPositions, ...parserPositions]);
return addFilterAsLabelFilter(query, [positionToAdd], filter);
const lastPositionsPerExpression = getLastPositionPerExpression(query, [
...streamSelectorPositions,
...labelFilterPositions,
...parserPositions,
]);
return addFilterAsLabelFilter(query, lastPositionsPerExpression, filter);
} else if (labelType === LabelType.Indexed) {
return addFilterToStreamSelector(query, streamSelectorPositions, filter);
} else {
@ -183,23 +188,31 @@ export function addLabelToQuery(
} else {
// If `labelType` is not set, it indicates a potential metric query (`labelType` is present only in log queries that came from a Loki instance supporting the `categorize-labels` API). In case we are not adding the label to stream selectors we need to find the last position to add in each expression.
// E.g. in `sum(rate({foo="bar"} | logfmt [$__auto])) / sum(rate({foo="baz"} | logfmt [$__auto]))` we need to add the label at two places.
const subExpressions = findLeaves(getNodePositionsFromQuery(query, [Expr]));
const parserFilterPositions = [...parserPositions, ...labelFilterPositions];
// find last position for each subexpression
const lastPositionsPerExpression = subExpressions.map((subExpression) => {
return findLastPosition(
parserFilterPositions.filter((p) => {
return subExpression.contains(p);
})
);
});
const lastPositionsPerExpression = getLastPositionPerExpression(query, [
...parserPositions,
...labelFilterPositions,
]);
return addFilterAsLabelFilter(query, lastPositionsPerExpression, filter);
}
}
}
function getLastPositionPerExpression(query: string, positions: NodePosition[]): NodePosition[] {
const subExpressions = findLeaves(getNodePositionsFromQuery(query, [Expr]));
const subPositions = [...positions];
// find last position for each subexpression
const lastPositionsPerExpression = subExpressions.map((subExpression) => {
return findLastPosition(
subPositions.filter((p) => {
return subExpression.contains(p);
})
);
});
return lastPositionsPerExpression;
}
/**
* Adds parser to existing query. Useful for query modification for hints.
* It uses LogQL parser to find instances of stream selectors or line filters and adds parser after them.