Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User Agent 2.0 #2955

Merged
merged 13 commits into from
Jun 27, 2023
Merged

User Agent 2.0 #2955

merged 13 commits into from
Jun 27, 2023

Conversation

jonemo
Copy link
Contributor

@jonemo jonemo commented May 26, 2023

This PR implements an updated User-Agent header format that is standardized across AWS SDKs. For example, the AWS Ruby SDK's equivalent PR is aws/aws-sdk-ruby#2854.

An example User-Agent header value before the change is:

Boto3/1.20.32 Python/3.9.13 Darwin/22.4.0 exec-env/AWS_Lambda_python3.7 Botocore/1.23.32

An example User-Agent header value after the change is:

Boto3/1.20.32 md/Botocore#1.23.32 ua/2.0 lang/python#3.7.16 os/linux#4.14.255-301-238.520.AMZN2.X86_64 exec-env/AWS_Lambda_python3.7

Various notes:

  • This PR includes the formerly separate (but then closed) change to add the AWS_SDK_UA_APP_ID config: Support for sdk_ua_app_id config setting #2942
  • Users who use the Config.user_agent will not see a change in their User-Agent header string
  • Both Session.user_agent_extra and Config.user_agent_extra continue to be appear at the end of the User-Agent header
  • Session.user_agent() is no longer used internally in Botocore but remains in place and unchanged for any third party users
  • In contrast to the Ruby SDK PR linked above, this PR does not include feature-related or any other request-level information in the User-Agent string.

@jonemo jonemo requested a review from nateprewitt May 26, 2023 00:03
@jonemo jonemo marked this pull request as draft May 26, 2023 00:13
@codecov-commenter
Copy link

codecov-commenter commented May 26, 2023

Codecov Report

Patch coverage: 93.86% and project coverage change: +0.03 🎉

Comparison is base (8bd1a4d) 93.29% compared to head (10b11b6) 93.32%.

❗ Current head 10b11b6 differs from pull request most recent head d33a106. Consider uploading reports for the commit d33a106 to get more accurate results

❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop    #2955      +/-   ##
===========================================
+ Coverage    93.29%   93.32%   +0.03%     
===========================================
  Files           64       65       +1     
  Lines        13588    13742     +154     
===========================================
+ Hits         12677    12825     +148     
- Misses         911      917       +6     
Impacted Files Coverage Δ
botocore/config.py 100.00% <ø> (ø)
botocore/configprovider.py 94.09% <ø> (ø)
botocore/session.py 97.64% <80.00%> (+0.74%) ⬆️
botocore/client.py 97.67% <83.33%> (-0.18%) ⬇️
botocore/useragent.py 94.73% <94.73%> (ø)
botocore/args.py 100.00% <100.00%> (ø)

... and 2 files with indirect coverage changes

☔ View full report in Codecov by Sentry.
📢 Do you have feedback about the report comment? Let us know in this issue.

@jonemo jonemo marked this pull request as ready for review May 27, 2023 02:20
botocore/args.py Outdated
@@ -66,13 +69,14 @@ def __init__(
loader,
exceptions_factory,
config_store,
user_agent_creator,
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this needs to be optional or we may end up breaking current callers. That may change how we use the attribute below.

Copy link
Contributor Author

@jonemo jonemo Jun 20, 2023

Choose a reason for hiding this comment

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

bda23a9 is a refactor that prioritizes backwards compatible interfaces over everything (especially over avoiding duplication).

@@ -249,7 +254,6 @@ def compute_client_args(
return {
'service_name': service_name,
'parameter_validation': parameter_validation,
'user_agent': user_agent,
Copy link
Contributor

Choose a reason for hiding this comment

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

This may also be problematic, I don't immediately know how we do this cleanly though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can bring back this line together with lines 196-203 above where its value gets computed using the legacy method. There is no harm in returning the user_agent key in the dict, it simply won't get used by botocore code. Do you think that's preferable? I was worried the confusion caused by the dead code existing and an unused value being returned might outweigh any benefit to any third-party that may be relying on the user_agent dict key being present.

Copy link
Contributor

Choose a reason for hiding this comment

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

Looking at other libraries that may have issues with this, I can't find one that relies on user_agent. I agree this may cause unnecessary confusion, so let's opt to remove it.

botocore/args.py Show resolved Hide resolved
botocore/config.py Outdated Show resolved Hide resolved
botocore/useragent.py Show resolved Hide resolved


@contextmanager
def uacap_client(client):
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this give us a testing efficiency over the HTTPStubber?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Somehow I couldn't figure out how to use HTTPStubber for this. Not sure if my requirements changed or I just got smarter since then, but your comment made me look at it again and it was straightforward. Done in eb7ded6.

tests/functional/test_useragent.py Show resolved Hide resolved
tests/functional/test_useragent.py Show resolved Hide resolved
tests/functional/test_useragent.py Outdated Show resolved Hide resolved
assert 'app/1234-' in uafields


def test_boto3_behavior(patched_session, stubbed_list_buckets):
Copy link
Contributor

Choose a reason for hiding this comment

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

nit; We may want to be more specific than behavior.

Suggested change
def test_boto3_behavior(patched_session, stubbed_list_buckets):
def test_boto3_user_agent(patched_session, stubbed_list_buckets):

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in eb7ded6

Comment on lines +116 to +117
ua_client = ua_session.with_client_config(Config(...))
ua_string = ua_request.to_string()
Copy link
Contributor

Choose a reason for hiding this comment

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

There seems to be inconsistent naming here. Both should be ua_client or ua_request.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't disagree with the naming being somewhat confusing. But I don't think your suggestions would clarify things. In fact your suggestions might be a sign that I successfully confused you!

  • ua_session is a UserAgentString object with session-level information only.
  • ua_client is a UserAgentString object with session-level and client-level information.
  • ua_string is a str.

myclient.operation()
print(cap_client.captured_ua_string)
"""
client.captured_ua_string = None
Copy link
Contributor

Choose a reason for hiding this comment

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

Would there be any value to add or replace this with a list that captures sequential ua_string's?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I ended up replacing this entire fixture in eb7ded6 to address another comment above. To answer the question though: I didn't see a reason to do more than one request in a single test because each request's UA is independent of the others.

Copy link
Contributor

@nateprewitt nateprewitt left a comment

Choose a reason for hiding this comment

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

2 minor comments, otherwise I think this looks ready to go. Thanks @jonemo!

@@ -249,7 +254,6 @@ def compute_client_args(
return {
'service_name': service_name,
'parameter_validation': parameter_validation,
'user_agent': user_agent,
Copy link
Contributor

Choose a reason for hiding this comment

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

Looking at other libraries that may have issues with this, I can't find one that relies on user_agent. I agree this may cause unnecessary confusion, so let's opt to remove it.

botocore/useragent.py Outdated Show resolved Hide resolved
Copy link
Contributor

@nateprewitt nateprewitt left a comment

Choose a reason for hiding this comment

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

:shipit:

@jonemo jonemo merged commit e5d52ae into boto:develop Jun 27, 2023
31 checks passed
jonemo added a commit to jonemo/botocore that referenced this pull request Jun 27, 2023
jonemo added a commit that referenced this pull request Jun 27, 2023
aws-sdk-python-automation added a commit that referenced this pull request Jun 27, 2023
* release-1.29.162:
  Bumping version to 1.29.162
  Update to latest models
  Revert "User Agent 2.0 (#2955)" (#2976)
  User Agent 2.0 (#2955)
  remove leftover print() statement (#2975)
  Fallback for situations where Python's fromtimestamp() raises OSError or OverflowError (#2972)
@jonemo jonemo mentioned this pull request Jul 12, 2023
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.

4 participants