diff --git a/server/s3/src/index.ts b/server/s3/src/index.ts index 0c022505e2..975995f79d 100644 --- a/server/s3/src/index.ts +++ b/server/s3/src/index.ts @@ -69,8 +69,9 @@ export class S3Service implements StorageAdapter { expireTime: number client: S3 constructor (readonly opt: S3Config) { + const endpoint = Number.isInteger(opt.port) ? `${opt.endpoint}:${opt.port}` : opt.endpoint this.client = new S3({ - endpoint: opt.endpoint, + endpoint, credentials: { accessKeyId: opt.accessKey, secretAccessKey: opt.secretKey diff --git a/services/datalake/pod-datalake/src/handlers/blob.ts b/services/datalake/pod-datalake/src/handlers/blob.ts index 398bbc1423..ba58354d4d 100644 --- a/services/datalake/pod-datalake/src/handlers/blob.ts +++ b/services/datalake/pod-datalake/src/handlers/blob.ts @@ -13,6 +13,7 @@ // limitations under the License. // +import { Analytics } from '@hcengineering/analytics' import { MeasureContext } from '@hcengineering/core' import { type Request, type Response } from 'express' import { UploadedFile } from 'express-fileupload' @@ -86,6 +87,7 @@ export async function handleBlobGet ( if (err != null) { const error = err instanceof Error ? err.message : String(err) ctx.error('error writing response', { workspace, name, error }) + Analytics.handleError(err) if (!res.headersSent) { res.status(500).send('Internal Server Error') } @@ -137,6 +139,7 @@ export async function handleBlobDelete ( res.status(204).send() } catch (error: any) { + Analytics.handleError(error) ctx.error('failed to delete blob', { error }) res.status(500).send() } @@ -157,6 +160,7 @@ export async function handleBlobDeleteList ( res.status(204).send() } catch (error: any) { + Analytics.handleError(error) ctx.error('failed to delete blobs', { error }) res.status(500).send() } @@ -175,6 +179,7 @@ export async function handleBlobSetParent ( await datalake.setParent(ctx, workspace, name, parent) res.status(204).send() } catch (error: any) { + Analytics.handleError(error) ctx.error('failed to delete blob', { error }) res.status(500).send() } @@ -211,6 +216,7 @@ export async function handleUploadFormData ( sha256 = file.tempFilePath !== undefined ? await getFileSha256(file.tempFilePath) : await getBufferSha256(file.data) } catch (err: any) { + Analytics.handleError(err) const error = err instanceof Error ? err.message : String(err) ctx.error('failed to calculate file hash', { error }) throw err @@ -229,6 +235,7 @@ export async function handleUploadFormData ( return { key, metadata } } catch (err: any) { + Analytics.handleError(err) const error = err instanceof Error ? err.message : String(err) ctx.error('failed to upload blob', { error: err }) return { key, error } diff --git a/services/datalake/pod-datalake/src/handlers/image.ts b/services/datalake/pod-datalake/src/handlers/image.ts index e3f2bd3cf5..caa33f4149 100644 --- a/services/datalake/pod-datalake/src/handlers/image.ts +++ b/services/datalake/pod-datalake/src/handlers/image.ts @@ -13,6 +13,7 @@ // limitations under the License. // +import { Analytics } from '@hcengineering/analytics' import { MeasureContext } from '@hcengineering/core' import { type Request, type Response } from 'express' import { createReadStream, createWriteStream } from 'fs' @@ -110,6 +111,7 @@ export async function handleImageGet ( await writeFileToResponse(ctx, outFile, res) } catch (err: any) { + Analytics.handleError(err) ctx.error('image processing error', { workspace, name, error: err }) res.setHeader('Content-Type', blob.contentType) @@ -237,6 +239,7 @@ async function writeFileToResponse (ctx: MeasureContext, path: string, res: Resp pipeline(stream, res, (err) => { if (err != null) { + Analytics.handleError(err) const error = err instanceof Error ? err.message : String(err) ctx.error('error writing response', { error }) if (!res.headersSent) { diff --git a/services/datalake/pod-datalake/src/handlers/s3.ts b/services/datalake/pod-datalake/src/handlers/s3.ts index ee84a443f4..e60cf81c7c 100644 --- a/services/datalake/pod-datalake/src/handlers/s3.ts +++ b/services/datalake/pod-datalake/src/handlers/s3.ts @@ -13,6 +13,7 @@ // limitations under the License. // +import { Analytics } from '@hcengineering/analytics' import { MeasureContext } from '@hcengineering/core' import { type Request, type Response } from 'express' @@ -46,6 +47,7 @@ export async function handleS3CreateBlob ( await datalake.create(ctx, workspace, name, filename) res.status(200).send() } catch (err: any) { + Analytics.handleError(err) const error = err instanceof Error ? err.message : String(err) ctx.error('failed to create blob', { workspace, name, error }) res.status(500).send() diff --git a/services/datalake/pod-datalake/src/handlers/video.ts b/services/datalake/pod-datalake/src/handlers/video.ts index d86c855dd8..fd484e98d6 100644 --- a/services/datalake/pod-datalake/src/handlers/video.ts +++ b/services/datalake/pod-datalake/src/handlers/video.ts @@ -13,6 +13,7 @@ // limitations under the License. // +import { Analytics } from '@hcengineering/analytics' import { type MeasureContext, getWorkspaceId, systemAccountEmail } from '@hcengineering/core' import { generateToken } from '@hcengineering/server-token' @@ -29,7 +30,8 @@ export async function requestHLS (ctx: MeasureContext, workspace: string, name: try { ctx.info('request for hls', { workspace, name }) await postTranscodingTask(ctx, workspace, name) - } catch (err) { + } catch (err: any) { + Analytics.handleError(err) ctx.error('can not schedule a task', { err }) } } diff --git a/services/datalake/pod-datalake/src/server.ts b/services/datalake/pod-datalake/src/server.ts index 5ca2139047..71bb881770 100644 --- a/services/datalake/pod-datalake/src/server.ts +++ b/services/datalake/pod-datalake/src/server.ts @@ -15,6 +15,7 @@ import { Analytics } from '@hcengineering/analytics' import { MeasureContext, metricsAggregate } from '@hcengineering/core' +import { getCPUInfo, getMemoryInfo } from '@hcengineering/server-core' import { decodeToken } from '@hcengineering/server-token' import cors from 'cors' @@ -229,6 +230,7 @@ export function createServer (ctx: MeasureContext, config: Config): { app: Expre return } + Analytics.handleError(err) res.status(500).json({ message: err.message?.length > 0 ? err.message : 'Internal Server Error' }) }) @@ -245,7 +247,8 @@ export function createServer (ctx: MeasureContext, config: Config): { app: Expre const json = JSON.stringify({ metrics: metricsAggregate((ctx as any).metrics), statistics: { - activeSessions: {} + cpu: getCPUInfo(), + memory: getMemoryInfo() }, admin })