Skip to content

Commit d09b5ac

Browse files
authored
[Darwin] Adding more metrics to capture BLE during setup (project-chip#32793)
- Added more metrics across BLE phase in Darwin - Fixed MetricsCollector to only capture first event of any kind - Reset metrics before any API is started - Fixed bug where duration was not being calculated correctly
1 parent 507161e commit d09b5ac

12 files changed

+289
-26
lines changed

src/darwin/Framework/CHIP/MTRCommissionableBrowser.mm

+24
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#import "MTRCommissionableBrowserResult_Internal.h"
2121
#import "MTRDeviceController.h"
2222
#import "MTRLogging_Internal.h"
23+
#import "MTRMetricKeys.h"
24+
#include <tracing/metric_macros.h>
2325

2426
#include <controller/CHIPDeviceController.h>
2527
#include <lib/dnssd/platform/Dnssd.h>
@@ -35,6 +37,8 @@
3537

3638
constexpr char kBleKey[] = "BLE";
3739

40+
using namespace chip::Tracing::DarwinFramework;
41+
3842
@implementation MTRCommissionableBrowserResultInterfaces
3943
@end
4044

@@ -70,6 +74,7 @@ CHIP_ERROR Start(id<MTRCommissionableBrowserDelegate> delegate, MTRDeviceControl
7074
mController = controller;
7175
mDispatchQueue = queue;
7276
mDiscoveredResults = [[NSMutableDictionary alloc] init];
77+
ResetCounters();
7378

7479
#if CONFIG_NETWORK_LAYER_BLE
7580
ReturnErrorOnFailure(PlatformMgrImpl().StartBleScan(this));
@@ -100,6 +105,7 @@ CHIP_ERROR Stop()
100105

101106
ClearBleDiscoveredDevices();
102107
ClearDnssdDiscoveredDevices();
108+
ResetCounters();
103109
mDiscoveredResults = nil;
104110

105111
#if CONFIG_NETWORK_LAYER_BLE
@@ -109,6 +115,12 @@ CHIP_ERROR Stop()
109115
return ChipDnssdStopBrowse(this);
110116
}
111117

118+
void ResetCounters()
119+
{
120+
mOnNetworkDevicesAdded = mOnNetworkDevicesRemoved = 0;
121+
mBLEDevicesAdded = mBLEDevicesRemoved = 0;
122+
}
123+
112124
void ClearBleDiscoveredDevices()
113125
{
114126
NSMutableDictionary<NSString *, MTRCommissionableBrowserResult *> * discoveredResultsCopy = @ {}.mutableCopy;
@@ -197,6 +209,8 @@ void OnBrowseAdd(DnssdService service) override
197209
VerifyOrReturn(mController != nil);
198210
VerifyOrReturn(mDispatchQueue != nil);
199211

212+
MATTER_LOG_METRIC(kMetricOnNetworkDevicesAdded, ++mOnNetworkDevicesAdded);
213+
200214
auto key = [NSString stringWithUTF8String:service.mName];
201215
if ([mDiscoveredResults objectForKey:key] == nil) {
202216
mDiscoveredResults[key] = [[MTRCommissionableBrowserResult alloc] init];
@@ -218,6 +232,8 @@ void OnBrowseRemove(DnssdService service) override
218232
VerifyOrReturn(mController != nil);
219233
VerifyOrReturn(mDispatchQueue != nil);
220234

235+
MATTER_LOG_METRIC(kMetricOnNetworkDevicesRemoved, ++mOnNetworkDevicesRemoved);
236+
221237
auto key = [NSString stringWithUTF8String:service.mName];
222238
if ([mDiscoveredResults objectForKey:key] == nil) {
223239
// It should not happens.
@@ -269,6 +285,8 @@ void OnBleScanAdd(BLE_CONNECTION_OBJECT connObj, const ChipBLEDeviceIdentificati
269285
result.commissioningMode = YES;
270286
result.params = chip::MakeOptional(chip::Controller::SetUpCodePairerParameters(connObj, false /* connected */));
271287

288+
MATTER_LOG_METRIC(kMetricBLEDevicesAdded, ++mBLEDevicesAdded);
289+
272290
auto key = [NSString stringWithFormat:@"%@", connObj];
273291
mDiscoveredResults[key] = result;
274292

@@ -290,6 +308,8 @@ void OnBleScanRemove(BLE_CONNECTION_OBJECT connObj) override
290308
auto result = mDiscoveredResults[key];
291309
mDiscoveredResults[key] = nil;
292310

311+
MATTER_LOG_METRIC(kMetricBLEDevicesRemoved, ++mBLEDevicesRemoved);
312+
293313
dispatch_async(mDispatchQueue, ^{
294314
[mDelegate controller:mController didFindCommissionableDevice:result];
295315
});
@@ -301,6 +321,10 @@ void OnBleScanRemove(BLE_CONNECTION_OBJECT connObj) override
301321
id<MTRCommissionableBrowserDelegate> mDelegate;
302322
MTRDeviceController * mController;
303323
NSMutableDictionary<NSString *, MTRCommissionableBrowserResult *> * mDiscoveredResults;
324+
int32_t mOnNetworkDevicesAdded;
325+
int32_t mOnNetworkDevicesRemoved;
326+
int32_t mBLEDevicesAdded;
327+
int32_t mBLEDevicesRemoved;
304328
};
305329

306330
@interface MTRCommissionableBrowser ()

src/darwin/Framework/CHIP/MTRDeviceController.mm

+46-7
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#import "MTRKeypair.h"
4141
#import "MTRLogging_Internal.h"
4242
#import "MTRMetricKeys.h"
43+
#import "MTRMetricsCollector.h"
4344
#import "MTROperationalCredentialsDelegate.h"
4445
#import "MTRP256KeypairBridge.h"
4546
#import "MTRPersistentStorageDelegateBridge.h"
@@ -610,10 +611,18 @@ static inline void emitMetricForSetupPayload(MTRSetupPayload * payload)
610611
MATTER_LOG_METRIC(kMetricDeviceProductID, [payload.productID unsignedIntValue]);
611612
}
612613

614+
- (void)preparePASESessionMetric:(chip::NodeId)nodeId
615+
{
616+
self->_deviceControllerDelegateBridge->SetDeviceNodeID(nodeId);
617+
MATTER_LOG_METRIC_BEGIN(kMetricSetupPASESession);
618+
}
619+
613620
- (BOOL)setupCommissioningSessionWithPayload:(MTRSetupPayload *)payload
614621
newNodeID:(NSNumber *)newNodeID
615622
error:(NSError * __autoreleasing *)error
616623
{
624+
[[MTRMetricsCollector sharedInstance] resetMetrics];
625+
617626
// Track overall commissioning
618627
MATTER_LOG_METRIC_BEGIN(kMetricDeviceCommissioning);
619628
emitMetricForSetupPayload(payload);
@@ -623,7 +632,7 @@ - (BOOL)setupCommissioningSessionWithPayload:(MTRSetupPayload *)payload
623632
__block CHIP_ERROR errorCode = CHIP_NO_ERROR;
624633

625634
auto block = ^BOOL {
626-
// Track just this portion of overall PASE setup
635+
// Track work until end of scope
627636
MATTER_LOG_METRIC_SCOPE(kMetricSetupWithPayload, errorCode);
628637

629638
// Try to get a QR code if possible (because it has a better
@@ -633,12 +642,17 @@ - (BOOL)setupCommissioningSessionWithPayload:(MTRSetupPayload *)payload
633642
pairingCode = [payload manualEntryCode];
634643
}
635644
if (pairingCode == nil) {
636-
return ![MTRDeviceController checkForError:CHIP_ERROR_INVALID_ARGUMENT logMsg:kErrorSetupCodeGen error:error];
645+
errorCode = CHIP_ERROR_INVALID_ARGUMENT;
646+
return ![MTRDeviceController checkForError:errorCode logMsg:kErrorSetupCodeGen error:error];
637647
}
638648

639649
chip::NodeId nodeId = [newNodeID unsignedLongLongValue];
640650
self->_operationalCredentialsDelegate->SetDeviceID(nodeId);
651+
652+
[self preparePASESessionMetric:nodeId];
641653
errorCode = self->_cppCommissioner->EstablishPASEConnection(nodeId, [pairingCode UTF8String]);
654+
VerifyOrDo(errorCode != CHIP_NO_ERROR, MATTER_LOG_METRIC_END(kMetricSetupPASESession, errorCode));
655+
642656
return ![MTRDeviceController checkForError:errorCode logMsg:kErrorPairDevice error:error];
643657
};
644658

@@ -654,6 +668,8 @@ - (BOOL)setupCommissioningSessionWithDiscoveredDevice:(MTRCommissionableBrowserR
654668
newNodeID:(NSNumber *)newNodeID
655669
error:(NSError * __autoreleasing *)error
656670
{
671+
[[MTRMetricsCollector sharedInstance] resetMetrics];
672+
657673
// Track overall commissioning
658674
MATTER_LOG_METRIC_BEGIN(kMetricDeviceCommissioning);
659675
emitMetricForSetupPayload(payload);
@@ -663,7 +679,7 @@ - (BOOL)setupCommissioningSessionWithDiscoveredDevice:(MTRCommissionableBrowserR
663679
__block CHIP_ERROR errorCode = CHIP_NO_ERROR;
664680

665681
auto block = ^BOOL {
666-
// Track just this portion of overall PASE setup
682+
// Track work until end of scope
667683
MATTER_LOG_METRIC_SCOPE(kMetricSetupWithDiscovered, errorCode);
668684

669685
chip::NodeId nodeId = [newNodeID unsignedLongLongValue];
@@ -675,7 +691,9 @@ - (BOOL)setupCommissioningSessionWithDiscoveredDevice:(MTRCommissionableBrowserR
675691
auto pinCode = static_cast<uint32_t>(payload.setupPasscode.unsignedLongValue);
676692
params.Value().SetSetupPINCode(pinCode);
677693

694+
[self preparePASESessionMetric:nodeId];
678695
errorCode = self->_cppCommissioner->EstablishPASEConnection(nodeId, params.Value());
696+
VerifyOrDo(errorCode != CHIP_NO_ERROR, MATTER_LOG_METRIC_END(kMetricSetupPASESession, errorCode));
679697
} else {
680698
// Try to get a QR code if possible (because it has a better
681699
// discriminator, etc), then fall back to manual code if that fails.
@@ -684,7 +702,8 @@ - (BOOL)setupCommissioningSessionWithDiscoveredDevice:(MTRCommissionableBrowserR
684702
pairingCode = [payload manualEntryCode];
685703
}
686704
if (pairingCode == nil) {
687-
return ![MTRDeviceController checkForError:CHIP_ERROR_INVALID_ARGUMENT logMsg:kErrorSetupCodeGen error:error];
705+
errorCode = CHIP_ERROR_INVALID_ARGUMENT;
706+
return ![MTRDeviceController checkForError:errorCode logMsg:kErrorSetupCodeGen error:error];
688707
}
689708

690709
for (id key in discoveredDevice.interfaces) {
@@ -693,9 +712,11 @@ - (BOOL)setupCommissioningSessionWithDiscoveredDevice:(MTRCommissionableBrowserR
693712
continue;
694713
}
695714

715+
[self preparePASESessionMetric:nodeId];
696716
errorCode = self->_cppCommissioner->EstablishPASEConnection(
697717
nodeId, [pairingCode UTF8String], chip::Controller::DiscoveryType::kDiscoveryNetworkOnly, resolutionData);
698718
if (CHIP_NO_ERROR != errorCode) {
719+
MATTER_LOG_METRIC_END(kMetricSetupPASESession, errorCode);
699720
break;
700721
}
701722
}
@@ -1616,6 +1637,8 @@ - (BOOL)pairDevice:(uint64_t)deviceID
16161637
setupPINCode:(uint32_t)setupPINCode
16171638
error:(NSError * __autoreleasing *)error
16181639
{
1640+
[[MTRMetricsCollector sharedInstance] resetMetrics];
1641+
16191642
// Track overall commissioning
16201643
MATTER_LOG_METRIC_BEGIN(kMetricDeviceCommissioning);
16211644

@@ -1624,7 +1647,7 @@ - (BOOL)pairDevice:(uint64_t)deviceID
16241647
__block CHIP_ERROR errorCode = CHIP_NO_ERROR;
16251648

16261649
auto block = ^BOOL {
1627-
// Track just this portion of overall PASE setup
1650+
// Track work until end of scope
16281651
MATTER_LOG_METRIC_SCOPE(kMetricPairDevice, errorCode);
16291652

16301653
std::string manualPairingCode;
@@ -1636,7 +1659,11 @@ - (BOOL)pairDevice:(uint64_t)deviceID
16361659
VerifyOrReturnValue(![MTRDeviceController checkForError:errorCode logMsg:kErrorSetupCodeGen error:error], NO);
16371660

16381661
self->_operationalCredentialsDelegate->SetDeviceID(deviceID);
1662+
1663+
[self preparePASESessionMetric:deviceID];
16391664
errorCode = self->_cppCommissioner->EstablishPASEConnection(deviceID, manualPairingCode.c_str());
1665+
VerifyOrDo(errorCode != CHIP_NO_ERROR, MATTER_LOG_METRIC_END(kMetricSetupPASESession, errorCode));
1666+
16401667
return ![MTRDeviceController checkForError:errorCode logMsg:kErrorPairDevice error:error];
16411668
};
16421669

@@ -1653,6 +1680,8 @@ - (BOOL)pairDevice:(uint64_t)deviceID
16531680
setupPINCode:(uint32_t)setupPINCode
16541681
error:(NSError * __autoreleasing *)error
16551682
{
1683+
[[MTRMetricsCollector sharedInstance] resetMetrics];
1684+
16561685
// Track overall commissioning
16571686
MATTER_LOG_METRIC_BEGIN(kMetricDeviceCommissioning);
16581687

@@ -1661,7 +1690,7 @@ - (BOOL)pairDevice:(uint64_t)deviceID
16611690
__block CHIP_ERROR errorCode = CHIP_NO_ERROR;
16621691

16631692
auto block = ^BOOL {
1664-
// Track just this portion of overall PASE setup
1693+
// Track work until end of scope
16651694
MATTER_LOG_METRIC_SCOPE(kMetricPairDevice, errorCode);
16661695

16671696
chip::Inet::IPAddress addr;
@@ -1671,7 +1700,11 @@ - (BOOL)pairDevice:(uint64_t)deviceID
16711700
self->_operationalCredentialsDelegate->SetDeviceID(deviceID);
16721701

16731702
auto params = chip::RendezvousParameters().SetSetupPINCode(setupPINCode).SetPeerAddress(peerAddress);
1703+
1704+
[self preparePASESessionMetric:deviceID];
16741705
errorCode = self->_cppCommissioner->EstablishPASEConnection(deviceID, params);
1706+
VerifyOrDo(errorCode != CHIP_NO_ERROR, MATTER_LOG_METRIC_END(kMetricSetupPASESession, errorCode));
1707+
16751708
return ![MTRDeviceController checkForError:errorCode logMsg:kErrorPairDevice error:error];
16761709
};
16771710

@@ -1684,6 +1717,8 @@ - (BOOL)pairDevice:(uint64_t)deviceID
16841717

16851718
- (BOOL)pairDevice:(uint64_t)deviceID onboardingPayload:(NSString *)onboardingPayload error:(NSError * __autoreleasing *)error
16861719
{
1720+
[[MTRMetricsCollector sharedInstance] resetMetrics];
1721+
16871722
// Track overall commissioning
16881723
MATTER_LOG_METRIC_BEGIN(kMetricDeviceCommissioning);
16891724
emitMetricForSetupPayload([MTRSetupPayload setupPayloadWithOnboardingPayload:onboardingPayload error:nil]);
@@ -1693,11 +1728,15 @@ - (BOOL)pairDevice:(uint64_t)deviceID onboardingPayload:(NSString *)onboardingPa
16931728
__block CHIP_ERROR errorCode = CHIP_NO_ERROR;
16941729

16951730
auto block = ^BOOL {
1696-
// Track just this portion of overall PASE setup
1731+
// Track work until end of scope
16971732
MATTER_LOG_METRIC_SCOPE(kMetricPairDevice, errorCode);
16981733

16991734
self->_operationalCredentialsDelegate->SetDeviceID(deviceID);
1735+
1736+
[self preparePASESessionMetric:deviceID];
17001737
errorCode = self->_cppCommissioner->EstablishPASEConnection(deviceID, [onboardingPayload UTF8String]);
1738+
VerifyOrDo(errorCode != CHIP_NO_ERROR, MATTER_LOG_METRIC_END(kMetricSetupPASESession, errorCode));
1739+
17011740
return ![MTRDeviceController checkForError:errorCode logMsg:kErrorPairDevice error:error];
17021741
};
17031742

src/darwin/Framework/CHIP/MTRDeviceControllerDelegateBridge.h

+3
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,13 @@ class MTRDeviceControllerDelegateBridge : public chip::Controller::DevicePairing
4242

4343
void OnCommissioningComplete(chip::NodeId deviceId, CHIP_ERROR error) override;
4444

45+
void SetDeviceNodeID(chip::NodeId deviceNodeId);
46+
4547
private:
4648
MTRDeviceController * __weak mController;
4749
_Nullable id<MTRDeviceControllerDelegate> mDelegate;
4850
_Nullable dispatch_queue_t mQueue;
51+
chip::NodeId mDeviceNodeId;
4952

5053
MTRCommissioningStatus MapStatus(chip::Controller::DevicePairingDelegate::Status status);
5154
};

src/darwin/Framework/CHIP/MTRDeviceControllerDelegateBridge.mm

+22
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@
6464
{
6565
MTR_LOG_DEFAULT("DeviceControllerDelegate status updated: %d", status);
6666

67+
// If pairing failed, PASE failed. However, since OnPairingComplete(failure_code) might not be invoked in all cases, mark
68+
// end of PASE with timeout as assumed failure. If OnPairingComplete is invoked, the right error code will be updated in
69+
// the end event
70+
if (status == chip::Controller::DevicePairingDelegate::Status::SecurePairingFailed) {
71+
MATTER_LOG_METRIC_END(kMetricSetupPASESession, CHIP_ERROR_TIMEOUT);
72+
}
73+
6774
id<MTRDeviceControllerDelegate> strongDelegate = mDelegate;
6875
MTRDeviceController * strongController = mController;
6976
if (strongDelegate && mQueue && strongController) {
@@ -73,12 +80,21 @@
7380
[strongDelegate controller:strongController statusUpdate:commissioningStatus];
7481
});
7582
}
83+
84+
// If PASE session setup fails and the client implements the delegate that accepts metrics, invoke the delegate
85+
// to mark end of commissioning request.
86+
// Since OnPairingComplete(failure_code) might not be invoked in all cases, use this opportunity to inform of failed commissioning
87+
// and default the error to timeout since that is best guess in this layer.
88+
if (status == chip::Controller::DevicePairingDelegate::Status::SecurePairingFailed && [strongDelegate respondsToSelector:@selector(controller:commissioningComplete:nodeID:metrics:)]) {
89+
OnCommissioningComplete(mDeviceNodeId, CHIP_ERROR_TIMEOUT);
90+
}
7691
}
7792
}
7893

7994
void MTRDeviceControllerDelegateBridge::OnPairingComplete(CHIP_ERROR error)
8095
{
8196
MTR_LOG_DEFAULT("DeviceControllerDelegate Pairing complete. Status %s", chip::ErrorStr(error));
97+
MATTER_LOG_METRIC_END(kMetricSetupPASESession, error);
8298

8399
id<MTRDeviceControllerDelegate> strongDelegate = mDelegate;
84100
MTRDeviceController * strongController = mController;
@@ -129,6 +145,7 @@
129145

130146
// Always collect the metrics to avoid unbounded growth of the stats in the collector
131147
MTRMetrics * metrics = [[MTRMetricsCollector sharedInstance] metricSnapshot:TRUE];
148+
MTR_LOG_INFO("Device commissioning complete with metrics %@", metrics);
132149

133150
if ([strongDelegate respondsToSelector:@selector(controller:commissioningComplete:nodeID:)] ||
134151
[strongDelegate respondsToSelector:@selector(controller:commissioningComplete:nodeID:metrics:)]) {
@@ -158,6 +175,11 @@
158175
}
159176
}
160177

178+
void MTRDeviceControllerDelegateBridge::SetDeviceNodeID(chip::NodeId deviceNodeId)
179+
{
180+
mDeviceNodeId = deviceNodeId;
181+
}
182+
161183
@implementation MTRProductIdentity
162184

163185
- (instancetype)initWithVendorID:(NSNumber *)vendorID productID:(NSNumber *)productID

0 commit comments

Comments
 (0)