Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
1308b8e
kick ci
xiazhvera Oct 20, 2025
cafa187
Merge branch 'main' of https://github.com/awslabs/aws-crt-cpp into io…
xiazhvera Dec 15, 2025
2dfc1fd
wip: add username
xiazhvera Dec 16, 2025
d9e87c5
fix compile issue
xiazhvera Dec 16, 2025
12ff848
add api to disable metrics
xiazhvera Dec 17, 2025
13f7258
add default value for enableMetrics
xiazhvera Dec 17, 2025
5f8ad51
default metrics to true
xiazhvera Dec 17, 2025
44f74f8
fix init order
xiazhvera Dec 17, 2025
efb6a7e
move metric to mqtt5 client option instead of connect packet
xiazhvera Dec 19, 2025
407182d
clean up
xiazhvera Dec 19, 2025
c87dd51
update submodule
xiazhvera Dec 19, 2025
cc0a9bf
Merge branch 'main' into iot_metrics
xiazhvera Dec 19, 2025
1fa43d5
move shared struct to a shared file
xiazhvera Dec 19, 2025
56b9dd5
Merge branch 'iot_metrics' of https://github.com/awslabs/aws-crt-cpp …
xiazhvera Dec 19, 2025
a376718
add DOXYGEN_PRIVATE
xiazhvera Dec 19, 2025
5c33a50
clean up
xiazhvera Dec 30, 2025
5b4de7b
Merge branch 'main' into iot_metrics
xiazhvera Jan 14, 2026
4bf6518
disable old metrics
xiazhvera Jan 14, 2026
9118d69
Merge branch 'main' into iot_metrics
xiazhvera Jan 14, 2026
5f46f21
fix init order
xiazhvera Jan 15, 2026
397d9f2
Revert "disable old metrics"
xiazhvera Jan 15, 2026
79f0f8d
improve doc
xiazhvera Jan 15, 2026
09ef78b
Merge branch 'main' into iot_metrics
xiazhvera Jan 15, 2026
fc7dc0c
kick ci
xiazhvera Jan 15, 2026
bdf3cfe
kick ci
xiazhvera Jan 15, 2026
294b2ca
and retry
xiazhvera Jan 16, 2026
d6e059a
handle set metrics failure
xiazhvera Jan 16, 2026
ef33cc7
and retry
xiazhvera Jan 16, 2026
8441493
Merge branch 'main' into iot_metrics
xiazhvera Feb 12, 2026
7b5033f
cr update
xiazhvera Feb 12, 2026
c13556c
update metrics structure naming
xiazhvera Feb 13, 2026
d91422c
update aws-c-mqtt
xiazhvera Feb 17, 2026
33fd51b
Merge branch 'main' into iot_metrics
xiazhvera Feb 19, 2026
f720cf2
Merge branch 'main' into iot_metrics
sbSteveK Feb 25, 2026
56d5d4e
try adding metrics collection test
xiazhvera Feb 27, 2026
bb6add8
format
xiazhvera Mar 2, 2026
54f28d2
add test for mqtt3 enable metrics
xiazhvera Mar 2, 2026
2320467
Merge branch 'main' into iot_metrics
xiazhvera Mar 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions include/aws/crt/mqtt/Mqtt5Client.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <aws/crt/http/HttpConnection.h>
#include <aws/crt/mqtt/Mqtt5Types.h>
#include <aws/crt/mqtt/MqttClient.h>
#include <aws/crt/mqtt/private/MqttShared.h>

namespace Aws
{
Expand Down Expand Up @@ -687,6 +688,14 @@ namespace Aws
*/
Mqtt5ClientOptions &WithPublishReceivedCallback(OnPublishReceivedHandler callback) noexcept;

/**
* Enable AWS IoT metrics. Default to enabled.
*
* @param enabled enable AWS IoT metrics to collect SDK usage data
* @return this option object
*/
Mqtt5ClientOptions &WithMetricsCollection(bool enabled) noexcept;
Comment on lines +691 to +697
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 we should provide more details to users about what info we collect (version, configuration, etc.) and what we don't (probably something general like "private data" would suffice), so users won't opt out of metrics just in case we collect something they don't want to share.
I'd add these details to all public API that expose metrics-related functionality.


/**
* Initializes the C aws_mqtt5_client_options from Mqtt5ClientOptions. For internal use
*
Expand Down Expand Up @@ -833,10 +842,14 @@ namespace Aws
*/
uint32_t m_ackTimeoutSec;

bool m_enableMetrics = true;
Mqtt::IoTDeviceSDKMetrics m_sdkMetrics;

/* Underlying Parameters */
Crt::Allocator *m_allocator;
aws_http_proxy_options m_httpProxyOptionsStorage;
aws_mqtt5_packet_connect_view m_packetConnectViewStorage;
struct aws_mqtt_iot_metrics m_metricsStorage;
};

} // namespace Mqtt5
Expand Down
8 changes: 6 additions & 2 deletions include/aws/crt/mqtt/MqttClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ namespace Aws
* @param socketOptions socket options to use when establishing the connection
* @param tlsContext tls context to use with the connection
* @param useWebsocket should the connection use websockets or should it use direct mqtt?
* @param enableMetrics enable AWS IoT metrics collection. Default to true.
*
* @return a new connection object. Connect() will still need to be called after all further
* configuration is finished.
Expand All @@ -94,7 +95,8 @@ namespace Aws
uint32_t port,
const Io::SocketOptions &socketOptions,
const Crt::Io::TlsContext &tlsContext,
bool useWebsocket = false) noexcept;
bool useWebsocket = false,
bool enableMetrics = true) noexcept;

/**
* Create a new connection object over plain text from the client. The client must outlive
Expand All @@ -103,6 +105,7 @@ namespace Aws
* @param port port to connect to
* @param socketOptions socket options to use when establishing the connection
* @param useWebsocket should the connection use websockets or should it use direct mqtt?
* @param enableMetrics enable AWS IoT metrics collection. Default to true
*
* @return a new connection object. Connect() will still need to be called after all further
* configuration is finished.
Expand All @@ -111,7 +114,8 @@ namespace Aws
const char *hostName,
uint32_t port,
const Io::SocketOptions &socketOptions,
bool useWebsocket = false) noexcept;
bool useWebsocket = false,
bool enableMetrics = true) noexcept;

private:
aws_mqtt_client *m_client;
Expand Down
1 change: 1 addition & 0 deletions include/aws/crt/mqtt/MqttTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ namespace Aws
Crt::Io::TlsConnectionOptions tlsConnectionOptions;
bool useWebsocket = false;
bool useTls = false;
bool enableMetrics = true;
Allocator *allocator = nullptr;
};

Expand Down
3 changes: 3 additions & 0 deletions include/aws/crt/mqtt/private/MqttConnectionCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <aws/crt/io/SocketOptions.h>
#include <aws/crt/io/TlsOptions.h>
#include <aws/crt/mqtt/MqttTypes.h>
#include <aws/crt/mqtt/private/MqttShared.h>

#include <aws/mqtt/client.h>
#include <aws/mqtt/v5/mqtt5_client.h>
Expand Down Expand Up @@ -372,6 +373,8 @@ namespace Aws
bool m_useTls;
bool m_useWebsocket;
MqttConnectionOperationStatistics m_operationStatistics;
bool m_enableMetrics = true;
IoTDeviceSDKMetrics m_sdkMetrics;
Allocator *m_allocator;

/**
Expand Down
38 changes: 38 additions & 0 deletions include/aws/crt/mqtt/private/MqttShared.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*! \cond DOXYGEN_PRIVATE
** Hide API from this file in doxygen. Set DOXYGEN_PRIVATE in doxygen
** config to enable this file for doxygen.
*/
#pragma once
/**
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0.
*/

#include <aws/crt/Types.h>

namespace Aws
{
namespace Crt
{
namespace Mqtt
{
/**
* @internal
* IoT Device SDK Metrics Structure
*/
struct IoTDeviceSDKMetrics
{
String LibraryName;

IoTDeviceSDKMetrics() { LibraryName = "IoTDeviceSDK/CPP"; }

void initializeRawOptions(aws_mqtt_iot_metrics &raw_options) noexcept
{
raw_options.library_name = ByteCursorFromString(LibraryName);
}
};
} // namespace Mqtt
} // namespace Crt
} // namespace Aws

/*! \endcond */
2 changes: 1 addition & 1 deletion include/aws/iot/Mqtt5Client.h
Original file line number Diff line number Diff line change
Expand Up @@ -670,8 +670,8 @@ namespace Aws
/* Error */
int m_lastError;

/** Enable AWS IoT Metrics Collection. This is always set to true for now. */
Copy link
Contributor

Choose a reason for hiding this comment

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

Trivial: Maybe it'll become clearer below but what does this mean it's always set to true? Is this not tied to the enableMetrics bools that can be set to false?

Copy link
Contributor

Choose a reason for hiding this comment

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

It seems like this can't be changed to false. Is there a reason we're not allowing metrics to be disabled?

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 option was originally there to match MQTT3 behavior, which allows users to disable metrics. Since the MQTT5 client does not supports toggling metrics collection, it should be safe to remove.

bool m_enableMetricsCollection;

Crt::String m_sdkName = "CPPv2";
Crt::String m_sdkVersion = AWS_CRT_CPP_VERSION;
Comment on lines 675 to 676
Copy link
Contributor

Choose a reason for hiding this comment

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

This part sill confuses me. Will the library name sometimes be set to CPPv2 (if mqtt client created with builder) and sometimes to IoTDeviceSDK/CPP (if created without builder) ? Can we change the default value of m_sdkName to IoTDeviceSDK/CPP ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As mentioned here, the SDK already exposes an API for setting a customized sdkName.
As we will introduce metadata later, once metadata is there, we will update the SDKs in a single change.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I understand that we can't remove this. But we can change the default value. Or am I missing something?

};
Expand Down
12 changes: 9 additions & 3 deletions include/aws/iot/MqttClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,14 @@ namespace Aws
* @param port port to connect to
* @param socketOptions socket options to use when establishing the connection
* @param tlsContext tls context that should be used for all connections sourced from this config
* @param enableMetrics Whether to set AWS IoT Metrics in the MQTT CONNECT packet. Default is True.
*/
MqttClientConnectionConfig(
const Crt::String &endpoint,
uint32_t port,
const Crt::Io::SocketOptions &socketOptions,
Crt::Io::TlsContext &&tlsContext);
Crt::Io::TlsContext &&tlsContext,
bool enableMetrics = true);

/**
* Creates a client configuration for use with making new AWS Iot specific MQTT Connections with web
Expand All @@ -57,14 +59,16 @@ namespace Aws
* @param tlsContext tls context that should be used for all connections sourced from this config
* @param interceptor websocket upgrade handshake transformation function
* @param proxyOptions proxy configuration options
* @param enableMetrics Whether to set AWS IoT Metrics in the MQTT CONNECT packet. Default is True.
*/
MqttClientConnectionConfig(
const Crt::String &endpoint,
uint32_t port,
const Crt::Io::SocketOptions &socketOptions,
Crt::Io::TlsContext &&tlsContext,
Crt::Mqtt::OnWebSocketHandshakeIntercept &&interceptor,
const Crt::Optional<Crt::Http::HttpClientConnectionProxyOptions> &proxyOptions);
const Crt::Optional<Crt::Http::HttpClientConnectionProxyOptions> &proxyOptions,
bool enableMetrics = true);

/**
* @return true if the instance is in a valid state, false otherwise.
Expand All @@ -84,7 +88,8 @@ namespace Aws
uint32_t port,
const Crt::Io::SocketOptions &socketOptions,
Crt::Io::TlsContext &&tlsContext,
const Crt::Optional<Crt::Http::HttpClientConnectionProxyOptions> &proxyOptions);
const Crt::Optional<Crt::Http::HttpClientConnectionProxyOptions> &proxyOptions,
bool enableMetrics = true);

Crt::String m_endpoint;
uint32_t m_port;
Expand All @@ -94,6 +99,7 @@ namespace Aws
Crt::String m_username;
Crt::String m_password;
Crt::Optional<Crt::Http::HttpClientConnectionProxyOptions> m_proxyOptions;
bool m_enableMetricsCollection;
int m_lastError;

friend class MqttClient;
Expand Down
2 changes: 2 additions & 0 deletions source/iot/Mqtt5Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,8 @@ namespace Aws
m_options->WithHttpProxyOptions(m_proxyOptions.value());
}

m_options->WithMetricsCollection(m_enableMetricsCollection);

return Crt::Mqtt5::Mqtt5Client::NewMqtt5Client(*m_options, m_allocator);
}

Expand Down
33 changes: 24 additions & 9 deletions source/iot/MqttClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ namespace Aws
const Crt::String &endpoint,
uint32_t port,
const Crt::Io::SocketOptions &socketOptions,
Crt::Io::TlsContext &&tlsContext)
Crt::Io::TlsContext &&tlsContext,
bool enableMetrics)
: m_endpoint(endpoint), m_port(port), m_context(std::move(tlsContext)), m_socketOptions(socketOptions),
m_lastError(0)
m_enableMetricsCollection(enableMetrics), m_lastError(0)
{
}

Expand All @@ -43,9 +44,11 @@ namespace Aws
const Crt::Io::SocketOptions &socketOptions,
Crt::Io::TlsContext &&tlsContext,
Crt::Mqtt::OnWebSocketHandshakeIntercept &&interceptor,
const Crt::Optional<Crt::Http::HttpClientConnectionProxyOptions> &proxyOptions)
const Crt::Optional<Crt::Http::HttpClientConnectionProxyOptions> &proxyOptions,
bool enableMetrics)
: m_endpoint(endpoint), m_port(port), m_context(std::move(tlsContext)), m_socketOptions(socketOptions),
m_webSocketInterceptor(std::move(interceptor)), m_proxyOptions(proxyOptions), m_lastError(0)
m_webSocketInterceptor(std::move(interceptor)), m_proxyOptions(proxyOptions),
m_enableMetricsCollection(enableMetrics), m_lastError(0)
{
}

Expand All @@ -54,9 +57,10 @@ namespace Aws
uint32_t port,
const Crt::Io::SocketOptions &socketOptions,
Crt::Io::TlsContext &&tlsContext,
const Crt::Optional<Crt::Http::HttpClientConnectionProxyOptions> &proxyOptions)
const Crt::Optional<Crt::Http::HttpClientConnectionProxyOptions> &proxyOptions,
bool enableMetrics)
: m_endpoint(endpoint), m_port(port), m_context(std::move(tlsContext)), m_socketOptions(socketOptions),
m_proxyOptions(proxyOptions), m_lastError(0)
m_proxyOptions(proxyOptions), m_enableMetricsCollection(enableMetrics), m_lastError(0)
{
}

Expand Down Expand Up @@ -532,7 +536,12 @@ namespace Aws
if (!m_websocketConfig)
{
auto config = MqttClientConnectionConfig(
m_endpoint, port, m_socketOptions, std::move(tlsContext), m_proxyOptions);
m_endpoint,
port,
m_socketOptions,
std::move(tlsContext),
m_proxyOptions,
m_enableMetricsCollection);
config.m_username = username;
config.m_password = password;
return config;
Expand Down Expand Up @@ -562,7 +571,8 @@ namespace Aws
m_socketOptions,
std::move(tlsContext),
signerTransform,
useWebsocketProxyOptions ? m_websocketConfig->ProxyOptions : m_proxyOptions);
useWebsocketProxyOptions ? m_websocketConfig->ProxyOptions : m_proxyOptions,
m_enableMetricsCollection);
config.m_username = username;
config.m_password = password;
return config;
Expand Down Expand Up @@ -593,7 +603,12 @@ namespace Aws

bool useWebsocket = config.m_webSocketInterceptor.operator bool();
auto newConnection = m_client.NewConnection(
config.m_endpoint.c_str(), config.m_port, config.m_socketOptions, config.m_context, useWebsocket);
config.m_endpoint.c_str(),
config.m_port,
config.m_socketOptions,
config.m_context,
useWebsocket,
config.m_enableMetricsCollection);

if (!newConnection)
{
Expand Down
10 changes: 9 additions & 1 deletion source/mqtt/Mqtt5Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,9 @@ namespace Aws
m_extendedValidationAndFlowControlOptions(AWS_MQTT5_EVAFCO_AWS_IOT_CORE_DEFAULTS),
m_offlineQueueBehavior(AWS_MQTT5_COQBT_DEFAULT),
m_reconnectionOptions({AWS_EXPONENTIAL_BACKOFF_JITTER_DEFAULT, 0, 0, 0}), m_pingTimeoutMs(0),
m_connackTimeoutMs(0), m_ackTimeoutSec(0), m_allocator(allocator)
m_connackTimeoutMs(0), m_ackTimeoutSec(0), m_enableMetrics(true), m_allocator(allocator)
{
m_sdkMetrics.initializeRawOptions(m_metricsStorage);
m_socketOptions.SetSocketType(Io::SocketType::Stream);
AWS_ZERO_STRUCT(m_packetConnectViewStorage);
AWS_ZERO_STRUCT(m_httpProxyOptionsStorage);
Expand Down Expand Up @@ -241,6 +242,7 @@ namespace Aws
raw_options.connack_timeout_ms = m_connackTimeoutMs;
raw_options.ack_timeout_seconds = m_ackTimeoutSec;
raw_options.topic_aliasing_options = &m_topicAliasingOptions;
raw_options.metrics = m_enableMetrics ? &m_metricsStorage : NULL;

return true;
}
Expand Down Expand Up @@ -417,6 +419,12 @@ namespace Aws
return *this;
}

Mqtt5ClientOptions &Mqtt5ClientOptions::WithMetricsCollection(bool enabled) noexcept
{
m_enableMetrics = enabled;
return *this;
}

} // namespace Mqtt5
} // namespace Crt
} // namespace Aws
8 changes: 6 additions & 2 deletions source/mqtt/MqttClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ namespace Aws
uint32_t port,
const Io::SocketOptions &socketOptions,
const Crt::Io::TlsContext &tlsContext,
bool useWebsocket) noexcept
bool useWebsocket,
bool enableMetrics) noexcept
{
if (!tlsContext)
{
Expand All @@ -89,6 +90,7 @@ namespace Aws
connectionOptions.tlsContext = tlsContext;
connectionOptions.tlsConnectionOptions = tlsContext.NewConnectionOptions();
connectionOptions.useWebsocket = useWebsocket;
connectionOptions.enableMetrics = enableMetrics;
connectionOptions.useTls = true;
connectionOptions.allocator = m_client->allocator;

Expand All @@ -99,7 +101,8 @@ namespace Aws
const char *hostName,
uint32_t port,
const Io::SocketOptions &socketOptions,
bool useWebsocket) noexcept
bool useWebsocket,
bool enableMetrics) noexcept

{
MqttConnectionOptions connectionOptions;
Expand All @@ -108,6 +111,7 @@ namespace Aws
connectionOptions.socketOptions = socketOptions;
connectionOptions.useWebsocket = useWebsocket;
connectionOptions.useTls = false;
connectionOptions.enableMetrics = enableMetrics;
connectionOptions.allocator = m_client->allocator;

return MqttConnection::s_CreateMqttConnection(m_client, std::move(connectionOptions));
Expand Down
19 changes: 17 additions & 2 deletions source/mqtt/MqttConnectionCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ namespace Aws
: m_underlyingConnection(nullptr), m_hostName(options.hostName), m_port(options.port),
m_tlsContext(std::move(options.tlsContext)), m_tlsOptions(std::move(options.tlsConnectionOptions)),
m_socketOptions(std::move(options.socketOptions)), m_onAnyCbData(nullptr), m_useTls(options.useTls),
m_useWebsocket(options.useWebsocket), m_allocator(options.allocator),
m_connection(std::move(connection))
m_useWebsocket(options.useWebsocket), m_enableMetrics(options.enableMetrics),
m_allocator(options.allocator), m_connection(std::move(connection))
{
if (client != nullptr)
{
Expand Down Expand Up @@ -471,6 +471,21 @@ namespace Aws

aws_mqtt_client_connection_set_connection_termination_handler(
m_underlyingConnection, MqttConnectionCore::s_onConnectionTermination, this);

if (m_enableMetrics)
{
struct aws_mqtt_iot_metrics metrics;
AWS_ZERO_STRUCT(metrics);
m_sdkMetrics.initializeRawOptions(metrics);
if (aws_mqtt_client_connection_set_metrics(m_underlyingConnection, &metrics))
Comment on lines +477 to +480
Copy link
Contributor

Choose a reason for hiding this comment

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

Will it be possible to add meta info into metrics later on? For example, afaiks the cleanSession flag is not available at this point, so we'll have to add it to metrics at the connection time.

{
AWS_LOGF_DEBUG(AWS_LS_MQTT_CLIENT, "Failed to set Mqtt Metrics");
}
}
else if (aws_mqtt_client_connection_set_metrics(m_underlyingConnection, nullptr))
{
AWS_LOGF_DEBUG(AWS_LS_MQTT_CLIENT, "Failed to set Mqtt Metrics");
}
}
else
{
Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ if(NOT BYO_CRYPTO)
# MQTT5 TESTS
add_net_test_case(Mqtt5DirectConnectionMinimal)
add_net_test_case(Mqtt5DirectConnectionWithBasicAuth)
add_net_test_case(Mqtt5DirectConnectionWithMetricsCollection)
add_net_test_case(Mqtt5DirectConnectionWithTLS)
add_net_test_case(Mqtt5DirectConnectionWithMutualTLS)
add_net_test_case(Mqtt5DirectConnectionWithHttpProxy)
Expand Down
Loading