Skip to content

Conversation

@xiazhvera
Copy link
Contributor

@xiazhvera xiazhvera commented Nov 21, 2025

Issue #, if available:

Description of changes:

  • Username field update: Now username field in MQTT CONNECT packet will treat string after the last "?" as URL query, and will re-process the string to form a valid query string.
  • Added a metrics struct
struct aws_mqtt_iot_sdk_metrics {
     struct aws_mqtt_metadata_entry *metadata_entries;
     size_t metadata_count;
    struct aws_byte_cursor library_name;
}

SDK name field
For the SDK name field, the library will use the format IoTDeviceSDK/[Language]. And the value would be unified across the CRT/SDKV2/SDKV1 for the same language. e.x.: aws-crt-cpp/aws-iot-device-sdk-cpp/aws-iot-deivce-sdk-cpp-v2 will all be tracked as IoTDeviceSDK/CPP. The binding layer is responsible for setting the SDK name field. If not set, the name will default to be IoTDeviceSDK/C, indicating the client is using aws-c-mqtt library.

Username encoding
IoT gateway team mentioned they are follow the query string format for username field. ( More specific, they used QueryStringDecoder API to decode the string. ) Beyond that, the username should follow the standard MQTT specs.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@codecov-commenter
Copy link

codecov-commenter commented Nov 21, 2025

Codecov Report

❌ Patch coverage is 84.53039% with 28 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.71%. Comparing base (c1ab0e2) to head (af2c8f7).

Files with missing lines Patch % Lines
source/mqtt_iot_sdk_metrics.c 85.03% 19 Missing ⚠️
source/client.c 83.33% 9 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #412      +/-   ##
==========================================
- Coverage   84.73%   84.71%   -0.03%     
==========================================
  Files          25       26       +1     
  Lines       10508    10683     +175     
==========================================
+ Hits         8904     9050     +146     
- Misses       1604     1633      +29     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@xiazhvera xiazhvera changed the title Add Metrics Support For Mqtt3 Client Add Platform Metrics Support For Mqtt3 Client Dec 15, 2025
source/client.c Outdated

if (connection->username) {
struct aws_byte_cursor username_cur = aws_byte_cursor_from_string(connection->username);
if (connection->username || connection->metrics) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Not a fan of this conditional complexity. We don't need to persist the username buffer in the connection object, we can just make a local buffer and free it after initing the packet. The rest of the logic could just be internalized in a metrics API that takes (username, metrics, output_buffer) which you already have I think.

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 removed the persist final username buffer and use a local one, while I didnt see much I can do with the conditional complexity here.

}

struct aws_byte_cursor sdk_attr_value =
metrics.library_name.len > 0 ? metrics.library_name : aws_byte_cursor_from_c_str("IoTDeviceSDK/C");
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we want to know the version # of aws-c-mqtt?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Currently, I plan to put the version into metadata list, in a format of Metadata=(aws-c-mqtt=X.Y.Z, aws-crt-cpp=A.B.C), so that we could collect version numbers for all stacks.


/* Add Platform if not present */
if (!has_platform) {
struct aws_byte_cursor platform_cursor = aws_get_platform_build_os_string();
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't like this function at all. I'd much rather see an append platform string function that could be dynamic (ie include version and other dynamic information) rather than something that's just a handful of static strings.

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 updated the function so it build username from flexible query params, which user would have ability to pass in dynamic information.
While I didn't see how we could avoid having the static string, as long as we would like to append the platform string by default.

Comment on lines 177 to 178
if (s_build_username_query(
original_username, base_username_length, &params_list, output_username, out_full_username_size)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Restoring the username from params may slightly change it (e.g. ?a&b becomes ?a=&b=). I don't think it'll cause any issues, but we still should be aware of this.

Copy link
Contributor Author

@xiazhvera xiazhvera Dec 31, 2025

Choose a reason for hiding this comment

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

Nice catch, updated s_build_username_query to handle the case.

While I figured that this is a behavior change. As we didn't have any restriction on the username, while now we start to treat the username as query string.
In a way, this should be fine, as the service side already treated the username as a query string, and use QueryStringDecoder to handle the username. It should build the same string we build here regardless. While, I will bring this to the team for further discussion.

.ptr = NULL,
.len = 0,
};
if (aws_byte_cursor_is_valid(&username_cur)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Under what conditions would this not be valid? Does it make sense to keep going?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is unlikely to happen, but the only scenario I can think of is when the username is not set, and the metrics string exceeds the size limit, resulting in an invalid username.

I believe it's still acceptable to continue the connection, as metrics are not mandatory for a successful connection.

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.

5 participants