The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/e2e/various-suite/loki-query-builder.spec.ts

106 lines
4.2 KiB

import { e2e } from '../utils';
const MISSING_LABEL_FILTER_ERROR_MESSAGE = 'Select at least 1 label filter (label and value)';
const dataSourceName = 'LokiBuilder';
const addDataSource = () => {
e2e.flows.addDataSource({
type: 'Loki',
expectedAlertMessage: 'Unable to connect with Loki. Please check the server logs for more details.',
name: dataSourceName,
form: () => {
cy.get('#connection-url').type('http://loki-url:3100');
},
});
};
const finalQuery = 'rate({instance=~"instance1|instance2"} | logfmt | __error__=`` [$__auto]';
describe('Loki query builder', () => {
beforeEach(() => {
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
cy.request({
url: `${Cypress.env('BASE_URL')}/api/datasources/name/${dataSourceName}`,
failOnStatusCode: false,
}).then((response) => {
if (response.isOkStatusCode) {
return;
}
addDataSource();
});
});
it('should be able to use all modes', () => {
cy.intercept(/labels\?/, (req) => {
req.reply({ status: 'success', data: ['instance', 'job', 'source'] });
}).as('labelsRequest');
cy.intercept(/series?/, (req) => {
req.reply({ status: 'success', data: [{ instance: 'instance1' }] });
});
cy.intercept(/values/, (req) => {
req.reply({ status: 'success', data: ['instance1', 'instance2'] });
}).as('valuesRequest');
cy.intercept(/index\/stats/, (req) => {
req.reply({ streams: 2, chunks: 2660, bytes: 2721792, entries: 14408 });
});
// Go to Explore and choose Loki data source
e2e.pages.Explore.visit();
e2e.components.DataSourcePicker.container().should('be.visible').click();
cy.contains(dataSourceName).scrollIntoView().should('be.visible').click();
// Start in builder mode, click and choose query pattern
e2e.components.QueryBuilder.queryPatterns().click();
cy.contains('Log query starters').click();
cy.contains('Use this query').click();
cy.contains('No pipeline errors').should('be.visible');
cy.contains('Logfmt').should('be.visible');
cy.contains('{} | logfmt | __error__=``').should('be.visible');
// Add operation
cy.contains('Operations').should('be.visible').click();
cy.contains('Range functions').should('be.visible').click();
cy.contains('Rate').should('be.visible').click();
cy.contains('rate({} | logfmt | __error__=`` [$__auto]').should('be.visible');
// Check for expected error
cy.contains(MISSING_LABEL_FILTER_ERROR_MESSAGE).should('be.visible');
// Add labels to remove error
e2e.components.QueryBuilder.labelSelect().should('be.visible').click();
// wait until labels are loaded and set on the component before starting to type
e2e.components.QueryBuilder.inputSelect().type('i');
cy.wait('@labelsRequest');
e2e.components.QueryBuilder.inputSelect().type('nstance{enter}');
e2e.components.QueryBuilder.matchOperatorSelect()
.should('be.visible')
.click({ force: true })
.children('div')
.children('input')
.type('=~{enter}', { force: true });
e2e.components.QueryBuilder.valueSelect().should('be.visible').click();
e2e.components.QueryBuilder.valueSelect().children('div').children('input').type('instance1{enter}');
cy.wait('@valuesRequest');
e2e.components.QueryBuilder.valueSelect().children('div').children('input').type('instance2{enter}');
cy.contains(MISSING_LABEL_FILTER_ERROR_MESSAGE).should('not.exist');
cy.contains(finalQuery).should('be.visible');
// Change to code editor
e2e.components.RadioButton.container().filter(':contains("Code")').click();
// We need to test this manually because the final query is split into separate DOM elements using cy.contains(finalQuery).should('be.visible'); does not detect the query.
cy.contains('rate').should('be.visible');
cy.contains('instance1|instance2').should('be.visible');
cy.contains('logfmt').should('be.visible');
cy.contains('__error__').should('be.visible');
cy.contains('$__auto').should('be.visible');
// Checks the explain mode toggle
cy.contains('label', 'Explain').click();
cy.contains('Fetch all log lines matching label filters.').should('be.visible');
});
});