Skip to content

Commit

Permalink
Merge branch 'master' of github.com:elastic/kibana into 110758-limit-…
Browse files Browse the repository at this point in the history
…alerts-table-size
  • Loading branch information
miltonhultgren committed Sep 3, 2021
2 parents 003150b + df8ed81 commit 0d83265
Show file tree
Hide file tree
Showing 72 changed files with 1,509 additions and 464 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ async function getDeprecations({ esClient, savedObjectsClient }: GetDeprecations
// Example of a manual correctiveAction
deprecations.push({
title: i18n.translate('xpack.timelion.deprecations.worksheetsTitle', {
defaultMessage: 'Found Timelion worksheets.'
defaultMessage: 'Timelion worksheets are deprecated'
}),
message: i18n.translate('xpack.timelion.deprecations.worksheetsMessage', {
defaultMessage: 'You have {count} Timelion worksheets. The Timelion app will be removed in 8.0. To continue using your Timelion worksheets, migrate them to a dashboard.',
defaultMessage: 'You have {count} Timelion worksheets. Migrate your Timelion worksheets to a dashboard to continue using them.',
values: { count },
}),
documentationUrl:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ Rules are taking a long time to execute and are impacting the overall health of

[IMPORTANT]
==============================================
By default, only users with a `superuser` role can query the {kib} event log because it is a system index. To enable additional users to execute this query, assign `read` privileges to the `.kibana-event-log*` index.
By default, only users with a `superuser` role can query the experimental[] {kib} event log because it is a system index. To enable additional users to execute this query, assign `read` privileges to the `.kibana-event-log*` index.
==============================================

*Solution*
Expand Down
2 changes: 2 additions & 0 deletions docs/user/alerting/troubleshooting/event-log-index.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
[[event-log-index]]
=== Event log index

experimental[]

Use the event log index to determine:

* Whether a rule successfully ran but its associated actions did not
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ Predicting the buffer required to account for actions depends heavily on the rul
[[event-log-ilm]]
=== Event log index lifecycle managment

experimental[]

Alerts and actions log activity in a set of "event log" indices. These indices are configured with an index lifecycle management (ILM) policy, which you can customize. The default policy rolls over the index when it reaches 50GB, or after 30 days. Indices over 90 days old are deleted.

The name of the index policy is `kibana-event-log-policy`. {kib} creates the index policy on startup, if it doesn't already exist. The index policy can be customized for your environment, but {kib} never modifies the index policy after creating it.
Expand Down
14 changes: 1 addition & 13 deletions packages/kbn-test/src/kbn_client/kbn_client_plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,14 @@

import { KbnClientStatus } from './kbn_client_status';

const PLUGIN_STATUS_ID = /^plugin:(.+?)@/;

export class KbnClientPlugins {
constructor(private readonly status: KbnClientStatus) {}
/**
* Get a list of plugin ids that are enabled on the server
*/
public async getEnabledIds() {
const pluginIds: string[] = [];
const apiResp = await this.status.get();

for (const status of apiResp.status.statuses) {
if (status.id) {
const match = status.id.match(PLUGIN_STATUS_ID);
if (match) {
pluginIds.push(match[1]);
}
}
}

return pluginIds;
return Object.keys(apiResp.status.plugins);
}
}
17 changes: 8 additions & 9 deletions packages/kbn-test/src/kbn_client/kbn_client_status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@
import { KbnClientRequester } from './kbn_client_requester';

interface Status {
state: 'green' | 'red' | 'yellow';
title?: string;
id?: string;
icon: string;
message: string;
uiColor: string;
since: string;
level: 'available' | 'degraded' | 'unavailable' | 'critical';
summary: string;
detail?: string;
documentationUrl?: string;
meta?: Record<string, unknown>;
}

interface ApiResponseStatus {
Expand All @@ -29,7 +27,8 @@ interface ApiResponseStatus {
};
status: {
overall: Status;
statuses: Status[];
core: Record<string, Status>;
plugins: Record<string, Status>;
};
metrics: unknown;
}
Expand All @@ -55,6 +54,6 @@ export class KbnClientStatus {
*/
public async getOverallState() {
const status = await this.get();
return status.status.overall.state;
return status.status.overall.level;
}
}
1 change: 1 addition & 0 deletions scripts/functional_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const onlyNotInCoverageTests = [
require.resolve('../test/api_integration/config.js'),
require.resolve('../test/interpreter_functional/config.ts'),
require.resolve('../test/examples/config.js'),
require.resolve('../test/functional_execution_context/config.ts'),
];

require('../src/setup_node_env');
Expand Down
2 changes: 1 addition & 1 deletion src/core/public/core_app/status/lib/load_status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ export async function loadStatus({
let response: StatusResponse;

try {
response = await http.get('/api/status', { query: { v8format: true } });
response = await http.get('/api/status');
} catch (e) {
// API returns a 503 response if not all services are available.
// In this case, we want to treat this as a successful API call, so that we can
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import { PublicMethodsOf } from '@kbn/utility-types';
import { BehaviorSubject } from 'rxjs';
import { CoreUsageDataService } from './core_usage_data_service';
import { coreUsageStatsClientMock } from './core_usage_stats_client.mock';
import { CoreUsageData, CoreUsageDataSetup, CoreUsageDataStart } from './types';
import { CoreUsageData, InternalCoreUsageDataSetup, CoreUsageDataStart } from './types';

const createSetupContractMock = (usageStatsClient = coreUsageStatsClientMock.create()) => {
const setupContract: jest.Mocked<CoreUsageDataSetup> = {
const setupContract: jest.Mocked<InternalCoreUsageDataSetup> = {
registerType: jest.fn(),
getClient: jest.fn().mockReturnValue(usageStatsClient),
registerUsageCounter: jest.fn(),
incrementUsageCounter: jest.fn(),
};
return setupContract;
};
Expand Down
44 changes: 44 additions & 0 deletions src/core/server/core_usage_data/core_usage_data_service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,50 @@ describe('CoreUsageDataService', () => {
expect(usageStatsClient).toBeInstanceOf(CoreUsageStatsClient);
});
});

describe('Usage Counter', () => {
it('registers a usage counter and uses it to increment the counters', async () => {
const http = httpServiceMock.createInternalSetupContract();
const metrics = metricsServiceMock.createInternalSetupContract();
const savedObjectsStartPromise = Promise.resolve(
savedObjectsServiceMock.createStartContract()
);
const changedDeprecatedConfigPath$ = configServiceMock.create().getDeprecatedConfigPath$();
const coreUsageData = service.setup({
http,
metrics,
savedObjectsStartPromise,
changedDeprecatedConfigPath$,
});
const myUsageCounter = { incrementCounter: jest.fn() };
coreUsageData.registerUsageCounter(myUsageCounter);
coreUsageData.incrementUsageCounter({ counterName: 'test' });
expect(myUsageCounter.incrementCounter).toHaveBeenCalledWith({ counterName: 'test' });
});

it('swallows errors when provided increment counter fails', async () => {
const http = httpServiceMock.createInternalSetupContract();
const metrics = metricsServiceMock.createInternalSetupContract();
const savedObjectsStartPromise = Promise.resolve(
savedObjectsServiceMock.createStartContract()
);
const changedDeprecatedConfigPath$ = configServiceMock.create().getDeprecatedConfigPath$();
const coreUsageData = service.setup({
http,
metrics,
savedObjectsStartPromise,
changedDeprecatedConfigPath$,
});
const myUsageCounter = {
incrementCounter: jest.fn(() => {
throw new Error('Something is really wrong');
}),
};
coreUsageData.registerUsageCounter(myUsageCounter);
expect(() => coreUsageData.incrementUsageCounter({ counterName: 'test' })).not.toThrow();
expect(myUsageCounter.incrementCounter).toHaveBeenCalledWith({ counterName: 'test' });
});
});
});

describe('start', () => {
Expand Down
26 changes: 23 additions & 3 deletions src/core/server/core_usage_data/core_usage_data_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import type {
CoreServicesUsageData,
CoreUsageData,
CoreUsageDataStart,
CoreUsageDataSetup,
InternalCoreUsageDataSetup,
ConfigUsageData,
CoreConfigUsageData,
} from './types';
Expand All @@ -39,6 +39,7 @@ import { LEGACY_URL_ALIAS_TYPE } from '../saved_objects/object_types';
import { CORE_USAGE_STATS_TYPE } from './constants';
import { CoreUsageStatsClient } from './core_usage_stats_client';
import { MetricsServiceSetup, OpsMetrics } from '..';
import { CoreIncrementUsageCounter } from './types';

export type ExposedConfigsToUsage = Map<string, Record<string, boolean>>;

Expand Down Expand Up @@ -86,7 +87,8 @@ const isCustomIndex = (index: string) => {
return index !== '.kibana';
};

export class CoreUsageDataService implements CoreService<CoreUsageDataSetup, CoreUsageDataStart> {
export class CoreUsageDataService
implements CoreService<InternalCoreUsageDataSetup, CoreUsageDataStart> {
private logger: Logger;
private elasticsearchConfig?: ElasticsearchConfigType;
private configService: CoreContext['configService'];
Expand All @@ -98,6 +100,7 @@ export class CoreUsageDataService implements CoreService<CoreUsageDataSetup, Cor
private kibanaConfig?: KibanaConfigType;
private coreUsageStatsClient?: CoreUsageStatsClient;
private deprecatedConfigPaths: ChangedDeprecatedPaths = { set: [], unset: [] };
private incrementUsageCounter: CoreIncrementUsageCounter = () => {}; // Initially set to noop

constructor(core: CoreContext) {
this.logger = core.logger.get('core-usage-stats-service');
Expand Down Expand Up @@ -495,7 +498,24 @@ export class CoreUsageDataService implements CoreService<CoreUsageDataSetup, Cor

this.coreUsageStatsClient = getClient();

return { registerType, getClient } as CoreUsageDataSetup;
const contract: InternalCoreUsageDataSetup = {
registerType,
getClient,
registerUsageCounter: (usageCounter) => {
this.incrementUsageCounter = (params) => usageCounter.incrementCounter(params);
},
incrementUsageCounter: (params) => {
try {
this.incrementUsageCounter(params);
} catch (e) {
// Self-defense mechanism since the handler is externally registered
this.logger.debug('Failed to increase the usage counter');
this.logger.debug(e);
}
},
};

return contract;
}

start({ savedObjects, elasticsearch, exposedConfigsToUsage }: StartDeps) {
Expand Down
10 changes: 9 additions & 1 deletion src/core/server/core_usage_data/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@
*/

export { CORE_USAGE_STATS_TYPE, CORE_USAGE_STATS_ID } from './constants';
export type { CoreUsageDataSetup, ConfigUsageData, CoreUsageDataStart } from './types';
export type {
InternalCoreUsageDataSetup,
ConfigUsageData,
CoreUsageDataStart,
CoreUsageDataSetup,
CoreUsageCounter,
CoreIncrementUsageCounter,
CoreIncrementCounterParams,
} from './types';
export { CoreUsageDataService } from './core_usage_data_service';
export { CoreUsageStatsClient, REPOSITORY_RESOLVE_OUTCOME_STATS } from './core_usage_stats_client';

Expand Down
49 changes: 48 additions & 1 deletion src/core/server/core_usage_data/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -280,12 +280,59 @@ export interface CoreConfigUsageData {
};
}

/**
* @internal Details about the counter to be incremented
*/
export interface CoreIncrementCounterParams {
/** The name of the counter **/
counterName: string;
/** The counter type ("count" by default) **/
counterType?: string;
/** Increment the counter by this number (1 if not specified) **/
incrementBy?: number;
}

/**
* @internal
* Method to call whenever an event occurs, so the counter can be increased.
*/
export type CoreIncrementUsageCounter = (params: CoreIncrementCounterParams) => void;

/**
* @internal
* API to track whenever an event occurs, so the core can report them.
*/
export interface CoreUsageCounter {
/** @internal {@link CoreIncrementUsageCounter} **/
incrementCounter: CoreIncrementUsageCounter;
}

/** @internal */
export interface CoreUsageDataSetup {
export interface InternalCoreUsageDataSetup extends CoreUsageDataSetup {
registerType(
typeRegistry: ISavedObjectTypeRegistry & Pick<SavedObjectTypeRegistry, 'registerType'>
): void;
getClient(): CoreUsageStatsClient;

/** @internal {@link CoreIncrementUsageCounter} **/
incrementUsageCounter: CoreIncrementUsageCounter;
}

/**
* Internal API for registering the Usage Tracker used for Core's usage data payload.
*
* @note This API should never be used to drive application logic and is only
* intended for telemetry purposes.
*
* @internal
*/
export interface CoreUsageDataSetup {
/**
* @internal
* API for a usage tracker plugin to inject the {@link CoreUsageCounter} to use
* when tracking events.
*/
registerUsageCounter: (usageCounter: CoreUsageCounter) => void;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ describe('fake elasticsearch', () => {

test('should return unknown product when it cannot perform the Product check (503 response)', async () => {
const resp = await supertest(kibanaHttpServer).get('/api/status').expect(503);
expect(resp.body.status.overall.state).toBe('red');
expect(resp.body.status.statuses[0].message).toBe(
expect(resp.body.status.overall.level).toBe('critical');
expect(resp.body.status.core.elasticsearch.summary).toBe(
'Unable to retrieve version information from Elasticsearch nodes. The client noticed that the server is not Elasticsearch and we do not support this unknown product.'
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ describe('ExecutionContextService', () => {
expect(loggingSystemMock.collect(core.logger).debug).toMatchInlineSnapshot(`
Array [
Array [
"set the execution context: {\\"type\\":\\"type-a\\",\\"name\\":\\"name-a\\",\\"id\\":\\"id-a\\",\\"description\\":\\"description-a\\"}",
"{\\"type\\":\\"type-a\\",\\"name\\":\\"name-a\\",\\"id\\":\\"id-a\\",\\"description\\":\\"description-a\\"}",
],
]
`);
Expand Down Expand Up @@ -351,7 +351,7 @@ describe('ExecutionContextService', () => {
expect(loggingSystemMock.collect(core.logger).debug).toMatchInlineSnapshot(`
Array [
Array [
"stored the execution context: {\\"type\\":\\"type-a\\",\\"name\\":\\"name-a\\",\\"id\\":\\"id-a\\",\\"description\\":\\"description-a\\"}",
"{\\"type\\":\\"type-a\\",\\"name\\":\\"name-a\\",\\"id\\":\\"id-a\\",\\"description\\":\\"description-a\\"}",
],
]
`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export class ExecutionContextService
// we have to use enterWith since Hapi lifecycle model is built on event emitters.
// therefore if we wrapped request handler in asyncLocalStorage.run(), we would lose context in other lifecycles.
this.contextStore.enterWith(contextContainer);
this.log.debug(`set the execution context: ${JSON.stringify(contextContainer)}`);
this.log.debug(JSON.stringify(contextContainer));
}

private withContext<R>(
Expand All @@ -136,7 +136,7 @@ export class ExecutionContextService
}
const parent = this.contextStore.getStore();
const contextContainer = new ExecutionContextContainer(context, parent);
this.log.debug(`stored the execution context: ${JSON.stringify(contextContainer)}`);
this.log.debug(JSON.stringify(contextContainer));

return this.contextStore.run(contextContainer, fn);
}
Expand Down
Loading

0 comments on commit 0d83265

Please sign in to comment.