Skip to content

feat: tag S3 client user agent for request attribution#9795

Open
goanpeca wants to merge 1 commit into
HumanSignal:developfrom
goanpeca:feat/s3-user-agent
Open

feat: tag S3 client user agent for request attribution#9795
goanpeca wants to merge 1 commit into
HumanSignal:developfrom
goanpeca:feat/s3-user-agent

Conversation

@goanpeca

@goanpeca goanpeca commented Jul 1, 2026

Copy link
Copy Markdown

Reason for change

Label Studio talks to object storage through boto3 in label_studio/io_storages/s3/utils.py. When it builds the S3 client and resource, it does not set a user_agent_extra, so every request goes out with only the default botocore user agent.

This makes it hard to identify Label Studio traffic against Amazon S3 or any S3-compatible object store (for example Backblaze B2, Cloudflare R2, or MinIO, all reached through the same code path via a custom endpoint_url). A stable client marker helps storage-side observability and support when diagnosing connection or throughput issues, without changing any request behavior.

The change attaches a label-studio/<version> token to user_agent_extra on the S3 client and resource. It follows the common framework/version user-agent convention, resolves the version from the installed package metadata, and falls back to label-studio/dev when the package is not installed (source checkout).

Screenshots

N/A. Backend-only change, no UI impact.

Rollout strategy

No feature flag required. The change is purely additive: it appends a token to the S3 client and resource user agent and leaves signature_version (s3v4) and the optional custom endpoint_url untouched. The client and resource now share a single boto3.session.Config instead of constructing two identical ones. No new configuration, environment variable, or dependency is introduced (importlib.metadata is standard library).

Testing

Added a unit test module label_studio/io_storages/s3/tests/test_user_agent.py that verifies:

  • _get_user_agent_extra() returns a label-studio/ prefixed token.
  • both the client and the resource carry that token in user_agent_extra.
  • signature_version stays s3v4.
  • a custom endpoint_url is preserved end to end (using an S3-compatible endpoint as one example, alongside the default AWS S3 path).

Acceptance criteria: when Label Studio issues an S3 request (against AWS S3 or an S3-compatible endpoint), the outgoing user agent contains a label-studio/<version> token, and signature version and endpoint configuration are unchanged.

Run locally:

cd label_studio
pytest io_storages/s3/tests/test_user_agent.py

Risks

Low. The token only extends the user-agent string that boto3 already sends; it does not alter authentication, signing, or the request path. The existing test_resolve_s3_url.py behavior is unaffected. If package metadata cannot be resolved, the code degrades to label-studio/dev rather than raising.

Reviewer notes

Scope is intentionally minimal and additive (two files, one small helper plus the shared Config), in line with the contributing guide's preference for small, single-purpose PRs. The PR title uses the feat: prefix per the repository's title convention. Happy to guard this behind a flag or adjust the token format if you would prefer a different convention.

@netlify

netlify Bot commented Jul 1, 2026

Copy link
Copy Markdown

👷 Deploy request for label-studio-docs-new-theme pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 0b3846f

@netlify

netlify Bot commented Jul 1, 2026

Copy link
Copy Markdown

👷 Deploy request for heartex-docs pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 0b3846f

@netlify

netlify Bot commented Jul 1, 2026

Copy link
Copy Markdown

Deploy Preview for label-studio-storybook canceled.

Name Link
🔨 Latest commit 0b3846f
🔍 Latest deploy log https://app.netlify.com/projects/label-studio-storybook/deploys/6a451d5a254e230007fa991e

@netlify

netlify Bot commented Jul 1, 2026

Copy link
Copy Markdown

Deploy Preview for label-studio-playground canceled.

Name Link
🔨 Latest commit 0b3846f
🔍 Latest deploy log https://app.netlify.com/projects/label-studio-playground/deploys/6a451d5a27235f0008f3fc4b

@github-actions github-actions Bot added the feat label Jul 1, 2026
@goanpeca goanpeca force-pushed the feat/s3-user-agent branch from 6927155 to 53ad241 Compare July 1, 2026 13:54
Signed-off-by: Gonzalo Peña-Castellanos <goanpeca@gmail.com>
@goanpeca goanpeca force-pushed the feat/s3-user-agent branch from 53ad241 to 0b3846f Compare July 1, 2026 13:59
@goanpeca goanpeca marked this pull request as ready for review July 8, 2026 19:06
Copilot AI review requested due to automatic review settings July 8, 2026 19:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds request attribution for S3 traffic by appending a stable label-studio/<version> token to the botocore user agent used by Label Studio’s S3 client/resource construction, improving storage-side observability without changing signing or endpoint behavior.

Changes:

  • Add _get_user_agent_extra() helper that resolves the installed label-studio package version and falls back to dev.
  • Pass a shared boto3.session.Config(signature_version='s3v4', user_agent_extra=...) to both S3 client and resource.
  • Add unit tests to verify the user agent token is attached and that signature version + endpoint URL are preserved.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
label_studio/io_storages/s3/utils.py Adds a Label Studio user-agent token to S3 client/resource config while keeping s3v4 signing and endpoint behavior intact.
label_studio/io_storages/s3/tests/test_user_agent.py Adds tests asserting user-agent tagging and that signature version and endpoint URL are preserved.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +19 to +34
def test_client_and_resource_carry_user_agent(self):
client, resource = get_client_and_resource()
expected = _get_user_agent_extra()
assert expected in (client.meta.config.user_agent_extra or '')
assert expected in (resource.meta.client.meta.config.user_agent_extra or '')

def test_signature_version_preserved(self):
client, _ = get_client_and_resource()
assert client.meta.config.signature_version == 's3v4'

def test_custom_endpoint_preserved(self):
endpoint = 'https://your-s3-endpoint.example.com'
client, resource = get_client_and_resource(s3_endpoint=endpoint)
assert client.meta.endpoint_url == endpoint
assert resource.meta.client.meta.endpoint_url == endpoint
assert _get_user_agent_extra() in (client.meta.config.user_agent_extra or '')

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Comment on lines +20 to +24
def _get_user_agent_extra():
try:
version = importlib.metadata.version('label-studio')
except importlib.metadata.PackageNotFoundError:
version = 'dev'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants