Send React Native JS logs to Apple's Unified Logging System (os_log) and Android's Log, with subsystem/category support for easy filtering in Console.app, log CLI, and Quern.
React Native's default console.log output goes to stdout/stderr and gets mixed in with everything else. By routing logs through os_log (iOS) and android.util.Log (Android), you get:
- Subsystem & category filtering — find your app's logs instantly in Console.app or with
log stream --predicate - Log levels — debug, info, default, error, fault — with appropriate system behavior (persistence, throttling)
- Quern integration — logs appear in Quern's log viewer, filterable by your app's subsystem
- Native tooling — works with Instruments,
log collect, and any tool that reads the unified log
npm install @quern/react-native-os-logger
# or
yarn add @quern/react-native-os-loggercd ios && pod installNo additional setup needed.
import { patchConsole } from '@quern/react-native-os-logger';
// Call once at app startup — that's it
patchConsole('com.myapp');
// All console methods now route through os_log
console.log('This appears in Console.app'); // → OS_LOG_TYPE_DEFAULT
console.info('Info message'); // → OS_LOG_TYPE_INFO
console.debug('Debug message'); // → OS_LOG_TYPE_DEBUG
console.warn('Warning!'); // → OS_LOG_TYPE_ERROR
console.error('Something broke'); // → OS_LOG_TYPE_ERROROriginal console methods are preserved — logs still appear in Metro as usual.
import { configure, logInfo, logError } from '@quern/react-native-os-logger';
// Call once at app startup
configure('com.myapp', 'js');
logInfo('App started');
logError('Something went wrong');Each createLogger call creates a separate os_log_t (iOS) or Log tag (Android), so you can filter by category independently:
import { createLogger } from '@quern/react-native-os-logger';
const netLogger = createLogger('com.myapp', 'networking');
const uiLogger = createLogger('com.myapp', 'ui');
netLogger.info('GET /api/users → 200 OK');
netLogger.error('POST /api/login → 401');
uiLogger.debug('ProfileScreen rendered in 12ms');
uiLogger.info('User tapped "Save" button');Filter in Console.app:
# Just networking logs
log stream --predicate 'subsystem == "com.myapp" AND category == "networking"'| JS Method | iOS (os_log) |
Android (Log) |
Notes |
|---|---|---|---|
logDebug |
OS_LOG_TYPE_DEBUG |
Log.d |
Not persisted by default on iOS |
logInfo |
OS_LOG_TYPE_INFO |
Log.i |
Not persisted by default on iOS |
logDefault |
OS_LOG_TYPE_DEFAULT |
Log.i |
Persisted on iOS |
logError |
OS_LOG_TYPE_ERROR |
Log.e |
Persisted, captures caller info |
logFault |
OS_LOG_TYPE_FAULT |
Log.wtf |
Persisted, captures stack |
# Stream logs from your app's subsystem
log stream --predicate 'subsystem == "com.myapp"'
# Filter by category
log stream --predicate 'subsystem == "com.myapp" AND category == "networking"'Configure the logger with a reverse-DNS subsystem identifier and a category. Call once at startup.
Creates a new logger with its own os_log_t (iOS) / Log tag (Android). Returns an object with default, info, debug, error, fault, and log methods. Multiple loggers can coexist with different categories.
Patches console.log/info/debug/warn/error to route through os_log. Original methods are preserved. Category defaults to "console". Call once at startup.
- React Native 0.76+ (New Architecture / TurboModules)
- iOS 13+
- Android API 21+
MIT