Real-time device performance monitoring and telemetry for React Native. Collect CPU, memory, network, storage, and battery metrics with configurable thresholds and event-driven streaming.
Android only. This library does not support iOS.
- Real-time monitoring — Background collection at configurable intervals
- Two collection modes — Raw metrics only, or detailed (raw + performance levels per class)
- Metrics — CPU, memory, network, storage, battery
- Dual architecture — Old React Native bridge and TurboModule
- Event-driven — Real-time updates via
DeviceEventEmitter - TypeScript — Full type definitions
- Configurable thresholds — Tune performance classification (low / average / high / excellent)
| Platform | Version / Notes |
|---|---|
| React Native CLI | 0.73+ |
| Expo (dev client) | SDK 50+ (not compatible with Expo Go) |
| Android | API 24+ (Android 7.0) |
| iOS | Not supported |
- minSdkVersion: 24
- compileSdkVersion: 35+
This library depends on a native Android SDK published to GitHub Packages. The Android build must have access to that Maven repository (see Installation).
npm install @lokal-dev/react-native-device-metrics
# or
yarn add @lokal-dev/react-native-device-metricsLinking is automatic. You still need to configure the GitHub Packages Maven repo so the Android dependency can be resolved.
Set these environment variables (token needs read:packages):
export GITHUB_USERNAME="your-github-username"
export GITHUB_TOKEN="your-github-personal-access-token"In your project’s project-level android/build.gradle:
allprojects {
repositories {
maven {
url = uri("https://maven.pkg.github.com/lokal-app/device-telemetry-toolkit")
credentials {
username = System.getenv("GITHUB_USERNAME") ?: ""
password = System.getenv("GITHUB_TOKEN") ?: ""
}
}
}
}Add the config plugin in app.json (it configures the Maven repo):
{
"expo": {
"plugins": ["@lokal-dev/react-native-device-metrics"]
}
}Then create a development build (Expo Go is not supported):
npx expo run:androidClasses (what you collect):
import { PerformanceClass } from '@lokal-dev/react-native-device-metrics';
PerformanceClass.CPU; // 0
PerformanceClass.MEMORY; // 1
PerformanceClass.STORAGE; // 2
PerformanceClass.NETWORK; // 3
PerformanceClass.BATTERY; // 4Levels (classification result):
import { PerformanceLevel } from '@lokal-dev/react-native-device-metrics';
PerformanceLevel.UNKNOWN; // 0
PerformanceLevel.LOW; // 1
PerformanceLevel.AVERAGE; // 2
PerformanceLevel.HIGH; // 3
PerformanceLevel.EXCELLENT;// 4Two independent flows; both can run at the same time. Only shutdown() stops everything.
| Raw collection | Detailed collection | |
|---|---|---|
| Data | Sensor/system values only | Raw + performanceLevel per class |
| Use case | Logging, custom logic | Ready-made performance assessment |
| Event | onRawPerformanceData |
onDetailedPerformanceData |
| Overhead | Lower | Slightly higher (includes classification) |
import * as DeviceMetrics from '@lokal-dev/react-native-device-metrics';
await DeviceMetrics.init();
// or with custom thresholds
await DeviceMetrics.init(customThresholds);// Start CPU + memory every 15s
await DeviceMetrics.startRawPerformanceDataCollection(
[DeviceMetrics.PerformanceClass.CPU, DeviceMetrics.PerformanceClass.MEMORY],
15
);
const subscription = DeviceMetrics.addRawPerformanceDataListener((data) => {
console.log('CPU cores:', data.cpu?.coreCount);
console.log('Available RAM:', data.memory?.availableRamGB, 'GB');
});
await DeviceMetrics.updateRawPerformanceDataCollection(10); // change interval
await DeviceMetrics.stopRawPerformanceDataCollection();
subscription.remove();await DeviceMetrics.startDetailedPerformanceDataCollection(
[DeviceMetrics.PerformanceClass.CPU, DeviceMetrics.PerformanceClass.MEMORY],
15
);
const subscription = DeviceMetrics.addDetailedPerformanceDataListener((data) => {
console.log('CPU level:', data.cpu?.performanceLevel);
console.log('Memory level:', data.memory?.performanceLevel);
});
await DeviceMetrics.stopDetailedPerformanceDataCollection();
subscription.remove();const results = await DeviceMetrics.getWeightedPerformanceLevels([
{ class: DeviceMetrics.PerformanceClass.CPU, weight: 2.0 },
{ class: DeviceMetrics.PerformanceClass.MEMORY, weight: 1.5 },
{ class: DeviceMetrics.PerformanceClass.NETWORK, weight: 1.0 },
]);
console.log('Overall:', results.overallPerformanceLevel);
console.log('CPU:', results.cpu, 'Memory:', results.memory);| Method | Description |
|---|---|
init(thresholds?) |
Initialize the SDK. Call before any other API. |
shutdown() |
Stop all flows and reset. Call init() again to reuse. |
| Method | Description |
|---|---|
startRawPerformanceDataCollection(classes, delaySeconds) |
Start periodic raw collection; emits onRawPerformanceData. |
updateRawPerformanceDataCollection(delaySeconds) |
Change interval; returns true if updated. |
stopRawPerformanceDataCollection() |
Stop raw collection only. |
getLatestRawPerformanceData() |
Last raw snapshot (parsed object, or null if none yet). |
addRawPerformanceDataListener(callback) |
Subscribe to raw events; returns EventSubscription. |
| Method | Description |
|---|---|
startDetailedPerformanceDataCollection(classes, delaySeconds) |
Start detailed collection; emits onDetailedPerformanceData. |
updateDetailedPerformanceDataCollection(delaySeconds) |
Change interval; returns true if updated. |
stopDetailedPerformanceDataCollection() |
Stop detailed collection only. |
getLatestDetailedPerformanceData() |
Last detailed snapshot (parsed object, or null if none yet). |
addDetailedPerformanceDataListener(callback) |
Subscribe to detailed events; returns EventSubscription. |
| Method | Description |
|---|---|
getWeightedPerformanceLevels(classesWithWeights) |
One-shot weighted assessment. Returns a parsed WeightedPerformanceLevels object (overall + per-class levels as strings). |
getPerformanceLevel(performanceClass) |
Current performance level for one class. Returns a number: 0 (UNKNOWN), 1 (LOW), 2 (AVERAGE), 3 (HIGH), 4 (EXCELLENT). |
Parameters
classes:number[]—PerformanceClassvalues (CPU=0, MEMORY=1, STORAGE=2, NETWORK=3, BATTERY=4). Only these are collected; others arenullin the result.delaySeconds:number— Interval in whole seconds (min 1).
Stop vs shutdown
stopRawPerformanceDataCollection()/stopDetailedPerformanceDataCollection()— Stop that flow only; SDK stays initialized.shutdown()— Stop all flows and tear down the SDK.
Pass a thresholds object into init() to customize how raw values map to performance levels (e.g. memory, battery, CPU). See the type definitions for the full shape; example for memory and battery:
const customThresholds = {
memory: {
low: { approxHeapRemainingInMBThreshold: 32, approxHeapLimitInMBThreshold: 64 },
average: { approxHeapRemainingInMBThreshold: 64, approxHeapLimitInMBThreshold: 128, availableRamGBThreshold: 1.5 },
high: { approxHeapRemainingInMBThreshold: 256, availableRamGBThreshold: 3 },
},
battery: {
excellent: { batteryPercentageThreshold: 80, isChargingBatteryPercentageThreshold: 70, temperatureThreshold: 30 },
high: { batteryPercentageThreshold: 55, isChargingBatteryPercentageThreshold: 50, temperatureThreshold: 34 },
average: { batteryPercentageThreshold: 40, isChargingBatteryPercentageThreshold: 35, temperatureThreshold: 38 },
},
// ... cpu, network, storage
};
await DeviceMetrics.init(customThresholds);| Use case | Interval (seconds) |
|---|---|
| Background monitoring | 15–30 |
| Active feature monitoring | 5–10 |
| Call/video monitoring | 2–5 |
- AGP / Kotlin version errors — Align Android Gradle Plugin and Kotlin versions with React Native 0.73+ (e.g. Kotlin 1.8.0+).
Cannot read property 'init' of undefined— Clean build and Metro cache:Reinstall deps if needed:cd android && ./gradlew clean && cd .. npx react-native start --reset-cache
rm -rf node_modules && npm install.- Collection never fires — Call
await DeviceMetrics.init()before anystart*method.
- Ensure you're logged in to npm:
npm login - Commit all changes, clean working tree.
- Build:
yarn prepare - Bump:
npm version patch(orminor/major) - Publish:
npm publish --access public - Push:
git push && git push --tags
yarn releaseThis bumps version, tags, publishes to npm, and can create a GitHub release (if configured).
- Fork the repo
- Create a branch (
git checkout -b feature/your-feature) - Commit (
git commit -m 'feat: your change') - Push (
git push origin feature/your-feature) - Open a Pull Request
See CONTRIBUTING.md and CODE_OF_CONDUCT.md.
MIT — see LICENSE.
- device-telemetry-toolkit — Native Android performance SDK used by this library.
Built by Lokal.