From 7c1bca8791448fa5259f158717f7964fb68a351e Mon Sep 17 00:00:00 2001 From: Lingeshwar S Date: Wed, 11 Sep 2024 07:52:23 +0530 Subject: [PATCH] [PLAT-14052][PLAT-15237] :Add advanced date-time option,Restrict CP for K8s Summary: **[PLAT-14052]** - Add advanced dateTime option for collecting prometheus metrics This is updated and rebased [[ https://phorge.dev.yugabyte.com/D35749 | diff ]] raised by rohitha . **[PLAT-15237]** - Restrict Connection Pooling option in UI for kubernetes. Test Plan: Tested manually Reviewers: kkannan Reviewed By: kkannan Subscribers: yugaware, ui Differential Revision: https://phorge.dev.yugabyte.com/D37953 --- .../UniverseDetail/UniverseDetail.js | 1 + .../SecondStep/SecondStep.js | 631 ++++++++++++++---- .../UniverseSupportBundle.js | 6 +- .../UniverseSupportBundle.scss | 36 +- .../advanced/AdvancedConfiguration.tsx | 2 +- 5 files changed, 535 insertions(+), 141 deletions(-) diff --git a/managed/ui/src/components/universes/UniverseDetail/UniverseDetail.js b/managed/ui/src/components/universes/UniverseDetail/UniverseDetail.js index 92429b76c3af..c162e21626f8 100644 --- a/managed/ui/src/components/universes/UniverseDetail/UniverseDetail.js +++ b/managed/ui/src/components/universes/UniverseDetail/UniverseDetail.js @@ -1227,6 +1227,7 @@ class UniverseDetail extends Component { )} {!universePaused && + !isItKubernetesUniverse && isConnectionPoolEnabled && isConfigureYSQLEnabled && isYSQLEnabledInUniverse && diff --git a/managed/ui/src/components/universes/UniverseSupportBundle/SecondStep/SecondStep.js b/managed/ui/src/components/universes/UniverseSupportBundle/SecondStep/SecondStep.js index c495b5d6aca3..dd9ac59def80 100644 --- a/managed/ui/src/components/universes/UniverseSupportBundle/SecondStep/SecondStep.js +++ b/managed/ui/src/components/universes/UniverseSupportBundle/SecondStep/SecondStep.js @@ -1,25 +1,42 @@ import { useRef, useState } from 'react'; -import { find } from 'lodash'; import { useQuery } from 'react-query'; import { useSelector } from 'react-redux'; import { useEffectOnce } from 'react-use'; -import { Box, Typography } from '@material-ui/core'; +import { Box, Collapse } from '@material-ui/core'; import { Alert, DropdownButton, MenuItem } from 'react-bootstrap'; import { YBLoading } from '../../../common/indicators'; -import { YBCheckBox } from '../../../common/forms/fields'; +import { YBButton, YBCheckBox } from '../../../common/forms/fields'; import { YBInput, YBLabel } from '../../../../redesign/components'; +import { DateTimePicker } from 'react-widgets'; import { CustomDateRangePicker } from '../DateRangePicker/DateRangePicker'; import { convertToISODateString } from '../../../../redesign/helpers/DateUtils'; import { fetchGlobalRunTimeConfigs } from '../../../../api/admin'; import { UniverseState } from '../../helpers/universeHelpers'; +import { DATE_FORMAT } from '../../../backupv2/common/BackupUtils'; +import YBInfoTip from '../../../common/descriptors/YBInfoTip'; +import moment from 'moment'; +import momentLocalizer from 'react-widgets-moment'; +momentLocalizer(moment); + +const CUSTOM = 'custom'; +const CUSTOM_WITH_VALUE = 'customWithValue'; const filterTypes = [ { label: 'Last 24 hrs', type: 'days', value: '1' }, { label: 'Last 3 days', type: 'days', value: '3' }, { label: 'Last 7 days', type: 'days', value: '7' }, { type: 'divider' }, - { label: 'Custom', type: 'custom', value: 'custom' } + { label: 'Custom', type: CUSTOM, value: CUSTOM } +]; + +const filterTypePromDump = [ + { label: 'Last 15 mins', type: 'minutes', value: '15' }, + { label: 'Last 1 hour', type: 'hours', value: '1' }, + { label: 'Last 3 hours', type: 'hours', value: '3' }, + { type: 'divider' }, + { label: 'Custom', type: CUSTOM, value: CUSTOM } ]; + export const selectionOptions = [ { label: 'All', value: 'All' }, { label: 'Application logs', value: 'ApplicationLogs' }, @@ -31,12 +48,22 @@ export const selectionOptions = [ { label: 'Instance files', value: 'Instance' }, { label: 'Consensus meta files', value: 'ConsensusMeta' }, { label: 'Tablet meta files', value: 'TabletMeta' }, - { label: 'Node agent logs', value: 'NodeAgent' } + { label: 'Node agent logs', value: 'NodeAgent' }, + { label: 'Core Files', value: 'CoreFiles' }, + { label: 'YB-Controller logs', value: 'YbcLogs' }, + { label: 'Kubernetes Info', value: 'K8sInfo' }, + { label: 'Prometheus metrics', value: 'PrometheusMetrics' } ]; -const coreFileOption = { label: 'Core Files', value: 'CoreFiles' }; -const YbcLogsOption = { label: 'YB-Controller logs', value: 'YbcLogs' }; -const K8sLogsOption = { label: 'Kubernetes Info', value: 'K8sInfo' }; +export const prometheusMetricsOptions = [ + { label: 'Master Export', value: 'MASTER_EXPORT' }, + { label: 'Node Export', value: 'NODE_EXPORT' }, + { label: 'Platform', value: 'PLATFORM' }, + { label: 'Prometheus', value: 'PROMETHEUS' }, + { label: 'TServer Export', value: 'TSERVER_EXPORT' }, + { label: 'YCQL Export', value: 'CQL_EXPORT' }, + { label: 'YSQL Export', value: 'YSQL_EXPORT' } +]; const ONE_GB_IN_BYTES = 1_07_37_41_824; @@ -45,8 +72,22 @@ const CoreFilesProps = { maxCoreFileSize: 25 * ONE_GB_IN_BYTES }; -const getBackDateByDay = (day) => { - return new Date(new Date().setDate(new Date().getDate() - day)); +const getBackDate = (amount, type) => { + return moment().subtract(amount, type).toDate(); +}; + +const getBackDateBeforeDate = (amount, type, date) => { + return moment(date).subtract(amount, type).toDate(); +}; + +const PrometheusMetricsProps = { + promDumpStartDate: getBackDate(15, 'minutes'), + promDumpEndDate: new Date(), + prometheusMetricsOptionsValue: prometheusMetricsOptions.map((_, index) => + index === 3 ? false : true + ), + isPromDumpDateTypeCustom: false, + promDumpDateType: filterTypePromDump[0] }; export const updateOptions = ( @@ -54,17 +95,18 @@ export const updateOptions = ( selectionOptionsValue, setIsDateTypeCustom, coreFileParams, + prometheusMetricsParams, startDate = new Date(), endDate = new Date() ) => { let payloadObj = {}; - if (dateType === 'custom') { + if (dateType.value === CUSTOM) { setIsDateTypeCustom(true); return; } - if (dateType !== 'customWithValue' && dateType !== 'custom') { - startDate = getBackDateByDay(+dateType); + if (dateType.value !== CUSTOM_WITH_VALUE && dateType.value !== CUSTOM) { + startDate = getBackDate(+dateType.value, dateType.type); setIsDateTypeCustom(false); } @@ -76,27 +118,89 @@ export const updateOptions = ( }); payloadObj = { startDate: convertToISODateString(startDate), + endDate: convertToISODateString(endDate), components: components }; - if (components.find((c) => c === coreFileOption.value)) { - payloadObj = { ...payloadObj, ...coreFileParams }; - } + components.forEach((component) => { + if (component === 'CoreFiles') { + payloadObj = { ...payloadObj, ...coreFileParams }; + } + + if (component === 'PrometheusMetrics') { + // if promDumpDateType: custom + if (prometheusMetricsParams.promDumpDateType.value === CUSTOM) { + prometheusMetricsParams.promDumpStartDate = startDate; + prometheusMetricsParams.promDumpEndDate = endDate; + } + + // if promDumpDateType: not-custom + if (!prometheusMetricsParams.isPromDumpDateTypeCustom) { + prometheusMetricsParams.promDumpStartDate = getBackDateBeforeDate( + +prometheusMetricsParams.promDumpDateType.value, + prometheusMetricsParams.promDumpDateType.type, + endDate + ); + prometheusMetricsParams.promDumpEndDate = endDate; + } + + // if promDumpDateType: customWithValue -or custom + payloadObj = { + ...payloadObj, + promDumpStartDate: convertToISODateString(prometheusMetricsParams.promDumpStartDate) + }; + payloadObj = { + ...payloadObj, + promDumpEndDate: convertToISODateString(prometheusMetricsParams.promDumpEndDate) + }; + + const prometheusMetricsTypes = []; + prometheusMetricsParams.prometheusMetricsOptionsValue.forEach((selectionOption, index) => { + if (selectionOption) { + prometheusMetricsTypes.push(prometheusMetricsOptions[index].value); + } + }); + payloadObj = { ...payloadObj, prometheusMetricsTypes: prometheusMetricsTypes }; + } + }); + console.warn('_______ payload obj'); + console.warn(payloadObj); return payloadObj; }; export const SecondStep = ({ onOptionsChange, isK8sUniverse, universeStatus }) => { - const [selectedFilterType, setSelectedFilterType] = useState(filterTypes[0].value); + const [selectedFilterType, setSelectedFilterType] = useState(filterTypes[0]); + const [selectedFilterTypePromDump, setSelectedFilterTypePromDump] = useState( + filterTypePromDump[0] + ); const [selectionOptionsValue, setSelectionOptionsValue] = useState( selectionOptions.map(() => true) ); + const [prometheusMetricsOptionsValue, setPrometheusMetricsOptionsValue] = useState( + // prometheus export is not required by default + prometheusMetricsOptions.map((_, index) => (index === 3 ? false : true)) + ); const [coreFileParams, setCoreFileParams] = useState(CoreFilesProps); + const [prometheusMetricsParams, setPrometheusMetricsParams] = useState(PrometheusMetricsProps); const [isDateTypeCustom, setIsDateTypeCustom] = useState(false); - const refs = useRef([]); + const [isPromDumpDateTypeCustom, setIsPromDumpDateTypeCustom] = useState(false); + const [startDate, setStartDate] = useState(getBackDate(1, 'days')); + const [endDate, setEndDate] = useState(new Date()); + const [promDumpStartDate, setPromDumpStartDate] = useState( + getBackDateBeforeDate(15, 'minutes', endDate) + ); + const [promDumpEndDate, setPromDumpEndDate] = useState(endDate); + const outerRefs = useRef([]); + const innerRefs = useRef([]); const featureFlags = useSelector((state) => state.featureFlags); const { data: globalRuntimeConfigs, isLoading } = useQuery(['globalRuntimeConfigs'], () => fetchGlobalRunTimeConfigs(true).then((res) => res.data) ); + const [isExpandedCoreFiles, setIsExpandedCoreFiles] = useState(false); + const [isExpandedPromMetrics, setIsExpandedPromMetrics] = useState(false); + + const getIndex = (key) => selectionOptions.findIndex((e) => e.value === key); + const isSelected = (key) => selectionOptionsValue[getIndex(key)]; useEffectOnce(() => { //This is to just check if selectiedOptions is intact with payload in universe Support bundle file @@ -104,7 +208,8 @@ export const SecondStep = ({ onOptionsChange, isK8sUniverse, universeStatus }) = selectedFilterType, selectionOptionsValue, setIsDateTypeCustom, - coreFileParams + coreFileParams, + prometheusMetricsParams ); onOptionsChange(changedOptions); }); @@ -120,48 +225,67 @@ export const SecondStep = ({ onOptionsChange, isK8sUniverse, universeStatus }) = (c) => c.key === 'yb.support_bundle.allow_cores_collection' )?.value === 'true'; - if (isCoreFileEnabled && !find(selectionOptions, coreFileOption)) { - selectionOptions.push(coreFileOption); - selectionOptionsValue.push(true); + const coreFilesIndex = getIndex('CoreFiles'); + if (!isCoreFileEnabled && coreFilesIndex > -1) { + selectionOptions.splice(coreFilesIndex, 1); + selectionOptionsValue.splice(coreFilesIndex, 1); const changedOptions = updateOptions( selectedFilterType, selectionOptionsValue, setIsDateTypeCustom, - coreFileParams + coreFileParams, + prometheusMetricsParams ); onOptionsChange(changedOptions); } - if ( - (featureFlags.test.enableYbc || featureFlags.released.enableYbc) && - !find(selectionOptions, YbcLogsOption) - ) { - selectionOptions.push(YbcLogsOption); - //check option by default - selectionOptionsValue.push(true); + const ybcLogsIndex = getIndex('YbcLogs'); + if (!featureFlags.test.enableYbc && !featureFlags.released.enableYbc && ybcLogsIndex > -1) { + selectionOptions.splice(ybcLogsIndex, 1); + selectionOptionsValue.splice(ybcLogsIndex, 1); const changedOptions = updateOptions( selectedFilterType, selectionOptionsValue, setIsDateTypeCustom, - coreFileParams + coreFileParams, + prometheusMetricsParams ); onOptionsChange(changedOptions); } - if (isK8sUniverse && !find(selectionOptions, K8sLogsOption)) { - selectionOptions.push(K8sLogsOption); - selectionOptionsValue.push(true); + const K8sInfoIndex = getIndex('K8sInfo'); + if (!isK8sUniverse && K8sInfoIndex > -1) { + selectionOptions.splice(K8sInfoIndex, 1); + selectionOptionsValue.splice(K8sInfoIndex, 1); const changedOptions = updateOptions( selectedFilterType, selectionOptionsValue, setIsDateTypeCustom, - coreFileParams + coreFileParams, + prometheusMetricsParams ); onOptionsChange(changedOptions); } - const isCoreFileSelected = - selectionOptionsValue[selectionOptions.findIndex((e) => e.value === coreFileOption.value)]; + const isCoreFileSelected = isSelected('CoreFiles'); + const isPrometheusMetricsSelected = isSelected('PrometheusMetrics'); + + const ExpandableButton = ({ isExpanded, onClick, text }) => ( + + {text} + +