Convert to using new status, and remove legacy plugin (#75806)
* Convert to using new status, and remove legacy plugin * PR feedback * Fix test Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
b21071e54b
commit
54926523e8
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
|
@ -85,7 +85,6 @@
|
|||
/x-pack/plugins/ingest_manager/ @elastic/ingest-management
|
||||
/x-pack/legacy/plugins/ingest_manager/ @elastic/ingest-management
|
||||
/x-pack/plugins/observability/ @elastic/observability-ui
|
||||
/x-pack/legacy/plugins/monitoring/ @elastic/stack-monitoring-ui
|
||||
/x-pack/plugins/monitoring/ @elastic/stack-monitoring-ui
|
||||
/x-pack/plugins/uptime @elastic/uptime
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
"xpack.main": "legacy/plugins/xpack_main",
|
||||
"xpack.maps": ["plugins/maps", "legacy/plugins/maps"],
|
||||
"xpack.ml": ["plugins/ml", "legacy/plugins/ml"],
|
||||
"xpack.monitoring": ["plugins/monitoring", "legacy/plugins/monitoring"],
|
||||
"xpack.monitoring": ["plugins/monitoring"],
|
||||
"xpack.remoteClusters": "plugins/remote_clusters",
|
||||
"xpack.painlessLab": "plugins/painless_lab",
|
||||
"xpack.reporting": ["plugins/reporting"],
|
||||
|
|
|
@ -5,10 +5,9 @@
|
|||
*/
|
||||
|
||||
import { xpackMain } from './legacy/plugins/xpack_main';
|
||||
import { monitoring } from './legacy/plugins/monitoring';
|
||||
import { security } from './legacy/plugins/security';
|
||||
import { spaces } from './legacy/plugins/spaces';
|
||||
|
||||
module.exports = function (kibana) {
|
||||
return [xpackMain(kibana), monitoring(kibana), spaces(kibana), security(kibana)];
|
||||
return [xpackMain(kibana), spaces(kibana), security(kibana)];
|
||||
};
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
## Using Monitoring
|
||||
|
||||
The easiest way to get to know the new Monitoring is probably by [reading the
|
||||
docs](https://github.com/elastic/x-plugins/blob/master/docs/public/marvel/index.asciidoc).
|
||||
|
||||
Install the distribution the way a customer would is pending the first release
|
||||
of Unified X-Pack plugins.
|
||||
|
||||
## Developing
|
||||
|
||||
You will need to get Elasticsearch and X-Pack plugins for ES that match the
|
||||
version of the UI. The best way to do this is to run `gradle run` from a clone
|
||||
of the x-plugins repository.
|
||||
|
||||
To set up Monitoring and automatic file syncing code changes into Kibana's plugin
|
||||
directory, clone the kibana and x-plugins repos in the same directory and from
|
||||
`x-plugins/kibana/monitoring`, run `yarn start`.
|
||||
|
||||
Once the syncing process has run at least once, start the Kibana server in
|
||||
development mode. It will handle restarting the server and re-optimizing the
|
||||
bundles as-needed. Go to https://localhost:5601 and click Monitoring from the App
|
||||
Drawer.
|
||||
|
||||
## Running tests
|
||||
|
||||
- Run the command:
|
||||
```
|
||||
yarn test
|
||||
```
|
||||
|
||||
- Debug tests
|
||||
Add a `debugger` line to create a breakpoint, and then:
|
||||
|
||||
```
|
||||
gulp sync && mocha debug --compilers js:@babel/register /pathto/kibana/plugins/monitoring/pathto/__tests__/testfile.js
|
||||
```
|
||||
|
||||
## Multicluster Setup for Development
|
||||
|
||||
To run the UI with multiple clusters, the easiest way is to run 2 nodes out of
|
||||
the same Elasticsearch directory, but use different start up commands for each one. One
|
||||
node will be assigned to the "monitoring" cluster and the other will be for the "production"
|
||||
cluster.
|
||||
|
||||
1. Add the Security users:
|
||||
```
|
||||
% ./bin/x-pack/users useradd -r remote_monitoring_agent -p notsecure remote
|
||||
% ./bin/x-pack/users useradd -r monitoring_user -p notsecure monitoring_user
|
||||
```
|
||||
|
||||
1. Start up the Monitoring cluster:
|
||||
```
|
||||
% ./bin/elasticsearch \
|
||||
-Ehttp.port=9210 \
|
||||
-Ecluster.name=monitoring \
|
||||
-Epath.data=monitoring-data \
|
||||
-Enode.name=monitor1node1
|
||||
```
|
||||
|
||||
1. Start up the Production cluster:
|
||||
```
|
||||
% ./bin/elasticsearch \
|
||||
-Expack.monitoring.exporters.id2.type=http \
|
||||
-Expack.monitoring.exporters.id2.host=http://127.0.0.1:9210 \
|
||||
-Expack.monitoring.exporters.id2.auth.username=remote \
|
||||
-Expack.monitoring.exporters.id2.auth.password=notsecure \
|
||||
-Ecluster.name=production \
|
||||
-Enode.name=prod1node1 \
|
||||
-Epath.data=production-data
|
||||
```
|
||||
|
||||
1. Set the Kibana config:
|
||||
```
|
||||
% cat config/kibana.dev.yml
|
||||
monitoring.ui.elasticsearch:
|
||||
hosts: "http://localhost:9210"
|
||||
username: "kibana_system"
|
||||
password: "changeme"
|
||||
```
|
||||
|
||||
1. Start another Kibana instance:
|
||||
```
|
||||
% yarn start
|
||||
```
|
||||
|
||||
1. Start a Kibana instance connected to the Monitoring cluster (for running queries in Sense on Monitoring data):
|
||||
```
|
||||
% ./bin/kibana --config config/kibana.dev.yml --elasticsearch.hosts http://localhost:9210 --server.name monitoring-kibana --server.port 5611
|
||||
```
|
|
@ -1,129 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* User-configurable settings for xpack.monitoring via configuration schema
|
||||
* @param {Object} Joi - HapiJS Joi module that allows for schema validation
|
||||
* @return {Object} config schema
|
||||
*/
|
||||
export const config = (Joi: any) => {
|
||||
const DEFAULT_REQUEST_HEADERS = ['authorization'];
|
||||
|
||||
return Joi.object({
|
||||
enabled: Joi.boolean().default(true),
|
||||
ui: Joi.object({
|
||||
enabled: Joi.boolean().default(true),
|
||||
logs: Joi.object({
|
||||
index: Joi.string().default('filebeat-*'),
|
||||
}).default(),
|
||||
ccs: Joi.object({
|
||||
enabled: Joi.boolean().default(true),
|
||||
}).default(),
|
||||
container: Joi.object({
|
||||
elasticsearch: Joi.object({
|
||||
enabled: Joi.boolean().default(false),
|
||||
}).default(),
|
||||
logstash: Joi.object({
|
||||
enabled: Joi.boolean().default(false),
|
||||
}).default(),
|
||||
}).default(),
|
||||
max_bucket_size: Joi.number().default(10000),
|
||||
min_interval_seconds: Joi.number().default(10),
|
||||
show_license_expiration: Joi.boolean().default(true),
|
||||
elasticsearch: Joi.object({
|
||||
customHeaders: Joi.object().default({}),
|
||||
logQueries: Joi.boolean().default(false),
|
||||
requestHeadersWhitelist: Joi.array().items().single().default(DEFAULT_REQUEST_HEADERS),
|
||||
sniffOnStart: Joi.boolean().default(false),
|
||||
sniffInterval: Joi.number().allow(false).default(false),
|
||||
sniffOnConnectionFault: Joi.boolean().default(false),
|
||||
hosts: Joi.array()
|
||||
.items(Joi.string().uri({ scheme: ['http', 'https'] }))
|
||||
.single(), // if empty, use Kibana's connection config
|
||||
username: Joi.string(),
|
||||
password: Joi.string(),
|
||||
requestTimeout: Joi.number().default(30000),
|
||||
pingTimeout: Joi.number().default(30000),
|
||||
ssl: Joi.object({
|
||||
verificationMode: Joi.string().valid('none', 'certificate', 'full').default('full'),
|
||||
certificateAuthorities: Joi.array().single().items(Joi.string()),
|
||||
certificate: Joi.string(),
|
||||
key: Joi.string(),
|
||||
keyPassphrase: Joi.string(),
|
||||
keystore: Joi.object({
|
||||
path: Joi.string(),
|
||||
password: Joi.string(),
|
||||
}).default(),
|
||||
truststore: Joi.object({
|
||||
path: Joi.string(),
|
||||
password: Joi.string(),
|
||||
}).default(),
|
||||
alwaysPresentCertificate: Joi.boolean().default(false),
|
||||
}).default(),
|
||||
apiVersion: Joi.string().default('master'),
|
||||
logFetchCount: Joi.number().default(10),
|
||||
}).default(),
|
||||
}).default(),
|
||||
kibana: Joi.object({
|
||||
collection: Joi.object({
|
||||
enabled: Joi.boolean().default(true),
|
||||
interval: Joi.number().default(10000), // op status metrics get buffered at `ops.interval` and flushed to the bulk endpoint at this interval
|
||||
}).default(),
|
||||
}).default(),
|
||||
elasticsearch: Joi.object({
|
||||
customHeaders: Joi.object().default({}),
|
||||
logQueries: Joi.boolean().default(false),
|
||||
requestHeadersWhitelist: Joi.array().items().single().default(DEFAULT_REQUEST_HEADERS),
|
||||
sniffOnStart: Joi.boolean().default(false),
|
||||
sniffInterval: Joi.number().allow(false).default(false),
|
||||
sniffOnConnectionFault: Joi.boolean().default(false),
|
||||
hosts: Joi.array()
|
||||
.items(Joi.string().uri({ scheme: ['http', 'https'] }))
|
||||
.single(), // if empty, use Kibana's connection config
|
||||
username: Joi.string(),
|
||||
password: Joi.string(),
|
||||
requestTimeout: Joi.number().default(30000),
|
||||
pingTimeout: Joi.number().default(30000),
|
||||
ssl: Joi.object({
|
||||
verificationMode: Joi.string().valid('none', 'certificate', 'full').default('full'),
|
||||
certificateAuthorities: Joi.array().single().items(Joi.string()),
|
||||
certificate: Joi.string(),
|
||||
key: Joi.string(),
|
||||
keyPassphrase: Joi.string(),
|
||||
keystore: Joi.object({
|
||||
path: Joi.string(),
|
||||
password: Joi.string(),
|
||||
}).default(),
|
||||
truststore: Joi.object({
|
||||
path: Joi.string(),
|
||||
password: Joi.string(),
|
||||
}).default(),
|
||||
alwaysPresentCertificate: Joi.boolean().default(false),
|
||||
}).default(),
|
||||
apiVersion: Joi.string().default('master'),
|
||||
}).default(),
|
||||
cluster_alerts: Joi.object({
|
||||
enabled: Joi.boolean().default(true),
|
||||
email_notifications: Joi.object({
|
||||
enabled: Joi.boolean().default(true),
|
||||
email_address: Joi.string().email(),
|
||||
}).default(),
|
||||
}).default(),
|
||||
licensing: Joi.object({
|
||||
api_polling_frequency: Joi.number().default(30001),
|
||||
}),
|
||||
agent: Joi.object({
|
||||
interval: Joi.string()
|
||||
.regex(/[\d\.]+[yMwdhms]/)
|
||||
.default('10s'),
|
||||
}).default(),
|
||||
tests: Joi.object({
|
||||
cloud_detector: Joi.object({
|
||||
enabled: Joi.boolean().default(true),
|
||||
}).default(),
|
||||
}).default(),
|
||||
}).default();
|
||||
};
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import Hapi from 'hapi';
|
||||
import { config } from './config';
|
||||
|
||||
/**
|
||||
* Invokes plugin modules to instantiate the Monitoring plugin for Kibana
|
||||
* @param kibana {Object} Kibana plugin instance
|
||||
* @return {Object} Monitoring UI Kibana plugin object
|
||||
*/
|
||||
const deps = ['kibana', 'elasticsearch', 'xpack_main'];
|
||||
export const monitoring = (kibana: any) => {
|
||||
return new kibana.Plugin({
|
||||
require: deps,
|
||||
id: 'monitoring',
|
||||
configPrefix: 'monitoring',
|
||||
init(server: Hapi.Server) {
|
||||
const npMonitoring = server.newPlatform.setup.plugins.monitoring as object & {
|
||||
registerLegacyAPI: (api: unknown) => void;
|
||||
};
|
||||
if (npMonitoring) {
|
||||
const kbnServerStatus = this.kbnServer.status;
|
||||
npMonitoring.registerLegacyAPI({
|
||||
getServerStatus: () => {
|
||||
const status = kbnServerStatus.toJSON();
|
||||
return status?.overall?.state;
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
config,
|
||||
});
|
||||
};
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
|
||||
import { defaultsDeep, uniq, compact } from 'lodash';
|
||||
|
||||
import { ServiceStatusLevels } from '../../../../../src/core/server';
|
||||
import {
|
||||
TELEMETRY_COLLECTION_INTERVAL,
|
||||
KIBANA_STATS_TYPE_MONITORING,
|
||||
|
@ -30,7 +30,7 @@ import { sendBulkPayload, monitoringBulk } from './lib';
|
|||
* @param {Object} xpackInfo server.plugins.xpack_main.info object
|
||||
*/
|
||||
export class BulkUploader {
|
||||
constructor({ log, interval, elasticsearch, kibanaStats }) {
|
||||
constructor({ log, interval, elasticsearch, statusGetter$, kibanaStats }) {
|
||||
if (typeof interval !== 'number') {
|
||||
throw new Error('interval number of milliseconds is required');
|
||||
}
|
||||
|
@ -52,11 +52,11 @@ export class BulkUploader {
|
|||
});
|
||||
|
||||
this.kibanaStats = kibanaStats;
|
||||
this.kibanaStatusGetter = null;
|
||||
}
|
||||
|
||||
setKibanaStatusGetter(getter) {
|
||||
this.kibanaStatusGetter = getter;
|
||||
this.kibanaStatus = null;
|
||||
this.kibanaStatusGetter$ = statusGetter$.subscribe((nextStatus) => {
|
||||
this.kibanaStatus = nextStatus.level;
|
||||
});
|
||||
}
|
||||
|
||||
filterCollectorSet(usageCollection) {
|
||||
|
@ -128,7 +128,7 @@ export class BulkUploader {
|
|||
async _fetchAndUpload(usageCollection) {
|
||||
const collectorsReady = await usageCollection.areAllCollectorsReady();
|
||||
const hasUsageCollectors = usageCollection.some(usageCollection.isUsageCollector);
|
||||
if (!collectorsReady || typeof this.kibanaStatusGetter !== 'function') {
|
||||
if (!collectorsReady) {
|
||||
this._log.debug('Skipping bulk uploading because not all collectors are ready');
|
||||
if (hasUsageCollectors) {
|
||||
this._lastFetchUsageTime = null;
|
||||
|
@ -172,10 +172,23 @@ export class BulkUploader {
|
|||
return await sendBulkPayload(this._cluster, this._interval, payload, this._log);
|
||||
}
|
||||
|
||||
getConvertedKibanaStatuss() {
|
||||
if (this.kibanaStatus === ServiceStatusLevels.available) {
|
||||
return 'green';
|
||||
}
|
||||
if (this.kibanaStatus === ServiceStatusLevels.critical) {
|
||||
return 'red';
|
||||
}
|
||||
if (this.kibanaStatus === ServiceStatusLevels.degraded) {
|
||||
return 'yellow';
|
||||
}
|
||||
return 'unknown';
|
||||
}
|
||||
|
||||
getKibanaStats(type) {
|
||||
const stats = {
|
||||
...this.kibanaStats,
|
||||
status: this.kibanaStatusGetter(),
|
||||
status: this.getConvertedKibanaStatuss(),
|
||||
};
|
||||
|
||||
if (type === KIBANA_STATS_TYPE_MONITORING) {
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
*/
|
||||
import { Plugin } from './plugin';
|
||||
import { combineLatest } from 'rxjs';
|
||||
// @ts-ignore
|
||||
import { initBulkUploader } from './kibana_monitoring';
|
||||
import { AlertsFactory } from './alerts';
|
||||
|
||||
jest.mock('rxjs', () => ({
|
||||
|
@ -27,10 +25,6 @@ jest.mock('./license_service', () => ({
|
|||
})),
|
||||
}));
|
||||
|
||||
jest.mock('./kibana_monitoring', () => ({
|
||||
initBulkUploader: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('Monitoring plugin', () => {
|
||||
const initializerContext = {
|
||||
logger: {
|
||||
|
@ -71,6 +65,11 @@ describe('Monitoring plugin', () => {
|
|||
createClient: jest.fn(),
|
||||
},
|
||||
},
|
||||
status: {
|
||||
overall$: {
|
||||
subscribe: jest.fn(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const setupPlugins = {
|
||||
|
@ -113,19 +112,13 @@ describe('Monitoring plugin', () => {
|
|||
|
||||
afterEach(() => {
|
||||
(setupPlugins.alerts.registerType as jest.Mock).mockReset();
|
||||
(coreSetup.status.overall$.subscribe as jest.Mock).mockReset();
|
||||
});
|
||||
|
||||
it('always create the bulk uploader', async () => {
|
||||
const setKibanaStatusGetter = jest.fn();
|
||||
(initBulkUploader as jest.Mock).mockImplementation(() => {
|
||||
return {
|
||||
setKibanaStatusGetter,
|
||||
};
|
||||
});
|
||||
const plugin = new Plugin(initializerContext as any);
|
||||
const contract = await plugin.setup(coreSetup as any, setupPlugins as any);
|
||||
contract.registerLegacyAPI(null as any);
|
||||
expect(setKibanaStatusGetter).toHaveBeenCalled();
|
||||
await plugin.setup(coreSetup as any, setupPlugins as any);
|
||||
expect(coreSetup.status.overall$.subscribe).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should register all alerts', async () => {
|
||||
|
|
|
@ -46,7 +46,6 @@ import {
|
|||
IBulkUploader,
|
||||
PluginsSetup,
|
||||
PluginsStart,
|
||||
LegacyAPI,
|
||||
LegacyRequest,
|
||||
} from './types';
|
||||
|
||||
|
@ -158,6 +157,7 @@ export class Plugin {
|
|||
elasticsearch: core.elasticsearch,
|
||||
config,
|
||||
log: kibanaMonitoringLog,
|
||||
statusGetter$: core.status.overall$,
|
||||
kibanaStats: {
|
||||
uuid: this.initializerContext.env.instanceUuid,
|
||||
name: serverInfo.name,
|
||||
|
@ -221,11 +221,6 @@ export class Plugin {
|
|||
}
|
||||
|
||||
return {
|
||||
// The legacy plugin calls this to register certain legacy dependencies
|
||||
// that are necessary for the plugin to properly run
|
||||
registerLegacyAPI: (legacyAPI: LegacyAPI) => {
|
||||
this.setupLegacy(legacyAPI);
|
||||
},
|
||||
// OSS stats api needs to call this in order to centralize how
|
||||
// we fetch kibana specific stats
|
||||
getKibanaStats: () => this.bulkUploader.getKibanaStats(),
|
||||
|
@ -280,11 +275,6 @@ export class Plugin {
|
|||
});
|
||||
}
|
||||
|
||||
async setupLegacy(legacyAPI: LegacyAPI) {
|
||||
// Set the stats getter
|
||||
this.bulkUploader.setKibanaStatusGetter(() => legacyAPI.getServerStatus());
|
||||
}
|
||||
|
||||
getLegacyShim(
|
||||
config: MonitoringConfig,
|
||||
legacyConfig: any,
|
||||
|
|
|
@ -33,10 +33,6 @@ export interface MonitoringElasticsearchConfig {
|
|||
hosts: string[];
|
||||
}
|
||||
|
||||
export interface LegacyAPI {
|
||||
getServerStatus: () => string;
|
||||
}
|
||||
|
||||
export interface PluginsSetup {
|
||||
encryptedSavedObjects: EncryptedSavedObjectsPluginSetup;
|
||||
telemetryCollectionManager?: TelemetryCollectionManagerPluginSetup;
|
||||
|
@ -77,7 +73,6 @@ export interface LegacyShimDependencies {
|
|||
}
|
||||
|
||||
export interface IBulkUploader {
|
||||
setKibanaStatusGetter: (getter: () => string | undefined) => void;
|
||||
getKibanaStats: () => any;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue