Skip to content

Commit

Permalink
feat: add app startup logs (#1992)
Browse files Browse the repository at this point in the history
  • Loading branch information
HUAHUAI23 committed Jun 3, 2024
1 parent 829c5eb commit 6e5da1a
Show file tree
Hide file tree
Showing 9 changed files with 332 additions and 27 deletions.
35 changes: 35 additions & 0 deletions server/src/application/pod.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ import http from 'http'
import { PodNameListDto, ContainerNameListDto } from './dto/pod.dto'
import { LABEL_KEY_APP_ID } from 'src/constants'

export type PodStatus = {
appid: string
podStatus: {
name: string
podStatus: string
initContainerId?: string
}[]
}
@Injectable()
export class PodService {
private readonly logger = new Logger(PodService.name)
Expand Down Expand Up @@ -53,4 +61,31 @@ export class PodService {

return containerNames
}

async getPodStatusListByAppid(appid: string): Promise<PodStatus> {
const region = await this.regionService.findByAppId(appid)
const namespaceOfApp = GetApplicationNamespace(region, appid)
const coreV1Api = this.cluster.makeCoreV1Api(region)
const res: { response: http.IncomingMessage; body: V1PodList } =
await coreV1Api.listNamespacedPod(
namespaceOfApp,
undefined,
undefined,
undefined,
undefined,
`${LABEL_KEY_APP_ID}=${appid}`,
)
const podStatus: PodStatus = {
appid: appid,
podStatus: [],
}
for (const item of res.body.items) {
podStatus.podStatus.push({
name: item.metadata.name,
podStatus: item.status.phase,
initContainerId: item.status.initContainerStatuses[0]?.containerID,
})
}
return podStatus
}
}
32 changes: 25 additions & 7 deletions server/src/log/log.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,36 @@ export class LogController {
containerName = appid
}

let podNameList: string[] = (
await this.podService.getPodNameListByAppid(appid)
).podNameList
const podStatus = await this.podService.getPodStatusListByAppid(appid)

if (!podNameList.includes(podName) && podName !== 'all') {
if (!podStatus.podStatus[0]) {
return new Observable<MessageEvent>((subscriber) => {
subscriber.error(new Error('podName not exist'))
subscriber.error(new Error('pod not exist'))
})
}

const podNameList = podStatus.podStatus.map((pod) => pod.name)

const initContainerId = podStatus.podStatus.map(
(pod) => pod.initContainerId,
)

if (containerName === 'init') {
for (const containerId of initContainerId) {
if (!containerId) {
return new Observable<MessageEvent>((subscriber) => {
subscriber.error(new Error('init container not exist'))
})
}
}
}

if (podName !== 'all') {
podNameList = undefined
if (!podNameList.includes(podName)) {
return new Observable<MessageEvent>((subscriber) => {
subscriber.error(new Error('podName not exist'))
})
}
}

const region = await this.regionService.findByAppId(appid)
Expand Down Expand Up @@ -223,7 +241,7 @@ export class LogController {
}
}

if (podNameList && podNameList.length > 0) {
if (podName === 'all' && podNameList.length > 0) {
podNameList.forEach((podName) => {
fetchLog(podName)
})
Expand Down
16 changes: 11 additions & 5 deletions web/src/layouts/Function.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import { Badge, Center, Spinner, useColorMode } from "@chakra-ui/react";
import { useQuery } from "@tanstack/react-query";
import clsx from "clsx";

import { APP_PHASE_STATUS, COLOR_MODE, Pages } from "@/constants/index";
import { APP_PHASE_STATUS, APP_STATUS, COLOR_MODE, Pages } from "@/constants/index";

import { ApplicationControllerFindOne } from "@/apis/v1/applications";
import InitLog from "@/pages/app/mods/StatusBar/LogsModal/initLog";
import useGlobalStore from "@/pages/globalStore";

export default function FunctionLayout() {
Expand Down Expand Up @@ -64,12 +65,17 @@ export default function FunctionLayout() {
</Center>
) : (
<>
{currentApp?.phase !== APP_PHASE_STATUS.Started &&
currentApp?.phase !== APP_PHASE_STATUS.Stopped &&
currentApp?.phase !== APP_PHASE_STATUS.Deleted ? (
{currentApp.phase === APP_PHASE_STATUS.Starting &&
currentApp.state !== APP_STATUS.Restarting ? (
<InitLog />
) : [
APP_PHASE_STATUS.Creating,
APP_PHASE_STATUS.Deleting,
APP_PHASE_STATUS.Stopping,
].includes(currentApp.phase) || currentApp.state === APP_STATUS.Restarting ? (
<div
className={clsx(
"absolute bottom-0 left-0 right-0 top-0 z-[999] flex flex-col items-center justify-center opacity-70 ",
"absolute bottom-0 left-0 right-0 top-0 z-[999] flex flex-col items-center justify-center opacity-70",
darkMode ? "bg-lafDark-100" : "bg-lafWhite-600",
)}
>
Expand Down
2 changes: 1 addition & 1 deletion web/src/pages/app/functions/mods/HeadPanel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ function HeadPanel() {
setCurrentFunction(item);
}}
>
<div className="max-w-20 flex truncate">
<div className="flex max-w-20 truncate">
<FunctionDetailPopOver
functionItem={item}
color={selected ? "#00A9A6" : ""}
Expand Down
14 changes: 14 additions & 0 deletions web/src/pages/app/mods/StatusBar/LogsModal/index.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* stylelint-disable selector-class-pattern */
#log-viewer-container {
.pf-v5-c-text-input-group__icon {
visibility: hidden;
Expand Down Expand Up @@ -29,3 +30,16 @@
background: #2b7873 !important;
}
}

.log-viewer-container-hide-scrollbar {
&,
& * {
&::-webkit-scrollbar {
width: 0 !important;
height: 0 !important;
}

-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
}
50 changes: 37 additions & 13 deletions web/src/pages/app/mods/StatusBar/LogsModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export default function LogsModal(props: { children: React.ReactElement }) {
const [podName, setPodName] = useState("");
const [containerName, setContainerName] = useState("");
const [isLoading, setIsLoading] = useState(true);
const [rowNumber, setRowNumber] = useState(0);
const [rowCount, setRowCount] = useState(0);
const [paused, setPaused] = useState(false);

const [logs, setLogs] = useState<Log[]>([]);
Expand All @@ -58,6 +58,23 @@ export default function LogsModal(props: { children: React.ReactElement }) {

const darkMode = useColorMode().colorMode === "dark";

const addOrUpdateLog = (newLog: Log) => {
setLogs((pre) => {
const existingLogIndex = pre.findIndex((existingLog) => existingLog.id === newLog.id);

if (existingLogIndex !== -1) {
const updatedLogs = [...pre];
updatedLogs[existingLogIndex] = {
...updatedLogs[existingLogIndex],
data: newLog.data,
};
return updatedLogs;
} else {
return [...pre, newLog];
}
});
};

const { data: podData } = useQuery(
["GetPodQuery"],
() => {
Expand Down Expand Up @@ -115,9 +132,7 @@ export default function LogsModal(props: { children: React.ReactElement }) {
}

if (msg.event === "log") {
const newLineCount = (msg.data.match(/\n/g) || []).length;
setLogs((pre) => [...pre, msg]);
setRowNumber((prevRowNumber) => prevRowNumber + newLineCount);
addOrUpdateLog(msg);
retryCountRef.current = 0;
}
},
Expand All @@ -126,8 +141,7 @@ export default function LogsModal(props: { children: React.ReactElement }) {
// if the server closes the connection unexpectedly, retry:
if (retryCountRef.current < MAX_RETRIES) {
retryCountRef.current += 1;
setRefresh((pre) => !pre);
setPaused(false);
throw new Error("connect closed unexpectedly, retrying...");
}
},

Expand All @@ -142,18 +156,23 @@ export default function LogsModal(props: { children: React.ReactElement }) {

useEffect(() => {
if (!isOpen) return;
setRowCount(0);
setLogs([]);
setIsLoading(true);
setPaused(false);
const ctrl = fetchLogs();

return () => {
ctrl?.abort();
};
}, [podName, containerName, isOpen, refresh, fetchLogs]);

useEffect(() => {
const sortedLogs = [...logs].sort((a, b) => parseInt(a.id) - parseInt(b.id));
const sortedLogs = logs.sort((a, b) => parseInt(a.id) - parseInt(b.id));
const concatenatedLogs = sortedLogs.map((log) => log.data).join("");
setRenderLogs(concatenatedLogs);
const totalRows = concatenatedLogs.split("\n").length;
setRowCount(totalRows);
}, [logs]);

useEffect(() => {
Expand Down Expand Up @@ -233,21 +252,26 @@ export default function LogsModal(props: { children: React.ReactElement }) {
) : (
<div
id="log-viewer-container"
className="text-sm flex h-full flex-col px-2 font-mono"
className={clsx("text-sm flex h-full flex-col px-2 font-mono", {
"log-viewer-container-hide-scrollbar": !paused,
})}
style={{ fontSize: settingStore.commonSettings.fontSize - 1 }}
onWheel={(e) => {
setPaused(true);
}}
>
<LogViewer
data={renderLogs}
hasLineNumbers={false}
scrollToRow={!paused ? rowNumber + 1 : undefined}
hasLineNumbers={true}
scrollToRow={paused ? undefined : rowCount + 300}
height={"98%"}
onScroll={(e) => {
if (e.scrollOffsetToBottom <= 0) {
setPaused(false);
return;
}
if (!e.scrollUpdateWasRequested) {
setPaused(true);
return;
}
setPaused(false);
}}
toolbar={
<div className="absolute right-24 top-4">
Expand Down
45 changes: 45 additions & 0 deletions web/src/pages/app/mods/StatusBar/LogsModal/initLog.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* stylelint-disable selector-class-pattern */
#log-viewer-cover-container {
.pf-v5-c-text-input-group__icon {
visibility: hidden;
}

.pf-v5-c-text-input-group__text-input:focus {
outline: none !important;
color: #000;
}

.pf-m-current {
background: #91ded9 !important;
}

.pf-m-match {
background: #daf4f2 !important;
}

[data-theme="dark"] & .pf-v5-c-text-input-group__text-input:focus {
outline: none !important;
color: #fff;
}

[data-theme="dark"] & .pf-m-current {
background: #47c8bf !important;
}

[data-theme="dark"] & .pf-m-match {
background: #2b7873 !important;
}
}

.log-viewer-cover-container-hide-scrollbar {
&,
& * {
&::-webkit-scrollbar {
width: 0 !important;
height: 0 !important;
}

-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
}
Loading

0 comments on commit 6e5da1a

Please sign in to comment.