Skip to content

Commit

Permalink
fix: report energy usage in nanojoules (#3262)
Browse files Browse the repository at this point in the history
  • Loading branch information
armcknight authored Aug 31, 2023
1 parent 4b1a58e commit 7bb0873
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 5 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
- Report database backing store information for Core Data (#3231)
- Add "data use" in privacy manifests (#3259)

### Fixes

- Report correct units (nanojoules) for profiling energy metrics (#3262)

## 8.10.0

### Features
Expand Down
3 changes: 2 additions & 1 deletion Sources/Sentry/SentryMetricProfiler.mm
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ @implementation SentryMetricReading

NSString *const kSentryMetricProfilerSerializationUnitBytes = @"byte";
NSString *const kSentryMetricProfilerSerializationUnitPercentage = @"percent";
NSString *const kSentryMetricProfilerSerializationUnitNanoJoules = @"nanojoule";

// Currently set to 10 Hz as we don't anticipate much utility out of a higher resolution when
// sampling CPU usage and memory footprint, and we want to minimize the overhead of making the
Expand Down Expand Up @@ -133,7 +134,7 @@ - (void)stop
if (cpuEnergyUsage.count > 0) {
dict[kSentryMetricProfilerSerializationKeyCPUEnergyUsage]
= serializeValuesWithNormalizedTime(cpuEnergyUsage,
kSentryMetricProfilerSerializationUnitBytes, startSystemTime, endSystemTime);
kSentryMetricProfilerSerializationUnitNanoJoules, startSystemTime, endSystemTime);
}

if (cpuUsage.count > 0) {
Expand Down
1 change: 1 addition & 0 deletions Sources/Sentry/include/SentryMetricProfiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ SENTRY_EXTERN NSString *const kSentryMetricProfilerSerializationKeyCPUEnergyUsag

SENTRY_EXTERN NSString *const kSentryMetricProfilerSerializationUnitBytes;
SENTRY_EXTERN NSString *const kSentryMetricProfilerSerializationUnitPercentage;
SENTRY_EXTERN NSString *const kSentryMetricProfilerSerializationUnitNanoJoules;

// The next two types are technically the same as far as the type system is concerned, but they
// actually contain different mixes of value types, so define them separately. If they ever change,
Expand Down
11 changes: 7 additions & 4 deletions Tests/SentryProfilerTests/SentryProfilerSwiftTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -603,12 +603,12 @@ private extension SentryProfilerSwiftTests {

let expectedUsageReadings = fixture.mockUsageReadingsPerBatch * metricsBatches

try assertMetricValue(measurements: measurements, key: kSentryMetricProfilerSerializationKeyCPUUsage, numberOfReadings: expectedUsageReadings, expectedValue: fixture.mockCPUUsage, transaction: transaction)
try assertMetricValue(measurements: measurements, key: kSentryMetricProfilerSerializationKeyCPUUsage, numberOfReadings: expectedUsageReadings, expectedValue: fixture.mockCPUUsage, transaction: transaction, expectedUnits: kSentryMetricProfilerSerializationUnitPercentage)

try assertMetricValue(measurements: measurements, key: kSentryMetricProfilerSerializationKeyMemoryFootprint, numberOfReadings: expectedUsageReadings, expectedValue: fixture.mockMemoryFootprint, transaction: transaction)
try assertMetricValue(measurements: measurements, key: kSentryMetricProfilerSerializationKeyMemoryFootprint, numberOfReadings: expectedUsageReadings, expectedValue: fixture.mockMemoryFootprint, transaction: transaction, expectedUnits: kSentryMetricProfilerSerializationUnitBytes)

// we wind up with one less energy reading. since we must use the difference between readings to get actual values, the first one is only the baseline reading.
try assertMetricValue(measurements: measurements, key: kSentryMetricProfilerSerializationKeyCPUEnergyUsage, numberOfReadings: expectedUsageReadings - 1, expectedValue: fixture.mockEnergyUsage, transaction: transaction)
try assertMetricValue(measurements: measurements, key: kSentryMetricProfilerSerializationKeyCPUEnergyUsage, numberOfReadings: expectedUsageReadings - 1, expectedValue: fixture.mockEnergyUsage, transaction: transaction, expectedUnits: kSentryMetricProfilerSerializationUnitNanoJoules)

#if !os(macOS)
try assertMetricEntries(measurements: measurements, key: kSentryProfilerSerializationKeySlowFrameRenders, expectedEntries: fixture.expectedSlowFrames, transaction: transaction)
Expand Down Expand Up @@ -655,7 +655,7 @@ private extension SentryProfilerSwiftTests {
}
}

func assertMetricValue<T: Equatable>(measurements: [String: Any], key: String, numberOfReadings: Int, expectedValue: T? = nil, transaction: Transaction) throws {
func assertMetricValue<T: Equatable>(measurements: [String: Any], key: String, numberOfReadings: Int, expectedValue: T? = nil, transaction: Transaction, expectedUnits: String) throws {
let metricContainer = try XCTUnwrap(measurements[key] as? [String: Any])
let values = try XCTUnwrap(metricContainer["values"] as? [[String: Any]])
XCTAssertEqual(values.count, numberOfReadings, "Wrong number of values under \(key)")
Expand All @@ -666,6 +666,9 @@ private extension SentryProfilerSwiftTests {

let timestamp = try XCTUnwrap(values[0]["elapsed_since_start_ns"] as? NSString)
try assertTimestampOccursWithinTransaction(timestamp: timestamp, transaction: transaction)

let actualUnits = try XCTUnwrap(metricContainer["unit"] as? String)
XCTAssertEqual(actualUnits, expectedUnits)
}
}

Expand Down

0 comments on commit 7bb0873

Please sign in to comment.