From 9ae3cd60e88ba8e0d7f59d382c2799dd817f1d61 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Mon, 20 Oct 2025 10:53:57 -0700 Subject: [PATCH 01/13] update crt metrics and platform --- awscrt/mqtt.py | 8 ++++---- awscrt/mqtt5.py | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/awscrt/mqtt.py b/awscrt/mqtt.py index 7529168ea..9706f6352 100644 --- a/awscrt/mqtt.py +++ b/awscrt/mqtt.py @@ -6,7 +6,7 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. -import _awscrt +import _awscrt, platform from concurrent.futures import Future from enum import IntEnum from inspect import signature @@ -15,8 +15,7 @@ from awscrt.http import HttpProxyOptions, HttpRequest from awscrt.io import ClientBootstrap, ClientTlsContext, SocketOptions from dataclasses import dataclass -from awscrt.mqtt5 import Client as Mqtt5Client - +from awscrt.mqtt5 import Client as Mqtt5Client, _get_awsiot_metrics_str class QoS(IntEnum): """Quality of Service enumeration @@ -404,7 +403,8 @@ def __init__(self, self.ping_timeout_ms = ping_timeout_ms self.protocol_operation_timeout_ms = protocol_operation_timeout_ms self.will = will - self.username = username + username = username if username else "" + self.username = username + _get_awsiot_metrics_str(username if username else "") self.password = password self.socket_options = socket_options if socket_options else SocketOptions() self.proxy_options = proxy_options if proxy_options else websocket_proxy_options diff --git a/awscrt/mqtt5.py b/awscrt/mqtt5.py index 7c5e4f31f..dfd59dda4 100644 --- a/awscrt/mqtt5.py +++ b/awscrt/mqtt5.py @@ -6,7 +6,7 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. from typing import Any, Callable, Union -import _awscrt +import _awscrt, platform from concurrent.futures import Future from enum import IntEnum from awscrt import NativeResource, exceptions @@ -16,6 +16,36 @@ from collections.abc import Sequence from inspect import signature +# Global variable to cache metrics string +_metrics_str = None +def _get_awsiot_metrics_str(current_username=""): + global _metrics_str + + username_has_query = False + if current_username.find("?") != -1: + username_has_query = True + # The SDK query is already set, skip adding it again + if username_has_query and current_username.find("SDK=") != -1: + return "" + + if _metrics_str is None: + try: + import importlib.metadata + try: + version = importlib.metadata.version("awscrt") + _metrics_str = "SDK=CRTPython&Version={}&Platform={}".format(version, platform.system()) + except importlib.metadata.PackageNotFoundError: + _metrics_str = "SDK=CRTPython&Version=dev&Platform={}".format(platform.system()) + except BaseException: + _metrics_str = "" + + if not _metrics_str == "": + if username_has_query: + return "&" + _metrics_str + else: + return "?" + _metrics_str + else: + return "" class QoS(IntEnum): """MQTT message delivery quality of service. @@ -1753,6 +1783,9 @@ def __init__(self, client_options: ClientOptions): is_will_none = False will = connect_options.will + username = connect_options.username if connect_options.username else "" + username += _get_awsiot_metrics_str(username) + connect_options.username = username websocket_is_none = client_options.websocket_handshake_transform is None self.tls_ctx = client_options.tls_ctx self._binding = _awscrt.mqtt5_client_new(self, From 6aae0f3c93836711c8717f52c8db1af51f302d2b Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Mon, 20 Oct 2025 10:56:22 -0700 Subject: [PATCH 02/13] lint --- awscrt/mqtt.py | 4 +++- awscrt/mqtt5.py | 52 ++++++++++++++++++++++++++----------------------- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/awscrt/mqtt.py b/awscrt/mqtt.py index 9706f6352..6260bfab3 100644 --- a/awscrt/mqtt.py +++ b/awscrt/mqtt.py @@ -6,7 +6,8 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. -import _awscrt, platform +import _awscrt +import platform from concurrent.futures import Future from enum import IntEnum from inspect import signature @@ -17,6 +18,7 @@ from dataclasses import dataclass from awscrt.mqtt5 import Client as Mqtt5Client, _get_awsiot_metrics_str + class QoS(IntEnum): """Quality of Service enumeration diff --git a/awscrt/mqtt5.py b/awscrt/mqtt5.py index dfd59dda4..c955927c0 100644 --- a/awscrt/mqtt5.py +++ b/awscrt/mqtt5.py @@ -6,7 +6,8 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. from typing import Any, Callable, Union -import _awscrt, platform +import _awscrt +import platform from concurrent.futures import Future from enum import IntEnum from awscrt import NativeResource, exceptions @@ -18,34 +19,37 @@ # Global variable to cache metrics string _metrics_str = None + + def _get_awsiot_metrics_str(current_username=""): - global _metrics_str + global _metrics_str - username_has_query = False - if current_username.find("?") != -1: - username_has_query = True - # The SDK query is already set, skip adding it again - if username_has_query and current_username.find("SDK=") != -1: - return "" + username_has_query = False + if current_username.find("?") != -1: + username_has_query = True + # The SDK query is already set, skip adding it again + if username_has_query and current_username.find("SDK=") != -1: + return "" - if _metrics_str is None: + if _metrics_str is None: + try: + import importlib.metadata try: - import importlib.metadata - try: - version = importlib.metadata.version("awscrt") - _metrics_str = "SDK=CRTPython&Version={}&Platform={}".format(version, platform.system()) - except importlib.metadata.PackageNotFoundError: - _metrics_str = "SDK=CRTPython&Version=dev&Platform={}".format(platform.system()) - except BaseException: - _metrics_str = "" - - if not _metrics_str == "": - if username_has_query: - return "&" + _metrics_str - else: - return "?" + _metrics_str + version = importlib.metadata.version("awscrt") + _metrics_str = "SDK=CRTPython&Version={}&Platform={}".format(version, platform.system()) + except importlib.metadata.PackageNotFoundError: + _metrics_str = "SDK=CRTPython&Version=dev&Platform={}".format(platform.system()) + except BaseException: + _metrics_str = "" + + if not _metrics_str == "": + if username_has_query: + return "&" + _metrics_str else: - return "" + return "?" + _metrics_str + else: + return "" + class QoS(IntEnum): """MQTT message delivery quality of service. From 7e5eea701bf2942189c3717fbf238b6b49a3a447 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Tue, 21 Oct 2025 10:53:39 -0700 Subject: [PATCH 03/13] bind out aws_get_platform_build_os_string --- awscrt/mqtt5.py | 4 ++-- crt/aws-c-common | 2 +- source/common.c | 8 ++++++++ source/common.h | 1 + source/module.c | 1 + 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/awscrt/mqtt5.py b/awscrt/mqtt5.py index c955927c0..51354d46d 100644 --- a/awscrt/mqtt5.py +++ b/awscrt/mqtt5.py @@ -36,9 +36,9 @@ def _get_awsiot_metrics_str(current_username=""): import importlib.metadata try: version = importlib.metadata.version("awscrt") - _metrics_str = "SDK=CRTPython&Version={}&Platform={}".format(version, platform.system()) + _metrics_str = "SDK=CRTPython&Version={}&Platform={}".format(version, _awscrt.get_platform_build_os_string()) except importlib.metadata.PackageNotFoundError: - _metrics_str = "SDK=CRTPython&Version=dev&Platform={}".format(platform.system()) + _metrics_str = "SDK=CRTPython&Version=dev&Platform={}".format(_awscrt.get_platform_build_os_string()) except BaseException: _metrics_str = "" diff --git a/crt/aws-c-common b/crt/aws-c-common index 31578beb2..7a67e7748 160000 --- a/crt/aws-c-common +++ b/crt/aws-c-common @@ -1 +1 @@ -Subproject commit 31578beb2309330fece3fb3a66035a568a2641e7 +Subproject commit 7a67e7748644ea01161215dc457165f96259dd8e diff --git a/source/common.c b/source/common.c index cd1b19ef6..2055bbf15 100644 --- a/source/common.c +++ b/source/common.c @@ -26,6 +26,14 @@ PyObject *aws_py_get_cpu_count_for_group(PyObject *self, PyObject *args) { return PyLong_FromSize_t(count); } +PyObject *aws_py_get_platform_build_os_string(PyObject *self, PyObject *args) { + (void)self; + (void)args; + + struct aws_byte_cursor os_string = aws_get_platform_build_os_string(); + return PyUnicode_FromStringAndSize((const char *)os_string.ptr, os_string.len); +} + PyObject *aws_py_thread_join_all_managed(PyObject *self, PyObject *args) { (void)self; diff --git a/source/common.h b/source/common.h index 48df0cf6f..45a23d09b 100644 --- a/source/common.h +++ b/source/common.h @@ -13,6 +13,7 @@ PyObject *aws_py_get_cpu_group_count(PyObject *self, PyObject *args); PyObject *aws_py_get_cpu_count_for_group(PyObject *self, PyObject *args); +PyObject *aws_py_get_platform_build_os_string(PyObject *self, PyObject *args); PyObject *aws_py_thread_join_all_managed(PyObject *self, PyObject *args); diff --git a/source/module.c b/source/module.c index 80699938c..46d6a1daf 100644 --- a/source/module.c +++ b/source/module.c @@ -746,6 +746,7 @@ static PyMethodDef s_module_methods[] = { AWS_PY_METHOD_DEF(get_corresponding_builtin_exception, METH_VARARGS), AWS_PY_METHOD_DEF(get_cpu_group_count, METH_VARARGS), AWS_PY_METHOD_DEF(get_cpu_count_for_group, METH_VARARGS), + AWS_PY_METHOD_DEF(get_platform_build_os_string, METH_VARARGS), AWS_PY_METHOD_DEF(native_memory_usage, METH_NOARGS), AWS_PY_METHOD_DEF(native_memory_dump, METH_NOARGS), AWS_PY_METHOD_DEF(thread_join_all_managed, METH_VARARGS), From 4148ec585bf0128832059f943f2b01cd81de114b Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Tue, 21 Oct 2025 11:02:14 -0700 Subject: [PATCH 04/13] update to use PyUnicode_FromAwsByteCursor instead --- source/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/common.c b/source/common.c index 2055bbf15..236fc2945 100644 --- a/source/common.c +++ b/source/common.c @@ -31,7 +31,7 @@ PyObject *aws_py_get_platform_build_os_string(PyObject *self, PyObject *args) { (void)args; struct aws_byte_cursor os_string = aws_get_platform_build_os_string(); - return PyUnicode_FromStringAndSize((const char *)os_string.ptr, os_string.len); + return PyUnicode_FromAwsByteCursor(&os_string); } PyObject *aws_py_thread_join_all_managed(PyObject *self, PyObject *args) { From 138a6e2cc0ca534cc6b1ff62c7ae901112835b68 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Tue, 21 Oct 2025 11:04:37 -0700 Subject: [PATCH 05/13] clean up --- awscrt/mqtt.py | 1 - awscrt/mqtt5.py | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/awscrt/mqtt.py b/awscrt/mqtt.py index 6260bfab3..50d2208b5 100644 --- a/awscrt/mqtt.py +++ b/awscrt/mqtt.py @@ -7,7 +7,6 @@ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0. import _awscrt -import platform from concurrent.futures import Future from enum import IntEnum from inspect import signature diff --git a/awscrt/mqtt5.py b/awscrt/mqtt5.py index 51354d46d..a4ca3871f 100644 --- a/awscrt/mqtt5.py +++ b/awscrt/mqtt5.py @@ -7,7 +7,6 @@ # SPDX-License-Identifier: Apache-2.0. from typing import Any, Callable, Union import _awscrt -import platform from concurrent.futures import Future from enum import IntEnum from awscrt import NativeResource, exceptions @@ -36,13 +35,15 @@ def _get_awsiot_metrics_str(current_username=""): import importlib.metadata try: version = importlib.metadata.version("awscrt") - _metrics_str = "SDK=CRTPython&Version={}&Platform={}".format(version, _awscrt.get_platform_build_os_string()) + _metrics_str = "SDK=CRTPython&Version={}&Platform={}".format( + version, _awscrt.get_platform_build_os_string()) except importlib.metadata.PackageNotFoundError: _metrics_str = "SDK=CRTPython&Version=dev&Platform={}".format(_awscrt.get_platform_build_os_string()) except BaseException: _metrics_str = "" if not _metrics_str == "": + print("Appending AWS IoT metrics to username: {}".format(_metrics_str)) if username_has_query: return "&" + _metrics_str else: From 38997775c70ea1c13f3d98dc867bb40a18ece9b5 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Tue, 21 Oct 2025 11:18:13 -0700 Subject: [PATCH 06/13] clean up print --- awscrt/mqtt5.py | 1 - 1 file changed, 1 deletion(-) diff --git a/awscrt/mqtt5.py b/awscrt/mqtt5.py index a4ca3871f..1ad76d7db 100644 --- a/awscrt/mqtt5.py +++ b/awscrt/mqtt5.py @@ -43,7 +43,6 @@ def _get_awsiot_metrics_str(current_username=""): _metrics_str = "" if not _metrics_str == "": - print("Appending AWS IoT metrics to username: {}".format(_metrics_str)) if username_has_query: return "&" + _metrics_str else: From fd13a3631d87990b1f78aed28a9eec14790ecdea Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Wed, 22 Oct 2025 11:29:29 -0700 Subject: [PATCH 07/13] fix mqtt3 basic auth test/mqtt5 still fail for testing --- awscrt/mqtt.py | 13 ++++++++++--- awscrt/mqtt5.py | 9 ++++++--- test/test_mqtt.py | 3 ++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/awscrt/mqtt.py b/awscrt/mqtt.py index 50d2208b5..56f364732 100644 --- a/awscrt/mqtt.py +++ b/awscrt/mqtt.py @@ -330,6 +330,8 @@ class Connection(NativeResource): proxy_options (Optional[awscrt.http.HttpProxyOptions]): Optional proxy options for all connections. + + enable_metrics (bool): If true, append AWS IoT metrics to the username. (Default to true) """ def __init__(self, @@ -355,7 +357,8 @@ def __init__(self, proxy_options=None, on_connection_success=None, on_connection_failure=None, - on_connection_closed=None + on_connection_closed=None, + enable_metrics=True ): assert isinstance(client, Client) or isinstance(client, Mqtt5Client) @@ -404,8 +407,12 @@ def __init__(self, self.ping_timeout_ms = ping_timeout_ms self.protocol_operation_timeout_ms = protocol_operation_timeout_ms self.will = will - username = username if username else "" - self.username = username + _get_awsiot_metrics_str(username if username else "") + + if enable_metrics: + username = username if username else "" + username += _get_awsiot_metrics_str(username) + + self.username = username self.password = password self.socket_options = socket_options if socket_options else SocketOptions() self.proxy_options = proxy_options if proxy_options else websocket_proxy_options diff --git a/awscrt/mqtt5.py b/awscrt/mqtt5.py index 1ad76d7db..ee28027c7 100644 --- a/awscrt/mqtt5.py +++ b/awscrt/mqtt5.py @@ -1758,10 +1758,11 @@ class Client(NativeResource): Args: client_options (ClientOptions): The ClientOptions dataclass to used to configure the new Client. + enable_metrics (bool): Whether to append AWS IoT metrics to the username field during CONNECT. Default: True """ - def __init__(self, client_options: ClientOptions): + def __init__(self, client_options: ClientOptions, enable_metrics: bool = True): super().__init__() @@ -1787,8 +1788,10 @@ def __init__(self, client_options: ClientOptions): is_will_none = False will = connect_options.will - username = connect_options.username if connect_options.username else "" - username += _get_awsiot_metrics_str(username) + username = connect_options.username + if enable_metrics: + username = username if username else "" + username += _get_awsiot_metrics_str(username) connect_options.username = username websocket_is_none = client_options.websocket_handshake_transform is None self.tls_ctx = client_options.tls_ctx diff --git a/test/test_mqtt.py b/test/test_mqtt.py index f8435316e..75ef63ca9 100644 --- a/test/test_mqtt.py +++ b/test/test_mqtt.py @@ -629,7 +629,8 @@ def _test_mqtt311_direct_connect_basic_auth(self): host_name=input_host_name, port=input_port, username=input_username, - password=input_password) + password=input_password, + enable_metrics=False) connection.connect().result(TIMEOUT) connection.disconnect().result(TIMEOUT) From 824a84295863d09291100cc68f34cca16806356f Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Wed, 29 Oct 2025 10:50:46 -0700 Subject: [PATCH 08/13] update tests for custom auth --- test/test_mqtt.py | 3 ++- test/test_mqtt5.py | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/test/test_mqtt.py b/test/test_mqtt.py index 75ef63ca9..4040601d1 100644 --- a/test/test_mqtt.py +++ b/test/test_mqtt.py @@ -761,7 +761,8 @@ def sign_function(transform_args, **kwargs): username=input_username, password=input_password, use_websockets=True, - websocket_handshake_transform=sign_function) + websocket_handshake_transform=sign_function, + enable_metrics=False) connection.connect().result(TIMEOUT) connection.disconnect().result(TIMEOUT) diff --git a/test/test_mqtt5.py b/test/test_mqtt5.py index 83ee5928a..c7e9abb62 100644 --- a/test/test_mqtt5.py +++ b/test/test_mqtt5.py @@ -229,7 +229,8 @@ def _test_direct_connect_basic_auth(self): client_options = mqtt5.ClientOptions( host_name=input_host_name, port=input_port, - connect_options=connect_options + connect_options=connect_options, + enable_metrics=False ) callbacks = Mqtt5TestCallbacks() client = self._create_client(client_options=client_options, callbacks=callbacks) @@ -411,7 +412,8 @@ def _test_websocket_connect_basic_auth(self): connect_options = mqtt5.ConnectPacket( client_id=create_client_id(), username=input_username, - password=input_password + password=input_password, + enable_metrics=False ) client_options = mqtt5.ClientOptions( host_name=input_host_name, From 3d25d8504e5bed483e60fd450482c79fbe298ea0 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Wed, 29 Oct 2025 14:30:25 -0700 Subject: [PATCH 09/13] update enable_aws_metrics --- awscrt/mqtt.py | 6 +++--- awscrt/mqtt5.py | 7 ++++--- test/test_mqtt.py | 4 ++-- test/test_mqtt5.py | 4 ++-- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/awscrt/mqtt.py b/awscrt/mqtt.py index 56f364732..675f57688 100644 --- a/awscrt/mqtt.py +++ b/awscrt/mqtt.py @@ -331,7 +331,7 @@ class Connection(NativeResource): proxy_options (Optional[awscrt.http.HttpProxyOptions]): Optional proxy options for all connections. - enable_metrics (bool): If true, append AWS IoT metrics to the username. (Default to true) + enable_aws_metrics (bool): If true, append AWS IoT metrics to the username. (Default to true) """ def __init__(self, @@ -358,7 +358,7 @@ def __init__(self, on_connection_success=None, on_connection_failure=None, on_connection_closed=None, - enable_metrics=True + enable_aws_metrics=True ): assert isinstance(client, Client) or isinstance(client, Mqtt5Client) @@ -408,7 +408,7 @@ def __init__(self, self.protocol_operation_timeout_ms = protocol_operation_timeout_ms self.will = will - if enable_metrics: + if enable_aws_metrics: username = username if username else "" username += _get_awsiot_metrics_str(username) diff --git a/awscrt/mqtt5.py b/awscrt/mqtt5.py index ee28027c7..5d1eba7f4 100644 --- a/awscrt/mqtt5.py +++ b/awscrt/mqtt5.py @@ -1372,6 +1372,7 @@ class ClientOptions: on_lifecycle_event_connection_success_fn (Callable[[LifecycleConnectSuccessData],]): Callback for Lifecycle Event Connection Success. on_lifecycle_event_connection_failure_fn (Callable[[LifecycleConnectFailureData],]): Callback for Lifecycle Event Connection Failure. on_lifecycle_event_disconnection_fn (Callable[[LifecycleDisconnectData],]): Callback for Lifecycle Event Disconnection. + enable_aws_metrics (bool): Whether to append AWS IoT metrics to the username field during CONNECT. Default: True """ host_name: str port: int = None @@ -1398,6 +1399,7 @@ class ClientOptions: on_lifecycle_event_connection_success_fn: Callable[[LifecycleConnectSuccessData], None] = None on_lifecycle_event_connection_failure_fn: Callable[[LifecycleConnectFailureData], None] = None on_lifecycle_event_disconnection_fn: Callable[[LifecycleDisconnectData], None] = None + enable_aws_metrics: bool = True def _check_callback(callback): @@ -1758,11 +1760,10 @@ class Client(NativeResource): Args: client_options (ClientOptions): The ClientOptions dataclass to used to configure the new Client. - enable_metrics (bool): Whether to append AWS IoT metrics to the username field during CONNECT. Default: True """ - def __init__(self, client_options: ClientOptions, enable_metrics: bool = True): + def __init__(self, client_options: ClientOptions): super().__init__() @@ -1789,7 +1790,7 @@ def __init__(self, client_options: ClientOptions, enable_metrics: bool = True): will = connect_options.will username = connect_options.username - if enable_metrics: + if client_options.enable_aws_metrics: username = username if username else "" username += _get_awsiot_metrics_str(username) connect_options.username = username diff --git a/test/test_mqtt.py b/test/test_mqtt.py index 4040601d1..6d2bf09e0 100644 --- a/test/test_mqtt.py +++ b/test/test_mqtt.py @@ -630,7 +630,7 @@ def _test_mqtt311_direct_connect_basic_auth(self): port=input_port, username=input_username, password=input_password, - enable_metrics=False) + enable_aws_metrics=False) connection.connect().result(TIMEOUT) connection.disconnect().result(TIMEOUT) @@ -762,7 +762,7 @@ def sign_function(transform_args, **kwargs): password=input_password, use_websockets=True, websocket_handshake_transform=sign_function, - enable_metrics=False) + enable_aws_metrics=False) connection.connect().result(TIMEOUT) connection.disconnect().result(TIMEOUT) diff --git a/test/test_mqtt5.py b/test/test_mqtt5.py index c7e9abb62..44d9feb15 100644 --- a/test/test_mqtt5.py +++ b/test/test_mqtt5.py @@ -230,7 +230,7 @@ def _test_direct_connect_basic_auth(self): host_name=input_host_name, port=input_port, connect_options=connect_options, - enable_metrics=False + enable_aws_metrics=False ) callbacks = Mqtt5TestCallbacks() client = self._create_client(client_options=client_options, callbacks=callbacks) @@ -413,7 +413,7 @@ def _test_websocket_connect_basic_auth(self): client_id=create_client_id(), username=input_username, password=input_password, - enable_metrics=False + enable_aws_metrics=False ) client_options = mqtt5.ClientOptions( host_name=input_host_name, From 7777b1b2a478970851eb1b353af619fb559f6673 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Wed, 29 Oct 2025 14:49:57 -0700 Subject: [PATCH 10/13] disable metrics for custom auth test --- test/test_mqtt5.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/test_mqtt5.py b/test/test_mqtt5.py index 44d9feb15..72bd5a4d2 100644 --- a/test/test_mqtt5.py +++ b/test/test_mqtt5.py @@ -412,13 +412,13 @@ def _test_websocket_connect_basic_auth(self): connect_options = mqtt5.ConnectPacket( client_id=create_client_id(), username=input_username, - password=input_password, - enable_aws_metrics=False + password=input_password ) client_options = mqtt5.ClientOptions( host_name=input_host_name, port=input_port, - connect_options=connect_options + connect_options=connect_options, + enable_aws_metrics=False ) callbacks = Mqtt5TestCallbacks() client_options.websocket_handshake_transform = callbacks.ws_handshake_transform @@ -617,7 +617,8 @@ def test_connect_with_incorrect_basic_authentication_credentials(self): client_options = mqtt5.ClientOptions( host_name=input_host_name, port=input_port, - connect_options=connect_options + connect_options=connect_options, + enable_aws_metrics=False ) callbacks = Mqtt5TestCallbacks() client = self._create_client(client_options=client_options, callbacks=callbacks) From 0e33a6609c2d72441a3df4ac153638fbc8165afc Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Mon, 3 Nov 2025 14:11:08 -0800 Subject: [PATCH 11/13] add more comments --- test/test_mqtt.py | 4 ++-- test/test_mqtt5.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/test_mqtt.py b/test/test_mqtt.py index 6d2bf09e0..45993059d 100644 --- a/test/test_mqtt.py +++ b/test/test_mqtt.py @@ -630,7 +630,7 @@ def _test_mqtt311_direct_connect_basic_auth(self): port=input_port, username=input_username, password=input_password, - enable_aws_metrics=False) + enable_aws_metrics=False) # Disable AWS metrics for basic auth on non-AWS broker connection.connect().result(TIMEOUT) connection.disconnect().result(TIMEOUT) @@ -762,7 +762,7 @@ def sign_function(transform_args, **kwargs): password=input_password, use_websockets=True, websocket_handshake_transform=sign_function, - enable_aws_metrics=False) + enable_aws_metrics=False) # Disable AWS metrics for basic auth on non-AWS broker connection.connect().result(TIMEOUT) connection.disconnect().result(TIMEOUT) diff --git a/test/test_mqtt5.py b/test/test_mqtt5.py index 72bd5a4d2..67722fdc3 100644 --- a/test/test_mqtt5.py +++ b/test/test_mqtt5.py @@ -230,7 +230,7 @@ def _test_direct_connect_basic_auth(self): host_name=input_host_name, port=input_port, connect_options=connect_options, - enable_aws_metrics=False + enable_aws_metrics=False # Disable AWS metrics for basic auth on non-AWS broker ) callbacks = Mqtt5TestCallbacks() client = self._create_client(client_options=client_options, callbacks=callbacks) @@ -418,7 +418,7 @@ def _test_websocket_connect_basic_auth(self): host_name=input_host_name, port=input_port, connect_options=connect_options, - enable_aws_metrics=False + enable_aws_metrics=False # Disable AWS metrics for basic auth on non-AWS broker ) callbacks = Mqtt5TestCallbacks() client_options.websocket_handshake_transform = callbacks.ws_handshake_transform @@ -618,7 +618,7 @@ def test_connect_with_incorrect_basic_authentication_credentials(self): host_name=input_host_name, port=input_port, connect_options=connect_options, - enable_aws_metrics=False + enable_aws_metrics=False # Disable AWS metrics for basic auth on non-AWS broker ) callbacks = Mqtt5TestCallbacks() client = self._create_client(client_options=client_options, callbacks=callbacks) From d72392cd75c56a833b1c1777027eb6037ccf49ec Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Mon, 3 Nov 2025 14:12:16 -0800 Subject: [PATCH 12/13] lint --- test/test_mqtt.py | 4 ++-- test/test_mqtt5.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/test_mqtt.py b/test/test_mqtt.py index 45993059d..ef54b6d94 100644 --- a/test/test_mqtt.py +++ b/test/test_mqtt.py @@ -630,7 +630,7 @@ def _test_mqtt311_direct_connect_basic_auth(self): port=input_port, username=input_username, password=input_password, - enable_aws_metrics=False) # Disable AWS metrics for basic auth on non-AWS broker + enable_aws_metrics=False) # Disable AWS metrics for basic auth on non-AWS broker connection.connect().result(TIMEOUT) connection.disconnect().result(TIMEOUT) @@ -762,7 +762,7 @@ def sign_function(transform_args, **kwargs): password=input_password, use_websockets=True, websocket_handshake_transform=sign_function, - enable_aws_metrics=False) # Disable AWS metrics for basic auth on non-AWS broker + enable_aws_metrics=False) # Disable AWS metrics for basic auth on non-AWS broker connection.connect().result(TIMEOUT) connection.disconnect().result(TIMEOUT) diff --git a/test/test_mqtt5.py b/test/test_mqtt5.py index 67722fdc3..db0a5f73b 100644 --- a/test/test_mqtt5.py +++ b/test/test_mqtt5.py @@ -230,7 +230,7 @@ def _test_direct_connect_basic_auth(self): host_name=input_host_name, port=input_port, connect_options=connect_options, - enable_aws_metrics=False # Disable AWS metrics for basic auth on non-AWS broker + enable_aws_metrics=False # Disable AWS metrics for basic auth on non-AWS broker ) callbacks = Mqtt5TestCallbacks() client = self._create_client(client_options=client_options, callbacks=callbacks) @@ -418,7 +418,7 @@ def _test_websocket_connect_basic_auth(self): host_name=input_host_name, port=input_port, connect_options=connect_options, - enable_aws_metrics=False # Disable AWS metrics for basic auth on non-AWS broker + enable_aws_metrics=False # Disable AWS metrics for basic auth on non-AWS broker ) callbacks = Mqtt5TestCallbacks() client_options.websocket_handshake_transform = callbacks.ws_handshake_transform @@ -618,7 +618,7 @@ def test_connect_with_incorrect_basic_authentication_credentials(self): host_name=input_host_name, port=input_port, connect_options=connect_options, - enable_aws_metrics=False # Disable AWS metrics for basic auth on non-AWS broker + enable_aws_metrics=False # Disable AWS metrics for basic auth on non-AWS broker ) callbacks = Mqtt5TestCallbacks() client = self._create_client(client_options=client_options, callbacks=callbacks) From cbd71ef65d3191565fc7c42ba50ec59242aafe66 Mon Sep 17 00:00:00 2001 From: Vera Xia Date: Wed, 19 Nov 2025 14:13:41 -0800 Subject: [PATCH 13/13] improve mqtt5 logic --- awscrt/mqtt5.py | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/awscrt/mqtt5.py b/awscrt/mqtt5.py index 5d1eba7f4..93955e71c 100644 --- a/awscrt/mqtt5.py +++ b/awscrt/mqtt5.py @@ -17,33 +17,36 @@ from inspect import signature # Global variable to cache metrics string -_metrics_str = None +_sdk_str = None +_platform_str = None def _get_awsiot_metrics_str(current_username=""): - global _metrics_str + global _sdk_str + global _platform_str - username_has_query = False - if current_username.find("?") != -1: - username_has_query = True - # The SDK query is already set, skip adding it again - if username_has_query and current_username.find("SDK=") != -1: - return "" - - if _metrics_str is None: + _metrics_str = "" + if _sdk_str is None: try: import importlib.metadata try: version = importlib.metadata.version("awscrt") - _metrics_str = "SDK=CRTPython&Version={}&Platform={}".format( - version, _awscrt.get_platform_build_os_string()) + _sdk_str = "SDK=CRTPython&Version={}".format(version) except importlib.metadata.PackageNotFoundError: - _metrics_str = "SDK=CRTPython&Version=dev&Platform={}".format(_awscrt.get_platform_build_os_string()) + _sdk_str = "SDK=CRTPython&Version=dev" except BaseException: - _metrics_str = "" + _sdk_str = "" + + if _platform_str is None: + _platform_str = "Platform={}".format(_awscrt.get_platform_build_os_string()) + + if current_username.find("SDK=") == -1: + _metrics_str += _sdk_str + if current_username.find("Platform=") == -1: + _metrics_str += ("&" if len(_metrics_str) > 0 else "") + _platform_str if not _metrics_str == "": - if username_has_query: + if current_username.find("?") != -1: return "&" + _metrics_str else: return "?" + _metrics_str @@ -1793,6 +1796,7 @@ def __init__(self, client_options: ClientOptions): if client_options.enable_aws_metrics: username = username if username else "" username += _get_awsiot_metrics_str(username) + connect_options.username = username websocket_is_none = client_options.websocket_handshake_transform is None self.tls_ctx = client_options.tls_ctx