Skip to content

Commit

Permalink
Merge branch 'master' into apm-error-rate
Browse files Browse the repository at this point in the history
  • Loading branch information
elasticmachine authored Sep 16, 2020
2 parents 463eafa + 9b6edc5 commit 5f542cf
Show file tree
Hide file tree
Showing 41 changed files with 8,511 additions and 584 deletions.
2 changes: 1 addition & 1 deletion docs/api/dashboard/import-dashboard.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ experimental[] Import dashboards and corresponding saved objects.
[[dashboard-api-import-request-body]]
==== Request body

Use the complete response body from the <<dashboard-api-export, Export dashboard API>> as the request body. Do not manually construct a payload to the endpoint.
Use the complete response body from the <<dashboard-api-export, Export dashboard API>> as the request body. Do not manually construct a payload to the endpoint. The max payload size is determined by the `savedObjects.maxImportPayloadBytes` configuration key.

[[dashboard-api-import-response-body]]
==== Response body
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ export declare type SharedGlobalConfig = RecursiveReadonly<{
kibana: Pick<KibanaConfigType, typeof SharedGlobalConfigKeys.kibana[number]>;
elasticsearch: Pick<ElasticsearchConfigType, typeof SharedGlobalConfigKeys.elasticsearch[number]>;
path: Pick<PathConfigType, typeof SharedGlobalConfigKeys.path[number]>;
savedObjects: Pick<SavedObjectsConfigType, typeof SharedGlobalConfigKeys.savedObjects[number]>;
}>;
```
4 changes: 4 additions & 0 deletions src/core/server/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
*/
import { of } from 'rxjs';
import { duration } from 'moment';
import { ByteSizeValue } from '@kbn/config-schema';
import { PluginInitializerContext, CoreSetup, CoreStart, StartServicesAccessor } from '.';
import { loggingSystemMock } from './logging/logging_system.mock';
import { loggingServiceMock } from './logging/logging_service.mock';
Expand Down Expand Up @@ -66,6 +67,9 @@ export function pluginInitializerContextConfigMock<T>(config: T) {
startupTimeout: duration('30s'),
},
path: { data: '/tmp' },
savedObjects: {
maxImportPayloadBytes: new ByteSizeValue(10485760),
},
};

const mock: jest.Mocked<PluginInitializerContext<T>['config']> = {
Expand Down
2 changes: 2 additions & 0 deletions src/core/server/plugins/plugin_context.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { rawConfigServiceMock, getEnvOptions } from '../config/mocks';
import { PluginManifest } from './types';
import { Server } from '../server';
import { fromRoot } from '../utils';
import { ByteSizeValue } from '@kbn/config-schema';

const logger = loggingSystemMock.create();

Expand Down Expand Up @@ -93,6 +94,7 @@ describe('createPluginInitializerContext', () => {
startupTimeout: duration(5, 's'),
},
path: { data: fromRoot('data') },
savedObjects: { maxImportPayloadBytes: new ByteSizeValue(10485760) },
});
});

Expand Down
11 changes: 7 additions & 4 deletions src/core/server/plugins/plugin_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
ElasticsearchConfigType,
config as elasticsearchConfig,
} from '../elasticsearch/elasticsearch_config';
import { SavedObjectsConfigType, savedObjectsConfig } from '../saved_objects/saved_objects_config';
import { CoreSetup, CoreStart } from '..';

export interface InstanceInfo {
Expand Down Expand Up @@ -91,16 +92,18 @@ export function createPluginInitializerContext(
* Note: naming not final here, it will be renamed in a near future (https://github.com/elastic/kibana/issues/46240)
* @deprecated
*/
globalConfig$: combineLatest(
globalConfig$: combineLatest([
coreContext.configService.atPath<KibanaConfigType>(kibanaConfig.path),
coreContext.configService.atPath<ElasticsearchConfigType>(elasticsearchConfig.path),
coreContext.configService.atPath<PathConfigType>(pathConfig.path)
).pipe(
map(([kibana, elasticsearch, path]) =>
coreContext.configService.atPath<PathConfigType>(pathConfig.path),
coreContext.configService.atPath<SavedObjectsConfigType>(savedObjectsConfig.path),
]).pipe(
map(([kibana, elasticsearch, path, savedObjects]) =>
deepFreeze({
kibana: pick(kibana, SharedGlobalConfigKeys.kibana),
elasticsearch: pick(elasticsearch, SharedGlobalConfigKeys.elasticsearch),
path: pick(path, SharedGlobalConfigKeys.path),
savedObjects: pick(savedObjects, SharedGlobalConfigKeys.savedObjects),
})
)
),
Expand Down
3 changes: 3 additions & 0 deletions src/core/server/plugins/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { ConfigPath, EnvironmentMode, PackageInfo, ConfigDeprecationProvider } f
import { LoggerFactory } from '../logging';
import { KibanaConfigType } from '../kibana_config';
import { ElasticsearchConfigType } from '../elasticsearch/elasticsearch_config';
import { SavedObjectsConfigType } from '../saved_objects/saved_objects_config';
import { CoreSetup, CoreStart } from '..';

/**
Expand Down Expand Up @@ -263,6 +264,7 @@ export const SharedGlobalConfigKeys = {
kibana: ['index', 'autocompleteTerminateAfter', 'autocompleteTimeout'] as const,
elasticsearch: ['shardTimeout', 'requestTimeout', 'pingTimeout', 'startupTimeout'] as const,
path: ['data'] as const,
savedObjects: ['maxImportPayloadBytes'] as const,
};

/**
Expand All @@ -272,6 +274,7 @@ export type SharedGlobalConfig = RecursiveReadonly<{
kibana: Pick<KibanaConfigType, typeof SharedGlobalConfigKeys.kibana[number]>;
elasticsearch: Pick<ElasticsearchConfigType, typeof SharedGlobalConfigKeys.elasticsearch[number]>;
path: Pick<PathConfigType, typeof SharedGlobalConfigKeys.path[number]>;
savedObjects: Pick<SavedObjectsConfigType, typeof SharedGlobalConfigKeys.savedObjects[number]>;
}>;

/**
Expand Down
6 changes: 4 additions & 2 deletions src/core/server/server.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2661,6 +2661,7 @@ export type SharedGlobalConfig = RecursiveReadonly<{
kibana: Pick<KibanaConfigType_2, typeof SharedGlobalConfigKeys.kibana[number]>;
elasticsearch: Pick<ElasticsearchConfigType, typeof SharedGlobalConfigKeys.elasticsearch[number]>;
path: Pick<PathConfigType, typeof SharedGlobalConfigKeys.path[number]>;
savedObjects: Pick<SavedObjectsConfigType, typeof SharedGlobalConfigKeys.savedObjects[number]>;
}>;

// @public
Expand Down Expand Up @@ -2745,7 +2746,8 @@ export const validBodyOutput: readonly ["data", "stream"];
//
// src/core/server/http/router/response.ts:316:3 - (ae-forgotten-export) The symbol "KibanaResponse" needs to be exported by the entry point index.d.ts
// src/core/server/legacy/types.ts:135:16 - (ae-forgotten-export) The symbol "LegacyPluginSpec" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:272:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:272:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:274:3 - (ae-forgotten-export) The symbol "KibanaConfigType" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:274:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts
// src/core/server/plugins/types.ts:277:3 - (ae-forgotten-export) The symbol "SavedObjectsConfigType" needs to be exported by the entry point index.d.ts

```
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,13 @@ describe('IndexPatterns', () => {
test('caches saved objects', async () => {
await indexPatterns.getIds();
await indexPatterns.getTitles();
await indexPatterns.getFields(['id', 'title']);
expect(savedObjectsClient.find).toHaveBeenCalledTimes(1);
});

test('can refresh the saved objects caches', async () => {
await indexPatterns.getIds();
await indexPatterns.getTitles(true);
await indexPatterns.getFields(['id', 'title'], true);
expect(savedObjectsClient.find).toHaveBeenCalledTimes(3);
expect(savedObjectsClient.find).toHaveBeenCalledTimes(2);
});

test('deletes the index pattern', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ const indexPatternCache = createIndexPatternCache();
const MAX_ATTEMPTS_TO_RESOLVE_CONFLICTS = 3;
const savedObjectType = 'index-pattern';

type IndexPatternCachedFieldType = 'id' | 'title';

export interface IndexPatternSavedObjectAttrs {
title: string;
}
Expand Down Expand Up @@ -116,22 +114,6 @@ export class IndexPatternsService {
return this.savedObjectsCache.map((obj) => obj?.attributes?.title);
};

getFields = async (fields: IndexPatternCachedFieldType[], refresh: boolean = false) => {
if (!this.savedObjectsCache || refresh) {
await this.refreshSavedObjectsCache();
}
if (!this.savedObjectsCache) {
return [];
}
return this.savedObjectsCache.map((obj: Record<string, any>) => {
const result: Partial<Record<IndexPatternCachedFieldType, string>> = {};
fields.forEach(
(f: IndexPatternCachedFieldType) => (result[f] = obj[f] || obj?.attributes?.[f])
);
return result;
});
};

getFieldsForTimePattern = (options: GetFieldsOptions = {}) => {
return this.apiClient.getFieldsForTimePattern(options);
};
Expand Down
17 changes: 11 additions & 6 deletions src/plugins/legacy_export/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,23 @@
*/

import { Plugin, CoreSetup, PluginInitializerContext } from 'kibana/server';
import { first } from 'rxjs/operators';
import { registerRoutes } from './routes';

export class LegacyExportPlugin implements Plugin<{}, {}> {
private readonly kibanaVersion: string;
constructor(private readonly initContext: PluginInitializerContext) {}

constructor(context: PluginInitializerContext) {
this.kibanaVersion = context.env.packageInfo.version;
}
public async setup({ http }: CoreSetup) {
const globalConfig = await this.initContext.config.legacy.globalConfig$
.pipe(first())
.toPromise();

public setup({ http }: CoreSetup) {
const router = http.createRouter();
registerRoutes(router, this.kibanaVersion);
registerRoutes(
router,
this.initContext.env.packageInfo.version,
globalConfig.savedObjects.maxImportPayloadBytes.getValueInBytes()
);

return {};
}
Expand Down
5 changes: 4 additions & 1 deletion src/plugins/legacy_export/server/routes/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { schema } from '@kbn/config-schema';
import { IRouter, SavedObject } from 'src/core/server';
import { importDashboards } from '../lib';

export const registerImportRoute = (router: IRouter) => {
export const registerImportRoute = (router: IRouter, maxImportPayloadBytes: number) => {
router.post(
{
path: '/api/kibana/dashboards/import',
Expand All @@ -39,6 +39,9 @@ export const registerImportRoute = (router: IRouter) => {
},
options: {
tags: ['api'],
body: {
maxBytes: maxImportPayloadBytes,
},
},
},
async (ctx, req, res) => {
Expand Down
8 changes: 6 additions & 2 deletions src/plugins/legacy_export/server/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ import { IRouter } from 'src/core/server';
import { registerImportRoute } from './import';
import { registerExportRoute } from './export';

export const registerRoutes = (router: IRouter, kibanaVersion: string) => {
export const registerRoutes = (
router: IRouter,
kibanaVersion: string,
maxImportPayloadBytes: number
) => {
registerExportRoute(router, kibanaVersion);
registerImportRoute(router);
registerImportRoute(router, maxImportPayloadBytes);
};

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ describe('Flyout', () => {
done: jest.fn(),
newIndexPatternUrl: '',
indexPatterns: {
getFields: jest.fn().mockImplementation(() => [{ id: '1' }, { id: '2' }]),
getCache: jest.fn().mockImplementation(() => [
{ id: '1', attributes: {} },
{ id: '2', attributes: {} },
]),
} as any,
overlays,
http,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,10 @@ export class Flyout extends Component<FlyoutProps, FlyoutState> {
}

fetchIndexPatterns = async () => {
const indexPatterns = await this.props.indexPatterns.getFields(['id', 'title']);
const indexPatterns = (await this.props.indexPatterns.getCache())?.map((savedObject) => ({
id: savedObject.id,
title: savedObject.attributes.title,
}));
this.setState({ indexPatterns } as any);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,22 @@
*/
import * as React from 'react';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';

import { useFetcher } from '../../../../hooks/useFetcher';
import { useUrlParams } from '../../../../hooks/useUrlParams';
import { CLS_LABEL, FID_LABEL, LCP_LABEL } from './translations';
import { CoreVitalItem } from './CoreVitalItem';
import { UXMetrics } from '../UXMetrics';

const CoreVitalsThresholds = {
LCP: { good: '2.5s', bad: '4.0s' },
FID: { good: '100ms', bad: '300ms' },
CLS: { good: '0.1', bad: '0.25' },
};

export function CoreVitals() {
const { urlParams, uiFilters } = useUrlParams();

const { start, end } = urlParams;

const { data, status } = useFetcher(
(callApmApi) => {
const { serviceName } = uiFilters;
if (start && end && serviceName) {
return callApmApi({
pathname: '/api/apm/rum-client/web-core-vitals',
params: {
query: { start, end, uiFilters: JSON.stringify(uiFilters) },
},
});
}
return Promise.resolve(null);
},
[start, end, uiFilters]
);
interface Props {
data?: UXMetrics | null;
loading: boolean;
}

export function CoreVitals({ data, loading }: Props) {
const { lcp, lcpRanks, fid, fidRanks, cls, clsRanks } = data || {};

return (
Expand All @@ -47,7 +30,7 @@ export function CoreVitals() {
title={LCP_LABEL}
value={lcp ? lcp + 's' : '0'}
ranks={lcpRanks}
loading={status !== 'success'}
loading={loading}
thresholds={CoreVitalsThresholds.LCP}
/>
</EuiFlexItem>
Expand All @@ -56,7 +39,7 @@ export function CoreVitals() {
title={FID_LABEL}
value={fid ? fid + 's' : '0'}
ranks={fidRanks}
loading={status !== 'success'}
loading={loading}
thresholds={CoreVitalsThresholds.FID}
/>
</EuiFlexItem>
Expand All @@ -65,7 +48,7 @@ export function CoreVitals() {
title={CLS_LABEL}
value={cls ?? '0'}
ranks={clsRanks}
loading={status !== 'success'}
loading={loading}
thresholds={CoreVitalsThresholds.CLS}
/>
</EuiFlexItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,27 @@ export const TBT_LABEL = i18n.translate('xpack.apm.rum.coreVitals.tbt', {
defaultMessage: 'Total blocking time',
});

export const NO_OF_LONG_TASK = i18n.translate(
'xpack.apm.rum.uxMetrics.noOfLongTasks',
{
defaultMessage: 'No. of long tasks',
}
);

export const LONGEST_LONG_TASK = i18n.translate(
'xpack.apm.rum.uxMetrics.longestLongTasks',
{
defaultMessage: 'Longest long task duration',
}
);

export const SUM_LONG_TASKS = i18n.translate(
'xpack.apm.rum.uxMetrics.sumLongTasks',
{
defaultMessage: 'Total long tasks duration',
}
);

export const POOR_LABEL = i18n.translate('xpack.apm.rum.coreVitals.poor', {
defaultMessage: 'a poor',
});
Expand Down
Loading

0 comments on commit 5f542cf

Please sign in to comment.