Skip to content

Commit

Permalink
Handled the new metrics event changes in collector
Browse files Browse the repository at this point in the history
  • Loading branch information
anush-apple committed Feb 17, 2024
1 parent 6a78523 commit af6363a
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 19 deletions.
28 changes: 26 additions & 2 deletions src/darwin/Framework/CHIP/MTRMetrics.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,38 @@
NS_ASSUME_NONNULL_BEGIN

/**
* A representation of metrics data for an operation.
* A representation of a metric data for an operation.
*/
MTR_NEWLY_AVAILABLE
@interface MTRMetricsData : NSObject

- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;

// Value for the metric. This can be null if the metric is just a fire event with no value
@property (nonatomic, nullable, readonly, copy) NSNumber * value;

// Relative time point at which the metric was emitted. This may be null.
@property (nonatomic, nullable, readonly, copy) NSNumber * timePointNanoseconds;

// During for the event. This may be null.
@property (nonatomic, nullable, readonly, copy) NSNumber * durationNanoseconds;

@end

/**
* A representation of collection of metrics data for an operation.
*/
MTR_NEWLY_AVAILABLE
@interface MTRMetrics : NSObject

- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;

@property (nonatomic, readonly, copy) NSArray<NSString *> * allKeys;

- (nullable id)valueForKey:(NSString *)key;
- (nullable MTRMetricsData *)valueForKey:(NSString *)key;

@end

NS_ASSUME_NONNULL_END
11 changes: 6 additions & 5 deletions src/darwin/Framework/CHIP/MTRMetrics.mm
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@
* limitations under the License.
*/
#import "MTRLogging_Internal.h"
#include <MTRMetrics.h>
#include <Foundation/Foundation.h>
#import "MTRMetrics_Internal.h"
#import <Matter/MTRDefines.h>

@implementation MTRMetrics {
NSMutableDictionary<NSString *, id> * _metricsData;
NSMutableDictionary<NSString *, MTRMetricsData *> * _metricsData;
}

- (instancetype)init
Expand All @@ -31,7 +32,7 @@ - (instancetype)init
return self;
}

- (instancetype)initWithDictionary:(NSDictionary *)metricsData
- (instancetype)initWithDictionary:(NSDictionary<NSString *, MTRMetricsData *> *)metricsData
{
if (self = [super init]) {
_metricsData = [NSMutableDictionary dictionary];
Expand All @@ -43,7 +44,7 @@ - (instancetype)initWithDictionary:(NSDictionary *)metricsData
}


+ (instancetype)metricsFromDictionary:(NSDictionary *)metricsData
+ (instancetype)metricsFromDictionary:(NSDictionary<NSString *, MTRMetricsData *> *)metricsData
{
MTRMetrics *metrics = [[MTRMetrics alloc] initWithDictionary:metricsData];
return metrics;
Expand All @@ -54,7 +55,7 @@ + (instancetype)metricsFromDictionary:(NSDictionary *)metricsData
return [_metricsData allKeys];
}

- (nullable id)valueForKey:(NSString *)key
- (nullable MTRMetricsData *)valueForKey:(NSString *)key
{
if (!key) {
MTR_LOG_ERROR("Cannot get metrics value for nil key");
Expand All @@ -64,7 +65,7 @@ - (nullable id)valueForKey:(NSString *)key
return _metricsData[key];
}

- (void)setValue:(id _Nullable)value forKey:(NSString *)key
- (void)setValue:(MTRMetricsData * _Nullable)value forKey:(NSString *)key
{
if (!key) {
MTR_LOG_ERROR("Cannot set metrics value for nil key");
Expand Down
108 changes: 96 additions & 12 deletions src/darwin/Framework/CHIP/MTRMetricsCollector.mm
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
* limitations under the License.
*/
#import "MTRMetricsCollector.h"
#include <sys/_types/_key_t.h>
#include <ctime>
#include <chrono>
#include <cmath>
#include <MTRMetrics.h>
#include <tracing/metric_event.h>
#include <MTRDefines_Internal.h>
Expand All @@ -25,6 +29,8 @@
#include <tracing/registry.h>
#import "MTRUnfairLock.h"

using MetricEvent = chip::Tracing::MetricEvent;

void InitializeMetricsCollection()
{
if ([MTRMetricsCollector sharedInstance])
Expand All @@ -33,9 +39,55 @@ void InitializeMetricsCollection()
}
}

@implementation MTRMetricsData {
std::chrono::steady_clock::time_point timePoint;
std::chrono::steady_clock::duration duration;
}

- (instancetype)initWithMetricEvent:(const MetricEvent&) event
{
if (!(self = [super init])) {
return nil;
}

if (event.value.type == MetricEvent::Value::ValueType::SignedValue) {
_value = [NSNumber numberWithInteger:event.value.store.svalue];
}
else {
_value = [NSNumber numberWithUnsignedInteger:event.value.store.uvalue];
}
timePoint = event.timePoint;
duration = std::chrono::steady_clock::duration();
return self;
}

- (void)setDurationFromMetricData:(MTRMetricsData *)fromData
{
duration = timePoint - fromData->timePoint;
}

- (NSNumber *)timePointNanoseconds
{
auto ns = std::chrono::time_point_cast<std::chrono::nanoseconds>(timePoint);
return [NSNumber numberWithLongLong:ns.time_since_epoch().count()];
}

- (NSNumber *)durationNanoseconds
{
auto ns = std::chrono::duration_cast<std::chrono::nanoseconds>(duration);
return [NSNumber numberWithLongLong:ns.count()];
}

- (NSString *)description
{
return [NSString stringWithFormat:@"Value = %@, TimePoint = %@, Duration = %@", self.value, self.timePointNanoseconds, self.durationNanoseconds];
}

@end

@implementation MTRMetricsCollector {
os_unfair_lock _lock;
NSMutableDictionary<NSString *, NSNumber*> * _metricsData;
NSMutableDictionary<NSString *, MTRMetricsData*> * _metricsDataCollection;
chip::Tracing::signposts::DarwinTracingBackend _tracingBackend;
}

Expand All @@ -48,7 +100,7 @@ + (instancetype)sharedInstance
singleton = [[MTRMetricsCollector alloc] init];
if (singleton) {
chip::Tracing::Register(singleton->_tracingBackend);
singleton->_tracingBackend.SetLogEventClientCallback(^(chip::Tracing::MetricEvent event) {
singleton->_tracingBackend.SetLogEventClientCallback(^(MetricEvent event) {
if (singleton) {
[singleton handleMetricEvent:event];
}
Expand All @@ -64,30 +116,62 @@ - (instancetype)init
return nil;
}
_lock = OS_UNFAIR_LOCK_INIT;
_metricsData = [NSMutableDictionary dictionary];
_metricsDataCollection = [NSMutableDictionary dictionary];
return self;
}

- (void)handleMetricEvent:(chip::Tracing::MetricEvent)event
static NSString * suffixNameForMetricTag(MetricEvent::Tag tag)
{
switch (tag) {
case MetricEvent::Tag::Begin: return @"-begin";
case MetricEvent::Tag::End: return @"-end";
case MetricEvent::Tag::Instant: return @"-instant";
}
}

static inline NSString * suffixNameForMetricTag(const MetricEvent & event)
{
return suffixNameForMetricTag(event.tag);
}

- (void)handleMetricEvent:(MetricEvent)event
{
MTR_LOG_INFO("Received metric event, type: %s, value: %u", event.key, event.value.store.uvalue);
std::lock_guard lock(_lock);
if (event.value.type == ::chip::Tracing::MetricEvent::Value::ValueType::SignedValue) {
[_metricsData setValue:[NSNumber numberWithInteger:event.value.store.svalue]
forKey:[NSString stringWithCString:event.key encoding:NSUTF8StringEncoding]];

auto metricsKey = [NSString stringWithFormat:@"%s%@", event.key, suffixNameForMetricTag(event)];
MTRMetricsData *data = [[MTRMetricsData alloc] initWithMetricEvent:event];

// If End event, compute its duration using the Begin event
if (event.tag == MetricEvent::Tag::End) {
auto metricsBeginKey = [NSString stringWithFormat:@"%s%@", event.key, suffixNameForMetricTag(MetricEvent::Tag::Begin)];
auto beginMetric = _metricsDataCollection[metricsBeginKey];
if (beginMetric) {
[data setDurationFromMetricData:beginMetric];
}
else {
MTR_LOG_ERROR("Unable to find Begin event corresponding to Metric Event: %s", event.key);
}
}
else {
[_metricsData setValue:[NSNumber numberWithUnsignedInteger:event.value.store.uvalue]
forKey:[NSString stringWithCString:event.key encoding:NSUTF8StringEncoding]];

[_metricsDataCollection setValue:data forKey:metricsKey];

// If the event is a being or end event, implicitly emit a corresponding instant event
if (event.tag == MetricEvent::Tag::Begin || event.tag == MetricEvent::Tag::End) {
MetricEvent instantEvent(event);
instantEvent.tag = MetricEvent::Tag::Instant;
data = [[MTRMetricsData alloc] initWithMetricEvent:event];
metricsKey = [NSString stringWithFormat:@"%s%@", event.key, suffixNameForMetricTag(MetricEvent::Tag::Instant)];
[_metricsDataCollection setValue:data forKey:metricsKey];
}
}

- (MTRMetrics *)metricSnapshot:(BOOL)resetCollection
{
std::lock_guard lock(_lock);
MTRMetrics *metrics = [MTRMetrics metricsFromDictionary:_metricsData];
MTRMetrics *metrics = [MTRMetrics metricsFromDictionary:_metricsDataCollection ];
if (resetCollection) {
[_metricsData removeAllObjects];
[_metricsDataCollection removeAllObjects];
}
return metrics;
}
Expand Down

0 comments on commit af6363a

Please sign in to comment.