Răsfoiți Sursa

implement log timeout (#3885)

Feroze Mohideen 2 ani în urmă
părinte
comite
8428e76793

+ 14 - 0
dashboard/package-lock.json

@@ -70,6 +70,7 @@
         "react-modal": "^3.11.2",
         "react-router-dom": "^5.2.0",
         "react-table": "^7.7.0",
+        "react-timer-hook": "^3.0.7",
         "react-transition-group": "^4.4.2",
         "regenerator-runtime": "^0.13.9",
         "semver": "^7.3.5",
@@ -11399,6 +11400,14 @@
         "react": "^16.8.3 || ^17.0.0-0 || ^18.0.0"
       }
     },
+    "node_modules/react-timer-hook": {
+      "version": "3.0.7",
+      "resolved": "https://registry.npmjs.org/react-timer-hook/-/react-timer-hook-3.0.7.tgz",
+      "integrity": "sha512-ATpNcU+PQRxxfNBPVqce2+REtjGAlwmfoNQfcEBMZFxPj0r3GYdKhyPHdStvqrejejEi0QvqaJZjy2lBlFvAsA==",
+      "peerDependencies": {
+        "react": ">=16.8.0"
+      }
+    },
     "node_modules/react-transition-group": {
       "version": "4.4.5",
       "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
@@ -24223,6 +24232,11 @@
       "resolved": "https://registry.npmjs.org/react-table/-/react-table-7.8.0.tgz",
       "integrity": "sha512-hNaz4ygkZO4bESeFfnfOft73iBUj8K5oKi1EcSHPAibEydfsX2MyU6Z8KCr3mv3C9Kqqh71U+DhZkFvibbnPbA=="
     },
+    "react-timer-hook": {
+      "version": "3.0.7",
+      "resolved": "https://registry.npmjs.org/react-timer-hook/-/react-timer-hook-3.0.7.tgz",
+      "integrity": "sha512-ATpNcU+PQRxxfNBPVqce2+REtjGAlwmfoNQfcEBMZFxPj0r3GYdKhyPHdStvqrejejEi0QvqaJZjy2lBlFvAsA=="
+    },
     "react-transition-group": {
       "version": "4.4.5",
       "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",

+ 1 - 0
dashboard/package.json

@@ -65,6 +65,7 @@
     "react-modal": "^3.11.2",
     "react-router-dom": "^5.2.0",
     "react-table": "^7.7.0",
+    "react-timer-hook": "^3.0.7",
     "react-transition-group": "^4.4.2",
     "regenerator-runtime": "^0.13.9",
     "semver": "^7.3.5",

+ 41 - 9
dashboard/src/main/home/app-dashboard/validate-apply/logs/Logs.tsx

@@ -4,9 +4,7 @@ import React, {
     useRef,
     useState,
 } from "react";
-
 import styled from "styled-components";
-
 import spinner from "assets/loading.gif";
 import api from "shared/api";
 import { useLogs } from "./utils";
@@ -27,6 +25,9 @@ import { useRevisionList } from "lib/hooks/useRevisionList";
 import { useLocation } from "react-router";
 import { useLatestRevision } from "../../app-view/LatestRevisionContext";
 import Filter from "components/porter/Filter";
+import { useTimer } from 'react-timer-hook';
+import { useIntercom } from "lib/hooks/useIntercom";
+import axios from "axios";
 
 type Props = {
     projectId: number;
@@ -44,6 +45,8 @@ type Props = {
     appId: number;
 };
 
+const DEFAULT_LOG_TIMEOUT_SECONDS = 60;
+
 const Logs: React.FC<Props> = ({
     projectId,
     clusterId,
@@ -65,7 +68,7 @@ const Logs: React.FC<Props> = ({
         revision_id: queryParams.get('revision_id'),
     }
 
-    const scrollToBottomRef = useRef<HTMLDivElement | undefined>(undefined);
+    const scrollToBottomRef = useRef<HTMLDivElement | null>(null);
     const [scrollToBottomEnabled, setScrollToBottomEnabled] = useState(true);
     const [enteredSearchText, setEnteredSearchText] = useState("");
     const [searchText, setSearchText] = useState("");
@@ -88,6 +91,8 @@ const Logs: React.FC<Props> = ({
     const { revisionIdToNumber } = useRevisionList({ appName, deploymentTargetId, projectId, clusterId });
     const { latestRevision: { revision_number: latestRevisionNumber } } = useLatestRevision();
 
+    const { showIntercomWithMessage } = useIntercom();
+
     const isAgentVersionUpdated = (agentImage: string | undefined) => {
         if (agentImage == null) {
             return false;
@@ -182,7 +187,7 @@ const Logs: React.FC<Props> = ({
         }, 5000);
     };
 
-    const { logs, refresh, moveCursor, paginationInfo } = useLogs({
+    const { logs, refresh, moveCursor, paginationInfo, stopLogStream } = useLogs({
         projectID: projectId,
         clusterID: clusterId,
         selectedFilterValues,
@@ -199,6 +204,20 @@ const Logs: React.FC<Props> = ({
         appID: appId,
     });
 
+    const { totalSeconds, isRunning, pause: pauseLogTimeout, restart: restartLogTimeout } = useTimer({
+        expiryTimestamp: dayjs().add(DEFAULT_LOG_TIMEOUT_SECONDS, 'seconds').toDate(),
+        onExpire: () => {
+            stopLogStream();
+            showIntercomWithMessage({ message: "I am having trouble receiving logs from my application." });
+        }
+    });
+
+    useEffect(() => {
+        if (logs.length) {
+            pauseLogTimeout();
+        }
+    },[logs.length]);
+
     useEffect(() => {
         setFilters([
             {
@@ -309,6 +328,7 @@ const Logs: React.FC<Props> = ({
                         <Spacer inline x={1} />
                         <ScrollButton
                             onClick={() => {
+                                restartLogTimeout(dayjs().add(DEFAULT_LOG_TIMEOUT_SECONDS, 'seconds').toDate());
                                 refresh({ isLive: selectedDate == null && timeRange?.endTime == null });
                             }}
                         >
@@ -320,7 +340,7 @@ const Logs: React.FC<Props> = ({
                 <Spacer y={0.5} />
                 <LogsSectionWrapper>
                     <StyledLogsSection>
-                        {isLoading && <Loading message="Waiting for logs..." />}
+                        {isLoading && <Loading message={"Initializing..."} />}
                         {!isLoading && logs.length !== 0 && (
                             <>
                                 <LoadMoreButton
@@ -355,8 +375,20 @@ const Logs: React.FC<Props> = ({
                                 </Highlight>
                             </Message>
                         )}
-                        {!isLoading && logs.length === 0 && selectedDate == null && (
-                            <Loading message="Waiting for logs..." />
+                        {!isLoading && logs.length === 0 && selectedDate == null && isRunning && (
+                            <Loading message={`Waiting ${totalSeconds} seconds for logs...`} />
+                        )}
+                        {!isLoading && logs.length === 0 && selectedDate == null && !isRunning && (
+                            <Message>
+                                Timed out waiting for logs.
+                                <Highlight onClick={() => {
+                                    restartLogTimeout(dayjs().add(DEFAULT_LOG_TIMEOUT_SECONDS, 'seconds').toDate());
+                                    refresh({ isLive: selectedDate == null && timeRange?.endTime == null });
+                                }}>
+                                    <i className="material-icons">autorenew</i>
+                                    Refresh
+                                </Highlight>
+                            </Message>
                         )}
                         <div ref={scrollToBottomRef} />
                     </StyledLogsSection>
@@ -400,7 +432,7 @@ const Logs: React.FC<Props> = ({
                 notify("Porter agent is outdated. Please upgrade to see logs.");
             }
         } catch (err) {
-            if (err.response?.status === 404) {
+            if (axios.isAxiosError(err) && err.response?.status === 404) {
                 setHasPorterAgent(false);
             }
         }
@@ -534,8 +566,8 @@ const Message = styled.div`
   justify-content: center;
   margin-left: 75px;
   text-align: center;
-  color: #ffffff44;
   font-size: 13px;
+  color: #aaaabb;
 `;
 
 const Highlight = styled.div`

+ 1 - 0
dashboard/src/main/home/app-dashboard/validate-apply/logs/utils.ts

@@ -501,5 +501,6 @@ export const useLogs = ({
     refresh,
     moveCursor,
     paginationInfo,
+    stopLogStream: closeAllWebsockets,
   };
 };