Skip to content

Commit

Permalink
[Synthetics] SLO Availability sync delay field to use timestamp inste…
Browse files Browse the repository at this point in the history
…ad of event.ingested !! (elastic#199308)

## Summary

Fixes elastic#196548

SLO Availability sync delay field to use `@timestamp` instead of
`event.ingested` !!


### Testing

- Make sure Synthetics availability SLOs works as expected in serverless
and stateful
- Make sure when SLO is updated, it continues to work
  • Loading branch information
shahzad31 authored and CAWilson94 committed Dec 12, 2024
1 parent 644de71 commit b8de361
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 39 deletions.
1 change: 1 addition & 0 deletions x-pack/plugins/observability_solution/slo/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ export class SLOPlugin
},
logger: this.logger,
repository: getSloServerRouteRepository({ isServerless: this.isServerless }),
isServerless: this.isServerless,
});

core
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,32 @@
import { CoreSetup, Logger } from '@kbn/core/server';
import { ServerRoute, registerRoutes } from '@kbn/server-route-repository';
import { ServerRouteCreateOptions } from '@kbn/server-route-repository-utils';
import { SLORoutesDependencies } from './types';
import { SLORequestHandlerContext, SLORoutesDependencies } from './types';

interface RegisterRoutes {
core: CoreSetup;
repository: Record<string, ServerRoute<string, any, any, any, ServerRouteCreateOptions>>;
logger: Logger;
dependencies: SLORoutesDependencies;
isServerless: boolean;
}

export function registerServerRoutes({ repository, core, logger, dependencies }: RegisterRoutes) {
export function registerServerRoutes({
repository,
core,
logger,
dependencies,
isServerless,
}: RegisterRoutes) {
core.http.registerRouteHandlerContext<SLORequestHandlerContext, 'slo'>(
'slo',
async (_context, _request) => {
return {
isServerless,
};
}
);

registerRoutes<SLORoutesDependencies>({
repository,
dependencies,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ const createSLORoute = createSloServerRoute({
handler: async ({ context, response, params, logger, request, plugins, corePlugins }) => {
await assertPlatinumLicense(plugins);

const sloContext = await context.slo;
const dataViews = await plugins.dataViews.start();
const core = await context.core;
const scopedClusterClient = core.elasticsearch.client;
Expand All @@ -124,7 +125,8 @@ const createSLORoute = createSloServerRoute({
scopedClusterClient,
logger,
spaceId,
dataViewsService
dataViewsService,
sloContext.isServerless
);
const summaryTransformManager = new DefaultSummaryTransformManager(
new DefaultSummaryTransformGenerator(),
Expand Down Expand Up @@ -156,6 +158,7 @@ const inspectSLORoute = createSloServerRoute({
handler: async ({ context, params, logger, request, plugins, corePlugins }) => {
await assertPlatinumLicense(plugins);

const sloContext = await context.slo;
const dataViews = await plugins.dataViews.start();
const spaceId = await getSpaceId(plugins, request);
const basePath = corePlugins.http.basePath;
Expand All @@ -170,7 +173,8 @@ const inspectSLORoute = createSloServerRoute({
scopedClusterClient,
logger,
spaceId,
dataViewsService
dataViewsService,
sloContext.isServerless
);
const summaryTransformManager = new DefaultSummaryTransformManager(
new DefaultSummaryTransformGenerator(),
Expand Down Expand Up @@ -206,6 +210,7 @@ const updateSLORoute = createSloServerRoute({
const spaceId = await getSpaceId(plugins, request);
const dataViews = await plugins.dataViews.start();

const sloContext = await context.slo;
const basePath = corePlugins.http.basePath;
const core = await context.core;
const scopedClusterClient = core.elasticsearch.client;
Expand All @@ -218,7 +223,8 @@ const updateSLORoute = createSloServerRoute({
scopedClusterClient,
logger,
spaceId,
dataViewsService
dataViewsService,
sloContext.isServerless
);
const summaryTransformManager = new DefaultSummaryTransformManager(
new DefaultSummaryTransformGenerator(),
Expand Down Expand Up @@ -254,6 +260,7 @@ const deleteSLORoute = createSloServerRoute({
const spaceId = await getSpaceId(plugins, request);
const dataViews = await plugins.dataViews.start();

const sloContext = await context.slo;
const core = await context.core;
const scopedClusterClient = core.elasticsearch.client;
const esClient = core.elasticsearch.client.asCurrentUser;
Expand All @@ -270,7 +277,8 @@ const deleteSLORoute = createSloServerRoute({
scopedClusterClient,
logger,
spaceId,
dataViewsService
dataViewsService,
sloContext.isServerless
);

const summaryTransformManager = new DefaultSummaryTransformManager(
Expand Down Expand Up @@ -331,7 +339,7 @@ const enableSLORoute = createSloServerRoute({

const spaceId = await getSpaceId(plugins, request);
const dataViews = await plugins.dataViews.start();

const sloContext = await context.slo;
const core = await context.core;
const scopedClusterClient = core.elasticsearch.client;
const soClient = core.savedObjects.client;
Expand All @@ -343,7 +351,8 @@ const enableSLORoute = createSloServerRoute({
scopedClusterClient,
logger,
spaceId,
dataViewsService
dataViewsService,
sloContext.isServerless
);
const summaryTransformManager = new DefaultSummaryTransformManager(
new DefaultSummaryTransformGenerator(),
Expand Down Expand Up @@ -372,6 +381,7 @@ const disableSLORoute = createSloServerRoute({
const spaceId = await getSpaceId(plugins, request);
const dataViews = await plugins.dataViews.start();

const sloContext = await context.slo;
const core = await context.core;
const scopedClusterClient = core.elasticsearch.client;
const soClient = core.savedObjects.client;
Expand All @@ -383,7 +393,8 @@ const disableSLORoute = createSloServerRoute({
scopedClusterClient,
logger,
spaceId,
dataViewsService
dataViewsService,
sloContext.isServerless
);
const summaryTransformManager = new DefaultSummaryTransformManager(
new DefaultSummaryTransformGenerator(),
Expand All @@ -408,6 +419,7 @@ const resetSLORoute = createSloServerRoute({
handler: async ({ context, request, params, logger, plugins, corePlugins }) => {
await assertPlatinumLicense(plugins);

const sloContext = await context.slo;
const dataViews = await plugins.dataViews.start();
const spaceId = await getSpaceId(plugins, request);
const core = await context.core;
Expand All @@ -423,7 +435,8 @@ const resetSLORoute = createSloServerRoute({
scopedClusterClient,
logger,
spaceId,
dataViewsService
dataViewsService,
sloContext.isServerless
);
const summaryTransformManager = new DefaultSummaryTransformManager(
new DefaultSummaryTransformGenerator(),
Expand Down
15 changes: 13 additions & 2 deletions x-pack/plugins/observability_solution/slo/server/routes/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { CoreSetup } from '@kbn/core/server';
import { CoreSetup, CustomRequestHandlerContext } from '@kbn/core/server';
import type { DefaultRouteHandlerResources } from '@kbn/server-route-repository';
import { SLOPluginSetupDependencies, SLOPluginStartDependencies } from '../types';

Expand All @@ -21,4 +21,15 @@ export interface SLORoutesDependencies {
corePlugins: CoreSetup;
}

export type SLORouteHandlerResources = SLORoutesDependencies & DefaultRouteHandlerResources;
export type SLORouteHandlerResources = SLORoutesDependencies &
DefaultRouteHandlerResources & {
context: SLORequestHandlerContext;
};

export interface SLORouteContext {
isServerless: boolean;
}

export type SLORequestHandlerContext = CustomRequestHandlerContext<{
slo: Promise<SLORouteContext>;
}>;
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('Synthetics Availability Transform Generator', () => {

it('returns the expected transform params', async () => {
const slo = createSLO({ id: 'irrelevant', indicator: createSyntheticsAvailabilityIndicator() });
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService);
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService, false);

expect(transform).toMatchSnapshot();
expect(transform.source.query?.bool?.filter).toContainEqual({
Expand All @@ -34,7 +34,7 @@ describe('Synthetics Availability Transform Generator', () => {
id: 'irrelevant',
indicator: createSyntheticsAvailabilityIndicator(),
});
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService);
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService, false);

expect(transform.pivot?.group_by).toEqual(
expect.objectContaining({
Expand All @@ -58,7 +58,7 @@ describe('Synthetics Availability Transform Generator', () => {
indicator: createSyntheticsAvailabilityIndicator(),
groupBy: ['host.name'],
});
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService);
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService, false);

expect(transform.pivot?.group_by).not.toEqual(
expect.objectContaining({
Expand Down Expand Up @@ -94,7 +94,7 @@ describe('Synthetics Availability Transform Generator', () => {
indicator: createSyntheticsAvailabilityIndicator(),
groupBy,
});
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService);
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService, false);

expect(transform.pivot?.group_by).toEqual(
expect.objectContaining({
Expand All @@ -121,7 +121,7 @@ describe('Synthetics Availability Transform Generator', () => {
indicator: createSyntheticsAvailabilityIndicator(),
groupBy,
});
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService);
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService, false);

expect(transform.pivot?.group_by).toEqual(
expect.objectContaining({
Expand All @@ -146,7 +146,7 @@ describe('Synthetics Availability Transform Generator', () => {
indicator: createSyntheticsAvailabilityIndicator(),
groupBy,
});
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService);
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService, false);

expect(transform.pivot?.group_by).toEqual(
expect.objectContaining({
Expand All @@ -161,7 +161,7 @@ describe('Synthetics Availability Transform Generator', () => {

it('filters by summary.final_attempt', async () => {
const slo = createSLO({ id: 'irrelevant', indicator: createSyntheticsAvailabilityIndicator() });
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService);
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService, false);

expect(transform.source.query?.bool?.filter).toContainEqual({
term: {
Expand All @@ -186,7 +186,7 @@ describe('Synthetics Availability Transform Generator', () => {
},
} as SLODefinition['indicator'],
});
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService);
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService, false);

expect(transform.source.query?.bool?.filter).toContainEqual({
terms: {
Expand Down Expand Up @@ -216,7 +216,7 @@ describe('Synthetics Availability Transform Generator', () => {
},
} as SLODefinition['indicator'],
});
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService);
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService, false);

expect(transform.source.query?.bool?.filter).toContainEqual({
terms: {
Expand Down Expand Up @@ -246,7 +246,7 @@ describe('Synthetics Availability Transform Generator', () => {
},
} as SLODefinition['indicator'],
});
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService);
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService, false);

expect(transform.source.query?.bool?.filter).toContainEqual({
terms: {
Expand All @@ -262,7 +262,7 @@ describe('Synthetics Availability Transform Generator', () => {

it('filters by space', async () => {
const slo = createSLO({ id: 'irrelevant', indicator: createSyntheticsAvailabilityIndicator() });
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService);
const transform = await generator.getTransformParams(slo, spaceId, dataViewsService, false);

expect(transform.source.query?.bool?.filter).toContainEqual({
term: {
Expand All @@ -281,7 +281,7 @@ describe('Synthetics Availability Transform Generator', () => {
},
});

const transform = await generator.getTransformParams(slo, 'default', dataViewsService);
const transform = await generator.getTransformParams(slo, 'default', dataViewsService, false);

// @ts-ignore
const rangeFilter = transform.source.query.bool.filter.find((f) => 'range' in f);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export class SyntheticsAvailabilityTransformGenerator extends TransformGenerator
public async getTransformParams(
slo: SLODefinition,
spaceId: string,
dataViewService: DataViewsService
dataViewService: DataViewsService,
isServerless: boolean
): Promise<TransformPutTransformRequest> {
if (!syntheticsAvailabilityIndicatorSchema.is(slo.indicator)) {
throw new InvalidTransformError(`Cannot handle SLO of indicator type: ${slo.indicator.type}`);
Expand All @@ -44,7 +45,7 @@ export class SyntheticsAvailabilityTransformGenerator extends TransformGenerator
this.buildDestination(slo),
this.buildGroupBy(slo, slo.indicator),
this.buildAggregations(slo),
this.buildSettings(slo, 'event.ingested'),
this.buildSettings(slo, isServerless ? '@timestamp' : 'event.ingested'),
slo
);
}
Expand All @@ -56,7 +57,7 @@ export class SyntheticsAvailabilityTransformGenerator extends TransformGenerator
private buildGroupBy(slo: SLODefinition, indicator: SyntheticsAvailabilityIndicator) {
// These are the group by fields that will be used in `groupings` key
// in the summary and rollup documents. For Synthetics, we want to use the
// user-readible `monitor.name` and `observer.geo.name` fields by default,
// user-readable `monitor.name` and `observer.geo.name` fields by default,
// unless otherwise specified by the user.
const flattenedGroupBy = [slo.groupBy].flat().filter((value) => !!value);
const groupings =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ export abstract class TransformGenerator {
public abstract getTransformParams(
slo: SLODefinition,
spaceId: string,
dataViewService: DataViewsService
dataViewService: DataViewsService,
isServerless: boolean
): Promise<TransformPutTransformRequest>;

public buildCommonRuntimeMappings(slo: SLODefinition, dataView?: DataView): MappingRuntimeFields {
Expand Down
Loading

0 comments on commit b8de361

Please sign in to comment.