From 314ba8c365232286a629c7648f1b707a757a42ed Mon Sep 17 00:00:00 2001 From: Dimitrios Vasilas Date: Thu, 16 Apr 2026 18:25:40 +0300 Subject: [PATCH] CLDSRV-894: Report turn-around time for PutObject and UploadPart Server access logs did not report turn-around time for PutObject and UploadPart while all other operations reported it correctly. AWS reports turn-around time for these operations. --- lib/api/api.js | 13 +++++++++++++ tests/unit/api/api.js | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/lib/api/api.js b/lib/api/api.js index 195441c3fe..349c29fc97 100644 --- a/lib/api/api.js +++ b/lib/api/api.js @@ -263,6 +263,19 @@ const api = { request.serverAccessLog.analyticsUserName = authNames.userName; } if (apiMethod === 'objectPut' || apiMethod === 'objectPutPart') { + const setStartTurnAroundTime = () => { + if (request.serverAccessLog) { + request.serverAccessLog.startTurnAroundTime = process.hrtime.bigint(); + } + }; + // For 0-byte uploads, downstream handlers do not consume + // the request stream, so 'end' never fires. Set + // startTurnAroundTime synchronously in that case. + if (request.headers['content-length'] === '0') { + setStartTurnAroundTime(); + } else { + request.on('end', setStartTurnAroundTime); + } return next(null, userInfo, authorizationResults, streamingV4Params, infos); } // issue 100 Continue to the client diff --git a/tests/unit/api/api.js b/tests/unit/api/api.js index 78626bd651..9d08d33207 100644 --- a/tests/unit/api/api.js +++ b/tests/unit/api/api.js @@ -115,6 +115,40 @@ describe('api.callApiMethod', () => { api.callApiMethod('multipartDelete', request, response, log); }); + ['objectPut', 'objectPutPart'].forEach(method => { + it(`should set startTurnAroundTime on request end for ${method}`, done => { + sandbox.stub(api, method).callsFake( + (userInfo, _request, streamingV4Params, _log, cb) => { + request.on('end', () => { + assert.strictEqual(typeof request.serverAccessLog.startTurnAroundTime, 'bigint'); + cb(); + }); + request.resume(); + }); + request.objectKey = 'testobject'; + request.serverAccessLog = {}; + api.callApiMethod(method, request, response, log, err => { + assert.ifError(err); + done(); + }); + }); + + it(`should set startTurnAroundTime synchronously for 0-byte ${method}`, done => { + sandbox.stub(api, method).callsFake( + (userInfo, _request, streamingV4Params, _log, cb) => { + assert.strictEqual(typeof request.serverAccessLog.startTurnAroundTime, 'bigint'); + cb(); + }); + request.objectKey = 'testobject'; + request.serverAccessLog = {}; + request.headers = Object.assign({}, request.headers, { 'content-length': '0' }); + api.callApiMethod(method, request, response, log, err => { + assert.ifError(err); + done(); + }); + }); + }); + describe('MD5 checksum validation', () => { const methodsWithChecksumValidation = [ 'bucketPutACL',