|
1 | 1 | import logging
|
2 | 2 | import os
|
3 |
| -import sys |
4 | 3 |
|
5 |
| -# Since Python 3.8 there is a built-in. Remove this when support for Python3.7 is dropped |
6 |
| -# See https://docs.python.org/3/library/importlib.metadata.html |
7 |
| -if sys.version_info >= (3, 8): |
8 |
| - from importlib.metadata import version |
9 |
| -else: |
10 |
| - from importlib_metadata import version |
| 4 | +from aws_lambda_powertools.shared.version import VERSION |
11 | 5 |
|
12 |
| -powertools_version = version("aws-lambda-powertools") |
| 6 | +powertools_version = VERSION |
| 7 | +inject_header = True |
13 | 8 |
|
14 | 9 | try:
|
15 |
| - from botocore import handlers |
| 10 | + import botocore |
16 | 11 | except ImportError:
|
17 |
| - # if botocore failed to import, user might be using custom runtime. We can ignore here |
18 |
| - handlers = None |
| 12 | + # if botocore failed to import, user might be using custom runtime and we can't inject header |
| 13 | + inject_header = False |
19 | 14 |
|
20 | 15 | logger = logging.getLogger(__name__)
|
21 | 16 |
|
22 |
| -EXEC_ENV = os.getenv("AWS_EXECUTION_ENV", "NA") |
23 |
| -TARGET_SDK_EVENT = "request-created" |
24 |
| -FEATURE_PREFIX = "PT" |
| 17 | +EXEC_ENV: str = os.environ.get("AWS_EXECUTION_ENV", "NA") |
| 18 | +TARGET_SDK_EVENT: str = "request-created" |
| 19 | +FEATURE_PREFIX: str = "PT" |
| 20 | +HEADER_NO_OP: str = f"{FEATURE_PREFIX}/no-op/{powertools_version} PTEnv/{EXEC_ENV}" |
25 | 21 |
|
26 | 22 |
|
27 |
| -# In case of no Powertools utility: PT/no-op/2.15.0 PTEnv/AWS_Lambda_python3.9 |
28 |
| -def _add_powertools_version(request, **kwargs): |
| 23 | +def _initializer_botocore_session(session): |
29 | 24 | try:
|
30 |
| - headers = request.headers |
31 |
| - headers["User-Agent"] = f"{headers['User-Agent']} {FEATURE_PREFIX}/no-op/{powertools_version} PTEnv/{EXEC_ENV}" |
| 25 | + session.user_agent_extra = HEADER_NO_OP |
32 | 26 | except Exception:
|
33 |
| - logger.debug("Missing header User-Agent") |
| 27 | + logger.debug("Can't add extra header User-Agent") |
34 | 28 |
|
35 | 29 |
|
36 |
| -# creates the `add_feature_string` function with given feature parameter |
37 | 30 | def _create_feature_function(feature):
|
38 | 31 | def add_powertools_feature(request, **kwargs):
|
39 |
| - headers = request.headers |
40 |
| - # Actually, only one handler can be registered, registering a new one will replace the prev handler |
41 |
| - # We don't need to replace/detect previous registered user-agent |
42 |
| - headers[ |
43 |
| - "User-Agent" |
44 |
| - ] = f"{headers['User-Agent']} {FEATURE_PREFIX}/{feature}/{powertools_version} PTEnv/{EXEC_ENV}" |
45 |
| - |
46 |
| - # return created function |
| 32 | + try: |
| 33 | + headers = request.headers |
| 34 | + header_user_agent: str = ( |
| 35 | + f"{headers['User-Agent']} {FEATURE_PREFIX}/{feature}/{powertools_version} PTEnv/{EXEC_ENV}" |
| 36 | + ) |
| 37 | + |
| 38 | + # This function is exclusive to client and resources objects created in Powertools |
| 39 | + # and must remove the no-op header, if present |
| 40 | + if HEADER_NO_OP in headers["User-Agent"]: |
| 41 | + # Remove HEADER_NO_OP + space |
| 42 | + header_user_agent = header_user_agent.replace(f"{HEADER_NO_OP} ", "") |
| 43 | + |
| 44 | + headers["User-Agent"] = f"{header_user_agent}" |
| 45 | + except Exception: |
| 46 | + logger.debug("Can't find User-Agent header") |
| 47 | + |
47 | 48 | return add_powertools_feature
|
48 | 49 |
|
49 | 50 |
|
50 |
| -# add feature user-agent to given sdk boto3.session |
| 51 | +# Add feature user-agent to given sdk boto3.session |
51 | 52 | def register_feature_to_session(session, feature):
|
52 | 53 | try:
|
53 | 54 | session.events.register(TARGET_SDK_EVENT, _create_feature_function(feature))
|
54 | 55 | except AttributeError as e:
|
55 | 56 | logger.debug(f"session passed in doesn't have a event system:{e}")
|
56 | 57 |
|
57 | 58 |
|
58 |
| -# add feature user-agent to given sdk boto3.client |
| 59 | +# Add feature user-agent to given sdk boto3.client |
59 | 60 | def register_feature_to_client(client, feature):
|
60 | 61 | try:
|
61 | 62 | client.meta.events.register(TARGET_SDK_EVENT, _create_feature_function(feature))
|
62 | 63 | except AttributeError as e:
|
63 | 64 | logger.debug(f"session passed in doesn't have a event system:{e}")
|
64 | 65 |
|
65 | 66 |
|
66 |
| -# add feature user-agent to given sdk boto3.resource |
| 67 | +# Add feature user-agent to given sdk boto3.resource |
67 | 68 | def register_feature_to_resource(resource, feature):
|
68 | 69 | try:
|
69 | 70 | resource.meta.client.meta.events.register(TARGET_SDK_EVENT, _create_feature_function(feature))
|
70 | 71 | except AttributeError as e:
|
71 | 72 | logger.debug(f"resource passed in doesn't have a event system:{e}")
|
72 | 73 |
|
73 | 74 |
|
74 |
| -# register add_pt_version for all AWS SDK in runtime |
75 | 75 | def inject_user_agent():
|
76 |
| - if handlers: |
77 |
| - # register add_user_agent to BUILTIN_HANDLERS so every aws sdk session will have this event registered |
78 |
| - handlers.BUILTIN_HANDLERS.append((TARGET_SDK_EVENT, _add_powertools_version)) |
| 76 | + if inject_header: |
| 77 | + # Customize botocore session to inject Powertools header |
| 78 | + # See: https://github.com/boto/botocore/pull/2682 |
| 79 | + botocore.register_initializer(_initializer_botocore_session) |
0 commit comments