From 28cd841c7d89d8c529ada89a29fe82c5cd556bed Mon Sep 17 00:00:00 2001 From: Joshua Li Date: Fri, 2 Dec 2022 21:07:40 +0000 Subject: [PATCH 1/2] Add frontend server metrics Signed-off-by: Joshua Li --- .../server/common/metrics/constants.ts | 45 +++++++++---------- .../server/common/metrics/metrics_helper.ts | 22 ++++----- .../server/common/metrics/types.ts | 8 ++-- .../app_analytics_router.ts | 13 ++++++ .../routes/custom_panels/panels_router.ts | 19 ++++++++ .../custom_panels/visualizations_router.ts | 3 ++ .../event_analytics/event_analytics_router.ts | 21 +++++++++ .../server/routes/notebooks/noteRouter.ts | 15 +++++++ .../server/routes/notebooks/sqlRouter.ts | 3 ++ .../server/routes/notebooks/vizRouter.ts | 3 ++ 10 files changed, 114 insertions(+), 38 deletions(-) diff --git a/dashboards-observability/server/common/metrics/constants.ts b/dashboards-observability/server/common/metrics/constants.ts index d67a38570..2065ed976 100644 --- a/dashboards-observability/server/common/metrics/constants.ts +++ b/dashboards-observability/server/common/metrics/constants.ts @@ -3,31 +3,31 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { ComponentType, CounterType } from './types'; +import _ from 'lodash'; +import { CounterType } from './types'; export const WINDOW = 3600; export const INTERVAL = 60; export const CAPACITY = (WINDOW / INTERVAL) * 2; export const MILLIS_MULTIPLIER = 1000; -export const COMPONENTS = [ - 'application_analytics', - 'operational_panels', - 'event_analytics', - 'notebooks', - 'trace_analytics', - 'metrics_analytics', -] as const; -export const REQUESTS = ['create', 'get', 'update', 'delete'] as const; +const commonRequests = ['create', 'get', 'update', 'delete', 'add_samples'] as const; + +// object of each component and its specific requests +export const COMPONENTS = { + application_analytics: commonRequests, + operational_panels: [...commonRequests, 'fetch_visualization'], + event_analytics: commonRequests, + notebooks: [...commonRequests, 'run_sql_query', 'run_ppl_query', 'fetch_visualization'], + trace_analytics: commonRequests, + metrics_analytics: commonRequests, +} as const; export const GLOBAL_BASIC_COUNTER: CounterType = (() => { const counter = {} as CounterType; - COMPONENTS.forEach((component) => { - counter[component] = {} as CounterType[ComponentType]; - REQUESTS.forEach((request) => { - counter[component][request] = { - total: 0, - }; + Object.entries(COMPONENTS).forEach(([component, requests]) => { + requests.forEach((request) => { + _.set(counter, [component, request, 'total'], 0); }); }); return counter; @@ -35,14 +35,11 @@ export const GLOBAL_BASIC_COUNTER: CounterType = (() => { export const DEFAULT_ROLLING_COUNTER: CounterType = (() => { const counter = {} as CounterType; - COMPONENTS.forEach((component) => { - counter[component] = {} as CounterType[ComponentType]; - REQUESTS.forEach((request) => { - counter[component][request] = { - count: 0, - system_error: 0, - user_error: 0, - }; + Object.entries(COMPONENTS).forEach(([component, requests]) => { + requests.forEach((request) => { + _.set(counter, [component, request, 'count'], 0); + _.set(counter, [component, request, 'system_error'], 0); + _.set(counter, [component, request, 'user_error'], 0); }); }); return counter; diff --git a/dashboards-observability/server/common/metrics/metrics_helper.ts b/dashboards-observability/server/common/metrics/metrics_helper.ts index 659f8c383..07aa67806 100644 --- a/dashboards-observability/server/common/metrics/metrics_helper.ts +++ b/dashboards-observability/server/common/metrics/metrics_helper.ts @@ -38,19 +38,19 @@ export function addClickToMetric(element: string, counter: CounterNameType = 'co time2CountWin.set(timeKey, rollingCounter); } -export function addRequestToMetric( - component: ComponentType, - request: RequestType, +export function addRequestToMetric( + component: T, + request: RequestType, error: { statusCode: number } ): void; -export function addRequestToMetric( - component: ComponentType, - request: RequestType, +export function addRequestToMetric( + component: T, + request: RequestType, counter: CounterNameType ): void; -export function addRequestToMetric( - component: ComponentType, - request: RequestType, +export function addRequestToMetric( + component: T, + request: RequestType, counterNameOrError: CounterNameType | { statusCode: number } ) { const counter = @@ -64,8 +64,10 @@ export function addRequestToMetric( const timeKey = getKey(Date.now()); const rollingCounter = time2CountWin.get(timeKey) || _.cloneDeep(DEFAULT_ROLLING_COUNTER); + // @ts-ignore not sure why 'request' can't be indexed rollingCounter[component][request][counter]!++; if (counter === 'count') { + // @ts-ignore GLOBAL_BASIC_COUNTER[component][request]['total']!++; } @@ -106,7 +108,7 @@ const getPreKey = (milliseconds: number) => { }; const isComponent = (arg: string): arg is ComponentType => { - return COMPONENTS.includes(arg as ComponentType); + return Object.keys(COMPONENTS).includes(arg); }; const buildMetrics = (rollingCounters?: CounterType) => { diff --git a/dashboards-observability/server/common/metrics/types.ts b/dashboards-observability/server/common/metrics/types.ts index e0bd1c7cb..b8fefc0fd 100644 --- a/dashboards-observability/server/common/metrics/types.ts +++ b/dashboards-observability/server/common/metrics/types.ts @@ -3,10 +3,10 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { COMPONENTS, REQUESTS } from './constants'; +import { COMPONENTS } from './constants'; -export type ComponentType = typeof COMPONENTS[number]; -export type RequestType = typeof REQUESTS[number]; +export type ComponentType = keyof typeof COMPONENTS; +export type RequestType = typeof COMPONENTS[T][number]; export type CounterNameType = 'count' | 'system_error' | 'user_error' | 'total'; // counter to track user click actions @@ -19,7 +19,7 @@ type ClickCounterType = { // counter to track requests to OpenSearch type RequestCounterType = { [component in ComponentType]: { - [request in RequestType]: { + [request in RequestType]: { [counter in CounterNameType]?: number; }; }; diff --git a/dashboards-observability/server/routes/application_analytics/app_analytics_router.ts b/dashboards-observability/server/routes/application_analytics/app_analytics_router.ts index 930e0d5f1..82a730507 100644 --- a/dashboards-observability/server/routes/application_analytics/app_analytics_router.ts +++ b/dashboards-observability/server/routes/application_analytics/app_analytics_router.ts @@ -14,6 +14,7 @@ import { import { APP_ANALYTICS_API_PREFIX as API_PREFIX } from '../../../common/constants/application_analytics'; import { ApplicationType } from '../../../common/types/application_analytics'; import { AppAnalyticsAdaptor } from '../../../server/adaptors/application_analytics/app_analytics_adaptor'; +import { addRequestToMetric } from '../../common/metrics/metrics_helper'; export function registerAppAnalyticsRouter(router: IRouter) { const appAnalyticsBackend = new AppAnalyticsAdaptor(); @@ -29,6 +30,7 @@ export function registerAppAnalyticsRouter(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('application_analytics', 'get', 'count'); const opensearchClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -41,6 +43,7 @@ export function registerAppAnalyticsRouter(router: IRouter) { }, }); } catch (err: any) { + addRequestToMetric('application_analytics', 'get', err); console.error('Error occurred while fetching applications', err); return response.custom({ statusCode: err.statusCode || 500, @@ -65,6 +68,7 @@ export function registerAppAnalyticsRouter(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('application_analytics', 'get', 'count'); const opensearchClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -77,6 +81,7 @@ export function registerAppAnalyticsRouter(router: IRouter) { body: appObject, }); } catch (err: any) { + addRequestToMetric('application_analytics', 'get', err); console.error('Error occurred while fetching application', err); return response.custom({ statusCode: err.statusCode || 500, @@ -106,6 +111,7 @@ export function registerAppAnalyticsRouter(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('application_analytics', 'create', 'count'); const opensearchClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -119,6 +125,7 @@ export function registerAppAnalyticsRouter(router: IRouter) { }, }); } catch (err: any) { + addRequestToMetric('application_analytics', 'get', err); console.error('Error occurred while creating a new application', err); return response.custom({ statusCode: err.statusCode || 500, @@ -144,6 +151,7 @@ export function registerAppAnalyticsRouter(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('application_analytics', 'update', 'count'); const opensearchClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -160,6 +168,7 @@ export function registerAppAnalyticsRouter(router: IRouter) { }, }); } catch (err: any) { + addRequestToMetric('application_analytics', 'update', err); console.error('Error occurred while renaming an existing application', err); return response.custom({ statusCode: err.statusCode || 500, @@ -192,6 +201,7 @@ export function registerAppAnalyticsRouter(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('application_analytics', 'update', 'count'); const opensearchClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -209,6 +219,7 @@ export function registerAppAnalyticsRouter(router: IRouter) { }, }); } catch (err: any) { + addRequestToMetric('application_analytics', 'update', err); console.error('Error occurred while updating an existing application', err); return response.custom({ statusCode: err.statusCode || 500, @@ -233,6 +244,7 @@ export function registerAppAnalyticsRouter(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('application_analytics', 'delete', 'count'); const opensearchClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -245,6 +257,7 @@ export function registerAppAnalyticsRouter(router: IRouter) { body: delResponse, }); } catch (err: any) { + addRequestToMetric('application_analytics', 'delete', err); return response.custom({ statusCode: err.statusCode || 500, body: err.message, diff --git a/dashboards-observability/server/routes/custom_panels/panels_router.ts b/dashboards-observability/server/routes/custom_panels/panels_router.ts index 27b452f75..9c2397292 100644 --- a/dashboards-observability/server/routes/custom_panels/panels_router.ts +++ b/dashboards-observability/server/routes/custom_panels/panels_router.ts @@ -12,6 +12,7 @@ import { ILegacyScopedClusterClient, } from '../../../../../src/core/server'; import { CUSTOM_PANELS_API_PREFIX as API_PREFIX } from '../../../common/constants/custom_panels'; +import { addRequestToMetric } from '../../common/metrics/metrics_helper'; export function PanelsRouter(router: IRouter) { const customPanelBackend = new CustomPanelsAdaptor(); @@ -26,6 +27,7 @@ export function PanelsRouter(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('operational_panels', 'get', 'count'); const opensearchNotebooksClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -38,6 +40,7 @@ export function PanelsRouter(router: IRouter) { }, }); } catch (error: any) { + addRequestToMetric('operational_panels', 'get', error); console.error('Issue in fetching panel list:', error); return response.custom({ statusCode: error.statusCode || 500, @@ -62,6 +65,7 @@ export function PanelsRouter(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('operational_panels', 'get', 'count'); const opensearchNotebooksClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -75,6 +79,7 @@ export function PanelsRouter(router: IRouter) { body: panelObject, }); } catch (error: any) { + addRequestToMetric('operational_panels', 'get', error); console.error('Issue in fetching panel:', error); return response.custom({ statusCode: error.statusCode || 500, @@ -100,6 +105,7 @@ export function PanelsRouter(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('operational_panels', 'create', 'count'); const opensearchNotebooksClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -116,6 +122,7 @@ export function PanelsRouter(router: IRouter) { }, }); } catch (error: any) { + addRequestToMetric('operational_panels', 'create', error); console.error('Issue in creating new panel', error); return response.custom({ statusCode: error.statusCode || 500, @@ -141,6 +148,7 @@ export function PanelsRouter(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('operational_panels', 'update', 'count'); const opensearchNotebooksClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -157,6 +165,7 @@ export function PanelsRouter(router: IRouter) { }, }); } catch (error: any) { + addRequestToMetric('operational_panels', 'update', error); console.error('Issue in renaming panel', error); return response.custom({ statusCode: error.statusCode || 500, @@ -183,6 +192,7 @@ export function PanelsRouter(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('operational_panels', 'create', 'count'); const opensearchNotebooksClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -202,6 +212,7 @@ export function PanelsRouter(router: IRouter) { }, }); } catch (error: any) { + addRequestToMetric('operational_panels', 'create', error); console.error('Issue in cloning panel', error); return response.custom({ statusCode: error.statusCode || 500, @@ -226,6 +237,7 @@ export function PanelsRouter(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('operational_panels', 'delete', 'count'); const opensearchNotebooksClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -241,6 +253,7 @@ export function PanelsRouter(router: IRouter) { }, }); } catch (error: any) { + addRequestToMetric('operational_panels', 'delete', error); console.error('Issue in deleting panel', error); return response.custom({ statusCode: error.statusCode || 500, @@ -265,6 +278,7 @@ export function PanelsRouter(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('operational_panels', 'delete', 'count'); const opensearchNotebooksClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -280,6 +294,7 @@ export function PanelsRouter(router: IRouter) { }, }); } catch (error: any) { + addRequestToMetric('operational_panels', 'delete', error); console.error('Issue in deleting panel', error); return response.custom({ statusCode: error.statusCode || 500, @@ -308,6 +323,7 @@ export function PanelsRouter(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('operational_panels', 'update', 'count'); const opensearchNotebooksClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -327,6 +343,7 @@ export function PanelsRouter(router: IRouter) { }, }); } catch (error: any) { + addRequestToMetric('operational_panels', 'update', error); console.error('Issue in adding query filter', error); return response.custom({ statusCode: error.statusCode || 500, @@ -351,6 +368,7 @@ export function PanelsRouter(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('operational_panels', 'add_samples', 'count'); const opensearchNotebooksClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -366,6 +384,7 @@ export function PanelsRouter(router: IRouter) { }, }); } catch (error: any) { + addRequestToMetric('operational_panels', 'add_samples', error); console.error('Issue in fetching panel list:', error); return response.custom({ statusCode: error.statusCode || 500, diff --git a/dashboards-observability/server/routes/custom_panels/visualizations_router.ts b/dashboards-observability/server/routes/custom_panels/visualizations_router.ts index c92aec633..6099870b2 100644 --- a/dashboards-observability/server/routes/custom_panels/visualizations_router.ts +++ b/dashboards-observability/server/routes/custom_panels/visualizations_router.ts @@ -12,6 +12,7 @@ import { ILegacyScopedClusterClient, } from '../../../../../src/core/server'; import { CUSTOM_PANELS_API_PREFIX as API_PREFIX } from '../../../common/constants/custom_panels'; +import { addRequestToMetric } from '../../common/metrics/metrics_helper'; export function VisualizationsRouter(router: IRouter) { // Fetch all the savedVisualzations @@ -26,6 +27,7 @@ export function VisualizationsRouter(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('operational_panels', 'fetch_visualization', 'count'); const opensearchNotebooksClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -39,6 +41,7 @@ export function VisualizationsRouter(router: IRouter) { }, }); } catch (error) { + addRequestToMetric('operational_panels', 'fetch_visualization', error); console.error('Issue in fetching saved visualizations:', error); return response.custom({ statusCode: error.statusCode || 500, diff --git a/dashboards-observability/server/routes/event_analytics/event_analytics_router.ts b/dashboards-observability/server/routes/event_analytics/event_analytics_router.ts index c2fd7c2d2..4d343c732 100644 --- a/dashboards-observability/server/routes/event_analytics/event_analytics_router.ts +++ b/dashboards-observability/server/routes/event_analytics/event_analytics_router.ts @@ -16,6 +16,7 @@ import { SAVED_QUERY, SAVED_VISUALIZATION, } from '../../../common/constants/shared'; +import { addRequestToMetric } from '../../common/metrics/metrics_helper'; import SavedObjectFacet from '../../services/facets/saved_objects'; export const registerEventAnalyticsRouter = ({ @@ -32,6 +33,7 @@ export const registerEventAnalyticsRouter = ({ validate: {}, }, async (context, req, res): Promise> => { + addRequestToMetric('event_analytics', 'get', 'count'); const savedRes = await savedObjectFacet.getSavedObject(req); const result: any = { body: { @@ -43,6 +45,7 @@ export const registerEventAnalyticsRouter = ({ result.statusCode = savedRes?.data?.statusCode || 500; result.message = savedRes?.data || ''; + addRequestToMetric('event_analytics', 'get', result); return res.custom(result); } ); @@ -57,6 +60,7 @@ export const registerEventAnalyticsRouter = ({ }, }, async (context, req, res): Promise> => { + addRequestToMetric('event_analytics', 'get', 'count'); const savedRes = await savedObjectFacet.getSavedObjectById(req, req.params.objectId); const result: any = { body: { @@ -68,6 +72,7 @@ export const registerEventAnalyticsRouter = ({ result.statusCode = savedRes?.data?.statusCode || 500; result.message = savedRes?.data || ''; + addRequestToMetric('event_analytics', 'get', result); return res.custom(result); } ); @@ -99,6 +104,7 @@ export const registerEventAnalyticsRouter = ({ }, }, async (context, req, res): Promise> => { + addRequestToMetric('event_analytics', 'create', 'count'); const savedRes = await savedObjectFacet.createSavedQuery(req); const result: any = { body: { @@ -110,6 +116,7 @@ export const registerEventAnalyticsRouter = ({ result.statusCode = savedRes?.data?.statusCode || 500; result.message = savedRes?.data || ''; + addRequestToMetric('event_analytics', 'create', result); return res.custom(result); } ); @@ -149,6 +156,7 @@ export const registerEventAnalyticsRouter = ({ }, }, async (context, req, res): Promise> => { + addRequestToMetric('event_analytics', 'create', 'count'); const savedRes = await savedObjectFacet.createSavedVisualization(req); const result: any = { body: { @@ -160,6 +168,7 @@ export const registerEventAnalyticsRouter = ({ result.statusCode = savedRes?.data?.statusCode || 500; result.message = savedRes?.data || ''; + addRequestToMetric('event_analytics', 'create', result); return res.custom(result); } ); @@ -192,6 +201,7 @@ export const registerEventAnalyticsRouter = ({ }, }, async (context, req, res): Promise> => { + addRequestToMetric('event_analytics', 'update', 'count'); const savedRes = await savedObjectFacet.updateSavedQuery(req); const result: any = { body: { @@ -201,6 +211,7 @@ export const registerEventAnalyticsRouter = ({ if (savedRes.success) return res.ok(result); result.statusCode = savedRes?.data?.statusCode || 500; result.message = savedRes?.data || ''; + addRequestToMetric('event_analytics', 'update', result); return res.custom(result); } ); @@ -241,6 +252,7 @@ export const registerEventAnalyticsRouter = ({ }, }, async (context, req, res): Promise> => { + addRequestToMetric('event_analytics', 'update', 'count'); const updateRes = await savedObjectFacet.updateSavedVisualization(req); const result: any = { body: { @@ -250,6 +262,7 @@ export const registerEventAnalyticsRouter = ({ if (updateRes.success) return res.ok(result); result.statusCode = updateRes?.data?.statusCode || 500; result.message = updateRes?.data || ''; + addRequestToMetric('event_analytics', 'update', result); return res.custom(result); } ); @@ -267,6 +280,7 @@ export const registerEventAnalyticsRouter = ({ }, }, async (context, req, res): Promise> => { + addRequestToMetric('event_analytics', 'create', 'count'); const savedRes = await savedObjectFacet.createSavedTimestamp(req); const result: any = { body: { @@ -278,6 +292,7 @@ export const registerEventAnalyticsRouter = ({ result.statusCode = savedRes?.data?.statusCode || 500; result.message = savedRes?.data || ''; + addRequestToMetric('event_analytics', 'create', result); return res.custom(result); } ); @@ -298,6 +313,7 @@ export const registerEventAnalyticsRouter = ({ }, }, async (context, req, res): Promise> => { + addRequestToMetric('event_analytics', 'update', 'count'); const savedRes = await savedObjectFacet.updateSavedTimestamp(req); const result: any = { body: { @@ -309,6 +325,7 @@ export const registerEventAnalyticsRouter = ({ result.statusCode = savedRes?.data?.statusCode || 500; result.message = savedRes?.data || ''; + addRequestToMetric('event_analytics', 'update', result); return res.custom(result); } ); @@ -323,6 +340,7 @@ export const registerEventAnalyticsRouter = ({ }, }, async (context, req, res): Promise> => { + addRequestToMetric('event_analytics', 'delete', 'count'); const deleteResponse = await savedObjectFacet.deleteSavedObject(req); const result: any = { body: { @@ -332,6 +350,7 @@ export const registerEventAnalyticsRouter = ({ if (deleteResponse.success) return res.ok(result); result.statusCode = deleteResponse?.data?.statusCode || 500; result.message = deleteResponse?.data || ''; + addRequestToMetric('event_analytics', 'delete', result); return res.custom(result); } ); @@ -346,6 +365,7 @@ export const registerEventAnalyticsRouter = ({ }, }, async (context, req, res): Promise> => { + addRequestToMetric('event_analytics', 'add_samples', 'count'); const savedRes = await savedObjectFacet.createSampleSavedObjects(req); const result: any = { body: { @@ -357,6 +377,7 @@ export const registerEventAnalyticsRouter = ({ result.statusCode = savedRes?.data?.statusCode || 500; result.message = savedRes?.data || ''; + addRequestToMetric('event_analytics', 'add_samples', result); return res.custom(result); } ); diff --git a/dashboards-observability/server/routes/notebooks/noteRouter.ts b/dashboards-observability/server/routes/notebooks/noteRouter.ts index 27e7682bb..8872888ce 100644 --- a/dashboards-observability/server/routes/notebooks/noteRouter.ts +++ b/dashboards-observability/server/routes/notebooks/noteRouter.ts @@ -12,6 +12,7 @@ import { } from '../../../../../src/core/server'; import { NOTEBOOKS_API_PREFIX, wreckOptions } from '../../../common/constants/notebooks'; import BACKEND from '../../adaptors/notebooks'; +import { addRequestToMetric } from '../../common/metrics/metrics_helper'; export function registerNoteRoute(router: IRouter) { // Fetch all the notebooks available @@ -25,6 +26,7 @@ export function registerNoteRoute(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('notebooks', 'get', 'count'); const opensearchNotebooksClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -37,6 +39,7 @@ export function registerNoteRoute(router: IRouter) { }, }); } catch (error) { + addRequestToMetric('notebooks', 'get', error); console.log('Notebook:', error); return response.custom({ statusCode: error.statusCode || 500, @@ -61,6 +64,7 @@ export function registerNoteRoute(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('notebooks', 'get', 'count'); const opensearchNotebooksClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -74,6 +78,7 @@ export function registerNoteRoute(router: IRouter) { body: notebookinfo, }); } catch (error) { + addRequestToMetric('notebooks', 'get', error); return response.custom({ statusCode: error.statusCode || 500, body: error.message, @@ -97,6 +102,7 @@ export function registerNoteRoute(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('notebooks', 'create', 'count'); const opensearchNotebooksClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -110,6 +116,7 @@ export function registerNoteRoute(router: IRouter) { body: addResponse.message.objectId, }); } catch (error) { + addRequestToMetric('notebooks', 'create', error); return response.custom({ statusCode: error.statusCode || 500, body: error.message, @@ -134,6 +141,7 @@ export function registerNoteRoute(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('notebooks', 'update', 'count'); const opensearchNotebooksClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -147,6 +155,7 @@ export function registerNoteRoute(router: IRouter) { body: renameResponse, }); } catch (error) { + addRequestToMetric('notebooks', 'update', error); return response.custom({ statusCode: error.statusCode || 500, body: error.message, @@ -171,6 +180,7 @@ export function registerNoteRoute(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('notebooks', 'create', 'count'); const opensearchNotebooksClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -184,6 +194,7 @@ export function registerNoteRoute(router: IRouter) { body: cloneResponse, }); } catch (error) { + addRequestToMetric('notebooks', 'create', error); return response.custom({ statusCode: error.statusCode || 500, body: error.message, @@ -207,6 +218,7 @@ export function registerNoteRoute(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('notebooks', 'delete', 'count'); const opensearchNotebooksClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -220,6 +232,7 @@ export function registerNoteRoute(router: IRouter) { body: delResponse, }); } catch (error) { + addRequestToMetric('notebooks', 'delete', error); return response.custom({ statusCode: error.statusCode || 500, body: error.message, @@ -243,6 +256,7 @@ export function registerNoteRoute(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('notebooks', 'add_samples', 'count'); const opensearchNotebooksClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped( request ); @@ -256,6 +270,7 @@ export function registerNoteRoute(router: IRouter) { body: addSampleNotesResponse, }); } catch (error) { + addRequestToMetric('notebooks', 'add_samples', error); return response.custom({ statusCode: error.statusCode || 500, body: error.message, diff --git a/dashboards-observability/server/routes/notebooks/sqlRouter.ts b/dashboards-observability/server/routes/notebooks/sqlRouter.ts index ec3c270fc..db1b81869 100644 --- a/dashboards-observability/server/routes/notebooks/sqlRouter.ts +++ b/dashboards-observability/server/routes/notebooks/sqlRouter.ts @@ -9,6 +9,7 @@ import { IRouter, ResponseError, } from '../../../../../src/core/server'; +import { addRequestToMetric } from '../../common/metrics/metrics_helper'; import QueryService from '../../services/queryService'; export function registerSqlRoute(server: IRouter, service: QueryService) { @@ -24,6 +25,7 @@ export function registerSqlRoute(server: IRouter, service: QueryService) { request, response ): Promise> => { + addRequestToMetric('notebooks', 'run_sql_query', 'count'); const retVal = await service.describeSQLQuery(request); return response.ok({ body: retVal, @@ -43,6 +45,7 @@ export function registerSqlRoute(server: IRouter, service: QueryService) { request, response ): Promise> => { + addRequestToMetric('notebooks', 'run_ppl_query', 'count'); const retVal = await service.describePPLQuery(request); return response.ok({ body: retVal, diff --git a/dashboards-observability/server/routes/notebooks/vizRouter.ts b/dashboards-observability/server/routes/notebooks/vizRouter.ts index 8d70ff644..65447b778 100644 --- a/dashboards-observability/server/routes/notebooks/vizRouter.ts +++ b/dashboards-observability/server/routes/notebooks/vizRouter.ts @@ -10,6 +10,7 @@ import { ResponseError, } from '../../../../../src/core/server'; import { NOTEBOOKS_API_PREFIX, NOTEBOOKS_FETCH_SIZE } from '../../../common/constants/notebooks'; +import { addRequestToMetric } from '../../common/metrics/metrics_helper'; export function registerVizRoute(router: IRouter) { // Fetches available saved visualizations for current user @@ -23,6 +24,7 @@ export function registerVizRoute(router: IRouter) { request, response ): Promise> => { + addRequestToMetric('notebooks', 'visualization', 'count'); const params: RequestParams.Search = { index: '.kibana', size: NOTEBOOKS_FETCH_SIZE, @@ -42,6 +44,7 @@ export function registerVizRoute(router: IRouter) { body: { savedVisualizations: vizResponse }, }); } catch (error) { + addRequestToMetric('notebooks', 'visualization', error); return response.custom({ statusCode: error.statusCode || 500, body: error.message, From 13123140f0a84ed0904b929c3e78223cb6851a1f Mon Sep 17 00:00:00 2001 From: Joshua Li Date: Mon, 5 Dec 2022 18:30:36 +0000 Subject: [PATCH 2/2] Add some click metrics Signed-off-by: Joshua Li --- .../public/components/common/search/search.tsx | 1 + .../__tests__/__snapshots__/data_grid.test.tsx.snap | 4 ++++ .../__tests__/__snapshots__/doc_viewer_row.test.tsx.snap | 2 ++ .../event_analytics/explorer/events_views/docViewRow.tsx | 1 + .../public/components/event_analytics/home/home.tsx | 7 ++++++- 5 files changed, 14 insertions(+), 1 deletion(-) diff --git a/dashboards-observability/public/components/common/search/search.tsx b/dashboards-observability/public/components/common/search/search.tsx index f6d30725a..989912f33 100644 --- a/dashboards-observability/public/components/common/search/search.tsx +++ b/dashboards-observability/public/components/common/search/search.tsx @@ -163,6 +163,7 @@ export const Search = (props: any) => { className={`ppl-link ${ uiSettingsService.get('theme:darkMode') ? 'ppl-link-dark' : 'ppl-link-light' }`} + data-click-metric-element="common.search.ppl_reference" color="hollow" onClick={() => showFlyout()} onClickAriaLabel={'pplLinkShowFlyout'} diff --git a/dashboards-observability/public/components/event_analytics/explorer/__tests__/__snapshots__/data_grid.test.tsx.snap b/dashboards-observability/public/components/event_analytics/explorer/__tests__/__snapshots__/data_grid.test.tsx.snap index df40c845c..0f9d221db 100644 --- a/dashboards-observability/public/components/event_analytics/explorer/__tests__/__snapshots__/data_grid.test.tsx.snap +++ b/dashboards-observability/public/components/event_analytics/explorer/__tests__/__snapshots__/data_grid.test.tsx.snap @@ -414,11 +414,13 @@ exports[`Datagrid component Renders data grid component 1`] = ` >