-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[scout] improve logs readability by using unique logger context per playwright worker #213218
base: main
Are you sure you want to change the base?
Changes from 12 commits
c9505eb
3be1df6
ec657c8
fbc4914
cbe40c0
36cc1f2
6eeb64d
dd47d57
bbe2beb
29bc0e4
0622113
53e8379
8565211
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,7 +33,7 @@ export const scoutPageParallelFixture = base.extend< | |
extendedPage.gotoApp = (appName: string, pathOptions?: PathOptions) => | ||
page.goto(kbnUrl.app(appName, { space: scoutSpace.id, pathOptions })); | ||
|
||
log.serviceLoaded(`scoutPage:${scoutSpace.id}`); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here, |
||
log.serviceLoaded(`scoutPage`); | ||
await use(extendedPage); | ||
}, | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the "Elastic License | ||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side | ||
* Public License v 1"; you may not use this file except in compliance with, at | ||
* your election, the "Elastic License 2.0", the "GNU Affero General Public | ||
* License v3.0 only", or the "Server Side Public License, v 1". | ||
*/ | ||
|
||
export { logFixture } from './single_thread'; | ||
export { logParallelFixture } from './parallel'; | ||
export type { ScoutLogger } from '../../../../common'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the "Elastic License | ||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side | ||
* Public License v 1"; you may not use this file except in compliance with, at | ||
* your election, the "Elastic License 2.0", the "GNU Affero General Public | ||
* License v3.0 only", or the "Server Side Public License, v 1". | ||
*/ | ||
|
||
import { test as base } from '@playwright/test'; | ||
import { getLogger } from '../../../../common/services'; | ||
import { ScoutLogger } from '../../../../common'; | ||
|
||
/** | ||
* Provides a scoped logger instance for each worker. This logger is shared across | ||
* all other fixtures within the worker scope. This fixture is used in the parallel | ||
* test execution mode to better diffirentiate between logs from different workers: `scout-1`, `scout-2`, etc. | ||
*/ | ||
export const logParallelFixture = base.extend< | ||
{}, | ||
{ | ||
log: ScoutLogger; | ||
} | ||
>({ | ||
log: [ | ||
({}, use, workerInfo) => { | ||
const loggerContext = `scout-worker-${workerInfo.parallelIndex + 1}`; | ||
use(getLogger(loggerContext)); | ||
}, | ||
{ scope: 'worker' }, | ||
], | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the "Elastic License | ||
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side | ||
* Public License v 1"; you may not use this file except in compliance with, at | ||
* your election, the "Elastic License 2.0", the "GNU Affero General Public | ||
* License v3.0 only", or the "Server Side Public License, v 1". | ||
*/ | ||
|
||
import { test as base } from '@playwright/test'; | ||
import { getLogger } from '../../../../common/services'; | ||
import { ScoutLogger } from '../../../../common'; | ||
|
||
/** | ||
* Provides a scoped logger instance for each worker. This logger is shared across | ||
* all other fixtures within the worker scope. | ||
*/ | ||
export const logFixture = base.extend< | ||
{}, | ||
{ | ||
log: ScoutLogger; | ||
} | ||
>({ | ||
log: [ | ||
({}, use) => { | ||
use(getLogger('scout-worker')); | ||
}, | ||
{ scope: 'worker' }, | ||
], | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,46 +19,42 @@ export const scoutSpaceParallelFixture = coreWorkerFixtures.extend< | |
>({ | ||
scoutSpace: [ | ||
async ({ log, kbnClient }, use, workerInfo) => { | ||
const spaceId = `test-space-${workerInfo.workerIndex}`; | ||
const spaceId = `test-space-${workerInfo.parallelIndex + 1}`; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Playwright created new worker after failure, https://playwright.dev/docs/api/class-workerinfo#worker-info-parallel-index |
||
const spacePayload = { | ||
id: spaceId, | ||
name: spaceId, | ||
disabledFeatures: [], | ||
}; | ||
await measurePerformanceAsync(log, `scoutSpace:${spaceId} 'spaces.create'`, async () => { | ||
await measurePerformanceAsync(log, `${spaceId}: 'spaces.create'`, async () => { | ||
return kbnClient.spaces.create(spacePayload); | ||
}); | ||
|
||
// cache saved objects ids in space | ||
const savedObjectsCache = new Map<string, string>(); | ||
|
||
const load = async (path: string) => { | ||
return measurePerformanceAsync( | ||
log, | ||
`scoutSpace:${spaceId} 'savedObjects.load'`, | ||
async () => { | ||
const response = await kbnClient.importExport.load(path, { | ||
space: spaceId, | ||
// will create new copies of saved objects with unique ids | ||
createNewCopies: true, | ||
}); | ||
return measurePerformanceAsync(log, `${spaceId}: 'savedObjects.load'`, async () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. simplifying message, as we know the worker index now |
||
const response = await kbnClient.importExport.load(path, { | ||
space: spaceId, | ||
// will create new copies of saved objects with unique ids | ||
createNewCopies: true, | ||
}); | ||
|
||
const imported = (response.successResults as ImportSavedObjects[]).map( | ||
(r: { type: string; destinationId: string; meta: { title: string } }) => { | ||
return { id: r.destinationId, type: r.type, title: r.meta.title }; | ||
} | ||
); | ||
const imported = (response.successResults as ImportSavedObjects[]).map( | ||
(r: { type: string; destinationId: string; meta: { title: string } }) => { | ||
return { id: r.destinationId, type: r.type, title: r.meta.title }; | ||
} | ||
); | ||
|
||
imported.forEach((so) => savedObjectsCache.set(so.title, so.id)); | ||
imported.forEach((so) => savedObjectsCache.set(so.title, so.id)); | ||
|
||
return imported; | ||
} | ||
); | ||
return imported; | ||
}); | ||
}; | ||
const cleanStandardList = async () => { | ||
return measurePerformanceAsync( | ||
log, | ||
`scoutSpace:${spaceId} 'savedObjects.cleanStandardList'`, | ||
`${spaceId}: 'savedObjects.cleanStandardList'`, | ||
async () => { | ||
savedObjectsCache.clear(); | ||
await kbnClient.savedObjects.cleanStandardList({ | ||
|
@@ -70,7 +66,7 @@ export const scoutSpaceParallelFixture = coreWorkerFixtures.extend< | |
const setDefaultIndex = async (dataViewName: string) => { | ||
return measurePerformanceAsync( | ||
log, | ||
`scoutSpace:${spaceId} 'savedObjects.setDefaultIndex'`, | ||
`${spaceId}: 'savedObjects.setDefaultIndex'`, | ||
async () => { | ||
if (savedObjectsCache.has(dataViewName)) { | ||
return kbnClient.uiSettings.update( | ||
|
@@ -91,31 +87,23 @@ export const scoutSpaceParallelFixture = coreWorkerFixtures.extend< | |
}); | ||
}; | ||
const unset = async (...keys: string[]) => { | ||
return measurePerformanceAsync( | ||
log, | ||
`scoutSpace:${spaceId} 'uiSettings.unset'`, | ||
async () => { | ||
return Promise.all( | ||
keys.map((key) => kbnClient.uiSettings.unset(key, { space: spaceId })) | ||
); | ||
} | ||
); | ||
return measurePerformanceAsync(log, `${spaceId}: 'uiSettings.unset'`, async () => { | ||
return Promise.all( | ||
keys.map((key) => kbnClient.uiSettings.unset(key, { space: spaceId })) | ||
); | ||
}); | ||
}; | ||
const setDefaultTime = async ({ from, to }: { from: string; to: string }) => { | ||
return measurePerformanceAsync( | ||
log, | ||
`scoutSpace:${spaceId} 'uiSettings.setDefaultTime'`, | ||
async () => { | ||
const utcFrom = isValidUTCDate(from) ? from : formatTime(from); | ||
const untcTo = isValidUTCDate(to) ? to : formatTime(to); | ||
return kbnClient.uiSettings.update( | ||
{ | ||
'timepicker:timeDefaults': `{ "from": "${utcFrom}", "to": "${untcTo}"}`, | ||
}, | ||
{ space: spaceId } | ||
); | ||
} | ||
); | ||
return measurePerformanceAsync(log, `${spaceId}: 'uiSettings.setDefaultTime'`, async () => { | ||
const utcFrom = isValidUTCDate(from) ? from : formatTime(from); | ||
const utcTo = isValidUTCDate(to) ? to : formatTime(to); | ||
return kbnClient.uiSettings.update( | ||
{ | ||
'timepicker:timeDefaults': `{ "from": "${utcFrom}", "to": "${utcTo}"}`, | ||
}, | ||
{ space: spaceId } | ||
); | ||
}); | ||
}; | ||
|
||
const savedObjects = { | ||
|
@@ -130,11 +118,12 @@ export const scoutSpaceParallelFixture = coreWorkerFixtures.extend< | |
setDefaultTime, | ||
}; | ||
|
||
log.serviceLoaded(`scoutSpace:${spaceId}`); | ||
log.serviceMessage('scoutSpace', `New Kibana space '${spaceId}' created`); | ||
await use({ savedObjects, uiSettings, id: spaceId }); | ||
|
||
// Cleanup space after tests via API call | ||
await measurePerformanceAsync(log, `scoutSpace:${spaceId} 'space.delete'`, async () => { | ||
await measurePerformanceAsync(log, `${spaceId} 'space.delete'`, async () => { | ||
log.debug(`Deleting space ${spaceId}`); | ||
return kbnClient.spaces.delete(spaceId); | ||
}); | ||
}, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it is redundant: logger context helps to understand the space we use, there is a 1 to 1 match.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good about the test space ID being redundant.
A possible improvement for the future (possibly out of scope for this PR): instead of logging just
pageObjects
(the service name), we could logpageObjects loaded
or perhapspageObjects service loaded
to make it clear the service was loaded (successfully). What do you think?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking about it too, how about having it this way (actually it was in PoC like that):
output
alternatively
but maybe we don't need that
[service]
context assuming we know that it is coming from playwright worker?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
locally run
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the
[service]
extra bit of information, I think it adds clarity to the log, and it doesn't take a lot of space after all, but I'm fine with leaving it out (up to you).