Merge branch '21128-toolbar-context-menu'
[arvados-workbench2.git] / src / services / log-service / log-service.ts
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import { AxiosInstance } from "axios";
6 import { LogEventType, LogResource } from 'models/log';
7 import { CommonResourceService } from "services/common-service/common-resource-service";
8 import { ApiActions } from "services/api/api-actions";
9 import { WebDAV } from "common/webdav";
10 import { extractFilesData } from "services/collection-service/collection-service-files-response";
11 import { CollectionFile } from "models/collection-file";
12 import { ContainerRequestResource } from "models/container-request";
13
14 export type LogFragment = {
15     logType: LogEventType;
16     contents: string[];
17 }
18
19 export class LogService extends CommonResourceService<LogResource> {
20     constructor(serverApi: AxiosInstance, private apiWebdavClient: WebDAV, actions: ApiActions) {
21         super(serverApi, "logs", actions);
22     }
23
24     async listLogFiles(containerRequest: Pick<ContainerRequestResource, 'uuid' | 'containerUuid'>) {
25         const request = await this.apiWebdavClient.propfind(`container_requests/${containerRequest.uuid}/log/${containerRequest.containerUuid}`);
26         if (request?.responseXML != null) {
27             return extractFilesData(request.responseXML)
28                 .filter((file) => (
29                     file.path === `/arvados/v1/container_requests/${containerRequest.uuid}/log/${containerRequest.containerUuid}`
30                 ));
31         }
32         return Promise.reject();
33     }
34
35     /**
36      * Fetches the specified log file contents from the given container request's container live logs endpoint
37      * @param containerRequest Container request to fetch logs for
38      * @param fileRecord Log file to fetch
39      * @param startByte First byte index of the log file to fetch
40      * @param endByte Last byte index to include in the response
41      * @returns A promise that resolves to the LogEventType and a string array of the log file contents
42      */
43     async getLogFileContents(containerRequest: Pick<ContainerRequestResource, 'uuid' | 'containerUuid'>, fileRecord: Pick<CollectionFile, 'name'>, startByte: number, endByte: number): Promise<LogFragment> {
44         const request = await this.apiWebdavClient.get(
45             `container_requests/${containerRequest.uuid}/log/${containerRequest.containerUuid}/${fileRecord.name}`,
46             {headers: {Range: `bytes=${startByte}-${endByte}`}}
47         );
48         const logFileType = logFileToLogType(fileRecord);
49
50         if (request?.responseText && logFileType) {
51             return {
52                 logType: logFileType,
53                 contents: request.responseText.split(/\r?\n/),
54             };
55         } else {
56             return Promise.reject();
57         }
58     }
59 }
60
61 export const logFileToLogType = (file: Pick<CollectionFile, 'name'>) => (file.name.replace(/\.(txt|json)$/, '') as LogEventType);