Path: blob/master/src/packages/frontend/compute/compute-server-log.tsx
1503 views
/*1Show the log entries for a specific compute server.23More precisely this is a little button that you click on, and4it shows the log in a modal.5*/67import {8Modal,9Button,10Checkbox,11Flex,12Radio,13Spin,14Table,15Tooltip,16} from "antd";17import { useEffect, useState } from "react";18import LogEntry from "./log-entry";19import type { ComputeServerEvent } from "@cocalc/util/compute/log";20import { TimeAgo } from "@cocalc/frontend/components";21import { getLog } from "./api";22import { Icon } from "@cocalc/frontend/components";23import getTitle from "./get-title";24import { getPurchases } from "@cocalc/frontend/purchases/api";25import type { Purchase } from "@cocalc/util/db-schema/purchases";26import ShowError from "@cocalc/frontend/components/error";27import {28DetailedPurchaseTable,29GroupedPurchaseTable,30} from "@cocalc/frontend/purchases/purchases";31import { currency } from "@cocalc/util/misc";3233export default function ComputeServerLog({34id,35style,36}: {37id: number;38style?;39color?: string;40}) {41const [open, setOpen] = useState<boolean>(false);4243return (44<Tooltip title={"Show configuration and control log"}>45<Button46size={"small"}47type="text"48style={{ color: "#666", ...style }}49onClick={() => {50setOpen(true);51}}52>53<Icon name="history" /> Log54</Button>55{open && <LogModal id={id} close={() => setOpen(false)} />}56</Tooltip>57);58}5960const OPTIONS = [61//{ label: "Files", value: "files" },62{ label: "Activity", value: "activity" },63{ label: "Purchases", value: "purchases" },64];6566const LIMIT = 500;6768export function LogModal({ id, close }) {69const [log, setLog] = useState<70| null71| any[]72| { time: Date; project_id: string; event: ComputeServerEvent }[]73| Purchase[]74>(null);75const [title, setTitle] = useState<string>("");76const [type, setType] = useState<string>("activity");77const [error, setError] = useState<string>("");78const [total, setTotal] = useState<number | null>(null);79const [group, setGroup] = useState<boolean>(false);8081useEffect(() => {82(async () => {83setTitle((await getTitle(id)).title);84})();85}, [id]);8687useEffect(() => {88(async () => {89try {90if (type == "files" || type == "activity") {91setLog(await getLog({ id, type }));92} else if (type == "purchases") {93const { purchases } = await getPurchases({94compute_server_id: id,95limit: LIMIT,96group,97});98setLog(purchases);99let total = 0;100for (const { cost, cost_so_far } of purchases) {101total += cost ?? cost_so_far ?? 0;102}103setTotal(total);104}105} catch (err) {106setError(`${err}`);107}108})();109}, [type, id, group]);110111return (112<Modal113width={1100}114title={115<>116<Icon name="server" /> Compute Server Log - "{title}"117</>118}119open120onCancel={close}121onOk={close}122>123<Flex style={{ marginBottom: "15px" }}>124<Radio.Group125options={OPTIONS}126onChange={({ target: { value } }) => {127setLog(null);128setTotal(null);129setType(value);130}}131value={type}132optionType="button"133/>134<div style={{ flex: 1 }} />135{type == "purchases" && (136<Checkbox137style={{ alignItems: "center" }}138checked={group}139onChange={(e) => {140setGroup(e.target.checked);141setLog(null);142setTotal(null);143}}144>145Group by Service146</Checkbox>147)}148<div style={{ flex: 1 }} />149{total != null && log != null && (150<div>151<b>152Total{" "}153{log.length <= LIMIT ? "Spend on Server" : "of Displayed Spend"}:{" "}154{currency(total)}155</b>156</div>157)}158</Flex>159<ShowError160error={error}161setError={setError}162style={{ margin: "15px 0" }}163/>164{log == null && (165<div style={{ textAlign: "center", margin: "15px" }}>166<Spin />167</div>168)}169{log != null && type == "purchases" && !group && (170<DetailedPurchaseTable171purchases={log}172hideColumns={new Set(["project"])}173style={{ maxHeight: "70vh", overflow: "auto" }}174/>175)}176{log != null && type == "purchases" && group && (177<GroupedPurchaseTable178purchases={log}179hideColumns={new Set(["project"])}180style={{ maxHeight: "70vh", overflow: "auto" }}181/>182)}183{log != null && type == "activity" && (184<Table185dataSource={log}186rowKey={(record) => record.id}187pagination={false}188style={{ maxHeight: "70vh", overflow: "auto" }}189>190<Table.Column191title={"Log Entry"}192render={(record) => {193return (194<LogEntry195event={record.event}196hideTitle197project_id={record.project_id}198/>199);200}}201/>202<Table.Column203title="Time"204render={(record) => <TimeAgo date={record.time} />}205/>206</Table>207)}208</Modal>209);210}211212213