Skip to content

Commit

Permalink
Add more metrics to frontend (#1326)
Browse files Browse the repository at this point in the history
Signed-off-by: Joshua Li <[email protected]>
  • Loading branch information
joshuali925 authored Dec 8, 2022
1 parent 65b1b95 commit 43297ae
Show file tree
Hide file tree
Showing 15 changed files with 128 additions and 39 deletions.
1 change: 1 addition & 0 deletions public/components/common/search/search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,11 +414,13 @@ exports[`Datagrid component Renders data grid component 1`] = `
>
<EuiButtonIcon
className="euiButtonIcon euiButtonIcon--text"
data-click-metric-element="event_analytics.events_view.toggle_details"
iconType="arrowRight"
onClick={[Function]}
>
<button
className="euiButtonIcon euiButtonIcon--primary euiButtonIcon--empty euiButtonIcon--xSmall euiButtonIcon euiButtonIcon--text"
data-click-metric-element="event_analytics.events_view.toggle_details"
disabled={false}
onClick={[Function]}
type="button"
Expand Down Expand Up @@ -642,11 +644,13 @@ exports[`Datagrid component Renders data grid component 1`] = `
>
<EuiButtonIcon
className="euiButtonIcon euiButtonIcon--text"
data-click-metric-element="event_analytics.events_view.toggle_details"
iconType="arrowRight"
onClick={[Function]}
>
<button
className="euiButtonIcon euiButtonIcon--primary euiButtonIcon--empty euiButtonIcon--xSmall euiButtonIcon euiButtonIcon--text"
data-click-metric-element="event_analytics.events_view.toggle_details"
disabled={false}
onClick={[Function]}
type="button"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ exports[`Datagrid Doc viewer row component Renders Doc viewer row component 1`]
>
<EuiButtonIcon
className="euiButtonIcon euiButtonIcon--text"
data-click-metric-element="event_analytics.events_view.toggle_details"
iconType="arrowRight"
onClick={[Function]}
>
<button
className="euiButtonIcon euiButtonIcon--primary euiButtonIcon--empty euiButtonIcon--xSmall euiButtonIcon euiButtonIcon--text"
data-click-metric-element="event_analytics.events_view.toggle_details"
disabled={false}
onClick={[Function]}
type="button"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ export const DocViewRow = forwardRef((props: IDocViewRowProps, ref) => {
<td className="osdDocTableCell__toggleDetails" key={uniqueId('grid-td-')}>
<EuiButtonIcon
className="euiButtonIcon euiButtonIcon--text"
data-click-metric-element="event_analytics.events_view.toggle_details"
onClick={() => {
toggleDetailOpen();
}}
Expand Down
7 changes: 6 additions & 1 deletion public/components/event_analytics/home/home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,12 @@ export const Home = (props: IHomeProps) => {
Use Events Analytics to monitor, correlate, analyze and visualize machine
generated data through Piped Processing Language. Save frequently searched queries
and visualizations for quick access{' '}
<EuiLink external={true} href={EVENT_ANALYTICS_DOCUMENTATION_URL} target="blank">
<EuiLink
data-click-metric-element="event_analytics.learn_more"
external={true}
href={EVENT_ANALYTICS_DOCUMENTATION_URL}
target="blank"
>
Learn more
</EuiLink>
</EuiText>
Expand Down
45 changes: 21 additions & 24 deletions server/common/metrics/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,46 +3,43 @@
* 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;
})();

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;
Expand Down
22 changes: 12 additions & 10 deletions server/common/metrics/metrics_helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<T extends ComponentType>(
component: T,
request: RequestType<T>,
error: { statusCode: number }
): void;
export function addRequestToMetric(
component: ComponentType,
request: RequestType,
export function addRequestToMetric<T extends ComponentType>(
component: T,
request: RequestType<T>,
counter: CounterNameType
): void;
export function addRequestToMetric(
component: ComponentType,
request: RequestType,
export function addRequestToMetric<T extends ComponentType>(
component: T,
request: RequestType<T>,
counterNameOrError: CounterNameType | { statusCode: number }
) {
const counter =
Expand All @@ -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']!++;
}

Expand Down Expand Up @@ -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) => {
Expand Down
8 changes: 4 additions & 4 deletions server/common/metrics/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<T extends ComponentType> = typeof COMPONENTS[T][number];
export type CounterNameType = 'count' | 'system_error' | 'user_error' | 'total';

// counter to track user click actions
Expand All @@ -19,7 +19,7 @@ type ClickCounterType = {
// counter to track requests to OpenSearch
type RequestCounterType = {
[component in ComponentType]: {
[request in RequestType]: {
[request in RequestType<component>]: {
[counter in CounterNameType]?: number;
};
};
Expand Down
13 changes: 13 additions & 0 deletions server/routes/application_analytics/app_analytics_router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -29,6 +30,7 @@ export function registerAppAnalyticsRouter(router: IRouter) {
request,
response
): Promise<IOpenSearchDashboardsResponse<any | ResponseError>> => {
addRequestToMetric('application_analytics', 'get', 'count');
const opensearchClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped(
request
);
Expand All @@ -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,
Expand All @@ -65,6 +68,7 @@ export function registerAppAnalyticsRouter(router: IRouter) {
request,
response
): Promise<IOpenSearchDashboardsResponse<any | ResponseError>> => {
addRequestToMetric('application_analytics', 'get', 'count');
const opensearchClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped(
request
);
Expand All @@ -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,
Expand Down Expand Up @@ -106,6 +111,7 @@ export function registerAppAnalyticsRouter(router: IRouter) {
request,
response
): Promise<IOpenSearchDashboardsResponse<any | ResponseError>> => {
addRequestToMetric('application_analytics', 'create', 'count');
const opensearchClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped(
request
);
Expand All @@ -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,
Expand All @@ -144,6 +151,7 @@ export function registerAppAnalyticsRouter(router: IRouter) {
request,
response
): Promise<IOpenSearchDashboardsResponse<any | ResponseError>> => {
addRequestToMetric('application_analytics', 'update', 'count');
const opensearchClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped(
request
);
Expand All @@ -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,
Expand Down Expand Up @@ -192,6 +201,7 @@ export function registerAppAnalyticsRouter(router: IRouter) {
request,
response
): Promise<IOpenSearchDashboardsResponse<any | ResponseError>> => {
addRequestToMetric('application_analytics', 'update', 'count');
const opensearchClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped(
request
);
Expand All @@ -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,
Expand All @@ -233,6 +244,7 @@ export function registerAppAnalyticsRouter(router: IRouter) {
request,
response
): Promise<IOpenSearchDashboardsResponse<any | ResponseError>> => {
addRequestToMetric('application_analytics', 'delete', 'count');
const opensearchClient: ILegacyScopedClusterClient = context.observability_plugin.observabilityClient.asScoped(
request
);
Expand All @@ -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,
Expand Down
Loading

0 comments on commit 43297ae

Please sign in to comment.