Skip to content

CLDSRV-899: Log replication events in server access logs#6164

Open
dvasilas wants to merge 5 commits intodevelopment/9.2from
improvement/CLDSRV-899-log-replication-events
Open

CLDSRV-899: Log replication events in server access logs#6164
dvasilas wants to merge 5 commits intodevelopment/9.2from
improvement/CLDSRV-899-log-replication-events

Conversation

@dvasilas
Copy link
Copy Markdown
Contributor

@dvasilas dvasilas commented May 4, 2026

Replication writes via the backbeat putData route are now visible in
the destination bucket's server access logs.

Reads from the source bucket are already logged as REST.GET.OBJECT.

MPU replication

MPU replication produces N × REST.PUT.OBJECT on the destination, not AWS's 1 × REST.POST.UPLOADS + N × REST.PUT.PART + 1 × REST.POST.UPLOAD.

Backbeat replicates an MPU as N PUT /_/backbeat/data calls + one stitching PUT /_/backbeat/metadata. The destination has no MPU lifecycle — parts land as raw data blobs and the metadata write turns them into a multipart-shaped object. AWS's initiate/parts/complete events correspond to operations that don't happen here, and the PutData API carries no uploadId/partNumber for cloudserver to even relabel parts as REST.PUT.PART.

Replication writes via the backbeat putData route are now visible in
bucket server access logs with operation = REST.PUT.OBJECT.
@bert-e
Copy link
Copy Markdown
Contributor

bert-e commented May 4, 2026

Hello dvasilas,

My role is to assist you with the merge of this
pull request. Please type @bert-e help to get information
on this process, or consult the user documentation.

Available options
name description privileged authored
/after_pull_request Wait for the given pull request id to be merged before continuing with the current one.
/bypass_author_approval Bypass the pull request author's approval
/bypass_build_status Bypass the build and test status
/bypass_commit_size Bypass the check on the size of the changeset TBA
/bypass_incompatible_branch Bypass the check on the source branch prefix
/bypass_jira_check Bypass the Jira issue check
/bypass_peer_approval Bypass the pull request peers' approval
/bypass_leader_approval Bypass the pull request leaders' approval
/approve Instruct Bert-E that the author has approved the pull request. ✍️
/create_pull_requests Allow the creation of integration pull requests.
/create_integration_branches Allow the creation of integration branches.
/no_octopus Prevent Wall-E from doing any octopus merge and use multiple consecutive merge instead
/unanimity Change review acceptance criteria from one reviewer at least to all reviewers
/wait Instruct Bert-E not to run until further notice.
Available commands
name description privileged
/help Print Bert-E's manual in the pull request.
/status Print Bert-E's current status in the pull request TBA
/clear Remove all comments from Bert-E from the history TBA
/retry Re-start a fresh build TBA
/build Re-start a fresh build TBA
/force_reset Delete integration branches & pull requests, and restart merge process from the beginning.
/reset Try to remove integration branches unless there are commits on them which do not appear on the source branch.

Status report is not available.

@bert-e
Copy link
Copy Markdown
Contributor

bert-e commented May 4, 2026

Incorrect fix version

The Fix Version/s in issue CLDSRV-899 contains:

  • None

Considering where you are trying to merge, I ignored possible hotfix versions and I expected to find:

  • 9.2.40

  • 9.3.7

  • 9.4.0

Please check the Fix Version/s of CLDSRV-899, or the target
branch of this pull request.

@claude
Copy link
Copy Markdown

claude Bot commented May 4, 2026

LGTM

Clean, well-scoped change. The replication flag flows correctly from putData through getOperation and logServerAccess. The loggingEnabled guard correctly allows replication entries through alongside expiration. The synthesized requestURI matches the pattern used by getURI(). Tests cover the key scenarios including error paths. No issues found.

Review by Claude Code

@codecov
Copy link
Copy Markdown

codecov Bot commented May 4, 2026

Codecov Report

❌ Patch coverage is 80.00000% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.41%. Comparing base (22f67e0) to head (2c9ff6d).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
lib/routes/routeBackbeat.js 41.66% 7 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

Files with missing lines Coverage Δ
lib/utilities/serverAccessLogger.js 84.81% <100.00%> (+1.41%) ⬆️
lib/routes/routeBackbeat.js 76.17% <41.66%> (-0.57%) ⬇️

... and 2 files with indirect coverage changes

@@                 Coverage Diff                 @@
##           development/9.2    #6164      +/-   ##
===================================================
- Coverage            84.50%   84.41%   -0.10%     
===================================================
  Files                  204      204              
  Lines                13180    13215      +35     
===================================================
+ Hits                 11138    11155      +17     
- Misses                2042     2060      +18     
Flag Coverage Δ
file-ft-tests 67.99% <14.28%> (-0.15%) ⬇️
kmip-ft-tests 28.42% <2.85%> (-0.07%) ⬇️
mongo-v0-ft-tests 69.20% <14.28%> (-0.17%) ⬇️
mongo-v1-ft-tests 69.21% <14.28%> (-0.20%) ⬇️
multiple-backend 35.68% <57.14%> (+0.05%) ⬆️
sur-tests 35.97% <2.85%> (-0.96%) ⬇️
sur-tests-inflights 37.81% <2.85%> (-0.10%) ⬇️
unit 70.30% <77.14%> (+0.01%) ⬆️
utapi-v2-tests 34.70% <2.85%> (-0.09%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@dvasilas dvasilas force-pushed the improvement/CLDSRV-899-log-replication-events branch from b922c2f to 803285c Compare May 7, 2026 11:16
@bert-e
Copy link
Copy Markdown
Contributor

bert-e commented May 7, 2026

Request integration branches

Waiting for integration branch creation to be requested by the user.

To request integration branches, please comment on this pull request with the following command:

/create_integration_branches

Alternatively, the /approve and /create_pull_requests commands will automatically
create the integration branches.

@claude
Copy link
Copy Markdown

claude Bot commented May 7, 2026

LGTM

Review by Claude Code

1 similar comment
@claude
Copy link
Copy Markdown

claude Bot commented May 7, 2026

LGTM

Review by Claude Code

dvasilas added 2 commits May 8, 2026 13:38
Destination-side delete-marker replication is now logged as
REST.DELETE.OBJECT, same as AWS.
Destination-side PutObjectTagging and DeleteObjectTagging
replication are now logged as REST.PUT.OBJECT_TAGGING (same as AWS).

AWS replicates a DeleteObjectTagging on the destination as
REST.PUT.OBJECT_TAGGING with an empty tag set and identical URI
shape (PUT /<bucket>/<key>?tagging&versionId=<vid>).
@dvasilas dvasilas force-pushed the improvement/CLDSRV-899-log-replication-events branch from 0c52210 to 812257c Compare May 8, 2026 10:51
@bert-e
Copy link
Copy Markdown
Contributor

bert-e commented May 8, 2026

Incorrect fix version

The Fix Version/s in issue CLDSRV-899 contains:

  • 9.2.40

  • 9.3.7

  • 9.4.0

Considering where you are trying to merge, I ignored possible hotfix versions and I expected to find:

  • 9.2.40

  • 9.3.8

  • 9.4.0

Please check the Fix Version/s of CLDSRV-899, or the target
branch of this pull request.

const { headers, bucketName, objectKey } = request;

// Destination-side delete-marker replication.
// We need the REPLICA status to distinquish from
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "distinquish" should be "distinguish".

```suggestion
// We need the REPLICA status to distinguish from

query = versionId ? `?tagging&versionId=${versionId}` : '?tagging';
}
logEntry.requestURI =
`${method} /${params.bucketName}/${params.objectKey}${query} HTTP/${req.httpVersion ?? '1.1'}`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

params.objectKey is URI-decoded (via _decodeURI at line 79 of routeBackbeat.js), so keys with special characters (spaces, unicode) will appear unencoded here (e.g. my file.txt), while normal S3 request URIs logged via getURI(req) preserve the raw HTTP encoding (my%20file.txt). This could cause inconsistent parsing for log consumers. Consider re-encoding the key to match non-replication entries.

— Claude Code

@claude
Copy link
Copy Markdown

claude Bot commented May 8, 2026

  • Typo in comment: "distinquish" → "distinguish" (routeBackbeat.js:540)
    • One-click suggestion provided
  • Synthesized requestURI for replication uses URI-decoded objectKey, while normal S3 entries use raw HTTP-encoded URL — could cause inconsistent log parsing for keys with special characters (serverAccessLogger.js:660)
    • Consider re-encoding the key to match non-replication entries

Review by Claude Code

dvasilas added 2 commits May 8, 2026 16:06
Destination-side PutObjectAcl replication is now logged as
REST.PUT.ACL (same as AWS).

The discriminator is replicationInfo.status === 'REPLICA' combined
with omVal.originOp === 's3:ObjectAcl:Put', set on the source by
objectPutACL and preserved through ObjectQueueEntry.toReplicaEntry()'s
clone.

AWS replicates a PutObjectAcl on the destination as REST.PUT.ACL
with URI shape PUT /<bucket>/<key>?acl&versionId=<srcVersionId>
and aclRequired = 'Yes'. Verified empirically against AWS in
eu-north-1 on 2026-05-08.
@dvasilas dvasilas force-pushed the improvement/CLDSRV-899-log-replication-events branch from 812257c to 2c9ff6d Compare May 8, 2026 18:49
const { headers, bucketName, objectKey } = request;

// Destination-side delete-marker replication.
// We need the REPLICA status to distinquish from
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "distinquish" should be "distinguish".

```suggestion
// We need the REPLICA status to distinguish from

query = versionId ? `?acl&versionId=${versionId}` : '?acl';
}
logEntry.requestURI =
`${method} /${params.bucketName}/${params.objectKey}${query} HTTP/${req.httpVersion ?? '1.1'}`;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The synthesized requestURI uses the decoded objectKey directly, but for non-replication requests getURI() uses the raw request.url which is URL-encoded. An object key like my file.txt would appear as PUT /bucket/my%20file.txt HTTP/1.1 in normal logs but PUT /bucket/my file.txt HTTP/1.1 here. Consider URL-encoding bucketName and objectKey to stay consistent with the non-replication log format.

— Claude Code

@claude
Copy link
Copy Markdown

claude Bot commented May 8, 2026

  • Typo in routeBackbeat.js:540 — "distinquish" should be "distinguish".
    - Suggestion applied inline.
    - Synthesized requestURI for replication logs uses decoded objectKey/bucketName, while normal requests use the raw URL-encoded request.url via getURI(). Object keys with special characters (spaces, unicode) will look different in replication vs. normal log entries.
    - Consider wrapping the bucket and key with encodeURIComponent (or S3-style encoding) to match the non-replication format.

    Review by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants