mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[TSVB] Gather stats for the usage of the aggregate function in table viz (#113247)
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
685a550806
commit
24bbf2cdfc
4 changed files with 136 additions and 9 deletions
|
@ -9088,6 +9088,12 @@
|
|||
"_meta": {
|
||||
"description": "Number of TSVB visualizations using \"last value\" as a time range"
|
||||
}
|
||||
},
|
||||
"timeseries_table_use_aggregate_function": {
|
||||
"type": "long",
|
||||
"_meta": {
|
||||
"description": "Number of TSVB table visualizations using aggregate function"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -49,6 +49,23 @@ const mockedSavedObject = {
|
|||
}),
|
||||
},
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
visState: JSON.stringify({
|
||||
type: 'metrics',
|
||||
title: 'TSVB visualization 4',
|
||||
params: {
|
||||
type: 'table',
|
||||
series: [
|
||||
{
|
||||
aggregate_by: 'test',
|
||||
aggregate_function: 'max',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
],
|
||||
} as SavedObjectsFindResponse;
|
||||
|
||||
|
@ -83,6 +100,27 @@ const mockedSavedObjectsByValue = [
|
|||
}),
|
||||
},
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
panelsJSON: JSON.stringify({
|
||||
type: 'visualization',
|
||||
embeddableConfig: {
|
||||
savedVis: {
|
||||
type: 'metrics',
|
||||
params: {
|
||||
type: 'table',
|
||||
series: [
|
||||
{
|
||||
aggregate_by: 'test1',
|
||||
aggregate_function: 'sum',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const getMockCollectorFetchContext = (
|
||||
|
@ -142,6 +180,58 @@ describe('Timeseries visualization usage collector', () => {
|
|||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
test('Returns undefined when aggregate function is null', async () => {
|
||||
const mockCollectorFetchContext = getMockCollectorFetchContext({
|
||||
saved_objects: [
|
||||
{
|
||||
attributes: {
|
||||
panelsJSON: JSON.stringify({
|
||||
type: 'visualization',
|
||||
embeddableConfig: {
|
||||
savedVis: {
|
||||
type: 'metrics',
|
||||
params: {
|
||||
type: 'table',
|
||||
series: [
|
||||
{
|
||||
aggregate_by: null,
|
||||
aggregate_function: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
{
|
||||
attributes: {
|
||||
panelsJSON: JSON.stringify({
|
||||
type: 'visualization',
|
||||
embeddableConfig: {
|
||||
savedVis: {
|
||||
type: 'metrics',
|
||||
params: {
|
||||
type: 'table',
|
||||
series: [
|
||||
{
|
||||
axis_position: 'right',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
],
|
||||
} as SavedObjectsFindResponse);
|
||||
|
||||
const result = await getStats(mockCollectorFetchContext.soClient);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
test('Summarizes visualizations response data', async () => {
|
||||
const mockCollectorFetchContext = getMockCollectorFetchContext(
|
||||
mockedSavedObject,
|
||||
|
@ -149,8 +239,9 @@ describe('Timeseries visualization usage collector', () => {
|
|||
);
|
||||
const result = await getStats(mockCollectorFetchContext.soClient);
|
||||
|
||||
expect(result).toMatchObject({
|
||||
timeseries_use_last_value_mode_total: 3,
|
||||
expect(result).toStrictEqual({
|
||||
timeseries_use_last_value_mode_total: 5,
|
||||
timeseries_table_use_aggregate_function: 2,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -15,14 +15,16 @@ import type {
|
|||
SavedObjectsFindResult,
|
||||
} from '../../../../../core/server';
|
||||
import type { SavedVisState } from '../../../../visualizations/common';
|
||||
import type { Panel } from '../../common/types';
|
||||
|
||||
export interface TimeseriesUsage {
|
||||
timeseries_use_last_value_mode_total: number;
|
||||
timeseries_table_use_aggregate_function: number;
|
||||
}
|
||||
|
||||
const doTelemetryFoVisualizations = async (
|
||||
soClient: SavedObjectsClientContract | ISavedObjectsRepository,
|
||||
telemetryUseLastValueMode: (savedVis: SavedVisState) => void
|
||||
calculateTelemetry: (savedVis: SavedVisState<Panel>) => void
|
||||
) => {
|
||||
const finder = await soClient.createPointInTimeFinder({
|
||||
type: 'visualization',
|
||||
|
@ -34,9 +36,9 @@ const doTelemetryFoVisualizations = async (
|
|||
(response.saved_objects || []).forEach(({ attributes }: SavedObjectsFindResult<any>) => {
|
||||
if (attributes?.visState) {
|
||||
try {
|
||||
const visState: SavedVisState = JSON.parse(attributes.visState);
|
||||
const visState: SavedVisState<Panel> = JSON.parse(attributes.visState);
|
||||
|
||||
telemetryUseLastValueMode(visState);
|
||||
calculateTelemetry(visState);
|
||||
} catch {
|
||||
// nothing to be here, "so" not valid
|
||||
}
|
||||
|
@ -48,12 +50,12 @@ const doTelemetryFoVisualizations = async (
|
|||
|
||||
const doTelemetryForByValueVisualizations = async (
|
||||
soClient: SavedObjectsClientContract | ISavedObjectsRepository,
|
||||
telemetryUseLastValueMode: (savedVis: SavedVisState) => void
|
||||
telemetryUseLastValueMode: (savedVis: SavedVisState<Panel>) => void
|
||||
) => {
|
||||
const byValueVisualizations = await findByValueEmbeddables(soClient, 'visualization');
|
||||
|
||||
for (const item of byValueVisualizations) {
|
||||
telemetryUseLastValueMode(item.savedVis as unknown as SavedVisState);
|
||||
telemetryUseLastValueMode(item.savedVis as unknown as SavedVisState<Panel>);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -62,9 +64,10 @@ export const getStats = async (
|
|||
): Promise<TimeseriesUsage | undefined> => {
|
||||
const timeseriesUsage = {
|
||||
timeseries_use_last_value_mode_total: 0,
|
||||
timeseries_table_use_aggregate_function: 0,
|
||||
};
|
||||
|
||||
function telemetryUseLastValueMode(visState: SavedVisState) {
|
||||
function telemetryUseLastValueMode(visState: SavedVisState<Panel>) {
|
||||
if (
|
||||
visState.type === 'metrics' &&
|
||||
visState.params.type !== 'timeseries' &&
|
||||
|
@ -75,10 +78,33 @@ export const getStats = async (
|
|||
}
|
||||
}
|
||||
|
||||
function telemetryTableAggFunction(visState: SavedVisState<Panel>) {
|
||||
if (
|
||||
visState.type === 'metrics' &&
|
||||
visState.params.type === 'table' &&
|
||||
visState.params.series &&
|
||||
visState.params.series.length > 0
|
||||
) {
|
||||
const usesAggregateFunction = visState.params.series.some(
|
||||
(s) => s.aggregate_by && s.aggregate_function
|
||||
);
|
||||
if (usesAggregateFunction) {
|
||||
timeseriesUsage.timeseries_table_use_aggregate_function++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all([
|
||||
// last value usage telemetry
|
||||
doTelemetryFoVisualizations(soClient, telemetryUseLastValueMode),
|
||||
doTelemetryForByValueVisualizations(soClient, telemetryUseLastValueMode),
|
||||
// table aggregate function telemetry
|
||||
doTelemetryFoVisualizations(soClient, telemetryTableAggFunction),
|
||||
doTelemetryForByValueVisualizations(soClient, telemetryTableAggFunction),
|
||||
]);
|
||||
|
||||
return timeseriesUsage.timeseries_use_last_value_mode_total ? timeseriesUsage : undefined;
|
||||
return timeseriesUsage.timeseries_use_last_value_mode_total ||
|
||||
timeseriesUsage.timeseries_table_use_aggregate_function
|
||||
? timeseriesUsage
|
||||
: undefined;
|
||||
};
|
||||
|
|
|
@ -18,6 +18,10 @@ export function registerTimeseriesUsageCollector(collectorSet: UsageCollectionSe
|
|||
type: 'long',
|
||||
_meta: { description: 'Number of TSVB visualizations using "last value" as a time range' },
|
||||
},
|
||||
timeseries_table_use_aggregate_function: {
|
||||
type: 'long',
|
||||
_meta: { description: 'Number of TSVB table visualizations using aggregate function' },
|
||||
},
|
||||
},
|
||||
fetch: async ({ soClient }) => await getStats(soClient),
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue