Merge branch 'main' into 15768-multi-select-operations Arvados-DCO-1.1-Signed-off...
[arvados-workbench2.git] / src / services / log-service / log-service.ts
index 9772e0b61ca0a9a08e5c2fc7494704cddd141012..f36044f425227f1b55d539b1903970e7b60b9230 100644 (file)
@@ -3,12 +3,59 @@
 // SPDX-License-Identifier: AGPL-3.0
 
 import { AxiosInstance } from "axios";
-import { LogResource } from 'models/log';
+import { LogEventType, LogResource } from 'models/log';
 import { CommonResourceService } from "services/common-service/common-resource-service";
 import { ApiActions } from "services/api/api-actions";
+import { WebDAV } from "common/webdav";
+import { extractFilesData } from "services/collection-service/collection-service-files-response";
+import { CollectionFile } from "models/collection-file";
+import { ContainerRequestResource } from "models/container-request";
+
+export type LogFragment = {
+    logType: LogEventType;
+    contents: string[];
+}
 
 export class LogService extends CommonResourceService<LogResource> {
-    constructor(serverApi: AxiosInstance, actions: ApiActions) {
+    constructor(serverApi: AxiosInstance, private apiWebdavClient: WebDAV, actions: ApiActions) {
         super(serverApi, "logs", actions);
     }
+
+    async listLogFiles(containerRequest: Pick<ContainerRequestResource, 'uuid' | 'containerUuid'>) {
+        const request = await this.apiWebdavClient.propfind(`container_requests/${containerRequest.uuid}/log/${containerRequest.containerUuid}`);
+        if (request?.responseXML != null) {
+            return extractFilesData(request.responseXML)
+                .filter((file) => (
+                    file.path === `/arvados/v1/container_requests/${containerRequest.uuid}/log/${containerRequest.containerUuid}`
+                ));
+        }
+        return Promise.reject();
+    }
+
+    /**
+     * Fetches the specified log file contents from the given container request's container live logs endpoint
+     * @param containerRequest Container request to fetch logs for
+     * @param fileRecord Log file to fetch
+     * @param startByte First byte index of the log file to fetch
+     * @param endByte Last byte index to include in the response
+     * @returns A promise that resolves to the LogEventType and a string array of the log file contents
+     */
+    async getLogFileContents(containerRequest: Pick<ContainerRequestResource, 'uuid' | 'containerUuid'>, fileRecord: Pick<CollectionFile, 'name'>, startByte: number, endByte: number): Promise<LogFragment> {
+        const request = await this.apiWebdavClient.get(
+            `container_requests/${containerRequest.uuid}/log/${containerRequest.containerUuid}/${fileRecord.name}`,
+            {headers: {Range: `bytes=${startByte}-${endByte}`}}
+        );
+        const logFileType = logFileToLogType(fileRecord);
+
+        if (request?.responseText && logFileType) {
+            return {
+                logType: logFileType,
+                contents: request.responseText.split(/\r?\n/),
+            };
+        } else {
+            return Promise.reject();
+        }
+    }
 }
+
+export const logFileToLogType = (file: Pick<CollectionFile, 'name'>) => (file.name.replace(/\.(txt|json)$/, '') as LogEventType);