Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: report energy usage in nanojoules #3262

Merged
merged 3 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
- Distributed tracing without performance (#3196)
- Report database backing store information for Core Data (#3231)

### 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