From e94906b3bfab3c9ea0c88e2707278cf91bef0d7f Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Tue, 25 Nov 2025 08:25:54 +0000 Subject: [PATCH] feat: Update error handling to use getErrorMessage utility and improve logging across multiple services --- deno.json | 2 +- mod.ts | 5 +- ts/classes/apiclient.ts | 3 +- ts/classes/database.ts | 12 ++--- ts/classes/docker.ts | 49 ++++++++++++------- ts/classes/encryption.ts | 2 +- ts/classes/httpserver.ts | 31 ++++++------ ts/classes/platform-services/manager.ts | 7 +-- .../platform-services/providers/minio.ts | 9 ++-- .../platform-services/providers/mongodb.ts | 7 +-- ts/classes/registry.ts | 16 +++--- ts/classes/reverseproxy.ts | 21 ++++---- ts/classes/services.ts | 8 +-- 13 files changed, 97 insertions(+), 75 deletions(-) diff --git a/deno.json b/deno.json index 48c2d52..d0186d2 100644 --- a/deno.json +++ b/deno.json @@ -17,7 +17,7 @@ "@std/encoding": "jsr:@std/encoding@^1.0.10", "@db/sqlite": "jsr:@db/sqlite@0.12.0", "@push.rocks/smartdaemon": "npm:@push.rocks/smartdaemon@^2.1.0", - "@apiclient.xyz/docker": "npm:@apiclient.xyz/docker@^5.0.2", + "@apiclient.xyz/docker": "npm:@apiclient.xyz/docker@^5.1.0", "@apiclient.xyz/cloudflare": "npm:@apiclient.xyz/cloudflare@6.4.3", "@push.rocks/smartacme": "npm:@push.rocks/smartacme@^8.0.0", "@push.rocks/smartregistry": "npm:@push.rocks/smartregistry@^1.8.0", diff --git a/mod.ts b/mod.ts index 64a9692..3d7a159 100644 --- a/mod.ts +++ b/mod.ts @@ -7,13 +7,14 @@ */ import { runCli } from './ts/index.ts'; +import { getErrorMessage } from './ts/utils/error.ts'; if (import.meta.main) { try { await runCli(); } catch (error) { - console.error(`Error: ${error.message}`); - if (Deno.args.includes('--debug')) { + console.error(`Error: ${getErrorMessage(error)}`); + if (Deno.args.includes('--debug') && error instanceof Error) { console.error(error.stack); } Deno.exit(1); diff --git a/ts/classes/apiclient.ts b/ts/classes/apiclient.ts index 2c0e89c..0f04f01 100644 --- a/ts/classes/apiclient.ts +++ b/ts/classes/apiclient.ts @@ -11,6 +11,7 @@ import type { ISslCertificate, IServiceDeployOptions, } from '../types.ts'; +import { getErrorMessage } from '../utils/error.ts'; export class OneboxApiClient { private baseUrl: string; @@ -193,7 +194,7 @@ export class OneboxApiClient { return await response.json(); } catch (error) { - if (error.name === 'TimeoutError') { + if (error instanceof Error && error.name === 'TimeoutError') { throw new Error('Request timed out. Daemon might be unresponsive.'); } throw error; diff --git a/ts/classes/database.ts b/ts/classes/database.ts index e778c08..5c1d1c7 100644 --- a/ts/classes/database.ts +++ b/ts/classes/database.ts @@ -836,7 +836,7 @@ export class OneboxDatabase { if (!this.db) throw new Error('Database not initialized'); const fields: string[] = []; - const values: unknown[] = []; + const values: BindValue[] = []; if (updates.image !== undefined) { fields.push('image = ?'); @@ -1202,7 +1202,7 @@ export class OneboxDatabase { if (!this.db) throw new Error('Database not initialized'); const fields: string[] = []; - const values: unknown[] = []; + const values: BindValue[] = []; if (updates.certPath) { fields.push('cert_path = ?'); @@ -1303,7 +1303,7 @@ export class OneboxDatabase { if (!this.db) throw new Error('Database not initialized'); const fields: string[] = []; - const values: unknown[] = []; + const values: BindValue[] = []; if (updates.domain !== undefined) { fields.push('domain = ?'); @@ -1405,7 +1405,7 @@ export class OneboxDatabase { if (!this.db) throw new Error('Database not initialized'); const fields: string[] = []; - const values: unknown[] = []; + const values: BindValue[] = []; if (updates.certDomain !== undefined) { fields.push('cert_domain = ?'); @@ -1524,7 +1524,7 @@ export class OneboxDatabase { if (!this.db) throw new Error('Database not initialized'); const fields: string[] = []; - const values: unknown[] = []; + const values: BindValue[] = []; if (updates.subdomain !== undefined) { fields.push('subdomain = ?'); @@ -1711,7 +1711,7 @@ export class OneboxDatabase { if (!this.db) throw new Error('Database not initialized'); const fields: string[] = []; - const values: unknown[] = []; + const values: BindValue[] = []; if (updates.status !== undefined) { fields.push('status = ?'); diff --git a/ts/classes/docker.ts b/ts/classes/docker.ts index 1acbaa0..64d355a 100644 --- a/ts/classes/docker.ts +++ b/ts/classes/docker.ts @@ -10,7 +10,7 @@ import { logger } from '../logging.ts'; import { getErrorMessage } from '../utils/error.ts'; export class OneboxDockerManager { - private dockerClient: plugins.docker.Docker | null = null; + private dockerClient: InstanceType | null = null; private networkName = 'onebox-network'; /** @@ -695,14 +695,6 @@ export class OneboxDockerManager { timestamps: true, }); - // v5 should return a string, but let's handle edge cases - if (typeof logs !== 'string') { - logger.error(`Unexpected logs type: ${typeof logs}, constructor: ${logs?.constructor?.name}`); - logger.error(`Logs content: ${JSON.stringify(logs).slice(0, 500)}`); - // If it's not a string, something went wrong - throw new Error(`Unexpected log format: expected string, got ${typeof logs}`); - } - // v5 returns already-parsed logs as a string return { stdout: logs, @@ -809,20 +801,17 @@ export class OneboxDockerManager { throw new Error(`Container not found: ${containerID}`); } - const exec = await container.exec({ - Cmd: cmd, - AttachStdout: true, - AttachStderr: true, + const { stream, inspect } = await container.exec(cmd, { + attachStdout: true, + attachStderr: true, }); - const stream = await exec.start({ Detach: false }); - let stdout = ''; let stderr = ''; - stream.on('data', (chunk: Buffer) => { + stream.on('data', (chunk: Uint8Array) => { const streamType = chunk[0]; - const content = chunk.slice(8).toString(); + const content = new TextDecoder().decode(chunk.slice(8)); if (streamType === 1) { stdout += content; @@ -834,8 +823,8 @@ export class OneboxDockerManager { // Wait for completion await new Promise((resolve) => stream.on('end', resolve)); - const inspect = await exec.inspect(); - const exitCode = inspect.ExitCode || 0; + const execInfo = await inspect(); + const exitCode = execInfo.ExitCode || 0; return { stdout, stderr, exitCode }; } catch (error) { @@ -928,4 +917,26 @@ export class OneboxDockerManager { throw error; } } + + /** + * Get a container by ID + * Public wrapper for Docker client method + */ + async getContainerById(containerID: string): Promise { + if (!this.dockerClient) { + throw new Error('Docker client not initialized'); + } + return this.dockerClient.getContainerById(containerID); + } + + /** + * List all containers + * Public wrapper for Docker client method + */ + async listAllContainers(): Promise { + if (!this.dockerClient) { + throw new Error('Docker client not initialized'); + } + return this.dockerClient.listContainers(); + } } diff --git a/ts/classes/encryption.ts b/ts/classes/encryption.ts index 4fa47b5..3813616 100644 --- a/ts/classes/encryption.ts +++ b/ts/classes/encryption.ts @@ -24,7 +24,7 @@ export class CredentialEncryption { } this.key = await crypto.subtle.importKey( 'raw', - keyBytes, + keyBytes.buffer as ArrayBuffer, { name: this.algorithm }, false, ['encrypt', 'decrypt'] diff --git a/ts/classes/httpserver.ts b/ts/classes/httpserver.ts index f4b90cc..06a38b6 100644 --- a/ts/classes/httpserver.ts +++ b/ts/classes/httpserver.ts @@ -8,7 +8,7 @@ import * as plugins from '../plugins.ts'; import { logger } from '../logging.ts'; import { getErrorMessage } from '../utils/error.ts'; import type { Onebox } from './onebox.ts'; -import type { IApiResponse, ICreateRegistryTokenRequest, IRegistryTokenView } from '../types.ts'; +import type { IApiResponse, ICreateRegistryTokenRequest, IRegistryTokenView, TPlatformServiceType } from '../types.ts'; export class OneboxHttpServer { private oneboxRef: Onebox; @@ -482,8 +482,8 @@ export class OneboxHttpServer { private async handleGetLogsRequest(name: string): Promise { try { const logs = await this.oneboxRef.services.getServiceLogs(name); - logger.log(`handleGetLogsRequest: logs type = ${typeof logs}, constructor = ${logs?.constructor?.name}`); - logger.log(`handleGetLogsRequest: logs value = ${String(logs).slice(0, 100)}`); + logger.debug(`handleGetLogsRequest: logs type = ${typeof logs}, constructor = ${logs?.constructor?.name}`); + logger.debug(`handleGetLogsRequest: logs value = ${String(logs).slice(0, 100)}`); return this.jsonResponse({ success: true, data: logs }); } catch (error) { logger.error(`Failed to get logs for service ${name}: ${getErrorMessage(error)}`); @@ -878,13 +878,13 @@ export class OneboxHttpServer { // Get the container (handle both direct container IDs and service IDs) logger.info(`Looking up container for service ${serviceName}, containerID: ${service.containerID}`); - let container = await this.oneboxRef.docker.dockerClient!.getContainerById(service.containerID!); + let container = await this.oneboxRef.docker.getContainerById(service.containerID!); logger.info(`Direct lookup result: ${container ? 'found' : 'null'}`); // If not found, it might be a service ID - try to get the actual container ID if (!container) { logger.info('Listing all containers to find matching service...'); - const containers = await this.oneboxRef.docker.dockerClient!.listContainers(); + const containers = await this.oneboxRef.docker.listAllContainers(); logger.info(`Found ${containers.length} containers`); const serviceContainer = containers.find((c: any) => { @@ -894,7 +894,7 @@ export class OneboxHttpServer { if (serviceContainer) { logger.info(`Found matching container: ${serviceContainer.Id}`); - container = await this.oneboxRef.docker.dockerClient!.getContainerById(serviceContainer.Id); + container = await this.oneboxRef.docker.getContainerById(serviceContainer.Id); logger.info(`Second lookup result: ${container ? 'found' : 'null'}`); } else { logger.error(`No container found with service label matching ${service.containerID}`); @@ -924,18 +924,21 @@ export class OneboxHttpServer { // Demultiplex and pipe log data to WebSocket // Docker streams use 8-byte headers: [STREAM_TYPE, 0, 0, 0, SIZE_BYTE1, SIZE_BYTE2, SIZE_BYTE3, SIZE_BYTE4] - let buffer = Buffer.alloc(0); + let buffer = new Uint8Array(0); - logStream.on('data', (chunk: Buffer) => { + logStream.on('data', (chunk: Uint8Array) => { if (socket.readyState !== WebSocket.OPEN) return; // Append new data to buffer - buffer = Buffer.concat([buffer, chunk]); + const newBuffer = new Uint8Array(buffer.length + chunk.length); + newBuffer.set(buffer); + newBuffer.set(chunk, buffer.length); + buffer = newBuffer; // Process complete frames while (buffer.length >= 8) { // Read frame size from header (bytes 4-7, big-endian) - const frameSize = buffer.readUInt32BE(4); + const frameSize = (buffer[4] << 24) | (buffer[5] << 16) | (buffer[6] << 8) | buffer[7]; // Check if we have the complete frame if (buffer.length < 8 + frameSize) { @@ -946,7 +949,7 @@ export class OneboxHttpServer { const frameData = buffer.slice(8, 8 + frameSize); // Send the clean log line - socket.send(frameData.toString('utf8')); + socket.send(new TextDecoder().decode(frameData)); // Remove processed frame from buffer buffer = buffer.slice(8 + frameSize); @@ -1083,7 +1086,7 @@ export class OneboxHttpServer { } } - private async handleGetPlatformServiceRequest(type: string): Promise { + private async handleGetPlatformServiceRequest(type: TPlatformServiceType): Promise { try { const provider = this.oneboxRef.platformServices.getProvider(type); if (!provider) { @@ -1123,7 +1126,7 @@ export class OneboxHttpServer { } } - private async handleStartPlatformServiceRequest(type: string): Promise { + private async handleStartPlatformServiceRequest(type: TPlatformServiceType): Promise { try { const provider = this.oneboxRef.platformServices.getProvider(type); if (!provider) { @@ -1154,7 +1157,7 @@ export class OneboxHttpServer { } } - private async handleStopPlatformServiceRequest(type: string): Promise { + private async handleStopPlatformServiceRequest(type: TPlatformServiceType): Promise { try { const provider = this.oneboxRef.platformServices.getProvider(type); if (!provider) { diff --git a/ts/classes/platform-services/manager.ts b/ts/classes/platform-services/manager.ts index db86d7e..6a1c0e0 100644 --- a/ts/classes/platform-services/manager.ts +++ b/ts/classes/platform-services/manager.ts @@ -15,6 +15,7 @@ import type { IPlatformServiceProvider } from './providers/base.ts'; import { MongoDBProvider } from './providers/mongodb.ts'; import { MinioProvider } from './providers/minio.ts'; import { logger } from '../../logging.ts'; +import { getErrorMessage } from '../../utils/error.ts'; import { credentialEncryption } from '../encryption.ts'; import type { Onebox } from '../onebox.ts'; @@ -126,7 +127,7 @@ export class PlatformServicesManager { // Refresh platform service from database platformService = this.oneboxRef.database.getPlatformServiceByType(type)!; } catch (error) { - logger.error(`Failed to start ${provider.displayName}: ${error.message}`); + logger.error(`Failed to start ${provider.displayName}: ${getErrorMessage(error)}`); this.oneboxRef.database.updatePlatformService(platformService.id!, { status: 'failed' }); throw error; } @@ -187,7 +188,7 @@ export class PlatformServicesManager { }); logger.success(`${provider.displayName} platform service stopped`); } catch (error) { - logger.error(`Failed to stop ${provider.displayName}: ${error.message}`); + logger.error(`Failed to stop ${provider.displayName}: ${getErrorMessage(error)}`); this.oneboxRef.database.updatePlatformService(platformService.id!, { status: 'failed' }); throw error; } @@ -292,7 +293,7 @@ export class PlatformServicesManager { this.oneboxRef.database.deletePlatformResource(resource.id!); logger.success(`Cleaned up ${resource.resourceType} '${resource.resourceName}'`); } catch (error) { - logger.error(`Failed to cleanup resource ${resource.id}: ${error.message}`); + logger.error(`Failed to cleanup resource ${resource.id}: ${getErrorMessage(error)}`); // Continue with other resources even if one fails } } diff --git a/ts/classes/platform-services/providers/minio.ts b/ts/classes/platform-services/providers/minio.ts index 245e38b..8550c25 100644 --- a/ts/classes/platform-services/providers/minio.ts +++ b/ts/classes/platform-services/providers/minio.ts @@ -13,6 +13,7 @@ import type { TPlatformResourceType, } from '../../../types.ts'; import { logger } from '../../../logging.ts'; +import { getErrorMessage } from '../../../utils/error.ts'; import { credentialEncryption } from '../../encryption.ts'; import type { Onebox } from '../../onebox.ts'; @@ -73,7 +74,7 @@ export class MinioProvider extends BasePlatformServiceProvider { await Deno.mkdir('/var/lib/onebox/minio', { recursive: true }); } catch (e) { if (!(e instanceof Deno.errors.AlreadyExists)) { - logger.warn(`Could not create MinIO data directory: ${e.message}`); + logger.warn(`Could not create MinIO data directory: ${getErrorMessage(e)}`); } } @@ -127,7 +128,7 @@ export class MinioProvider extends BasePlatformServiceProvider { return response.ok; } catch (error) { - logger.debug(`MinIO health check failed: ${error.message}`); + logger.debug(`MinIO health check failed: ${getErrorMessage(error)}`); return false; } } @@ -205,7 +206,7 @@ export class MinioProvider extends BasePlatformServiceProvider { })); logger.info(`Set bucket policy for '${bucketName}'`); } catch (e) { - logger.warn(`Could not set bucket policy: ${e.message}`); + logger.warn(`Could not set bucket policy: ${getErrorMessage(e)}`); } // Note: For proper per-service credentials, MinIO Admin API should be used @@ -292,7 +293,7 @@ export class MinioProvider extends BasePlatformServiceProvider { logger.success(`MinIO bucket '${resource.resourceName}' deleted`); } catch (e) { - logger.error(`Failed to delete MinIO bucket: ${e.message}`); + logger.error(`Failed to delete MinIO bucket: ${getErrorMessage(e)}`); throw e; } } diff --git a/ts/classes/platform-services/providers/mongodb.ts b/ts/classes/platform-services/providers/mongodb.ts index 6ea642b..55a2d7c 100644 --- a/ts/classes/platform-services/providers/mongodb.ts +++ b/ts/classes/platform-services/providers/mongodb.ts @@ -13,6 +13,7 @@ import type { TPlatformResourceType, } from '../../../types.ts'; import { logger } from '../../../logging.ts'; +import { getErrorMessage } from '../../../utils/error.ts'; import { credentialEncryption } from '../../encryption.ts'; import type { Onebox } from '../../onebox.ts'; @@ -69,7 +70,7 @@ export class MongoDBProvider extends BasePlatformServiceProvider { } catch (e) { // Directory might already exist if (!(e instanceof Deno.errors.AlreadyExists)) { - logger.warn(`Could not create MongoDB data directory: ${e.message}`); + logger.warn(`Could not create MongoDB data directory: ${getErrorMessage(e)}`); } } @@ -135,7 +136,7 @@ export class MongoDBProvider extends BasePlatformServiceProvider { return true; } catch (error) { - logger.debug(`MongoDB health check failed: ${error.message}`); + logger.debug(`MongoDB health check failed: ${getErrorMessage(error)}`); return false; } } @@ -233,7 +234,7 @@ export class MongoDBProvider extends BasePlatformServiceProvider { await db.command({ dropUser: credentials.username }); logger.info(`Dropped MongoDB user '${credentials.username}'`); } catch (e) { - logger.warn(`Could not drop MongoDB user: ${e.message}`); + logger.warn(`Could not drop MongoDB user: ${getErrorMessage(e)}`); } // Drop the database diff --git a/ts/classes/registry.ts b/ts/classes/registry.ts index 42560aa..b18ece1 100644 --- a/ts/classes/registry.ts +++ b/ts/classes/registry.ts @@ -8,6 +8,7 @@ import * as plugins from '../plugins.ts'; import { logger } from '../logging.ts'; +import { getErrorMessage } from '../utils/error.ts'; export class RegistryManager { private s3Server: any = null; @@ -86,7 +87,7 @@ export class RegistryManager { this.isInitialized = true; logger.success('Onebox Registry initialized successfully'); } catch (error) { - logger.error(`Failed to initialize registry: ${error.message}`); + logger.error(`Failed to initialize registry: ${getErrorMessage(error)}`); throw error; } } @@ -102,7 +103,7 @@ export class RegistryManager { try { return await this.registry.handleRequest(req); } catch (error) { - logger.error(`Registry request error: ${error.message}`); + logger.error(`Registry request error: ${getErrorMessage(error)}`); return new Response('Internal registry error', { status: 500 }); } } @@ -119,7 +120,7 @@ export class RegistryManager { const tags = await this.registry.getTags(repository); return tags || []; } catch (error) { - logger.warn(`Failed to get tags for ${repository}: ${error.message}`); + logger.warn(`Failed to get tags for ${repository}: ${getErrorMessage(error)}`); return []; } } @@ -146,8 +147,9 @@ export class RegistryManager { return null; } catch (error) { // Only log if it's not a "not a function" error - if (!error.message.includes('not a function')) { - logger.warn(`Failed to get digest for ${repository}:${tag}: ${error.message}`); + const errMsg = getErrorMessage(error); + if (!errMsg.includes('not a function')) { + logger.warn(`Failed to get digest for ${repository}:${tag}: ${errMsg}`); } return null; } @@ -165,7 +167,7 @@ export class RegistryManager { await this.registry.deleteManifest(repository, tag); logger.info(`Deleted image ${repository}:${tag}`); } catch (error) { - logger.error(`Failed to delete image ${repository}:${tag}: ${error.message}`); + logger.error(`Failed to delete image ${repository}:${tag}: ${getErrorMessage(error)}`); throw error; } } @@ -212,7 +214,7 @@ export class RegistryManager { await this.s3Server.stop(); logger.info('smarts3 server stopped'); } catch (error) { - logger.error(`Error stopping smarts3: ${error.message}`); + logger.error(`Error stopping smarts3: ${getErrorMessage(error)}`); } } diff --git a/ts/classes/reverseproxy.ts b/ts/classes/reverseproxy.ts index 6199c16..01387e3 100644 --- a/ts/classes/reverseproxy.ts +++ b/ts/classes/reverseproxy.ts @@ -5,6 +5,7 @@ */ import { logger } from '../logging.ts'; +import { getErrorMessage } from '../utils/error.ts'; import { OneboxDatabase } from './database.ts'; interface IProxyRoute { @@ -43,7 +44,7 @@ export class OneboxReverseProxy { try { logger.info('Reverse proxy initialized'); } catch (error) { - logger.error(`Failed to initialize reverse proxy: ${error.message}`); + logger.error(`Failed to initialize reverse proxy: ${getErrorMessage(error)}`); throw error; } } @@ -77,7 +78,7 @@ export class OneboxReverseProxy { logger.success(`HTTP reverse proxy started on port ${this.httpPort}`); } catch (error) { - logger.error(`Failed to start HTTP reverse proxy: ${error.message}`); + logger.error(`Failed to start HTTP reverse proxy: ${getErrorMessage(error)}`); throw error; } } @@ -122,7 +123,7 @@ export class OneboxReverseProxy { logger.success(`HTTPS reverse proxy started on port ${this.httpsPort}`); } catch (error) { - logger.error(`Failed to start HTTPS reverse proxy: ${error.message}`); + logger.error(`Failed to start HTTPS reverse proxy: ${getErrorMessage(error)}`); // Don't throw - HTTPS is optional logger.warn('Continuing without HTTPS support'); } @@ -197,7 +198,7 @@ export class OneboxReverseProxy { headers: this.filterResponseHeaders(response.headers), }); } catch (error) { - logger.error(`Proxy error for ${host}: ${error.message}`); + logger.error(`Proxy error for ${host}: ${getErrorMessage(error)}`); return new Response('Bad Gateway', { status: 502, headers: { 'Content-Type': 'text/plain' }, @@ -264,7 +265,7 @@ export class OneboxReverseProxy { return response; } catch (error) { - logger.error(`WebSocket upgrade error: ${error.message}`); + logger.error(`WebSocket upgrade error: ${getErrorMessage(error)}`); return new Response('WebSocket Upgrade Failed', { status: 500, headers: { 'Content-Type': 'text/plain' }, @@ -353,7 +354,7 @@ export class OneboxReverseProxy { this.routes.set(domain, route); logger.success(`Added proxy route: ${domain} -> ${targetHost}:${targetPort}`); } catch (error) { - logger.error(`Failed to add route for ${domain}: ${error.message}`); + logger.error(`Failed to add route for ${domain}: ${getErrorMessage(error)}`); throw error; } } @@ -395,7 +396,7 @@ export class OneboxReverseProxy { logger.success(`Loaded ${this.routes.size} proxy routes`); } catch (error) { - logger.error(`Failed to reload routes: ${error.message}`); + logger.error(`Failed to reload routes: ${getErrorMessage(error)}`); throw error; } } @@ -423,7 +424,7 @@ export class OneboxReverseProxy { logger.warn('HTTPS server restart required for new certificate to take effect'); } } catch (error) { - logger.error(`Failed to add certificate for ${domain}: ${error.message}`); + logger.error(`Failed to add certificate for ${domain}: ${getErrorMessage(error)}`); throw error; } } @@ -455,7 +456,7 @@ export class OneboxReverseProxy { try { await this.addCertificate(cert.domain, cert.fullChainPath, cert.keyPath); } catch (error) { - logger.warn(`Failed to load certificate for ${cert.domain}: ${error.message}`); + logger.warn(`Failed to load certificate for ${cert.domain}: ${getErrorMessage(error)}`); } } } @@ -470,7 +471,7 @@ export class OneboxReverseProxy { await this.startHttps(); } } catch (error) { - logger.error(`Failed to reload certificates: ${error.message}`); + logger.error(`Failed to reload certificates: ${getErrorMessage(error)}`); throw error; } } diff --git a/ts/classes/services.ts b/ts/classes/services.ts index 0bb28a8..35db95f 100644 --- a/ts/classes/services.ts +++ b/ts/classes/services.ts @@ -382,9 +382,9 @@ export class OneboxServicesManager { const logs = await this.docker.getContainerLogs(service.containerID, tail); // Debug: check what we got - logger.log(`getServiceLogs: logs type = ${typeof logs}, constructor = ${logs?.constructor?.name}`); - logger.log(`getServiceLogs: logs.stdout type = ${typeof logs.stdout}`); - logger.log(`getServiceLogs: logs.stdout value = ${String(logs.stdout).slice(0, 100)}`); + logger.debug(`getServiceLogs: logs type = ${typeof logs}, constructor = ${logs?.constructor?.name}`); + logger.debug(`getServiceLogs: logs.stdout type = ${typeof logs.stdout}`); + logger.debug(`getServiceLogs: logs.stdout value = ${String(logs.stdout).slice(0, 100)}`); // v5 API returns combined stdout/stderr with proper formatting return logs.stdout; @@ -746,7 +746,7 @@ export class OneboxServicesManager { }); } } catch (error) { - logger.error(`Failed to check updates for ${service.name}: ${error.message}`); + logger.error(`Failed to check updates for ${service.name}: ${getErrorMessage(error)}`); } } }