Skip to content

Commit

Permalink
[RAC][Rule Registry] Improve RuleDataService API and index bootstrapp…
Browse files Browse the repository at this point in the history
…ing implementation (#108115) (#108638)

**Addresses:** #106421, #106428, #102089, #106433

## Summary

This PR focuses on consolidation of indexing implementations in `rule_registry` (#101016). It addresses some of the sub-tasks of the parent ticket.

- [x] Encapsulate index bootstrapping logic in a new improved API exposed by `RuleDataService`.
- [x] Enforce allowed values for the `datasetSuffix` on the API level.
- [x] Migrate plugins using the existing `RuleDataService` API to the improved one.
- [x] Make sure index names comply with design architecture.
    - #102089
- [x] Improve the API of `RuleDataClient`.
- [x] Enhance index bootstrapping: support custom ILM policy per index (`{registrationContext}.{datasetSuffix}`).
- [x] Enhance index bootstrapping: create index template per namespace and support rollovers properly
    - based on #107700
- [x] Enhance index bootstrapping: support secondary aliases
    - based on #107700
- [x] Remove `EventLogService` implementation
    - #106433

This will be addressed in follow-up PRs:

- [ ] Enhance index bootstrapping: implement suggestions for backwards compatibility (naming scheme for alias and backing indices; versioning).
- [ ] Enhance index bootstrapping: implement upgrades of existing index templates.
- [ ] Make index bootstrapping logic more robust. This _is partially addressed_ in this PR, but more improvements are needed.
- [ ] Change the way index prefix works.
- [ ] Add support for optional TS schema (static typing).
- [ ] Update `README` in `rule_registry`.

### Checklist

- [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials
- [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios

Co-authored-by: Georgii Gorbachev <georgii.gorbachev@elastic.co>
  • Loading branch information
kibanamachine and banderror authored Aug 15, 2021
1 parent 0f406c0 commit 51244c8
Show file tree
Hide file tree
Showing 88 changed files with 1,266 additions and 2,596 deletions.
4 changes: 2 additions & 2 deletions x-pack/plugins/apm/server/lib/alerts/register_apm_alerts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { Observable } from 'rxjs';
import { Logger } from 'kibana/server';
import { PluginSetupContract as AlertingPluginSetupContract } from '../../../../alerting/server';
import { RuleDataClient } from '../../../../rule_registry/server';
import { IRuleDataClient } from '../../../../rule_registry/server';
import { registerTransactionDurationAlertType } from './register_transaction_duration_alert_type';
import { registerTransactionDurationAnomalyAlertType } from './register_transaction_duration_anomaly_alert_type';
import { registerErrorCountAlertType } from './register_error_count_alert_type';
Expand All @@ -17,7 +17,7 @@ import { MlPluginSetup } from '../../../../ml/server';
import { registerTransactionErrorRateAlertType } from './register_transaction_error_rate_alert_type';

export interface RegisterRuleDependencies {
ruleDataClient: RuleDataClient;
ruleDataClient: IRuleDataClient;
ml?: MlPluginSetup;
alerting: AlertingPluginSetupContract;
config$: Observable<APMConfig>;
Expand Down
5 changes: 3 additions & 2 deletions x-pack/plugins/apm/server/lib/alerts/test_utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { Logger } from 'kibana/server';
import { of } from 'rxjs';
import { elasticsearchServiceMock } from 'src/core/server/mocks';
import type { RuleDataClient } from '../../../../../rule_registry/server';
import type { IRuleDataClient } from '../../../../../rule_registry/server';
import { PluginSetupContract as AlertingPluginSetupContract } from '../../../../../alerting/server';
import { APMConfig, APM_SERVER_FEATURE_ID } from '../../..';

Expand Down Expand Up @@ -63,7 +63,8 @@ export const createRuleTypeMocks = () => {
};
},
isWriteEnabled: jest.fn(() => true),
} as unknown) as RuleDataClient,
indexName: '.alerts-observability.apm.alerts',
} as unknown) as IRuleDataClient,
},
services,
scheduleActions,
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/apm/server/lib/services/get_service_alerts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import type { EVENT_KIND as EVENT_KIND_TYPED } from '@kbn/rule-data-utils';
// @ts-expect-error
import { EVENT_KIND as EVENT_KIND_NON_TYPED } from '@kbn/rule-data-utils/target_node/technical_field_names';
import { RuleDataClient } from '../../../../rule_registry/server';
import { IRuleDataClient } from '../../../../rule_registry/server';
import {
SERVICE_NAME,
TRANSACTION_TYPE,
Expand All @@ -26,7 +26,7 @@ export async function getServiceAlerts({
environment,
transactionType,
}: {
ruleDataClient: RuleDataClient;
ruleDataClient: IRuleDataClient;
start: number;
end: number;
serviceName: string;
Expand Down
100 changes: 32 additions & 68 deletions x-pack/plugins/apm/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ import {
Plugin,
PluginInitializerContext,
} from 'src/core/server';
import { isEmpty, mapValues, once } from 'lodash';
import { isEmpty, mapValues } from 'lodash';
import { SavedObjectsClient } from '../../../../src/core/server';
import { TECHNICAL_COMPONENT_TEMPLATE_NAME } from '../../rule_registry/common/assets';
import { mappingFromFieldMap } from '../../rule_registry/common/mapping_from_field_map';
import { Dataset } from '../../rule_registry/server';
import { APMConfig, APMXPackConfig, APM_SERVER_FEATURE_ID } from '.';
import { mergeConfigs } from './index';
import { UI_SETTINGS } from '../../../../src/plugins/data/common';
Expand Down Expand Up @@ -106,79 +106,43 @@ export class APMPlugin

registerFeaturesUsage({ licensingPlugin: plugins.licensing });

const { ruleDataService } = plugins.ruleRegistry;
const getCoreStart = () =>
core.getStartServices().then(([coreStart]) => coreStart);

const alertsIndexPattern = ruleDataService.getFullAssetName(
'observability-apm*'
);

const initializeRuleDataTemplates = once(async () => {
const componentTemplateName = ruleDataService.getFullAssetName(
'apm-mappings'
);

if (!ruleDataService.isWriteEnabled()) {
return;
}

await ruleDataService.createOrUpdateComponentTemplate({
name: componentTemplateName,
body: {
template: {
settings: {
number_of_shards: 1,
},
mappings: mappingFromFieldMap(
{
[SERVICE_NAME]: {
type: 'keyword',
},
[SERVICE_ENVIRONMENT]: {
type: 'keyword',
},
[TRANSACTION_TYPE]: {
type: 'keyword',
},
[PROCESSOR_EVENT]: {
type: 'keyword',
},
const { ruleDataService } = plugins.ruleRegistry;
const ruleDataClient = ruleDataService.initializeIndex({
feature: APM_SERVER_FEATURE_ID,
registrationContext: 'observability.apm',
dataset: Dataset.alerts,
componentTemplateRefs: [],
componentTemplates: [
{
name: 'mappings',
version: 0,
mappings: mappingFromFieldMap(
{
[SERVICE_NAME]: {
type: 'keyword',
},
'strict'
),
},
},
});

await ruleDataService.createOrUpdateIndexTemplate({
name: ruleDataService.getFullAssetName('apm-index-template'),
body: {
index_patterns: [alertsIndexPattern],
composed_of: [
ruleDataService.getFullAssetName(TECHNICAL_COMPONENT_TEMPLATE_NAME),
componentTemplateName,
],
[SERVICE_ENVIRONMENT]: {
type: 'keyword',
},
[TRANSACTION_TYPE]: {
type: 'keyword',
},
[PROCESSOR_EVENT]: {
type: 'keyword',
},
},
'strict'
),
},
});
await ruleDataService.updateIndexMappingsMatchingPattern(
alertsIndexPattern
);
],
indexTemplate: {
version: 0,
},
});

// initialize eagerly
const initializeRuleDataTemplatesPromise = initializeRuleDataTemplates().catch(
(err) => {
this.logger!.error(err);
}
);

const ruleDataClient = ruleDataService.getRuleDataClient(
APM_SERVER_FEATURE_ID,
ruleDataService.getFullAssetName('observability-apm'),
() => initializeRuleDataTemplatesPromise
);

const resourcePlugins = mapValues(plugins, (value, key) => {
return {
setup: value,
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/apm/server/routes/typings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
KibanaRequest,
CoreStart,
} from 'src/core/server';
import { RuleDataClient } from '../../../rule_registry/server';
import { IRuleDataClient } from '../../../rule_registry/server';
import { AlertingApiRequestHandlerContext } from '../../../alerting/server';
import type { RacApiRequestHandlerContext } from '../../../rule_registry/server';
import { LicensingApiRequestHandlerContext } from '../../../licensing/server';
Expand Down Expand Up @@ -72,6 +72,6 @@ export interface APMRouteHandlerResources {
start: () => Promise<Required<APMPluginDependencies>[key]['start']>;
};
};
ruleDataClient: RuleDataClient;
ruleDataClient: IRuleDataClient;
telemetryUsageCounter?: TelemetryUsageCounter;
}
63 changes: 15 additions & 48 deletions x-pack/plugins/infra/server/services/rules/rule_data_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@
* 2.0.
*/

import { once } from 'lodash';
import { CoreSetup, Logger } from 'src/core/server';
import { TECHNICAL_COMPONENT_TEMPLATE_NAME } from '../../../../rule_registry/common/assets';
import { RuleRegistryPluginSetupContract } from '../../../../rule_registry/server';
import { Dataset, RuleRegistryPluginSetupContract } from '../../../../rule_registry/server';
import type { InfraFeatureId } from '../../../common/constants';
import { RuleRegistrationContext, RulesServiceStartDeps } from './types';

Expand All @@ -25,51 +23,20 @@ export const createRuleDataClient = ({
logger: Logger;
ruleDataService: RuleRegistryPluginSetupContract['ruleDataService'];
}) => {
const initializeRuleDataTemplates = once(async () => {
const componentTemplateName = ruleDataService.getFullAssetName(
`${registrationContext}-mappings`
);

const indexNamePattern = ruleDataService.getFullAssetName(`${registrationContext}*`);

if (!ruleDataService.isWriteEnabled()) {
return;
}

await ruleDataService.createOrUpdateComponentTemplate({
name: componentTemplateName,
body: {
template: {
settings: {
number_of_shards: 1,
},
mappings: {},
},
},
});

await ruleDataService.createOrUpdateIndexTemplate({
name: ruleDataService.getFullAssetName(registrationContext),
body: {
index_patterns: [indexNamePattern],
composed_of: [
ruleDataService.getFullAssetName(TECHNICAL_COMPONENT_TEMPLATE_NAME),
componentTemplateName,
],
return ruleDataService.initializeIndex({
feature: ownerFeatureId,
registrationContext,
dataset: Dataset.alerts,
componentTemplateRefs: [],
componentTemplates: [
{
name: 'mappings',
version: 0,
mappings: {},
},
});

await ruleDataService.updateIndexMappingsMatchingPattern(indexNamePattern);
});

// initialize eagerly
const initializeRuleDataTemplatesPromise = initializeRuleDataTemplates().catch((err) => {
logger.error(err);
],
indexTemplate: {
version: 0,
},
});

return ruleDataService.getRuleDataClient(
ownerFeatureId,
ruleDataService.getFullAssetName(registrationContext),
() => initializeRuleDataTemplatesPromise
);
};
4 changes: 2 additions & 2 deletions x-pack/plugins/infra/server/services/rules/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { PluginSetupContract as AlertingPluginSetup } from '../../../../alerting/server';
import {
createLifecycleExecutor,
RuleDataClient,
IRuleDataClient,
RuleRegistryPluginSetupContract,
} from '../../../../rule_registry/server';

Expand All @@ -24,7 +24,7 @@ export interface RulesServiceStartDeps {}

export interface RulesServiceSetup {
createLifecycleRuleExecutor: LifecycleRuleExecutorCreator;
ruleDataClient: RuleDataClient;
ruleDataClient: IRuleDataClient;
}

// eslint-disable-next-line @typescript-eslint/no-empty-interface
Expand Down
18 changes: 12 additions & 6 deletions x-pack/plugins/observability/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
ScopedAnnotationsClientFactory,
AnnotationsAPI,
} from './lib/annotations/bootstrap_annotations';
import type { RuleRegistryPluginSetupContract } from '../../rule_registry/server';
import { Dataset, RuleRegistryPluginSetupContract } from '../../rule_registry/server';
import { PluginSetupContract as FeaturesSetup } from '../../features/server';
import { uiSettings } from './ui_settings';
import { registerRoutes } from './routes/register_routes';
Expand Down Expand Up @@ -100,11 +100,17 @@ export class ObservabilityPlugin implements Plugin<ObservabilityPluginSetup> {

const start = () => core.getStartServices().then(([coreStart]) => coreStart);

const ruleDataClient = plugins.ruleRegistry.ruleDataService.getRuleDataClient(
'observability',
plugins.ruleRegistry.ruleDataService.getFullAssetName(),
() => Promise.resolve()
);
const { ruleDataService } = plugins.ruleRegistry;
const ruleDataClient = ruleDataService.initializeIndex({
feature: 'observability',
registrationContext: 'observability',
dataset: Dataset.alerts,
componentTemplateRefs: [],
componentTemplates: [],
indexTemplate: {
version: 0,
},
});

registerRoutes({
core: {
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/observability/server/routes/register_routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
import { CoreSetup, CoreStart, Logger, RouteRegistrar } from 'kibana/server';
import Boom from '@hapi/boom';
import { RequestAbortedError } from '@elastic/elasticsearch/lib/errors';
import { RuleDataClient } from '../../../rule_registry/server';
import { IRuleDataClient } from '../../../rule_registry/server';
import { ObservabilityRequestHandlerContext } from '../types';
import { AbstractObservabilityServerRouteRepository } from './types';

Expand All @@ -29,7 +29,7 @@ export function registerRoutes({
};
repository: AbstractObservabilityServerRouteRepository;
logger: Logger;
ruleDataClient: RuleDataClient;
ruleDataClient: IRuleDataClient;
}) {
const routes = repository.getRoutes();

Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/observability/server/routes/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type {
ServerRouteRepository,
} from '@kbn/server-route-repository';
import { CoreSetup, CoreStart, KibanaRequest, Logger } from 'kibana/server';
import { RuleDataClient } from '../../../rule_registry/server';
import { IRuleDataClient } from '../../../rule_registry/server';

import { ObservabilityServerRouteRepository } from './get_global_observability_server_route_repository';
import { ObservabilityRequestHandlerContext } from '../types';
Expand All @@ -24,7 +24,7 @@ export interface ObservabilityRouteHandlerResources {
start: () => Promise<CoreStart>;
setup: CoreSetup;
};
ruleDataClient: RuleDataClient;
ruleDataClient: IRuleDataClient;
request: KibanaRequest;
context: ObservabilityRequestHandlerContext;
logger: Logger;
Expand Down
4 changes: 0 additions & 4 deletions x-pack/plugins/rule_registry/common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@

import { estypes } from '@elastic/elasticsearch';

export type PutIndexTemplateRequest = estypes.IndicesPutIndexTemplateRequest & {
body?: { composed_of?: string[] };
};

export interface ClusterPutComponentTemplateBody {
template: {
settings: {
Expand Down
1 change: 0 additions & 1 deletion x-pack/plugins/rule_registry/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
"requiredPlugins": [
"alerting",
"data",
"spaces",
"triggersActionsUi"
],
"optionalPlugins": ["security"],
Expand Down

This file was deleted.

Loading

0 comments on commit 51244c8

Please sign in to comment.