Skip to content

Commit

Permalink
create copy logs and download logs button
Browse files Browse the repository at this point in the history
  • Loading branch information
tedim52 committed Dec 1, 2023
1 parent 164b316 commit 0b4b334
Show file tree
Hide file tree
Showing 11 changed files with 668 additions and 29 deletions.
63 changes: 63 additions & 0 deletions enclave-manager/web/src/components/CopyLogsButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { useState } from "react";import streamsaver from "streamsaver";
import { useKurtosisClient } from "../../../client/enclaveManager/KurtosisClientContext";
import { EnclaveFullInfo } from "../../../emui/enclaves/types";
import { DownloadButton } from "../../CopyButton";
import {ServiceInfo} from "enclave-manager-sdk/build/api_container_service_pb";
import {isDefined, stripAnsi} from "../utils";

type DownloadLogsButtonProps = {
enclave:EnclaveFullInfo,
service?:ServiceInfo,
};

export const DownloadLogsButton = ({ enclave, service }: DownloadLogsButtonProps) => {
const kurtosisClient = useKurtosisClient();
const [isLoading, setIsLoading] = useState(false);
const [logLinesToDownload, setLogLinesToDownload] = useState(propsLogLines);

const handleDownloadClick = async () => {
setIsLoading(true);
const abortController = new AbortController();
const writableStream = streamsaver.createWriteStream(logsFileName || "logs.txt");
const writer = writableStream.getWriter();

if (service) {
console.log("pulling logs")
for await (const lineGroup of await kurtosisClient.getServiceLogs(abortController, enclave, [service], false, 0, true)) {
const lineGroupForService = lineGroup.serviceLogsByServiceUuid[service.serviceUuid];
if (!isDefined(lineGroupForService)) continue;
const parsedLogLines = serviceLogLineToLogLineMessage(lineGroupForService.line, lineGroupForService.timestamp);
console.log("writing logs")
setLogLinesToDownload((logLinesToDownload) => [...logLinesToDownload, ...parsedLogLines]);
}
} else {
setLogLinesToDownload(() => [...logLines])
}

try {
console.log("downloading logs")
await writer.write(logLinesToDownload.map(({message}) => message)
.filter(isDefined)
.map(stripAnsi)
.join("\n"));
} catch(err) {
console.error(err)
}
await writer.close();
console.log("finished downloading logs")
setLogLinesToDownload(() => [])
setIsLoading(false);
};

return (
<CopyButton
contentName={"logs"}
valueToCopy={getLogsValue}
size={"sm"}
isDisabled={logLines.length === 0}
isIconButton
aria-label={"Copy logs"}
color={"gray.100"}
/>
);
};
87 changes: 87 additions & 0 deletions enclave-manager/web/src/components/DownloadLogsButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { useState } from "react";import streamsaver from "streamsaver";
import { useKurtosisClient } from "../client/enclaveManager/KurtosisClientContext";
import { EnclaveFullInfo } from "../emui/enclaves/types";
import { DownloadButton } from "./DownloadButton";
import {ServiceInfo} from "enclave-manager-sdk/build/api_container_service_pb";
import {isDefined, stripAnsi} from "../utils";
import {Timestamp} from "@bufbuild/protobuf/dist/esm";
import {LogLineMessage} from "./enclaves/logs/types";
import {DateTime} from "luxon";

type DownloadLogsButtonProps = {
logsFileName:string,
enclave:EnclaveFullInfo,
service?: ServiceInfo,
logsToDownload: LogLineMessage[];
};

export const DownloadLogsButton = ({ logsFileName, enclave, service, logsToDownload }: DownloadLogsButtonProps) => {
const kurtosisClient = useKurtosisClient();
const [isLoading, setIsLoading] = useState(false);
const [logLinesToDownload, setLogLinesToDownload] = useState(logsToDownload);

const serviceLogLineToLogLineMessage = (lines: string[], timestamp?: Timestamp): LogLineMessage[] => {
return lines.map((line) => ({
message: line,
timestamp: isDefined(timestamp) ? DateTime.fromJSDate(timestamp?.toDate()) : undefined,
}));
};

const handleDownloadClick = async () => {
setIsLoading(true);
const writableStream = streamsaver.createWriteStream(logsFileName || "logs.txt");
const writer = writableStream.getWriter();

if (service){
console.log("pulling logs")
const abortController = new AbortController();
for await (const lineGroup of await kurtosisClient.getServiceLogs(abortController, enclave, [service], false, 0, true)) {
const lineGroupForService = lineGroup.serviceLogsByServiceUuid[service.serviceUuid];
if (!isDefined(lineGroupForService)) continue;
const parsedLogLines = serviceLogLineToLogLineMessage(lineGroupForService.line, lineGroupForService.timestamp);
console.log("writing logs")
setLogLinesToDownload((logLinesToDownload) => [...logLinesToDownload, ...parsedLogLines]);
}

try {
console.log("downloading logs")
await writer.write(logLinesToDownload.map(({message}) => message)
.filter(isDefined)
.map(stripAnsi)
.join("\n"));
} catch(err) {
console.error(err)
}
await writer.close();
}


if(logsToDownload) {

}

console.log("finished downloading logs")
setIsLoading(false);
};

const getLogsValue = () => {
return logsToDownload
.map(({ message }) => message)
.filter(isDefined)
.map(stripAnsi)
.join("\n");
};

return (
<DownloadButton
size={"sm"}
fileName={logsFileName || `logs.txt`}
isDisabled={logLinesToDownload.length === 0}
isIconButton
aria-label={"Download logs"}
color={"gray.100"}
isLoading={isLoading}
onClick={handleDownloadClick()}
/>
);
};
43 changes: 23 additions & 20 deletions enclave-manager/web/src/components/enclaves/logs/LogViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,18 @@ import { MdArrowBackIosNew, MdArrowForwardIos } from "react-icons/md";
import { Virtuoso, VirtuosoHandle } from "react-virtuoso";
import { isDefined, isNotEmpty, stringifyError, stripAnsi } from "../../../utils";
import { CopyButton } from "../../CopyButton";
import { DownloadButton } from "../../DownloadButton";
import { DownloadLogsButton } from "../../DownloadLogsButton";
import { FindCommand } from "../../KeyboardCommands";
import { LogLine } from "./LogLine";
import { LogLineMessage } from "./types";
import { normalizeLogText } from "./utils";
import {EnclaveFullInfo} from "../../../emui/enclaves/types";
import {ServiceInfo} from "enclave-manager-sdk/build/api_container_service_pb";

type LogViewerProps = {
logLines: LogLineMessage[];
enclave:EnclaveFullInfo,
service?:ServiceInfo,
progressPercent?: number | "indeterminate" | "failed";
ProgressWidget?: ReactElement;
logsFileName?: string;
Expand Down Expand Up @@ -65,6 +69,8 @@ type SearchState = SearchInitState | SearchErrorState | SearchSuccessState;
export const LogViewer = ({
progressPercent,
logLines: propsLogLines,
enclave,
service,
ProgressWidget,
logsFileName,
searchEnabled,
Expand Down Expand Up @@ -109,10 +115,10 @@ export const LogViewer = ({

const getLogsValue = () => {
return logLines
.map(({ message }) => message)
.filter(isDefined)
.map(stripAnsi)
.join("\n");
.map(({ message }) => message)
.filter(isDefined)
.map(stripAnsi)
.join("\n");
};

const isIndexSelected = (index: number) => {
Expand Down Expand Up @@ -179,22 +185,19 @@ export const LogViewer = ({
</FormControl>
<ButtonGroup>
<CopyButton
contentName={"logs"}
valueToCopy={getLogsValue}
size={"sm"}
isDisabled={logLines.length === 0}
isIconButton
aria-label={"Copy logs"}
color={"gray.100"}
contentName={"logs"}
valueToCopy={getLogsValue}
size={"sm"}
isDisabled={logLines.length === 0}
isIconButton
aria-label={"Copy logs"}
color={"gray.100"}
/>
<DownloadButton
valueToDownload={getLogsValue}
size={"sm"}
fileName={logsFileName || `logs.txt`}
isDisabled={logLines.length === 0}
isIconButton
aria-label={"Download logs"}
color={"gray.100"}
<DownloadLogsButton
logsFileName={logsFileName || "logs.txt"}
enclave={enclave}
service={service}
logsToDownload={logLines}
/>
</ButtonGroup>
</Flex>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ export const EnclaveLogs = () => {
<AppPageLayout>
<LogViewer
logLines={logLines}
enclave={enclave}
progressPercent={progressPercent}
ProgressWidget={
<Flex justifyContent={"space-between"} alignItems={"center"} width={"100%"}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,5 @@ export const ServiceLogs = ({ enclave, service }: ServiceLogsProps) => {
}, [enclave, service, kurtosisClient]);

const logsFileName = `${enclave.name}--${service.name}-logs.txt`;
return <LogViewer logLines={logLines} logsFileName={logsFileName} searchEnabled />;
return <LogViewer logLines={logLines} enclave={enclave} service={service} logsFileName={logsFileName} searchEnabled />;
};
6 changes: 3 additions & 3 deletions engine/server/webapp/asset-manifest.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"files": {
"main.js": "./static/js/main.d987c6a5.js",
"main.js": "./static/js/main.61105ad3.js",
"index.html": "./index.html",
"main.d987c6a5.js.map": "./static/js/main.d987c6a5.js.map"
"main.61105ad3.js.map": "./static/js/main.61105ad3.js.map"
},
"entrypoints": [
"static/js/main.d987c6a5.js"
"static/js/main.61105ad3.js"
]
}
2 changes: 1 addition & 1 deletion engine/server/webapp/index.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Kurtosis Enclave Manager"/><title>Kurtosis Enclave Manager</title><script defer="defer" src="./static/js/main.d987c6a5.js"></script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="./favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Kurtosis Enclave Manager"/><title>Kurtosis Enclave Manager</title><script defer="defer" src="./static/js/main.61105ad3.js"></script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Loading

0 comments on commit 0b4b334

Please sign in to comment.