/* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* eslint-disable react/display-name */ import React, { useState, useEffect } from "react"; import RefreshIcon from "@material-ui/icons/Refresh"; import { SelectType, TablePanel } from "components/TablePanel"; import { Link, useHistory } from "react-router-dom"; import Button from "components/Button"; import { Pagination } from "@material-ui/lab"; import LoadingText from "components/LoadingText"; import { AppLogIngestion, AppPipeline, LogSource, LogSourceType, PipelineStatus, } from "API"; import { appSyncRequestMutation, appSyncRequestQuery } from "assets/js/request"; import { getLogSource, listAppLogIngestions } from "graphql/queries"; import Modal from "components/Modal"; import { deleteAppLogIngestion } from "graphql/mutations"; import { formatLocalTime } from "assets/js/utils"; import { useTranslation } from "react-i18next"; import Status, { StatusType } from "components/Status/Status"; import ButtonDropdown from "components/ButtonDropdown"; import { AUTO_REFRESH_INT } from "assets/js/const"; import Alert from "components/Alert"; import { AlertType } from "components/Alert/alert"; import { getSourceInfoValueByKey } from "assets/js/applog"; const PAGE_SIZE = 20; const TIMP_SPAN = 2 * 60 * 1000; interface OverviewProps { pipelineInfo: AppPipeline | undefined; changeTab: (index: number) => void; } enum INGESTION_TYPE { INSTANCE = "instance", S3 = "s3", SYSLOG = "syslog", EKS = "esk", } interface AppIngestionItem { id: string; // AppLogIngestionId ingestion: AppLogIngestion; sourceData: LogSource | null; } const Ingestion: React.FC = (props: OverviewProps) => { const { pipelineInfo, changeTab } = props; const { t } = useTranslation(); const [loadingData, setLoadingData] = useState(false); const [ingestionList, setIngestionList] = useState([]); const [selectedIngestion, setSelectedIngestion] = useState( [] ); const [openDeleteModel, setOpenDeleteModel] = useState(false); const [loadingDelete, setLoadingDelete] = useState(false); const [disableDelete, setDisableDelete] = useState(true); const [curPage, setCurPage] = useState(1); const [totoalCount, setTotoalCount] = useState(0); const [userSelectType, setUserSelectType] = useState(""); const history = useHistory(); const [hasRecentASG, setHasRecentASG] = useState(false); const [recentASGIngestList, setRecentASGIngestList] = useState< AppLogIngestion[] >([]); const [showASGModal, setShowASGModal] = useState(false); const [instanceGroupLink, setInstanceGroupLink] = useState( "/resources/instance-group" ); const [groupButtonDisabled, setGroupButtonDisabled] = useState(true); const confirmRemoveLogIngestion = async () => { const idsParams = { ids: selectedIngestion.map((ingestion) => ingestion.id), }; try { setLoadingDelete(true); const deleteRes = await appSyncRequestMutation( deleteAppLogIngestion, idsParams ); console.info("deleteRes:", deleteRes); setLoadingDelete(false); setOpenDeleteModel(false); getIngestionByAppPipelineId(); setSelectedIngestion([]); } catch (error) { setLoadingDelete(false); setOpenDeleteModel(false); console.error(error); } }; const getIngestionByAppPipelineId = async (hideLoading = false) => { try { if (!hideLoading) { setLoadingData(true); setIngestionList([]); } const resData: any = await appSyncRequestQuery(listAppLogIngestions, { page: curPage, count: PAGE_SIZE, appPipelineId: pipelineInfo?.id, }); console.info("ingestion resData:", resData); const dataIngestion: AppLogIngestion[] = resData.data.listAppLogIngestions.appLogIngestions; console.info("dataIngestion:dataIngestion:", dataIngestion); const tmpRecentASGIngestionList: AppLogIngestion[] = []; const creatingASGIngestionList: AppLogIngestion[] = []; dataIngestion.forEach((element) => { const timeSpan = new Date().getTime() - new Date(element?.createdDt || "").getTime(); if ( element.sourceInfo?.sourceType === LogSourceType.ASG && timeSpan < TIMP_SPAN ) { tmpRecentASGIngestionList.push(element); if (element.status === PipelineStatus.CREATING) { creatingASGIngestionList.push(element); } } }); if (creatingASGIngestionList.length > 0) { setGroupButtonDisabled(true); } else { setGroupButtonDisabled(false); } if (tmpRecentASGIngestionList.length > 0) { setHasRecentASG(true); } else { setHasRecentASG(false); } setRecentASGIngestList(tmpRecentASGIngestionList); const tmpAppIngestions: AppIngestionItem[] = await Promise.all( dataIngestion.map(async (appLogIngestion: AppLogIngestion) => { if (appLogIngestion.sourceType === LogSourceType.Syslog) { const sourceData = await appSyncRequestQuery(getLogSource, { sourceType: appLogIngestion.sourceType, id: appLogIngestion.sourceId, }); return { id: appLogIngestion.id, ingestion: appLogIngestion, sourceData: sourceData.data.getLogSource, }; } else { return { id: appLogIngestion.id, ingestion: appLogIngestion, sourceData: null, }; } }) ); setIngestionList(tmpAppIngestions); setTotoalCount(resData.data?.listAppLogIngestions?.total || 0); setLoadingData(false); } catch (error) { setLoadingData(false); console.error(error); } }; const handlePageChange = (event: any, value: number) => { setCurPage(value); }; useEffect(() => { if (pipelineInfo && pipelineInfo.id) { getIngestionByAppPipelineId(); } }, [pipelineInfo, curPage]); useEffect(() => { console.info("selectedIngestion:", selectedIngestion); if (selectedIngestion && selectedIngestion.length > 0) { const statusArr = selectedIngestion.map((element) => { return element.status; }); if ( statusArr.includes(StatusType.Creating.toUpperCase()) || statusArr.includes(StatusType.Deleting.toUpperCase()) ) { setDisableDelete(true); } else { setDisableDelete(false); } } else { setDisableDelete(true); } }, [selectedIngestion]); // Redirect create ingestion page by ingestion type const redirectToCreateIngestionPage = (type?: string) => { const ingestionType = type || userSelectType; if (ingestionType === INGESTION_TYPE.INSTANCE) { history.push({ pathname: `/log-pipeline/application-log/detail/${pipelineInfo?.id}/create-ingestion-instance`, }); } if (ingestionType === INGESTION_TYPE.S3) { history.push({ pathname: `/log-pipeline/application-log/detail/${pipelineInfo?.id}/create-ingestion-s3`, }); } if (ingestionType === INGESTION_TYPE.EKS) { history.push({ pathname: `/log-pipeline/application-log/detail/${pipelineInfo?.id}/create-ingestion-eks`, }); } if (ingestionType === INGESTION_TYPE.SYSLOG) { history.push({ pathname: `/log-pipeline/application-log/detail/${pipelineInfo?.id}/create-ingestion-syslog`, }); } }; // go to instance group const goToInstanceGroup = () => { history.push({ pathname: instanceGroupLink, }); }; // Auto Refresh List useEffect(() => { const refreshInterval = setInterval(() => { getIngestionByAppPipelineId(true); }, AUTO_REFRESH_INT); return () => clearInterval(refreshInterval); }, [curPage]); useEffect(() => { console.info("hasRecentASG:", hasRecentASG); if (hasRecentASG) { // show modal setShowASGModal(true); } }, [hasRecentASG]); useEffect(() => { if (recentASGIngestList.length === 1) { setInstanceGroupLink( `/resources/instance-group/detail/${recentASGIngestList[0].sourceId}` ); } else { setInstanceGroupLink("/resources/instance-group"); } }, [recentASGIngestList]); return (
{t("applog:detail.tip1")} { changeTab(1); }} className="link" > {t("applog:detail.tip2")} {t("applog:detail.tip3")}
} /> { console.info("item:", item); setSelectedIngestion(item); }} loading={loadingData} selectType={SelectType.CHECKBOX} columnDefinitions={[ { id: "id", header: "ID", width: 320, cell: (e: AppIngestionItem) => { if (e.ingestion?.sourceType === LogSourceType.EKSCluster) { return ( {e.id} ); } if ( e.ingestion.sourceType === LogSourceType.EC2 || e.ingestion.sourceType === LogSourceType.S3 || e.ingestion.sourceType === LogSourceType.Syslog ) { return ( {e.id} ); } return e.id; }, }, { id: "type", header: t("applog:ingestion.type"), width: 120, cell: (e: AppIngestionItem) => { return e.ingestion.sourceType === LogSourceType.EC2 ? e.ingestion.sourceInfo?.sourceType === LogSourceType.ASG ? "EC2/ASG" : "EC2" : e.ingestion.sourceType; }, }, { id: "source", header: t("applog:ingestion.source"), cell: (e: AppIngestionItem) => { if (e.ingestion?.sourceType === LogSourceType.EKSCluster) { return ( {e.ingestion.sourceInfo?.sourceName} ); } if (e.ingestion?.sourceType === LogSourceType.Syslog) { return ( getSourceInfoValueByKey( "syslogProtocol", e.sourceData?.sourceInfo ) + ":" + getSourceInfoValueByKey( "syslogPort", e.sourceData?.sourceInfo ) ); } return ( {e.ingestion?.sourceInfo?.sourceName} ); }, }, { // width: 110, id: "logCOnfig", header: t("applog:detail.ingestion.logConfig"), cell: (e: AppIngestionItem) => { return ( {e.ingestion.confName} ); }, }, { width: 170, id: "created", header: t("applog:detail.ingestion.created"), cell: (e: AppIngestionItem) => { return formatLocalTime(e?.ingestion.createdDt || ""); }, }, { width: 120, id: "status", header: t("applog:list.status"), cell: (e: AppIngestionItem) => { return ( ); }, }, ]} items={ingestionList} actions={
{ setUserSelectType(item.id); redirectToCreateIngestionPage(item.id); }} > {t("button.createAnIngestion")}
} pagination={ } /> { setOpenDeleteModel(false); }} actions={
} >
{t("applog:detail.ingestion.deleteTips")} {JSON.parse(JSON.stringify(selectedIngestion)).map( (element: any, index: number) => { return (
{element.id}
); } )}
{ setShowASGModal(false); }} actions={
} >
{t("applog:detail.ingestion.groupTips")}
} />
); }; export default Ingestion;