From fd3e0c37976b604b7582e209d51c7c4ac2eb8833 Mon Sep 17 00:00:00 2001 From: Corey Robertson Date: Mon, 19 Apr 2021 17:01:46 -0400 Subject: [PATCH 1/3] Adds telemetry for recent function usage --- .../collectors/workpad_collector.test.ts | 51 ++++++++++++++++++- .../server/collectors/workpad_collector.ts | 39 +++++++++++++- 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/canvas/server/collectors/workpad_collector.test.ts b/x-pack/plugins/canvas/server/collectors/workpad_collector.test.ts index 0e132047b2bbd..a82a0d45fa896 100644 --- a/x-pack/plugins/canvas/server/collectors/workpad_collector.test.ts +++ b/x-pack/plugins/canvas/server/collectors/workpad_collector.test.ts @@ -8,6 +8,7 @@ import { cloneDeep } from 'lodash'; import { summarizeWorkpads } from './workpad_collector'; import { workpads } from '../../__fixtures__/workpads'; +import moment from 'moment'; describe('usage collector handle es response data', () => { it('should summarize workpads, pages, and elements', () => { @@ -49,6 +50,8 @@ describe('usage collector handle es response data', () => { 'image', 'shape', ], + in_use_30d: [], + in_use_90d: [], }, variables: { total: 7, @@ -71,7 +74,13 @@ describe('usage collector handle es response data', () => { workpads: { total: 1 }, pages: { total: 1, per_workpad: { avg: 1, min: 1, max: 1 } }, elements: { total: 1, per_page: { avg: 1, min: 1, max: 1 } }, - functions: { total: 1, in_use: ['toast'], per_element: { avg: 1, min: 1, max: 1 } }, + functions: { + total: 1, + in_use: ['toast'], + in_use_30d: [], + in_use_90d: [], + per_element: { avg: 1, min: 1, max: 1 }, + }, variables: { total: 1, per_workpad: { avg: 1, min: 1, max: 1 } }, }); }); @@ -116,6 +125,8 @@ describe('usage collector handle es response data', () => { 'plot', 'seriesStyle', ], + in_use_30d: [], + in_use_90d: [], per_element: { avg: 7, min: 7, max: 7 }, }, variables: { total: 0, per_workpad: { avg: 0, min: 0, max: 0 } }, // Variables still possible even with no pages @@ -126,4 +137,42 @@ describe('usage collector handle es response data', () => { const usage = summarizeWorkpads([]); expect(usage).toEqual({}); }); + + describe('functions', () => { + it('collects funtions used in the most recent 30d and 90d', () => { + const thirtyDayFunction = '30d'; + const ninetyDayFunction = '90d'; + const otherFunction = '180d'; + + const workpad30d = cloneDeep(workpads[0]); + const workpad90d = cloneDeep(workpads[0]); + const workpad180d = cloneDeep(workpads[0]); + + const now = moment(); + + workpad30d['@timestamp'] = now.subtract(1, 'day').toDate().toISOString(); + workpad90d['@timestamp'] = now.subtract(80, 'day').toDate().toISOString(); + workpad180d['@timestamp'] = now.subtract(180, 'day').toDate().toISOString(); + + workpad30d.pages[0].elements[0].expression = `${thirtyDayFunction}`; + workpad90d.pages[0].elements[0].expression = `${ninetyDayFunction}`; + workpad180d.pages[0].elements[0].expression = `${otherFunction}`; + + const mockWorkpads = [workpad30d, workpad90d, workpad180d]; + const usage = summarizeWorkpads(mockWorkpads); + + expect(usage.functions?.in_use_30d).toHaveLength(1); + expect(usage.functions?.in_use_30d).toEqual(expect.arrayContaining([thirtyDayFunction])); + + expect(usage.functions?.in_use_90d).toHaveLength(2); + expect(usage.functions?.in_use_90d).toEqual( + expect.arrayContaining([thirtyDayFunction, ninetyDayFunction]) + ); + + expect(usage.functions?.in_use).toHaveLength(3); + expect(usage.functions?.in_use).toEqual( + expect.arrayContaining([thirtyDayFunction, ninetyDayFunction, otherFunction]) + ); + }); + }); }); diff --git a/x-pack/plugins/canvas/server/collectors/workpad_collector.ts b/x-pack/plugins/canvas/server/collectors/workpad_collector.ts index 7342cb5d40357..f96b1887a1531 100644 --- a/x-pack/plugins/canvas/server/collectors/workpad_collector.ts +++ b/x-pack/plugins/canvas/server/collectors/workpad_collector.ts @@ -6,6 +6,7 @@ */ import { sum as arraySum, min as arrayMin, max as arrayMax, get } from 'lodash'; +import moment from 'moment'; import { MakeSchemaFrom } from 'src/plugins/usage_collection/server'; import { CANVAS_TYPE } from '../../common/lib/constants'; import { collectFns } from './collector_helpers'; @@ -39,6 +40,8 @@ export interface WorkpadTelemetry { functions?: { total: number; in_use: string[]; + in_use_30d: string[]; + in_use_90d: string[]; per_element: { avg: number; min: number; @@ -76,6 +79,8 @@ export const workpadSchema: MakeSchemaFrom = { functions: { total: { type: 'long' }, in_use: { type: 'array', items: { type: 'keyword' } }, + in_use_30d: { type: 'array', items: { type: 'keyword' } }, + in_use_90d: { type: 'array', items: { type: 'keyword' } }, per_element: { avg: { type: 'float' }, min: { type: 'long' }, @@ -98,6 +103,11 @@ export const workpadSchema: MakeSchemaFrom = { @returns Workpad Telemetry Data */ export function summarizeWorkpads(workpadDocs: CanvasWorkpad[]): WorkpadTelemetry { + const functionCollection = { + all: new Set(), + '30d': new Set(), + '90d': new Set(), + }; const functionSet = new Set(); if (workpadDocs.length === 0) { @@ -106,6 +116,21 @@ export function summarizeWorkpads(workpadDocs: CanvasWorkpad[]): WorkpadTelemetr // make a summary of info about each workpad const workpadsInfo = workpadDocs.map((workpad) => { + let this30Days = false; + let this90Days = false; + + if (workpad['@timestamp'] !== undefined) { + const lastReadDaysAgo = moment().diff(moment(workpad['@timestamp']), 'days'); + + if (lastReadDaysAgo < 30) { + this30Days = true; + } + + if (lastReadDaysAgo < 90) { + this90Days = true; + } + } + let pages = { count: 0 }; try { pages = { count: workpad.pages.length }; @@ -121,6 +146,16 @@ export function summarizeWorkpads(workpadDocs: CanvasWorkpad[]): WorkpadTelemetr return page.elements.map((element) => { const ast = parseExpression(element.expression); collectFns(ast, (cFunction) => { + functionCollection.all.add(cFunction); + + if (this30Days) { + functionCollection['30d'].add(cFunction); + } + + if (this90Days) { + functionCollection['90d'].add(cFunction); + } + functionSet.add(cFunction); }); return ast.chain.length; // get the number of parts in the expression @@ -203,7 +238,9 @@ export function summarizeWorkpads(workpadDocs: CanvasWorkpad[]): WorkpadTelemetr elementsTotal > 0 ? { total: functionsTotal, - in_use: Array.from(functionSet), + in_use: Array.from(functionCollection.all), + in_use_30d: Array.from(functionCollection['30d']), + in_use_90d: Array.from(functionCollection['90d']), per_element: { avg: functionsTotal / functionCounts.length, min: arrayMin(functionCounts) || 0, From 4a060322a6e34adbd671db11ec385dbebca7fbc2 Mon Sep 17 00:00:00 2001 From: Corey Robertson Date: Tue, 20 Apr 2021 09:21:56 -0400 Subject: [PATCH 2/3] Adds description for telemetry fields --- .../collectors/custom_element_collector.ts | 38 ++++- .../server/collectors/workpad_collector.ts | 156 +++++++++++++++--- 2 files changed, 169 insertions(+), 25 deletions(-) diff --git a/x-pack/plugins/canvas/server/collectors/custom_element_collector.ts b/x-pack/plugins/canvas/server/collectors/custom_element_collector.ts index 144d77df064c7..18cfe1a3df56c 100644 --- a/x-pack/plugins/canvas/server/collectors/custom_element_collector.ts +++ b/x-pack/plugins/canvas/server/collectors/custom_element_collector.ts @@ -34,13 +34,41 @@ export interface CustomElementTelemetry { export const customElementSchema: MakeSchemaFrom = { custom_elements: { - count: { type: 'long' }, + count: { + type: 'long', + _meta: { + description: 'The total number of custom Canvas elements', + }, + }, elements: { - min: { type: 'long' }, - max: { type: 'long' }, - avg: { type: 'float' }, + min: { + type: 'long', + _meta: { + description: 'The minimum number of elements used across all Canvas Custom Elements', + }, + }, + max: { + type: 'long', + _meta: { + description: 'The maximum number of elements used across all Canvas Custom Elements', + }, + }, + avg: { + type: 'float', + _meta: { + description: 'The average number of elements used in Canvas Custom Element', + }, + }, + }, + functions_in_use: { + type: 'array', + items: { + type: 'keyword', + _meta: { + description: 'The functions in use by Canvas Custom Elements', + }, + }, }, - functions_in_use: { type: 'array', items: { type: 'keyword' } }, }, }; diff --git a/x-pack/plugins/canvas/server/collectors/workpad_collector.ts b/x-pack/plugins/canvas/server/collectors/workpad_collector.ts index f96b1887a1531..427c8c8a6571f 100644 --- a/x-pack/plugins/canvas/server/collectors/workpad_collector.ts +++ b/x-pack/plugins/canvas/server/collectors/workpad_collector.ts @@ -59,40 +59,156 @@ export interface WorkpadTelemetry { } export const workpadSchema: MakeSchemaFrom = { - workpads: { total: { type: 'long' } }, + workpads: { + total: { + type: 'long', + _meta: { + description: 'The total number of Canvas Workpads in the cluster', + }, + }, + }, pages: { - total: { type: 'long' }, + total: { + type: 'long', + _meta: { + description: 'The total number of pages across all Canvas Workpads', + }, + }, per_workpad: { - avg: { type: 'float' }, - min: { type: 'long' }, - max: { type: 'long' }, + avg: { + type: 'float', + _meta: { + description: 'The average number of pages across all Canvas Workpads', + }, + }, + min: { + type: 'long', + _meta: { + description: 'The minimum number of pages found in a Canvas Workpad', + }, + }, + max: { + type: 'long', + _meta: { + description: 'The maximum number of pages found in a Canvas Workpad', + }, + }, }, }, elements: { - total: { type: 'long' }, + total: { + type: 'long', + _meta: { + description: 'The total number of elements across all Canvas Workpads', + }, + }, per_page: { - avg: { type: 'float' }, - min: { type: 'long' }, - max: { type: 'long' }, + avg: { + type: 'float', + _meta: { + description: 'The average number of elements per page across all Canvas Workpads', + }, + }, + min: { + type: 'long', + _meta: { + description: 'The minimum number of elements on a page across all Canvas Workpads', + }, + }, + max: { + type: 'long', + _meta: { + description: 'The maximum number of elements on a page across all Canvas Workpads', + }, + }, }, }, functions: { - total: { type: 'long' }, - in_use: { type: 'array', items: { type: 'keyword' } }, - in_use_30d: { type: 'array', items: { type: 'keyword' } }, - in_use_90d: { type: 'array', items: { type: 'keyword' } }, + total: { + type: 'long', + _meta: { + description: 'The total number of functions in use across all Canvas Workpads', + }, + }, + in_use: { + type: 'array', + items: { + type: 'keyword', + _meta: { + description: 'A function in use in any Canvas Workpad', + }, + }, + }, + in_use_30d: { + type: 'array', + items: { + type: 'keyword', + _meta: { + description: + 'A function in use in a Canvas Workpad that has been modified in the last 30 days', + }, + }, + }, + in_use_90d: { + type: 'array', + items: { + type: 'keyword', + _meta: { + description: + 'A function in use in a Canvas Workpad that has been modified in the last 90 days', + }, + }, + }, per_element: { - avg: { type: 'float' }, - min: { type: 'long' }, - max: { type: 'long' }, + avg: { + type: 'float', + _meta: { + description: 'Average number of functions used per element across all Canvas Workpads', + }, + }, + min: { + type: 'long', + _meta: { + description: + 'The minimum number of functions used in an element across all Canvas Workpads', + }, + }, + max: { + type: 'long', + _meta: { + description: + 'The maximum number of functions used in an element across all Canvas Workpads', + }, + }, }, }, variables: { - total: { type: 'long' }, + total: { + type: 'long', + _meta: { + description: 'The total number of variables defined across all Canvas Workpads', + }, + }, + per_workpad: { - avg: { type: 'float' }, - min: { type: 'long' }, - max: { type: 'long' }, + avg: { + type: 'float', + _meta: { + description: 'The average number of variables set per Canvas Workpad', + }, + }, + min: { + type: 'long', + _meta: { + description: 'The minimum number variables set across all Canvas Workpads', + }, + }, + max: { + type: 'long', + _meta: { + description: 'The maximum number of variables set across all Canvas Workpads', + }, + }, }, }, }; From f5d584097388df59ac24caa2869c646f9b17492e Mon Sep 17 00:00:00 2001 From: Corey Robertson Date: Tue, 20 Apr 2021 10:05:19 -0400 Subject: [PATCH 3/3] Update Telemetry Schema --- src/plugins/telemetry/schema/oss_plugins.json | 2 +- .../schema/xpack_plugins.json | 133 +++++++++++++++--- 2 files changed, 111 insertions(+), 24 deletions(-) diff --git a/src/plugins/telemetry/schema/oss_plugins.json b/src/plugins/telemetry/schema/oss_plugins.json index dc653062931c2..842496815c15c 100644 --- a/src/plugins/telemetry/schema/oss_plugins.json +++ b/src/plugins/telemetry/schema/oss_plugins.json @@ -4084,7 +4084,7 @@ } } } - }, + }, "security_account": { "properties": { "appId": { diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index 1d1cd8c0c7667..40493f343a6bd 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -1578,25 +1578,40 @@ "workpads": { "properties": { "total": { - "type": "long" + "type": "long", + "_meta": { + "description": "The total number of Canvas Workpads in the cluster" + } } } }, "pages": { "properties": { "total": { - "type": "long" + "type": "long", + "_meta": { + "description": "The total number of pages across all Canvas Workpads" + } }, "per_workpad": { "properties": { "avg": { - "type": "float" + "type": "float", + "_meta": { + "description": "The average number of pages across all Canvas Workpads" + } }, "min": { - "type": "long" + "type": "long", + "_meta": { + "description": "The minimum number of pages found in a Canvas Workpad" + } }, "max": { - "type": "long" + "type": "long", + "_meta": { + "description": "The maximum number of pages found in a Canvas Workpad" + } } } } @@ -1605,18 +1620,30 @@ "elements": { "properties": { "total": { - "type": "long" + "type": "long", + "_meta": { + "description": "The total number of elements across all Canvas Workpads" + } }, "per_page": { "properties": { "avg": { - "type": "float" + "type": "float", + "_meta": { + "description": "The average number of elements per page across all Canvas Workpads" + } }, "min": { - "type": "long" + "type": "long", + "_meta": { + "description": "The minimum number of elements on a page across all Canvas Workpads" + } }, "max": { - "type": "long" + "type": "long", + "_meta": { + "description": "The maximum number of elements on a page across all Canvas Workpads" + } } } } @@ -1625,24 +1652,57 @@ "functions": { "properties": { "total": { - "type": "long" + "type": "long", + "_meta": { + "description": "The total number of functions in use across all Canvas Workpads" + } }, "in_use": { "type": "array", "items": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "A function in use in any Canvas Workpad" + } + } + }, + "in_use_30d": { + "type": "array", + "items": { + "type": "keyword", + "_meta": { + "description": "A function in use in a Canvas Workpad that has been modified in the last 30 days" + } + } + }, + "in_use_90d": { + "type": "array", + "items": { + "type": "keyword", + "_meta": { + "description": "A function in use in a Canvas Workpad that has been modified in the last 90 days" + } } }, "per_element": { "properties": { "avg": { - "type": "float" + "type": "float", + "_meta": { + "description": "Average number of functions used per element across all Canvas Workpads" + } }, "min": { - "type": "long" + "type": "long", + "_meta": { + "description": "The minimum number of functions used in an element across all Canvas Workpads" + } }, "max": { - "type": "long" + "type": "long", + "_meta": { + "description": "The maximum number of functions used in an element across all Canvas Workpads" + } } } } @@ -1651,18 +1711,30 @@ "variables": { "properties": { "total": { - "type": "long" + "type": "long", + "_meta": { + "description": "The total number of variables defined across all Canvas Workpads" + } }, "per_workpad": { "properties": { "avg": { - "type": "float" + "type": "float", + "_meta": { + "description": "The average number of variables set per Canvas Workpad" + } }, "min": { - "type": "long" + "type": "long", + "_meta": { + "description": "The minimum number variables set across all Canvas Workpads" + } }, "max": { - "type": "long" + "type": "long", + "_meta": { + "description": "The maximum number of variables set across all Canvas Workpads" + } } } } @@ -1671,25 +1743,40 @@ "custom_elements": { "properties": { "count": { - "type": "long" + "type": "long", + "_meta": { + "description": "The total number of custom Canvas elements" + } }, "elements": { "properties": { "min": { - "type": "long" + "type": "long", + "_meta": { + "description": "The minimum number of elements used across all Canvas Custom Elements" + } }, "max": { - "type": "long" + "type": "long", + "_meta": { + "description": "The maximum number of elements used across all Canvas Custom Elements" + } }, "avg": { - "type": "float" + "type": "float", + "_meta": { + "description": "The average number of elements used in Canvas Custom Element" + } } } }, "functions_in_use": { "type": "array", "items": { - "type": "keyword" + "type": "keyword", + "_meta": { + "description": "The functions in use by Canvas Custom Elements" + } } } }