From 3184e01307d7b3ac98073ef2957d210cd2bf4741 Mon Sep 17 00:00:00 2001 From: Neal Shah <30693865+ProgrammerIn-wonderland@users.noreply.github.com> Date: Fri, 17 Oct 2025 17:03:57 -0400 Subject: [PATCH] add puter.workers.getLoggingHandle (#1779) --- .../src/services/worker/WorkerService.js | 17 +++--- src/puter-js/src/modules/Workers.js | 52 ++++++++++++++++++- 2 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/backend/src/services/worker/WorkerService.js b/src/backend/src/services/worker/WorkerService.js index 89d6dbc80..2914187a7 100644 --- a/src/backend/src/services/worker/WorkerService.js +++ b/src/backend/src/services/worker/WorkerService.js @@ -326,6 +326,9 @@ class WorkerService extends BaseService { async endLogs({ workerName, authorization }) { return await this.exec_({ runtime, code }); }, + async getLoggingUrl({ }) { + return this.config.loggingUrl; + } } } async ['__on_driver.register.interfaces']() { @@ -381,19 +384,11 @@ class WorkerService extends BaseService { }, result: { type: 'json' }, }, - endLogs: { - description: 'Get logs for your backend worker', + getLoggingUrl: { + description: 'Get logging endpoint for your backend worker', parameters: { - workerName: { - type: "string", - description: "The name of the worker you want the logs of" - }, - authorization: { - type: "string", - description: "Puter token" - } }, - result: { type: 'json' }, + result: { type: 'string' }, }, destroy: { description: 'Get rid of your backend worker', diff --git a/src/puter-js/src/modules/Workers.js b/src/puter-js/src/modules/Workers.js index 573a8c15f..5ee23c30f 100644 --- a/src/puter-js/src/modules/Workers.js +++ b/src/puter-js/src/modules/Workers.js @@ -97,7 +97,7 @@ export class WorkersHandler { workerName = workerName.toLocaleLowerCase(); // just incase // const driverCall = await puter.drivers.call("workers", "worker-service", "destroy", { authorization: puter.authToken, workerName }); - const driverResult = await utils.make_driver_method(['authorization', 'workerName'], 'workers', "worker-service", 'destroy')(puter.authToken, workerName);; + const driverResult = await utils.make_driver_method(['authorization', 'workerName'], 'workers', "worker-service", 'destroy')(puter.authToken, workerName); if (!driverResult.result) { if (!driverResult.result) { @@ -116,5 +116,55 @@ export class WorkersHandler { return true; } } + + async getLoggingHandle (workerName) { + const loggingEndpoint = await utils.make_driver_method([], 'workers', "worker-service", 'getLoggingUrl')(puter.authToken, workerName); + const socket = new WebSocket(`${loggingEndpoint}/${puter.authToken}/${workerName}`); + const logStreamObject = new EventTarget(); + logStreamObject.onLog = (data) => { }; + + // Coercibility to ReadableStream + Object.defineProperty(logStreamObject, 'start', { + enumerable: false, + value: async (controller) => { + socket.addEventListener("message", (event) => { + controller.enqueue(JSON.parse(event.data)); + }); + socket.addEventListener("close", (event) => { + try { + controller.close(); + } catch (e) { } + }); + } + }); + Object.defineProperty(logStreamObject, 'cancel', { + enumerable: false, + value: async () => { + socket.close(); + } + }); + + + socket.addEventListener("message", (event) => { + const logEvent = new MessageEvent("log", { data: JSON.parse(event.data) }); + + logStreamObject.dispatchEvent(logEvent) + logStreamObject.onLog(logEvent); + }); + logStreamObject.close = socket.close; + return new Promise((res, rej) => { + let done = false; + socket.onopen = ()=>{ + done = true; + res(logStreamObject); + } + + socket.onerror = () => { + if (!done) { + rej("Failed to open logging connection"); + } + } + }) + } }