mirror of
https://github.com/openobserve/openobserve.git
synced 2026-11-05 16:10:43 +00:00
## Reduce `Logs-Builder-Basic` e2e shard runtime — ~10 min → ~5 min
### 🎯 Result (measured on CI)
| Metric | Before | After | Saved |
|--------|--------|-------|-------|
| **`Logs-Builder-Basic` shard** | **10m 05s** | **5m 12s** | **~4m 53s
(≈48% faster)** |
The shard runtime is cut roughly in half. Most of the old time was fixed
sleeps, waits that always ran their full timeout, and duplicated
per-test setup — not actual test logic. **No test cases, steps, or
assertions were removed.**
### What we changed
| # | Area | Before | After | Saving |
|---|------|--------|-------|--------|
| 1 | `initQueryBuilderTest` setup | Logs page loaded twice (helper
`goto` + `selectStream` navigates again) | Navigate once | 1 page load ×
~41 tests |
| 2 | `waitForBuildTabLoaded` | Always waited up to 10s for editor to
fill, even when it's meant to be empty | Skip when SQL mode is off |
~10s dead wait on many tests |
| 3 | `enableSqlModeIfNeeded` | 2s watcher wait + 500ms sleep, even
where the watcher never fires | Gated to Build tab; waits on real signal
| ~2.5s × ~35 tests |
| 4 | `disableSqlModeIfNeeded` | Fixed 500–600ms sleeps | Deterministic
wait on editor update | Blind sleeps removed |
| 5 | `applyQueryButton` | Clicked Run blindly | Waits for button ready
first | Fewer early-click retries |
| 6 | `pagination.spec` | Fresh stream ingest + index-wait per test (9×)
| One ingest per worker, reused | 8 redundant ingests + waits |
| 7 | `pagination.spec` | Dead `waitForTimeout(2000)` per streaming test
| Removed | ~2s × 5 tests |
| 8 | `unflattened.spec` | Search run twice with 3s + 1s sleeps | Single
run | ~5s × ~8 calls |
| 9 | `unflattened` row scan | Fixed 3s sleep per row | Wait for content
to render | 15-row scan: ~97s → seconds |
| 10 | `unflattened.spec` | Blind sleep after ingest | Poll until stream
queryable | No over-waiting |
### Bonus
Items 2–5 live in the shared `logsPage` page object, so
`Logs-Builder-Advanced`, `Logs-Core`, and `Logs-Features` shards get
faster for free too.
### Notes
| Item | Detail |
|------|--------|
| `playwright.yml` | Unchanged — shard layout stays as-is |
| Assertions | Preserved everywhere (e.g. pagination still checks the
same record counts) |
| Validation | All 52 tests still discovered by `playwright --list`;
shard confirmed green on CI at 5m 12s |
89 lines
3.7 KiB
JavaScript
89 lines
3.7 KiB
JavaScript
const testLogger = require('./test-logger.js');
|
|
const logsdata = require('../../../test-data/logs_data.json');
|
|
const { getOrgIdentifier, getAuthHeaders } = require('./cloud-auth.js');
|
|
|
|
/**
|
|
* Ingest test data via Playwright request fixture (for beforeAll).
|
|
* Uses the request APIRequestContext — no browser page needed.
|
|
*/
|
|
async function ingestForQueryBuilderTest(request, streamName = "e2e_automate") {
|
|
const orgId = getOrgIdentifier();
|
|
const headers = getAuthHeaders();
|
|
const baseUrl = process.env.INGESTION_URL.endsWith('/')
|
|
? process.env.INGESTION_URL.slice(0, -1)
|
|
: process.env.INGESTION_URL;
|
|
|
|
const response = await request.post(`${baseUrl}/api/${orgId}/${streamName}/_json`, {
|
|
headers: headers,
|
|
data: logsdata
|
|
});
|
|
if (!response.ok()) throw new Error(`Ingestion failed: ${response.status()} ${await response.text()}`);
|
|
const responseData = await response.json();
|
|
testLogger.debug('Test data ingestion response', { response: responseData, streamName });
|
|
return responseData;
|
|
}
|
|
|
|
async function applyQueryButton(pm) {
|
|
// Stream selection fires an auto-search that leaves the Run button disabled,
|
|
// aria-busy, or swapped to "Cancel" while in flight. Clicking blind during that
|
|
// window fails with "Element is not visible" — wait for the button to be ready
|
|
// first. The catch falls through to the click, which then reports loudly.
|
|
await pm.page.waitForFunction((selector) => {
|
|
const el = document.querySelector(selector);
|
|
if (!el) return false;
|
|
if (el.getAttribute('aria-busy') === 'true') return false;
|
|
if (el.hasAttribute('disabled') || el.getAttribute('aria-disabled') === 'true') return false;
|
|
if (((el.textContent || '').trim()).includes('Cancel')) return false;
|
|
return el.offsetParent !== null;
|
|
}, pm.logsPage.queryButton, { timeout: 60000, polling: 100 }).catch(() => {});
|
|
|
|
const searchPromise = pm.page.waitForResponse(
|
|
response => response.url().includes('/_search') && response.status() === 200,
|
|
{ timeout: 60000 }
|
|
);
|
|
|
|
await pm.logsPage.clickRefreshButton();
|
|
|
|
try {
|
|
await searchPromise;
|
|
testLogger.info('Search query completed successfully');
|
|
} catch (error) {
|
|
testLogger.warn('Search response wait timed out, continuing test');
|
|
await pm.page.waitForLoadState('networkidle').catch(() => {});
|
|
}
|
|
}
|
|
|
|
async function setupQueryAndSwitchToBuild(pm, page, query) {
|
|
await pm.logsPage.enableSqlModeIfNeeded();
|
|
await page.waitForLoadState('domcontentloaded');
|
|
await pm.logsPage.setQueryEditorContent(query);
|
|
await pm.logsPage.runQueryAndWaitForResults();
|
|
await pm.logsPage.clickBuildToggle();
|
|
await pm.logsPage.waitForBuildTabLoaded();
|
|
}
|
|
|
|
/**
|
|
* Full init: select stream (selectStream navigates to the logs page itself, so no
|
|
* separate page.goto here — that would just load the same page twice), then run
|
|
* the initial match_all query.
|
|
* Ingestion is handled by ingestForQueryBuilderTest in beforeAll.
|
|
*
|
|
* The applyQueryButton call is NOT optional setup: selecting a stream fires an
|
|
* auto-search, and waiting for its /_search response here absorbs it before the
|
|
* test body runs. Skipping it lets that response land mid-test and overwrite the
|
|
* test's query state (observed as table/metric chart-type tests flaking to the
|
|
* default bar chart under load).
|
|
*/
|
|
async function initQueryBuilderTest(page, pm) {
|
|
await page.waitForLoadState('domcontentloaded');
|
|
await pm.logsPage.selectStream("e2e_automate");
|
|
await applyQueryButton(pm);
|
|
}
|
|
|
|
module.exports = {
|
|
ingestForQueryBuilderTest,
|
|
applyQueryButton,
|
|
setupQueryAndSwitchToBuild,
|
|
initQueryBuilderTest,
|
|
};
|