Skip to content

Commit 056a697

Browse files
feat(site): add download logs option (coder#13466)
1 parent 48ecee1 commit 056a697

20 files changed

+801
-149
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -922,7 +922,7 @@ jobs:
922922
uses: actions/dependency-review-action@v4.3.2
923923
with:
924924
allow-licenses: Apache-2.0, BSD-2-Clause, BSD-3-Clause, CC0-1.0, ISC, MIT, MIT-0, MPL-2.0
925-
allow-dependencies-licenses: "pkg:golang/github.com/coder/wgtunnel@0.1.13-0.20240522110300-ade90dfb2da0"
925+
allow-dependencies-licenses: "pkg:golang/github.com/coder/wgtunnel@0.1.13-0.20240522110300-ade90dfb2da0, pkg:npm/pako@1.0.11"
926926
license-check: true
927927
vulnerability-check: false
928928
- name: "Report"

site/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"@mui/system": "5.14.0",
4646
"@mui/utils": "5.14.11",
4747
"@tanstack/react-query-devtools": "4.35.3",
48+
"@types/file-saver": "2.0.7",
4849
"ansi-to-html": "0.7.2",
4950
"axios": "1.6.0",
5051
"canvas": "2.11.0",
@@ -58,8 +59,10 @@
5859
"date-fns": "2.30.0",
5960
"dayjs": "1.11.4",
6061
"emoji-mart": "5.4.0",
62+
"file-saver": "2.0.5",
6163
"formik": "2.4.1",
6264
"front-matter": "4.0.2",
65+
"jszip": "3.10.1",
6366
"lodash": "4.17.21",
6467
"monaco-editor": "0.44.0",
6568
"pretty-bytes": "6.1.0",

site/pnpm-lock.yaml

Lines changed: 44 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

site/src/api/api.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,10 +1142,9 @@ class ApiMethods {
11421142

11431143
getWorkspaceBuildLogs = async (
11441144
buildId: string,
1145-
before: Date,
11461145
): Promise<TypesGen.ProvisionerJobLog[]> => {
11471146
const response = await this.axios.get<TypesGen.ProvisionerJobLog[]>(
1148-
`/api/v2/workspacebuilds/${buildId}/logs?before=${before.getTime()}`,
1147+
`/api/v2/workspacebuilds/${buildId}/logs`,
11491148
);
11501149

11511150
return response.data;

site/src/api/queries/util.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { UseQueryOptions, QueryKey } from "react-query";
22
import type { MetadataState, MetadataValue } from "hooks/useEmbeddedMetadata";
33

4-
const disabledFetchOptions = {
4+
export const disabledRefetchOptions = {
55
cacheTime: Infinity,
66
staleTime: Infinity,
77
refetchOnMount: false,
@@ -62,7 +62,7 @@ export function cachedQuery<
6262

6363
// Make sure the disabled options are always serialized last, so that no
6464
// one using this function can accidentally override the values
65-
...(metadata.available ? disabledFetchOptions : {}),
65+
...(metadata.available ? disabledRefetchOptions : {}),
6666
};
6767

6868
return newOptions as FormattedQueryOptionsResult<

site/src/api/queries/workspaces.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type {
1414
WorkspacesRequest,
1515
WorkspacesResponse,
1616
} from "api/typesGenerated";
17+
import { disabledRefetchOptions } from "./util";
1718
import { workspaceBuildsKey } from "./workspaceBuilds";
1819

1920
export const workspaceByOwnerAndNameKey = (owner: string, name: string) => [
@@ -283,3 +284,32 @@ export const toggleFavorite = (
283284
},
284285
};
285286
};
287+
288+
export const buildLogsKey = (workspaceId: string) => [
289+
"workspaces",
290+
workspaceId,
291+
"logs",
292+
];
293+
294+
export const buildLogs = (workspace: Workspace) => {
295+
return {
296+
queryKey: buildLogsKey(workspace.id),
297+
queryFn: () => API.getWorkspaceBuildLogs(workspace.latest_build.id),
298+
};
299+
};
300+
301+
export const agentLogsKey = (workspaceId: string, agentId: string) => [
302+
"workspaces",
303+
workspaceId,
304+
"agents",
305+
agentId,
306+
"logs",
307+
];
308+
309+
export const agentLogs = (workspaceId: string, agentId: string) => {
310+
return {
311+
queryKey: agentLogsKey(workspaceId, agentId),
312+
queryFn: () => API.getWorkspaceAgentLogs(agentId),
313+
...disabledRefetchOptions,
314+
};
315+
};

site/src/components/DropdownArrow/DropdownArrow.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ export const DropdownArrow: FC<ArrowProps> = ({
2626
};
2727

2828
const styles = {
29-
base: (theme) => ({
30-
color: theme.palette.primary.contrastText,
29+
base: {
30+
color: "currentcolor",
3131
width: 16,
3232
height: 16,
33-
}),
33+
},
3434

3535
withMargin: {
3636
marginLeft: 8,

site/src/modules/resources/AgentLogs/AgentLogs.tsx

Lines changed: 1 addition & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,7 @@
11
import type { Interpolation, Theme } from "@emotion/react";
22
import Tooltip from "@mui/material/Tooltip";
3-
import {
4-
type ComponentProps,
5-
forwardRef,
6-
useEffect,
7-
useMemo,
8-
useState,
9-
} from "react";
3+
import { type ComponentProps, forwardRef, useMemo } from "react";
104
import { FixedSizeList as List } from "react-window";
11-
import { watchWorkspaceAgentLogs } from "api/api";
125
import type { WorkspaceAgentLogSource } from "api/typesGenerated";
136
import {
147
AGENT_LOG_LINE_HEIGHT,
@@ -179,64 +172,6 @@ export const AgentLogs = forwardRef<List, AgentLogsProps>(
179172
},
180173
);
181174

182-
export const useAgentLogs = (
183-
agentId: string,
184-
options?: { enabled?: boolean; initialData?: LineWithID[] },
185-
) => {
186-
const initialData = options?.initialData;
187-
const enabled = options?.enabled === undefined ? true : options.enabled;
188-
const [logs, setLogs] = useState<LineWithID[] | undefined>(initialData);
189-
190-
useEffect(() => {
191-
if (!enabled) {
192-
setLogs([]);
193-
return;
194-
}
195-
196-
const socket = watchWorkspaceAgentLogs(agentId, {
197-
// Get all logs
198-
after: 0,
199-
onMessage: (logs) => {
200-
// Prevent new logs getting added when a connection is not open
201-
if (socket.readyState !== WebSocket.OPEN) {
202-
return;
203-
}
204-
205-
setLogs((previousLogs) => {
206-
const newLogs: LineWithID[] = logs.map((log) => ({
207-
id: log.id,
208-
level: log.level || "info",
209-
output: log.output,
210-
time: log.created_at,
211-
sourceId: log.source_id,
212-
}));
213-
214-
if (!previousLogs) {
215-
return newLogs;
216-
}
217-
218-
return [...previousLogs, ...newLogs];
219-
});
220-
},
221-
onError: (error) => {
222-
// For some reason Firefox and Safari throw an error when a websocket
223-
// connection is close in the middle of a message and because of that we
224-
// can't safely show to the users an error message since most of the
225-
// time they are just internal stuff. This does not happen to Chrome at
226-
// all and I tried to find better way to "soft close" a WS connection on
227-
// those browsers without success.
228-
console.error(error);
229-
},
230-
});
231-
232-
return () => {
233-
socket.close();
234-
};
235-
}, [agentId, enabled]);
236-
237-
return logs;
238-
};
239-
240175
// These colors were picked at random. Feel free
241176
// to add more, adjust, or change! Users will not
242177
// depend on these colors.

0 commit comments

Comments
 (0)