Skip to content

Commit

Permalink
#384: Add filters to overview tab (#407)
Browse files Browse the repository at this point in the history
Signed-off-by: Eugene Lee <eugenesk@amazon.com>
  • Loading branch information
eugenesk24 authored Jan 25, 2022
1 parent ab9be3c commit ef15591
Show file tree
Hide file tree
Showing 10 changed files with 108 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@
*/

import {
EuiPage,
EuiPageBody,
EuiPageHeader,
EuiPageHeaderSection,
EuiSpacer,
EuiTabbedContent,
EuiTabbedContentTab,
EuiText,
EuiTitle,
} from '@elastic/eui';
EuiPage,
EuiPageBody,
EuiPageHeader,
EuiPageHeaderSection,
EuiSpacer,
EuiTabbedContent,
EuiTabbedContentTab,
EuiText,
EuiTitle,
} from '@elastic/eui';
import { LogExplorer } from '../../explorer/log_explorer';
import { Dashboard } from '../../trace_analytics/components/dashboard';
import { Services } from '../../trace_analytics/components/services';
Expand All @@ -26,8 +26,7 @@ import SavedObjects from 'public/services/saved_objects/event_analytics/saved_ob
import TimestampUtils from 'public/services/timestamp/timestamp';
import React, { ReactChild, useEffect, useState } from 'react';
import { isEmpty, uniqueId } from 'lodash';
import {
ApplicationType,
import {
APP_ANALYTICS_API_PREFIX,
TAB_CONFIG_ID_TXT_PFX,
TAB_CONFIG_TITLE,
Expand All @@ -46,6 +45,7 @@ import { Toast } from '@elastic/eui/src/components/toast/global_toast_list';
import { RAW_QUERY } from '../../../../common/constants/explorer';
import { NotificationsStart } from '../../../../../../src/core/public';
import { AppAnalyticsComponentDeps } from '../home';
import { ApplicationType } from 'common/types/app_analytics';


const TAB_OVERVIEW_ID = uniqueId(TAB_OVERVIEW_ID_TXT_PFX);
Expand Down Expand Up @@ -73,7 +73,7 @@ interface AppDetailProps extends AppAnalyticsComponentDeps {
}

export function Application(props: AppDetailProps) {
const { pplService, dslService, timestampUtils, savedObjects, http, notifications, appId, chrome, parentBreadcrumb } = props;
const { pplService, dslService, timestampUtils, savedObjects, http, notifications, appId, chrome, parentBreadcrumb, setFilters } = props;
const [application, setApplication] = useState<ApplicationType>();
const [selectedTabId, setSelectedTab] = useState<string>(TAB_OVERVIEW_ID);
const handleContentTabClick = (selectedTab: IQueryTab) => setSelectedTab(selectedTab.id);
Expand All @@ -86,6 +86,25 @@ export function Application(props: AppDetailProps) {
.get(`${APP_ANALYTICS_API_PREFIX}/${appId}`)
.then((res) => {
setApplication(res.application);
const serviceFilters = res.application.servicesEntities.map((ser: string) => {
return {
field: 'serviceName',
operator: 'is',
value: ser,
inverted: false,
disabled: false
}
})
const traceFilters = res.application.traceGroups.map((tra: string) => {
return {
field: 'traceGroup',
operator: 'is',
value: tra,
inverted: false,
disabled: false
}
})
setFilters([...serviceFilters, ...traceFilters]);
})
.catch((err) => {
setToast('Error occurred while fetching application', 'danger');
Expand Down Expand Up @@ -253,6 +272,9 @@ export function Application(props: AppDetailProps) {
<EuiTitle size="l">
<h1>{application?.name || ''}</h1>
</EuiTitle>
<EuiText>
<p>{application?.description}</p>
</EuiText>
</EuiPageHeaderSection>
</EuiPageHeader>
<EuiTabbedContent
Expand All @@ -261,7 +283,7 @@ export function Application(props: AppDetailProps) {
selectedTab={ appAnalyticsTabs.find(tab => { tab.id === selectedTabId }) }
onTabClick={ (selectedTab: EuiTabbedContentTab) => handleContentTabClick(selectedTab) }
tabs={ appAnalyticsTabs }
/>
/>
</EuiPageBody>
</EuiPage>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ interface LogConfigProps extends AppAnalyticsComponentDeps {
}

export const LogConfig = (props: LogConfigProps) => {
const { dslService, query, setQuery, setIsFlyoutVisible } = props;
const { dslService, query, setQueryWithStorage, setIsFlyoutVisible } = props;
const [logOpen, setLogOpen] = useState(false);
const [isModalVisible, setIsModalVisible] = useState(false);
const [modalLayout, setModalLayout] = useState(<EuiOverlayMask></EuiOverlayMask>);
const tempQuery ='';

const handleQueryChange = async (query: string) => setQuery(query);
const handleQueryChange = async (query: string) => setQueryWithStorage(query);

const showFlyout = () => {
setIsFlyoutVisible(true);
Expand Down Expand Up @@ -105,4 +105,4 @@ export const LogConfig = (props: LogConfigProps) => {
{isModalVisible && modalLayout}
</div>
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ interface ServiceConfigProps extends AppAnalyticsComponentDeps {
}

export const ServiceConfig = (props: ServiceConfigProps) => {
const { dslService, filters, setFilters, http, selectedServices, setSelectedServices } = props;
const { dslService, filters, setFiltersWithStorage, http, selectedServices, setSelectedServices } = props;
const [servicesOpen, setServicesOpen] = useState(false);
const [serviceMap, setServiceMap] = useState<ServiceObject>({});
const [serviceMapIdSelected, setServiceMapIdSelected] = useState<'latency' | 'error_rate' | 'throughput'>('latency');
Expand Down Expand Up @@ -50,7 +50,7 @@ export const ServiceConfig = (props: ServiceConfigProps) => {
}
}
const newFilters = [...filters, filter];
setFilters(newFilters);
setFiltersWithStorage(newFilters);
};

const onServiceChange = (selectedServices: any) => {
Expand All @@ -64,12 +64,12 @@ export const ServiceConfig = (props: ServiceConfigProps) => {
}
})
const nonServiceFilters = filters.filter((f) => f.field !== 'serviceName');
setFilters([...nonServiceFilters, ...serviceFilters]);
setFiltersWithStorage([...nonServiceFilters, ...serviceFilters]);
};

const clearServices = () => {
const withoutServices = filters.filter((f) => f.field !== 'serviceName')
setFilters(withoutServices);
setFiltersWithStorage(withoutServices);
};

const services = Object.keys(serviceMap).map((service) => { return { label: service } });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ interface TraceConfigProps extends AppAnalyticsComponentDeps {
}

export const TraceConfig = (props: TraceConfigProps) => {
const { dslService, query, filters, setFilters, http, startTime, endTime, selectedTraces, setSelectedTraces } = props;
const { dslService, query, filters, setFiltersWithStorage, http, startTime, endTime, selectedTraces, setSelectedTraces } = props;
const [traceOpen, setTraceOpen] = useState(false);
const [loading, setLoading] = useState(false);
const [traceItems, setTraceItems] = useState([]);
Expand Down Expand Up @@ -76,12 +76,12 @@ export const TraceConfig = (props: TraceConfigProps) => {
addedFilter.value === filter.value
) {
const removed = filters.filter(fil => fil.field !== addedFilter.field);
setFilters(removed);
setFiltersWithStorage(removed);
return;
}
}
const newFilters = [...filters, filter];
setFilters(newFilters);
setFiltersWithStorage(newFilters);
};

const onTraceChange = (selectedTraces: any) => {
Expand All @@ -95,7 +95,7 @@ export const TraceConfig = (props: TraceConfigProps) => {
}
})
const nonTraceFilters = filters.filter((f) => f.field !== 'traceGroup');
setFilters([...nonTraceFilters, ...traceFilters]);
setFiltersWithStorage([...nonTraceFilters, ...traceFilters]);
};

const onCreateTrace = (searchValue: string, flattenedOptions: any) => {
Expand All @@ -122,14 +122,14 @@ export const TraceConfig = (props: TraceConfigProps) => {
setTraceOptions([...traceOptions, newTraceOption]);
}
// Select the option.
setFilters([...filters, newTraceFilter]);
setFiltersWithStorage([...filters, newTraceFilter]);
};

const addPercentileFilter = (condition = 'gte', additionalFilters = [] as FilterType[]) => {
if (traceItems.length === 0 || Object.keys(percentileMap).length === 0) return;
for (let i = 0; i < props.filters.length; i++) {
if (props.filters[i].custom) {
const newFilter = JSON.parse(JSON.stringify(props.filters[i]));
for (let i = 0; i < filters.length; i++) {
if (filters[i].custom) {
const newFilter = JSON.parse(JSON.stringify(filters[i]));
newFilter.custom.query.bool.should.forEach((should: any) =>
should.bool.must.forEach((must: any) => {
const range = must?.range?.['traceGroupFields.durationInNanos'];
Expand All @@ -146,15 +146,15 @@ export const TraceConfig = (props: TraceConfigProps) => {
newFilter.value = condition === 'gte' ? '>= 95th' : '< 95th';
const newFilters = [...filters, ...additionalFilters];
newFilters.splice(i, 1, newFilter);
setFilters(newFilters);
setFiltersWithStorage(newFilters);
return;
}
}
}

const clearTraces = () => {
const withoutTraces = filters.filter((f) => f.field !== 'traceGroup')
setFilters(withoutTraces);
setFiltersWithStorage(withoutTraces);
};

const onCancel = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import {
} from "@elastic/eui";
import DSLService from "public/services/requests/dsl";
import React, { useEffect, useState } from "react";
import { ChangeEvent } from "react";
import { AppAnalyticsComponentDeps } from "../home";
import { TraceConfig } from './config_components/trace_config';
import { ServiceConfig } from "./config_components/service_config";
Expand All @@ -38,14 +37,10 @@ interface CreateAppProps extends AppAnalyticsComponentDeps {
};

export const CreateApp = (props: CreateAppProps) => {
const { parentBreadcrumb, chrome, query, createApp } = props;
const { parentBreadcrumb, chrome, query, createApp, name, description, setNameWithStorage, setDescriptionWithStorage } = props;
const [isFlyoutVisible, setIsFlyoutVisible] = useState(false);
const [selectedServices, setSelectedServices] = useState<Array<optionType>>([]);
const [selectedTraces, setSelectedTraces] = useState<Array<optionType>>([]);
const [state, setState] = useState({
name: '',
description: ''
});

useEffect(() => {
chrome.setBreadcrumbs(
Expand All @@ -71,19 +66,12 @@ export const CreateApp = (props: CreateAppProps) => {
flyout = <PPLReferenceFlyout module="explorer" closeFlyout={closeFlyout} />;
}

const onChange = (e: ChangeEvent<HTMLInputElement>) => {
setState({
...state,
[e.target.name]: e.target.value
});
};

const isDisabled = !state.name || !query || !selectedTraces.length || !selectedServices.length;
const isDisabled = !name || !query || !selectedTraces.length || !selectedServices.length;

const missingField = () => {
if (isDisabled) {
let popoverContent = '';
if (!state.name) {
if (!name) {
popoverContent = 'Name is required.'
} else if (!query) {
popoverContent = 'Log Source is required.'
Expand All @@ -97,7 +85,7 @@ export const CreateApp = (props: CreateAppProps) => {
};

const onCreate = () => {
createApp(state.name, state.description, query, selectedServices, selectedTraces);
createApp(name, description, query, selectedServices, selectedTraces);
}

const onCancel = () => {
Expand Down Expand Up @@ -128,15 +116,15 @@ export const CreateApp = (props: CreateAppProps) => {
<EuiFormRow label="Name">
<EuiFieldText
name="name"
value={state.name}
onChange={(e) => onChange(e)}
value={name}
onChange={(e) => setNameWithStorage(e.target.value)}
/>
</EuiFormRow>
<EuiFormRow label="Description">
<EuiFieldText
name="description"
value={state.description}
onChange={(e) => onChange(e)}
value={description}
onChange={(e) => setDescriptionWithStorage(e.target.value)}
/>
</EuiFormRow>
</EuiForm>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ import {
EuiOverlayMask,
EuiConfirmModal,
} from '@elastic/eui';
import { CustomInputModal } from '../../../../public/components/custom_panels/helpers/custom_input_modal';

/* The file contains helper functions for modal layouts
* getDeleteModal - returns a confirm-modal with clear option
* getClearModal - returns a confirm-modal with clear option
*/

export const getClearModal = (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,16 @@ interface HomeProps extends RouteComponentProps, AppAnalyticsCoreDeps {
notifications: NotificationsStart;
}

export interface AppAnalyticsComponentDeps extends TraceAnalyticsComponentDeps {}
export interface AppAnalyticsComponentDeps extends TraceAnalyticsComponentDeps {
name: string;
description: string;
setNameWithStorage: (newName: string) => void;
setDescriptionWithStorage: (newDescription: string) => void;
setQueryWithStorage: (newQuery: string) => void;
setFiltersWithStorage: (newFilters: FilterType[]) => void;
setStartTimeWithStorage: (newStartTime: string) => void;
setEndTimeWithStorage: (newEndTime: string) => void;
}

export const Home = (props: HomeProps) => {
const { pplService, dslService, timestampUtils, savedObjects, parentBreadcrumb, http, chrome, notifications } = props;
Expand All @@ -43,6 +52,8 @@ export const Home = (props: HomeProps) => {
const [indicesExist, setIndicesExist] = useState(true);
const storedFilters = sessionStorage.getItem('AppAnalyticsFilters');
const [filters, setFilters] = useState<FilterType[]>(storedFilters ? JSON.parse(storedFilters) : []);
const [name, setName] = useState(sessionStorage.getItem('AppAnalyticsName') || '');
const [description, setDescription] = useState(sessionStorage.getItem('AppAnalyticsDescription') || '');
const [query, setQuery] = useState<string>(sessionStorage.getItem('AppAnalyticsQuery') || '');
const [startTime, setStartTime] = useState<string>(sessionStorage.getItem('AppAnalyticsStartTime') || 'now-24h');
const [endTime, setEndTime] = useState<string>(sessionStorage.getItem('AppAnalyticsEndTime') || 'now');
Expand All @@ -52,6 +63,14 @@ export const Home = (props: HomeProps) => {
setFilters(newFilters);
sessionStorage.setItem('AppAnalyticsFilters', JSON.stringify(newFilters));
};
const setNameWithStorage = (newName: string) => {
setName(newName);
sessionStorage.setItem('AppAnalyticsName', newName);
};
const setDescriptionWithStorage = (newDescription: string) => {
setDescription(newDescription);
sessionStorage.setItem('AppAnalyticsDescription', newDescription);
};
const setQueryWithStorage = (newQuery: string) => {
setQuery(newQuery);
sessionStorage.setItem('AppAnalyticsQuery', newQuery);
Expand All @@ -73,14 +92,22 @@ export const Home = (props: HomeProps) => {
parentBreadcrumb: parentBreadcrumb,
http: http,
chrome: chrome,
name,
setNameWithStorage,
description,
setDescriptionWithStorage,
query,
setQuery: setQueryWithStorage,
setQuery,
setQueryWithStorage,
filters,
setFilters: setFiltersWithStorage,
setFilters,
setFiltersWithStorage,
startTime,
setStartTime: setStartTimeWithStorage,
setStartTime,
setStartTimeWithStorage,
endTime,
setEndTime: setEndTimeWithStorage,
setEndTime,
setEndTimeWithStorage,
indicesExist,
};

Expand All @@ -105,7 +132,7 @@ export const Home = (props: HomeProps) => {
// Create a new application
const createApp = (name: string, description: string, query: string, selectedServices: Array<optionType>, selectedTraces: Array<optionType>) => {
const toast = isNameValid(name);
if (toast) {
if (toast.length > 0) {
setToast(toast.join(', '), 'danger');
return;
}
Expand All @@ -124,6 +151,8 @@ export const Home = (props: HomeProps) => {
})
.then((res) => {
setToast(`Application "${name}" successfully created!`);
setNameWithStorage('');
setDescriptionWithStorage('');
setFiltersWithStorage([]);
setQueryWithStorage('');
window.location.assign(`${parentBreadcrumb.href}application_analytics/${res.newAppId}`)
Expand Down
Loading

0 comments on commit ef15591

Please sign in to comment.