Explorar o código

Merge pull request #1193 from porter-dev/log-overflow-fix

[POR-31] Fix large number of logs crashing frontend
abelanger5 %!s(int64=4) %!d(string=hai) anos
pai
achega
6eee3f1b74

+ 34 - 12
dashboard/src/main/home/cluster-dashboard/expanded-chart/status/Logs.tsx

@@ -4,6 +4,8 @@ import { Context } from "shared/Context";
 import * as Anser from "anser";
 import api from "shared/api";
 
+const MAX_LOGS = 1000;
+
 type PropsType = {
   selectedPod: any;
   podError: string;
@@ -11,15 +13,19 @@ type PropsType = {
 };
 
 type StateType = {
-  logs: Anser.AnserJsonEntry[][];
+  logs: [number, Anser.AnserJsonEntry[]][];
+  numLogs: number;
   ws: any;
   scroll: boolean;
   currentTab: string;
 };
 
 export default class Logs extends Component<PropsType, StateType> {
+  private numLogs: React.RefObject<number>;
+
   state = {
-    logs: [] as Anser.AnserJsonEntry[][],
+    logs: [] as [number, Anser.AnserJsonEntry[]][],
+    numLogs: 0,
     ws: null as any,
     scroll: true,
     currentTab: "Application",
@@ -76,15 +82,16 @@ export default class Logs extends Component<PropsType, StateType> {
     }
 
     return this.state.logs.map((log, i) => {
+      const key = log[0];
       return (
-        <Log key={i}>
-          {this.state.logs[i].map((ansi, j) => {
+        <Log key={key}>
+          {this.state.logs[i][1].map((ansi, j) => {
             if (ansi.clearLine) {
               return null;
             }
 
             return (
-              <LogSpan key={i + "." + j} ansi={ansi}>
+              <LogSpan key={key + "." + j} ansi={ansi}>
                 {ansi.content.replace(/ /g, "\u00a0")}
               </LogSpan>
             );
@@ -109,13 +116,28 @@ export default class Logs extends Component<PropsType, StateType> {
       let ansiLog = Anser.ansiToJson(evt.data);
 
       let logs = this.state.logs;
-      logs.push(ansiLog);
+      logs.push([this.state.numLogs, ansiLog]);
+
+      // this is technically not as efficient as things could be
+      // if there are performance issues, a deque can be used in place of a list
+      // for storing logs
+      if (logs.length > MAX_LOGS) {
+        logs.shift();
+      }
 
-      this.setState({ logs: logs }, () => {
-        if (this.state.scroll) {
-          this.scrollToBottom(false);
+      this.setState(
+        (prev) => {
+          return {
+            logs: prev.logs,
+            numLogs: prev.numLogs + 1,
+          };
+        },
+        () => {
+          if (this.state.scroll) {
+            this.scrollToBottom(false);
+          }
         }
-      });
+      );
     };
 
     this.ws.onerror = (err: ErrorEvent) => {};
@@ -167,7 +189,7 @@ export default class Logs extends Component<PropsType, StateType> {
         }
       )
       .then((res) => {
-        let logs = [] as Anser.AnserJsonEntry[][];
+        let logs = [] as [number, Anser.AnserJsonEntry[]][];
         // TODO: column view
         // logs.push(Anser.ansiToJson("\u001b[33;5;196mEvent Type\u001b[0m \t || \t \u001b[43m\u001b[34m\tReason\t\u001b[0m \t ||\tMessage"))
 
@@ -176,7 +198,7 @@ export default class Logs extends Component<PropsType, StateType> {
           let ansiLog = Anser.ansiToJson(
             `${ansiEvtType}${evt.type}\u001b[0m \t \u001b[43m\u001b[34m\t${evt.reason} \u001b[0m \t ${evt.message}`
           );
-          logs.push(ansiLog);
+          logs.push([logs.length, ansiLog]);
         });
         this.setState({ logs: logs });
         console.log(res);