mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
# Backport This will backport the following commits from `main` to `8.6`: - [Unskip Execution Context FTRs (#149070)](https://github.com/elastic/kibana/pull/149070) <!--- Backport version: 8.9.7 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Alejandro Fernández Haro","email":"alejandro.haro@elastic.co"},"sourceCommit":{"committedDate":"2023-01-24T01:33:53Z","message":"Unskip Execution Context FTRs (#149070)\n\nResolves https://github.com/elastic/kibana/issues/112102","sha":"4c626f16c0bfc333bf0591f586b082f6c09dd3b1","branchLabelMapping":{"^v8.7.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:Core","release_note:skip","backport:all-open","v8.7.0"],"number":149070,"url":"https://github.com/elastic/kibana/pull/149070","mergeCommit":{"message":"Unskip Execution Context FTRs (#149070)\n\nResolves https://github.com/elastic/kibana/issues/112102","sha":"4c626f16c0bfc333bf0591f586b082f6c09dd3b1"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v8.7.0","labelRegex":"^v8.7.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/149070","number":149070,"mergeCommit":{"message":"Unskip Execution Context FTRs (#149070)\n\nResolves https://github.com/elastic/kibana/issues/112102","sha":"4c626f16c0bfc333bf0591f586b082f6c09dd3b1"}}]}] BACKPORT--> Co-authored-by: Alejandro Fernández Haro <alejandro.haro@elastic.co>
This commit is contained in:
parent
3b020352a5
commit
b76e760c95
7 changed files with 341 additions and 155 deletions
|
@ -87,6 +87,7 @@ describe('ExecutionContextService', () => {
|
|||
`
|
||||
Object {
|
||||
"name": "app2",
|
||||
"type": "application",
|
||||
"url": "/",
|
||||
}
|
||||
`
|
||||
|
@ -244,6 +245,7 @@ describe('ExecutionContextService', () => {
|
|||
execContext.clear();
|
||||
expect(sub).toHaveBeenCalledWith({
|
||||
name: 'app1',
|
||||
type: 'application',
|
||||
url: '/',
|
||||
});
|
||||
|
||||
|
|
|
@ -98,6 +98,7 @@ export class ExecutionContextService
|
|||
|
||||
private getDefaultContext() {
|
||||
return {
|
||||
type: 'application',
|
||||
name: this.appId,
|
||||
url: window.location.pathname,
|
||||
};
|
||||
|
|
|
@ -9,17 +9,26 @@ import Path from 'path';
|
|||
import { isEqualWith } from 'lodash';
|
||||
import type { Ecs, KibanaExecutionContext } from '@kbn/core/server';
|
||||
import type { RetryService } from '@kbn/ftr-common-functional-services';
|
||||
import { concatMap, defer, filter, firstValueFrom, ReplaySubject, scan, timeout } from 'rxjs';
|
||||
|
||||
export const logFilePath = Path.resolve(__dirname, './kibana.log');
|
||||
export const ANY = Symbol('any');
|
||||
|
||||
let logstream$: ReplaySubject<Ecs> | undefined;
|
||||
|
||||
export function getExecutionContextFromLogRecord(record: Ecs | undefined): KibanaExecutionContext {
|
||||
if (record?.log?.logger !== 'execution_context' || !record?.message) {
|
||||
throw new Error(`The record is not an entry of execution context`);
|
||||
}
|
||||
return JSON.parse(record.message);
|
||||
}
|
||||
|
||||
export function isExecutionContextLog(
|
||||
record: string | undefined,
|
||||
record: Ecs | undefined,
|
||||
executionContext: KibanaExecutionContext
|
||||
) {
|
||||
if (!record) return false;
|
||||
try {
|
||||
const object = JSON.parse(record);
|
||||
const object = getExecutionContextFromLogRecord(record);
|
||||
return isEqualWith(object, executionContext, function customizer(obj1: any, obj2: any) {
|
||||
if (obj2 === ANY) return true;
|
||||
});
|
||||
|
@ -41,12 +50,89 @@ export async function assertLogContains({
|
|||
}): Promise<void> {
|
||||
// logs are written to disk asynchronously. I sacrificed performance to reduce flakiness.
|
||||
await retry.waitFor(description, async () => {
|
||||
const logsStr = await Fs.readFile(logFilePath, 'utf-8');
|
||||
const normalizedRecords = logsStr
|
||||
.split(endOfLine)
|
||||
.filter(Boolean)
|
||||
.map((s) => JSON.parse(s));
|
||||
|
||||
return normalizedRecords.some(predicate);
|
||||
if (!logstream$) {
|
||||
logstream$ = getLogstream$();
|
||||
}
|
||||
try {
|
||||
await firstValueFrom(logstream$.pipe(filter(predicate), timeout(5_000)));
|
||||
return true;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an observable that continuously tails the log file.
|
||||
*/
|
||||
function getLogstream$(): ReplaySubject<Ecs> {
|
||||
const stream$ = new ReplaySubject<Ecs>();
|
||||
|
||||
defer(async function* () {
|
||||
const fd = await Fs.open(logFilePath, 'rs');
|
||||
while (!stream$.isStopped) {
|
||||
const { bytesRead, buffer } = await fd.read();
|
||||
if (bytesRead) {
|
||||
yield buffer.toString('utf8', 0, bytesRead);
|
||||
}
|
||||
}
|
||||
await fd.close();
|
||||
})
|
||||
.pipe(
|
||||
scan<string, { buffer: string; records: Ecs[] }>(
|
||||
({ buffer }, chunk) => {
|
||||
const logString = buffer.concat(chunk);
|
||||
const lines = logString.split(endOfLine);
|
||||
const lastLine = lines.pop();
|
||||
const records = lines.map((s) => JSON.parse(s));
|
||||
|
||||
let leftover = '';
|
||||
if (lastLine) {
|
||||
try {
|
||||
const validRecord = JSON.parse(lastLine);
|
||||
records.push(validRecord);
|
||||
} catch (err) {
|
||||
leftover = lastLine;
|
||||
}
|
||||
}
|
||||
|
||||
return { buffer: leftover, records };
|
||||
},
|
||||
{
|
||||
records: [], // The ECS entries in the logs
|
||||
buffer: '', // Accumulated leftovers from the previous operation
|
||||
}
|
||||
),
|
||||
concatMap(({ records }) => records)
|
||||
)
|
||||
.subscribe(stream$);
|
||||
|
||||
// let the content start flowing
|
||||
stream$.subscribe();
|
||||
|
||||
return stream$;
|
||||
}
|
||||
|
||||
export function closeLogstream() {
|
||||
logstream$?.complete();
|
||||
logstream$ = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncates the log file to avoid tests looking at the logs from previous executions.
|
||||
*/
|
||||
export async function clearLogFile() {
|
||||
closeLogstream();
|
||||
await Fs.writeFile(logFilePath, '', 'utf8');
|
||||
await forceSyncLogFile();
|
||||
logstream$ = getLogstream$();
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the completion of all the pending I/O operations in the OS related to the log file.
|
||||
*/
|
||||
export async function forceSyncLogFile() {
|
||||
const fileDescriptor = await Fs.open(logFilePath);
|
||||
await fileDescriptor.datasync();
|
||||
await fileDescriptor.close();
|
||||
}
|
||||
|
|
|
@ -5,15 +5,15 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import type { Ecs, KibanaExecutionContext } from '@kbn/core/server';
|
||||
import type { FtrProviderContext } from '../ftr_provider_context';
|
||||
import { assertLogContains, isExecutionContextLog } from '../test_utils';
|
||||
import { assertLogContains, forceSyncLogFile, isExecutionContextLog } from '../test_utils';
|
||||
|
||||
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||
const PageObjects = getPageObjects(['common', 'dashboard', 'header', 'home']);
|
||||
const retry = getService('retry');
|
||||
|
||||
// FLAKY: https://github.com/elastic/kibana/issues/125743
|
||||
describe.skip('Browser apps', () => {
|
||||
describe('Browser apps', () => {
|
||||
before(async () => {
|
||||
await PageObjects.common.navigateToUrl('home', '/tutorial_directory/sampleData', {
|
||||
useActualUrl: true,
|
||||
|
@ -34,8 +34,20 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
before(async () => {
|
||||
await PageObjects.common.navigateToApp('discover');
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await forceSyncLogFile();
|
||||
});
|
||||
|
||||
function checkExecutionContextEntry(expectedExecutionContext: KibanaExecutionContext) {
|
||||
return (record: Ecs) =>
|
||||
isExecutionContextLog(record, expectedExecutionContext) ||
|
||||
isExecutionContextLog(record, {
|
||||
...expectedExecutionContext,
|
||||
// There is a race condition that makes these 2 fields to show up some times
|
||||
page: 'app',
|
||||
id: 'new',
|
||||
});
|
||||
}
|
||||
|
||||
it('propagates context for Discover', async () => {
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Elasticsearch via "x-opaque-id" header',
|
||||
|
@ -45,31 +57,50 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Kibana logs',
|
||||
predicate: (record) =>
|
||||
isExecutionContextLog(record?.message, {
|
||||
description: 'fetch documents',
|
||||
id: '',
|
||||
description: 'execution context propagates to Kibana logs (fetch documents)',
|
||||
predicate: checkExecutionContextEntry({
|
||||
type: 'application',
|
||||
name: 'discover',
|
||||
url: '/app/discover',
|
||||
child: {
|
||||
name: 'discover',
|
||||
type: 'application',
|
||||
// discovery doesn't have an URL since one of from the example dataset is not saved separately
|
||||
url: '/app/discover',
|
||||
}),
|
||||
type: 'application',
|
||||
page: 'app',
|
||||
id: 'new',
|
||||
description: 'fetch documents',
|
||||
},
|
||||
}),
|
||||
retry,
|
||||
});
|
||||
|
||||
/*
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Kibana logs',
|
||||
predicate: (record) =>
|
||||
isExecutionContextLog(record?.message, {
|
||||
description: 'fetch chart data and total hits',
|
||||
id: '',
|
||||
description:
|
||||
'execution context propagates to Kibana logs (fetch chart data and total hits)',
|
||||
predicate: checkExecutionContextEntry({
|
||||
type: 'application',
|
||||
name: 'discover',
|
||||
url: '/app/discover',
|
||||
child: {
|
||||
name: 'discover',
|
||||
type: 'application',
|
||||
url: '/app/discover',
|
||||
}),
|
||||
type: 'application',
|
||||
page: 'app',
|
||||
id: 'new',
|
||||
description: 'fetch chart data and total hits',
|
||||
child: {
|
||||
type: 'lens',
|
||||
name: 'lnsXY',
|
||||
id: 'unifiedHistogramLensComponent',
|
||||
description: 'Edit visualization',
|
||||
url: '/app/lens#/edit_by_value',
|
||||
},
|
||||
},
|
||||
}),
|
||||
retry,
|
||||
});
|
||||
*/
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -79,30 +110,76 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await PageObjects.dashboard.loadSavedDashboard('[Flights] Global Flight Dashboard');
|
||||
await PageObjects.dashboard.waitForRenderComplete();
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
await forceSyncLogFile();
|
||||
});
|
||||
|
||||
function checkHttpRequestId(suffix: string) {
|
||||
return (record: Ecs): boolean =>
|
||||
Boolean(
|
||||
[
|
||||
'kibana:application:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;',
|
||||
// Race conditions may miss the dashboard ID at the top level
|
||||
'kibana:application:dashboards:;',
|
||||
// Race conditions may assign the dashboard type to the top level
|
||||
'kibana:dashboard:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;',
|
||||
].some((prefix) => record.http?.request?.id?.includes(`${prefix}${suffix}`))
|
||||
);
|
||||
}
|
||||
|
||||
function checkExecutionContextEntry(expectedExecutionContext: KibanaExecutionContext) {
|
||||
return (record: Ecs) =>
|
||||
isExecutionContextLog(record, expectedExecutionContext) ||
|
||||
isExecutionContextLog(record, { ...expectedExecutionContext, page: 'list' }) ||
|
||||
isExecutionContextLog(record, { ...expectedExecutionContext, page: 'app' }) ||
|
||||
isExecutionContextLog(record, {
|
||||
...expectedExecutionContext,
|
||||
// There is a race condition that makes this field to be missed sometimes
|
||||
page: 'app',
|
||||
id: '7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
}) ||
|
||||
isExecutionContextLog(record, {
|
||||
...expectedExecutionContext,
|
||||
// There is a race condition that makes the top context to match the child one
|
||||
page: 'app',
|
||||
type: 'dashboard',
|
||||
id: '7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
}) ||
|
||||
isExecutionContextLog(record, {
|
||||
...expectedExecutionContext,
|
||||
// There is a race condition that makes the top context to match the child one
|
||||
page: 'app',
|
||||
type: 'dashboard',
|
||||
id: '7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
description: '[Flights] Global Flight Dashboard',
|
||||
}) ||
|
||||
// Some race conditions misses one nested step
|
||||
(!!expectedExecutionContext.child &&
|
||||
isExecutionContextLog(record, expectedExecutionContext.child));
|
||||
}
|
||||
|
||||
describe('propagates context for Lens visualizations', () => {
|
||||
it('lnsXY', async () => {
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Elasticsearch via "x-opaque-id" header',
|
||||
predicate: (record) =>
|
||||
Boolean(
|
||||
record.http?.request?.id?.includes(
|
||||
'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;lens:lnsXY:086ac2e9-dd16-4b45-92b8-1e43ff7e3f65'
|
||||
)
|
||||
),
|
||||
predicate: checkHttpRequestId(
|
||||
'dashboard:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;lens:lnsXY:086ac2e9-dd16-4b45-92b8-1e43ff7e3f65'
|
||||
),
|
||||
retry,
|
||||
});
|
||||
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Kibana logs',
|
||||
predicate: (record) =>
|
||||
isExecutionContextLog(record?.message, {
|
||||
type: 'application',
|
||||
name: 'dashboard',
|
||||
predicate: checkExecutionContextEntry({
|
||||
type: 'application',
|
||||
name: 'dashboards',
|
||||
url: '/app/dashboards',
|
||||
child: {
|
||||
name: 'dashboards',
|
||||
url: '/app/dashboards',
|
||||
type: 'dashboard',
|
||||
page: 'app',
|
||||
id: '7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
description: '[Flights] Global Flight Dashboard',
|
||||
url: '/view/7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
child: {
|
||||
type: 'lens',
|
||||
name: 'lnsXY',
|
||||
|
@ -110,7 +187,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
description: '[Flights] Flight count',
|
||||
url: '/app/lens#/edit_by_value',
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
retry,
|
||||
});
|
||||
});
|
||||
|
@ -118,32 +196,34 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
it('lnsMetric', async () => {
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Elasticsearch via "x-opaque-id" header',
|
||||
predicate: (record) =>
|
||||
Boolean(
|
||||
record.http?.request?.id?.includes(
|
||||
'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;lens:lnsMetric:b766e3b8-4544-46ed-99e6-9ecc4847e2a2'
|
||||
)
|
||||
),
|
||||
predicate: checkHttpRequestId(
|
||||
'dashboard:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;lens:lnsLegacyMetric:b766e3b8-4544-46ed-99e6-9ecc4847e2a2'
|
||||
),
|
||||
retry,
|
||||
});
|
||||
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Kibana logs',
|
||||
predicate: (record) =>
|
||||
isExecutionContextLog(record?.message, {
|
||||
type: 'application',
|
||||
name: 'dashboard',
|
||||
predicate: checkExecutionContextEntry({
|
||||
name: 'dashboards',
|
||||
url: '/app/dashboards',
|
||||
type: 'application',
|
||||
child: {
|
||||
name: 'dashboards',
|
||||
url: '/app/dashboards',
|
||||
type: 'dashboard',
|
||||
page: 'app',
|
||||
id: '7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
description: '[Flights] Global Flight Dashboard',
|
||||
url: '/view/7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
child: {
|
||||
type: 'lens',
|
||||
name: 'lnsMetric',
|
||||
id: '2e33ade5-96e5-40b4-b460-493e5d4fa834',
|
||||
name: 'lnsLegacyMetric',
|
||||
id: 'b766e3b8-4544-46ed-99e6-9ecc4847e2a2',
|
||||
description: '',
|
||||
url: '/app/lens#/edit_by_value',
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
retry,
|
||||
});
|
||||
});
|
||||
|
@ -151,24 +231,25 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
it('lnsDatatable', async () => {
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Elasticsearch via "x-opaque-id" header',
|
||||
predicate: (record) =>
|
||||
Boolean(
|
||||
record.http?.request?.id?.includes(
|
||||
'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;lens:lnsDatatable:fb86b32f-fb7a-45cf-9511-f366fef51bbd'
|
||||
)
|
||||
),
|
||||
predicate: checkHttpRequestId(
|
||||
'dashboard:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;lens:lnsDatatable:fb86b32f-fb7a-45cf-9511-f366fef51bbd'
|
||||
),
|
||||
retry,
|
||||
});
|
||||
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Kibana logs',
|
||||
predicate: (record) =>
|
||||
isExecutionContextLog(record?.message, {
|
||||
type: 'application',
|
||||
name: 'dashboard',
|
||||
predicate: checkExecutionContextEntry({
|
||||
name: 'dashboards',
|
||||
url: '/app/dashboards',
|
||||
type: 'application',
|
||||
child: {
|
||||
name: 'dashboards',
|
||||
url: '/app/dashboards',
|
||||
type: 'dashboard',
|
||||
page: 'app',
|
||||
id: '7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
description: '[Flights] Global Flight Dashboard',
|
||||
url: '/view/7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
child: {
|
||||
type: 'lens',
|
||||
name: 'lnsDatatable',
|
||||
|
@ -176,7 +257,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
description: 'Cities by delay, cancellation',
|
||||
url: '/app/lens#/edit_by_value',
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
retry,
|
||||
});
|
||||
});
|
||||
|
@ -184,23 +266,24 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
it('lnsPie', async () => {
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Elasticsearch via "x-opaque-id" header',
|
||||
predicate: (record) =>
|
||||
Boolean(
|
||||
record.http?.request?.id?.includes(
|
||||
'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;lens:lnsPie:5d53db36-2d5a-4adc-af7b-cec4c1a294e0'
|
||||
)
|
||||
),
|
||||
predicate: checkHttpRequestId(
|
||||
'dashboard:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;lens:lnsPie:5d53db36-2d5a-4adc-af7b-cec4c1a294e0'
|
||||
),
|
||||
retry,
|
||||
});
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Kibana logs',
|
||||
predicate: (record) =>
|
||||
isExecutionContextLog(record?.message, {
|
||||
type: 'application',
|
||||
name: 'dashboard',
|
||||
predicate: checkExecutionContextEntry({
|
||||
name: 'dashboards',
|
||||
url: '/app/dashboards',
|
||||
type: 'application',
|
||||
child: {
|
||||
name: 'dashboards',
|
||||
url: '/app/dashboards',
|
||||
type: 'dashboard',
|
||||
page: 'app',
|
||||
id: '7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
description: '[Flights] Global Flight Dashboard',
|
||||
url: '/view/7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
child: {
|
||||
type: 'lens',
|
||||
name: 'lnsPie',
|
||||
|
@ -208,7 +291,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
description: '[Flights] Delay Type',
|
||||
url: '/app/lens#/edit_by_value',
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
retry,
|
||||
});
|
||||
});
|
||||
|
@ -217,23 +301,24 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
it('propagates context for built-in Discover', async () => {
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Elasticsearch via "x-opaque-id" header',
|
||||
predicate: (record) =>
|
||||
Boolean(
|
||||
record.http?.request?.id?.includes(
|
||||
'application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;search:discover:571aaf70-4c88-11e8-b3d7-01146121b73d'
|
||||
)
|
||||
),
|
||||
predicate: checkHttpRequestId(
|
||||
'dashboard:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;search:discover:571aaf70-4c88-11e8-b3d7-01146121b73d'
|
||||
),
|
||||
retry,
|
||||
});
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Kibana logs',
|
||||
predicate: (record) =>
|
||||
isExecutionContextLog(record?.message, {
|
||||
type: 'application',
|
||||
name: 'dashboard',
|
||||
predicate: checkExecutionContextEntry({
|
||||
type: 'application',
|
||||
name: 'dashboards',
|
||||
url: '/app/dashboards',
|
||||
child: {
|
||||
type: 'dashboard',
|
||||
name: 'dashboards',
|
||||
url: '/app/dashboards',
|
||||
page: 'app',
|
||||
id: '7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
description: '[Flights] Global Flight Dashboard',
|
||||
url: '/view/7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
child: {
|
||||
type: 'search',
|
||||
name: 'discover',
|
||||
|
@ -241,7 +326,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
description: '[Flights] Flight Log',
|
||||
url: '/app/discover#/view/571aaf70-4c88-11e8-b3d7-01146121b73d',
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
retry,
|
||||
});
|
||||
});
|
||||
|
@ -249,66 +335,61 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
it('propagates context for TSVB visualizations', async () => {
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Elasticsearch via "x-opaque-id" header',
|
||||
predicate: (record) =>
|
||||
Boolean(
|
||||
record.http?.request?.id?.includes(
|
||||
'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:metrics:bcb63b50-4c89-11e8-b3d7-01146121b73d'
|
||||
)
|
||||
),
|
||||
predicate: checkHttpRequestId('agg_based:metrics:bcb63b50-4c89-11e8-b3d7-01146121b73d'),
|
||||
retry,
|
||||
});
|
||||
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Kibana logs',
|
||||
predicate: (record) =>
|
||||
isExecutionContextLog(record?.message, {
|
||||
type: 'application',
|
||||
name: 'dashboard',
|
||||
id: '7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
description: '[Flights] Global Flight Dashboard',
|
||||
url: '/view/7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
child: {
|
||||
type: 'visualization',
|
||||
name: 'metrics',
|
||||
id: 'bcb63b50-4c89-11e8-b3d7-01146121b73d',
|
||||
description: '[Flights] Delays & Cancellations',
|
||||
url: '/app/visualize#/edit/bcb63b50-4c89-11e8-b3d7-01146121b73d',
|
||||
},
|
||||
}),
|
||||
predicate: checkExecutionContextEntry({
|
||||
name: 'dashboards',
|
||||
url: '/app/dashboards',
|
||||
type: 'application',
|
||||
page: 'app',
|
||||
description: '[Flights] Global Flight Dashboard',
|
||||
child: {
|
||||
type: 'agg_based',
|
||||
name: 'metrics',
|
||||
id: 'bcb63b50-4c89-11e8-b3d7-01146121b73d',
|
||||
description: '[Flights] Delays & Cancellations',
|
||||
url: '/app/visualize#/edit/bcb63b50-4c89-11e8-b3d7-01146121b73d',
|
||||
},
|
||||
}),
|
||||
retry,
|
||||
});
|
||||
});
|
||||
|
||||
// application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:vega:ed78a660-53a0-11e8-acbd-0be0ad9d822b
|
||||
it('propagates context for Vega visualizations', async () => {
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Elasticsearch via "x-opaque-id" header',
|
||||
predicate: (record) =>
|
||||
Boolean(
|
||||
record.http?.request?.id?.includes(
|
||||
'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:vega:ed78a660-53a0-11e8-acbd-0be0ad9d822b'
|
||||
)
|
||||
),
|
||||
predicate: checkHttpRequestId(
|
||||
'dashboard:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;agg_based:vega:ed78a660-53a0-11e8-acbd-0be0ad9d822b'
|
||||
),
|
||||
retry,
|
||||
});
|
||||
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Kibana logs',
|
||||
predicate: (record) =>
|
||||
isExecutionContextLog(record?.message, {
|
||||
type: 'application',
|
||||
name: 'dashboard',
|
||||
predicate: checkExecutionContextEntry({
|
||||
name: 'dashboards',
|
||||
url: '/app/dashboards',
|
||||
type: 'application',
|
||||
child: {
|
||||
name: 'dashboards',
|
||||
url: '/app/dashboards',
|
||||
type: 'dashboard',
|
||||
page: 'app',
|
||||
id: '7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
description: '[Flights] Global Flight Dashboard',
|
||||
url: '/view/7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
child: {
|
||||
type: 'visualization',
|
||||
type: 'agg_based',
|
||||
name: 'vega',
|
||||
id: 'ed78a660-53a0-11e8-acbd-0be0ad9d822b',
|
||||
description: '[Flights] Airport Connections (Hover Over Airport)',
|
||||
url: '/app/visualize#/edit/ed78a660-53a0-11e8-acbd-0be0ad9d822b',
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
retry,
|
||||
});
|
||||
});
|
||||
|
@ -316,32 +397,34 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
it('propagates context for Tag Cloud visualization', async () => {
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Elasticsearch via "x-opaque-id" header',
|
||||
predicate: (record) =>
|
||||
Boolean(
|
||||
record.http?.request?.id?.includes(
|
||||
'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:tagcloud:293b5a30-4c8f-11e8-b3d7-01146121b73d'
|
||||
)
|
||||
),
|
||||
predicate: checkHttpRequestId(
|
||||
'dashboard:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;agg_based:tagcloud:293b5a30-4c8f-11e8-b3d7-01146121b73d'
|
||||
),
|
||||
retry,
|
||||
});
|
||||
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Kibana logs',
|
||||
predicate: (record) =>
|
||||
isExecutionContextLog(record?.message, {
|
||||
type: 'application',
|
||||
name: 'dashboard',
|
||||
predicate: checkExecutionContextEntry({
|
||||
name: 'dashboards',
|
||||
url: '/app/dashboards',
|
||||
type: 'application',
|
||||
child: {
|
||||
name: 'dashboards',
|
||||
url: '/app/dashboards',
|
||||
type: 'dashboard',
|
||||
page: 'app',
|
||||
id: '7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
description: '[Flights] Global Flight Dashboard',
|
||||
url: '/view/7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
child: {
|
||||
type: 'visualization',
|
||||
type: 'agg_based',
|
||||
name: 'tagcloud',
|
||||
id: '293b5a30-4c8f-11e8-b3d7-01146121b73d',
|
||||
description: '[Flights] Destination Weather',
|
||||
url: '/app/visualize#/edit/293b5a30-4c8f-11e8-b3d7-01146121b73d',
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
retry,
|
||||
});
|
||||
});
|
||||
|
@ -349,32 +432,34 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
it('propagates context for Vertical bar visualization', async () => {
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Elasticsearch via "x-opaque-id" header',
|
||||
predicate: (record) =>
|
||||
Boolean(
|
||||
record.http?.request?.id?.includes(
|
||||
'kibana:application:dashboard:7adfa750-4c81-11e8-b3d7-01146121b73d;visualization:histogram:9886b410-4c8b-11e8-b3d7-01146121b73d'
|
||||
)
|
||||
),
|
||||
predicate: checkHttpRequestId(
|
||||
'dashboard:dashboards:7adfa750-4c81-11e8-b3d7-01146121b73d;agg_based:histogram:9886b410-4c8b-11e8-b3d7-01146121b73d'
|
||||
),
|
||||
retry,
|
||||
});
|
||||
|
||||
await assertLogContains({
|
||||
description: 'execution context propagates to Kibana logs',
|
||||
predicate: (record) =>
|
||||
isExecutionContextLog(record?.message, {
|
||||
type: 'application',
|
||||
name: 'dashboard',
|
||||
predicate: checkExecutionContextEntry({
|
||||
type: 'application',
|
||||
name: 'dashboards',
|
||||
url: '/app/dashboards',
|
||||
child: {
|
||||
type: 'dashboard',
|
||||
name: 'dashboards',
|
||||
url: '/app/dashboards',
|
||||
page: 'app',
|
||||
id: '7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
description: '[Flights] Global Flight Dashboard',
|
||||
url: '/view/7adfa750-4c81-11e8-b3d7-01146121b73d',
|
||||
child: {
|
||||
type: 'visualization',
|
||||
type: 'agg_based',
|
||||
name: 'histogram',
|
||||
id: '9886b410-4c8b-11e8-b3d7-01146121b73d',
|
||||
description: '[Flights] Delay Buckets',
|
||||
url: '/app/visualize#/edit/9886b410-4c8b-11e8-b3d7-01146121b73d',
|
||||
},
|
||||
}),
|
||||
},
|
||||
}),
|
||||
retry,
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,9 +6,19 @@
|
|||
*/
|
||||
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
import { clearLogFile, closeLogstream } from '../test_utils';
|
||||
|
||||
export default function ({ loadTestFile }: FtrProviderContext) {
|
||||
describe('Execution context', function () {
|
||||
before(async () => {
|
||||
// Cleaning the log file used for the tests to avoid false positives caused by previous runs.
|
||||
// If any of the tests rely on logs generating during bootstrap, we might need to change this.
|
||||
await clearLogFile();
|
||||
});
|
||||
after(() => {
|
||||
closeLogstream();
|
||||
});
|
||||
|
||||
loadTestFile(require.resolve('./browser'));
|
||||
loadTestFile(require.resolve('./server'));
|
||||
loadTestFile(require.resolve('./log_correlation'));
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
*/
|
||||
import expect from '@kbn/expect';
|
||||
import type { FtrProviderContext } from '../ftr_provider_context';
|
||||
import { assertLogContains } from '../test_utils';
|
||||
import { assertLogContains, forceSyncLogFile } from '../test_utils';
|
||||
|
||||
export default function ({ getService }: FtrProviderContext) {
|
||||
const retry = getService('retry');
|
||||
|
@ -24,12 +24,14 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
|
||||
expect(response2.body.traceId).not.to.be(response1.body.traceId);
|
||||
|
||||
await forceSyncLogFile();
|
||||
|
||||
let responseTraceId: string | undefined;
|
||||
await assertLogContains({
|
||||
description: 'traceId included in the http logs',
|
||||
predicate: (record) => {
|
||||
// we don't check trace.id value since trace.id in the test plugin and Kibana are different on CI.
|
||||
// because different 'elastic-apm-node' instaces are imported
|
||||
// because different 'elastic-apm-node' instances are imported
|
||||
if (
|
||||
record.log?.logger === 'http.server.response' &&
|
||||
record.url?.path === '/emit_log_with_trace_id'
|
||||
|
|
|
@ -92,7 +92,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
await assertLogContains({
|
||||
description: 'execution context propagates to Kibana logs',
|
||||
predicate: (record) =>
|
||||
isExecutionContextLog(record?.message, {
|
||||
isExecutionContextLog(record, {
|
||||
type: 'task manager',
|
||||
name: 'run alerting:test.executionContext',
|
||||
// @ts-expect-error. it accepts strings only
|
||||
|
@ -132,7 +132,7 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
await assertLogContains({
|
||||
description: 'execution context propagates to Kibana logs',
|
||||
predicate: (record) =>
|
||||
isExecutionContextLog(record?.message, {
|
||||
isExecutionContextLog(record, {
|
||||
type: 'usage_collection',
|
||||
name: 'collector.fetch',
|
||||
id: 'application_usage',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue