Skip to content

Commit 2cc88f3

Browse files
authored
Add a VisAugmenter stats API (#4006)
* Update augment-vis saved obj mappings Signed-off-by: Tyler Ohlsen <ohltyler@amazon.com> * Finish implementation; add tests; update attributes Signed-off-by: Tyler Ohlsen <ohltyler@amazon.com> * remove log Signed-off-by: Tyler Ohlsen <ohltyler@amazon.com> --------- Signed-off-by: Tyler Ohlsen <ohltyler@amazon.com>
1 parent 609bcc1 commit 2cc88f3

17 files changed

+582
-39
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import { SavedObjectAttributes } from 'opensearch-dashboards/server';
7+
8+
export interface AugmentVisSavedObjectAttributes extends SavedObjectAttributes {
9+
id: string;
10+
title: string;
11+
description?: string;
12+
originPlugin: string;
13+
pluginResource: {
14+
type: string;
15+
id: string;
16+
};
17+
visLayerExpressionFn: {
18+
type: string;
19+
name: string;
20+
};
21+
version: number;
22+
// Following fields are optional since they will get set/removed during the extraction/injection
23+
// of the vis reference
24+
visName?: string;
25+
visId?: string;
26+
visReference?: {
27+
id: string;
28+
name: string;
29+
};
30+
// Error may be populated if there is some issue when parsing the attribute values
31+
error?: string;
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
export const APP_PATH = {
7+
STATS: '/stats',
8+
};
9+
export const APP_API = '/api/vis_augmenter';
10+
11+
// used for limiting results received from the stats API
12+
export const PER_PAGE_REQUEST_NUMBER = 50;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/*
2+
* Copyright OpenSearch Contributors
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
export * from './constants';
7+
export { AugmentVisSavedObjectAttributes } from './augment_vis_saved_object_attributes';

src/plugins/vis_augmenter/public/saved_augment_vis/_saved_augment_vis.ts

+6-15
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ import {
1414
SavedObject,
1515
SavedObjectOpenSearchDashboardsServices,
1616
} from '../../../saved_objects/public';
17-
import { IIndexPattern } from '../../../data/public';
1817
import { extractReferences, injectReferences } from './saved_augment_vis_references';
18+
import { AugmentVisSavedObjectAttributes } from '../../common';
1919

2020
const name = 'augment-vis';
2121

@@ -24,28 +24,19 @@ export function createSavedAugmentVisClass(services: SavedObjectOpenSearchDashbo
2424

2525
class SavedAugmentVis extends SavedObjectClass {
2626
public static type: string = name;
27-
public static mapping: Record<string, string> = {
28-
description: 'text',
29-
pluginResourceId: 'text',
30-
visId: 'keyword',
31-
visLayerExpressionFn: 'text',
32-
version: 'integer',
33-
};
27+
public static mapping: AugmentVisSavedObjectAttributes;
3428

35-
constructor(opts: Record<string, unknown> | string = {}) {
36-
if (typeof opts !== 'object') {
37-
opts = { id: opts };
38-
}
29+
constructor(opts: AugmentVisSavedObjectAttributes) {
3930
super({
4031
type: SavedAugmentVis.type,
4132
mapping: SavedAugmentVis.mapping,
4233
extractReferences,
4334
injectReferences,
4435
id: (opts.id as string) || '',
45-
indexPattern: opts.indexPattern as IIndexPattern,
4636
defaults: {
4737
description: get(opts, 'description', ''),
48-
pluginResourceId: get(opts, 'pluginResourceId', ''),
38+
originPlugin: get(opts, 'originPlugin', ''),
39+
pluginResource: get(opts, 'pluginResource', {}),
4940
visId: get(opts, 'visId', ''),
5041
visLayerExpressionFn: get(opts, 'visLayerExpressionFn', {}),
5142
version: 1,
@@ -55,5 +46,5 @@ export function createSavedAugmentVisClass(services: SavedObjectOpenSearchDashbo
5546
}
5647
}
5748

58-
return SavedAugmentVis as new (opts: Record<string, unknown> | string) => SavedObject;
49+
return SavedAugmentVis as new (opts: AugmentVisSavedObjectAttributes) => SavedObject;
5950
}

src/plugins/vis_augmenter/public/saved_augment_vis/saved_augment_vis.test.ts

+91-5
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
* SPDX-License-Identifier: Apache-2.0
44
*/
55

6-
import { VisLayerExpressionFn, VisLayerTypes } from '../types';
6+
import { VisLayerTypes } from '../types';
7+
import { VisLayerExpressionFn } from '../expressions';
78
import {
89
createSavedAugmentVisLoader,
910
SavedObjectOpenSearchDashboardsServicesWithAugmentVis,
1011
} from './saved_augment_vis';
1112
import { generateAugmentVisSavedObject, getMockAugmentVisSavedObjectClient } from './utils';
13+
import { ISavedPluginResource } from './types';
1214

1315
describe('SavedObjectLoaderAugmentVis', () => {
1416
const fn = {
@@ -18,22 +20,74 @@ describe('SavedObjectLoaderAugmentVis', () => {
1820
testArg: 'test-value',
1921
},
2022
} as VisLayerExpressionFn;
21-
const validObj1 = generateAugmentVisSavedObject('valid-obj-id-1', fn, 'test-vis-id');
22-
const validObj2 = generateAugmentVisSavedObject('valid-obj-id-2', fn, 'test-vis-id');
23+
const originPlugin = 'test-plugin';
24+
const pluginResource = {
25+
type: 'test-plugin',
26+
id: 'test-plugin-resource-id',
27+
};
28+
const validObj1 = generateAugmentVisSavedObject(
29+
'valid-obj-id-1',
30+
fn,
31+
'test-vis-id',
32+
originPlugin,
33+
pluginResource
34+
);
35+
const validObj2 = generateAugmentVisSavedObject(
36+
'valid-obj-id-2',
37+
fn,
38+
'test-vis-id',
39+
originPlugin,
40+
pluginResource
41+
);
2342
const invalidFnTypeObj = generateAugmentVisSavedObject(
2443
'invalid-fn-obj-id-1',
2544
{
2645
...fn,
2746
// @ts-ignore
2847
type: 'invalid-type',
2948
},
30-
'test-vis-id'
49+
'test-vis-id',
50+
originPlugin,
51+
pluginResource
3152
);
3253

3354
const missingFnObj = generateAugmentVisSavedObject(
3455
'missing-fn-obj-id-1',
3556
{} as VisLayerExpressionFn,
36-
'test-vis-id'
57+
'test-vis-id',
58+
originPlugin,
59+
pluginResource
60+
);
61+
62+
const missingOriginPluginObj = generateAugmentVisSavedObject(
63+
'missing-origin-plugin-obj-id-1',
64+
fn,
65+
'test-vis-id',
66+
// @ts-ignore
67+
undefined,
68+
pluginResource
69+
);
70+
71+
const missingPluginResourceTypeObj = generateAugmentVisSavedObject(
72+
'missing-plugin-resource-type-obj-id-1',
73+
fn,
74+
'test-vis-id',
75+
// @ts-ignore
76+
originPlugin,
77+
{
78+
id: pluginResource.id,
79+
} as ISavedPluginResource
80+
);
81+
82+
const missingPluginResourceIdObj = generateAugmentVisSavedObject(
83+
'missing-plugin-resource-id-obj-id-1',
84+
fn,
85+
'test-vis-id',
86+
// @ts-ignore
87+
originPlugin,
88+
{
89+
type: pluginResource.type,
90+
} as ISavedPluginResource
3791
);
3892

3993
it('find returns single saved obj', async () => {
@@ -105,4 +159,36 @@ describe('SavedObjectLoaderAugmentVis', () => {
105159
expect(resp.hits[0].id).toEqual('valid-obj-id-1');
106160
expect(resp.hits[0].error).toEqual('visReference is missing in augment-vis saved object');
107161
});
162+
163+
it('findAll returns obj with missing originPlugin', async () => {
164+
const loader = createSavedAugmentVisLoader({
165+
savedObjectsClient: getMockAugmentVisSavedObjectClient([missingOriginPluginObj]),
166+
} as SavedObjectOpenSearchDashboardsServicesWithAugmentVis);
167+
const resp = await loader.findAll();
168+
expect(resp.hits.length).toEqual(1);
169+
expect(resp.hits[0].id).toEqual('missing-origin-plugin-obj-id-1');
170+
expect(resp.hits[0].error).toEqual('originPlugin is missing in augment-vis saved object');
171+
});
172+
173+
it('findAll returns obj with missing plugin resource type', async () => {
174+
const loader = createSavedAugmentVisLoader({
175+
savedObjectsClient: getMockAugmentVisSavedObjectClient([missingPluginResourceTypeObj]),
176+
} as SavedObjectOpenSearchDashboardsServicesWithAugmentVis);
177+
const resp = await loader.findAll();
178+
expect(resp.hits.length).toEqual(1);
179+
expect(resp.hits[0].id).toEqual('missing-plugin-resource-type-obj-id-1');
180+
expect(resp.hits[0].error).toEqual(
181+
'pluginResource.type is missing in augment-vis saved object'
182+
);
183+
});
184+
185+
it('findAll returns obj with missing plugin resource id', async () => {
186+
const loader = createSavedAugmentVisLoader({
187+
savedObjectsClient: getMockAugmentVisSavedObjectClient([missingPluginResourceIdObj]),
188+
} as SavedObjectOpenSearchDashboardsServicesWithAugmentVis);
189+
const resp = await loader.findAll();
190+
expect(resp.hits.length).toEqual(1);
191+
expect(resp.hits[0].id).toEqual('missing-plugin-resource-id-obj-id-1');
192+
expect(resp.hits[0].error).toEqual('pluginResource.id is missing in augment-vis saved object');
193+
});
108194
});

src/plugins/vis_augmenter/public/saved_augment_vis/saved_augment_vis.ts

+17-4
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
} from '../../../saved_objects/public';
1111
import { createSavedAugmentVisClass } from './_saved_augment_vis';
1212
import { VisLayerTypes } from '../types';
13+
import { AugmentVisSavedObjectAttributes } from '../../common';
1314

1415
// eslint-disable-next-line @typescript-eslint/no-empty-interface
1516
export interface SavedObjectOpenSearchDashboardsServicesWithAugmentVis
@@ -21,9 +22,9 @@ export function createSavedAugmentVisLoader(
2122
const { savedObjectsClient } = services;
2223

2324
class SavedObjectLoaderAugmentVis extends SavedObjectLoader {
24-
mapHitSource = (source: Record<string, any>, id: string) => {
25+
mapHitSource = (source: AugmentVisSavedObjectAttributes, id: string) => {
2526
source.id = id;
26-
source.visId = get(source, 'visReference.id', '');
27+
source.visId = get(source, 'visReference.id', '') as string;
2728

2829
if (isEmpty(source.visReference)) {
2930
source.error = 'visReference is missing in augment-vis saved object';
@@ -33,10 +34,22 @@ export function createSavedAugmentVisLoader(
3334
source.error = 'visLayerExpressionFn is missing in augment-vis saved object';
3435
return source;
3536
}
36-
if (!(get(source, 'visLayerExpressionFn.type', '') in VisLayerTypes)) {
37+
if (!((get(source, 'visLayerExpressionFn.type', '') as string) in VisLayerTypes)) {
3738
source.error = 'Unknown VisLayer expression function type';
3839
return source;
3940
}
41+
if (get(source, 'originPlugin', undefined) === undefined) {
42+
source.error = 'originPlugin is missing in augment-vis saved object';
43+
return source;
44+
}
45+
if (get(source, 'pluginResource.type', undefined) === undefined) {
46+
source.error = 'pluginResource.type is missing in augment-vis saved object';
47+
return source;
48+
}
49+
if (get(source, 'pluginResource.id', undefined) === undefined) {
50+
source.error = 'pluginResource.id is missing in augment-vis saved object';
51+
return source;
52+
}
4053
return source;
4154
};
4255

@@ -48,7 +61,7 @@ export function createSavedAugmentVisLoader(
4861
*/
4962
mapSavedObjectApiHits(hit: {
5063
references: any[];
51-
attributes: Record<string, unknown>;
64+
attributes: AugmentVisSavedObjectAttributes;
5265
id: string;
5366
}) {
5467
// For now we are assuming only one vis reference per saved object.

src/plugins/vis_augmenter/public/saved_augment_vis/saved_augment_vis_references.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
injectReferences,
99
VIS_REFERENCE_NAME,
1010
} from './saved_augment_vis_references';
11-
import { AugmentVisSavedObject } from '../types';
11+
import { AugmentVisSavedObject } from './types';
1212

1313
describe('extractReferences()', () => {
1414
test('extracts nothing if visId is null', () => {

src/plugins/vis_augmenter/public/saved_augment_vis/saved_augment_vis_references.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
*/
55

66
import { SavedObjectAttributes, SavedObjectReference } from '../../../../core/public';
7-
import { AugmentVisSavedObject } from '../types';
7+
import { AugmentVisSavedObjectAttributes } from '../../common';
8+
import { AugmentVisSavedObject } from './types';
89

910
/**
1011
* Note that references aren't stored in the object's client-side interface (AugmentVisSavedObject).
@@ -35,7 +36,7 @@ export function extractReferences({
3536
attributes: SavedObjectAttributes;
3637
references: SavedObjectReference[];
3738
}) {
38-
const updatedAttributes = { ...attributes };
39+
const updatedAttributes = { ...attributes } as AugmentVisSavedObjectAttributes;
3940
const updatedReferences = [...references];
4041

4142
// Extract saved object

src/plugins/vis_augmenter/public/saved_augment_vis/types.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,17 @@
66
import { SavedObject } from '../../../saved_objects/public';
77
import { VisLayerExpressionFn } from '../expressions';
88

9+
export interface ISavedPluginResource {
10+
type: string;
11+
id: string;
12+
}
13+
914
export interface ISavedAugmentVis {
1015
id?: string;
1116
title: string;
1217
description?: string;
13-
pluginResourceId: string;
18+
originPlugin: string;
19+
pluginResource: ISavedPluginResource;
1420
visName?: string;
1521
visId?: string;
1622
visLayerExpressionFn: VisLayerExpressionFn;

src/plugins/vis_augmenter/public/saved_augment_vis/utils/helpers.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*/
55

66
import { getSavedAugmentVisLoader } from '../../services';
7-
import { ISavedAugmentVis } from '../../types';
7+
import { ISavedAugmentVis } from '../types';
88

99
/**
1010
* Create an augment vis saved object given an object that

src/plugins/vis_augmenter/public/saved_augment_vis/utils/test_helpers.ts

+6-4
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,24 @@
44
*/
55

66
import { cloneDeep } from 'lodash';
7-
import { VisLayerExpressionFn, ISavedAugmentVis } from '../../';
7+
import { VisLayerExpressionFn, ISavedAugmentVis, ISavedPluginResource } from '../../';
88
import { VIS_REFERENCE_NAME } from '../saved_augment_vis_references';
99

10-
const pluginResourceId = 'test-plugin-resource-id';
1110
const title = 'test-title';
1211
const version = 1;
1312

1413
export const generateAugmentVisSavedObject = (
1514
idArg: string,
1615
exprFnArg: VisLayerExpressionFn,
17-
visIdArg: string
16+
visIdArg: string,
17+
originPluginArg: string,
18+
pluginResourceArg: ISavedPluginResource
1819
) => {
1920
return {
2021
id: idArg,
2122
title,
22-
pluginResourceId,
23+
originPlugin: originPluginArg,
24+
pluginResource: pluginResourceArg,
2325
visLayerExpressionFn: exprFnArg,
2426
VIS_REFERENCE_NAME,
2527
visId: visIdArg,

0 commit comments

Comments
 (0)