Package Exports
- rn-structured-logger
Readme
RN Structured Logger
📚 For detailed guides, API reference, and examples, visit our documentation site.
📦 NPM Package: https://www.npmjs.com/package/rn-structured-logger
An enterprise-grade logging library for React Native, Expo, and cross-platform JavaScript applications. It provides structured logs, namespaces, context injection, batching, rate limiting, and redaction out of the box. Logs are batched and flushed asynchronously to reduce impact on the UI thread and can be persisted locally or forwarded to remote services such as Sentry.
Table of Contents
- Features
- Platform Compatibility
- Installation
- Quick Start
- Usage
- Transports
- Configuration Options
- Documentation
- Examples
- Troubleshooting
- Contributing
- License
Features
- Structured log records: Each entry includes a timestamp, level, message, namespace, and arbitrary context.
- Pluggable transports: Send logs to the JavaScript console, persist them to the local filesystem (with rotation), or forward them to Sentry or your own HTTP endpoint. Multiple transports can run concurrently.
- Namespaces (child loggers): Create scoped loggers (e.g.,
auth:login
) to filter or group logs. - Context injection: Attach correlation IDs, user identifiers, device metadata, or any other static information to every log record.
- Redaction: Mask sensitive properties (password, token, etc.) before they leave the device. You can specify additional keys to redact.
- Rate limiting and sampling: Protect your backend and devices by limiting the number of logs per minute and sampling non-error logs at configurable rates.
- Batching and asynchronous flushing: Logs are buffered and written in batches on a background queue, minimizing UI thread impact. You control the batch size and flush interval.
- Conditional logging: Dynamically adjust severity levels at runtime (e.g., verbose debugging in development, minimal logging in production).
- Console patching (optional): Redirect
console.log
,warn
,error
, andinfo
through your logger so all third-party libraries follow your policies. - TypeScript types: First-class TypeScript support with strict typings.
Platform Compatibility
This library is designed for cross-platform React Native and Expo applications:
- iOS & Android: Full functionality including file system logging via
react-native-fs
. - Web (Expo): Console logging with full structured logging features (timestamps, levels, context, redaction).
- macOS & Windows: Console logging only (file system access not supported).
The logger automatically adapts to the platform - on web, it uses only the ConsoleTransport, while on native platforms, it can include file logging.
Installation
npm install rn-structured-logger
# or
yarn add rn-structured-logger
Peer Dependencies
You must install the following peer dependencies if you intend to use the corresponding transports:
# For file logging on native platforms
npm install react-native-fs
# For Sentry integration
npm install @sentry/react-native
# For Expo device info (optional, for enhanced device context)
npm install expo-device
These are declared as peer dependencies so your project controls their versions.
Quick Start
import { initLogger, getLogger, ConsoleTransport } from 'rn-structured-logger';
// Initialize the logger
initLogger({
level: 'info',
transports: [ConsoleTransport],
});
// Get a logger and start logging
const logger = getLogger('app');
logger.info('App started successfully');
Usage
Setup
Initialize the logger once, typically during app bootstrap. Provide transports appropriate to your environment and inject static device information.
import { initLogger, ConsoleTransport, FileTransport, SentryTransport, makeRedactor } from 'rn-structured-logger';
import * as Device from 'expo-device'; // or react-native-device-info
// Gather static device/app info
const device = {
platform: Platform.OS,
appVersion: '1.0.0',
deviceModel: Device.modelName || 'unknown',
osVersion: Device.osVersion || 'unknown',
};
initLogger({
level: __DEV__ ? 'debug' : 'info',
transports: __DEV__
? [ConsoleTransport]
: [ConsoleTransport, FileTransport({ fileName: 'app.log', maxBytes: 1024 * 1024 }), SentryTransport()],
redactor: makeRedactor(['password', 'token', 'email', 'phone']),
sampling: { rate: __DEV__ ? 1 : 0.1 },
rateLimit: { maxPerMin: 300 },
batch: { size: 50, intervalMs: 2000 },
device,
patchConsole: true,
});
Logging Events
Retrieve a logger via getLogger()
and use its methods:
import { getLogger } from 'rn-structured-logger';
const logger = getLogger('auth:login');
logger.debug('Attempting login', { username: 'alice@example.com' });
try {
const result = await login(credentials);
logger.info('Login successful', { userId: result.id });
} catch (error) {
logger.error('Login failed', { error: error.message });
}
Namespaces
Create scoped loggers for different parts of your application:
const authLogger = getLogger('auth');
const apiLogger = getLogger('api');
const uiLogger = getLogger('ui');
authLogger.info('User authentication flow started');
apiLogger.debug('API request to /user/profile');
uiLogger.warn('UI component failed to render');
Context and Correlation IDs
Attach context to all logs in a session or request:
const logger = getLogger();
// Set correlation ID for an entire flow
logger.setCorrelationId('req-9b2c1d4e');
// All subsequent logs will include this correlation ID
logger.info('Processing request', { action: 'validate' });
Redaction
Automatically mask sensitive data:
const logger = getLogger();
logger.info('User registration', {
username: 'john_doe',
password: 'secret123', // Will be redacted to [REDACTED]
email: 'john@example.com', // Will be redacted
age: 25, // Not redacted
});
Rate Limiting and Sampling
Control log volume:
initLogger({
// Sample 10% of non-error logs in production
sampling: { rate: 0.1 },
// Limit to 300 logs per minute
rateLimit: { maxPerMin: 300 },
});
Flushing and Disposing
Flush pending logs or clean up resources:
import { getLogger } from 'rn-structured-logger';
const logger = getLogger();
// Flush queued records
await logger.flush();
// Flush and dispose transports (e.g., on app exit)
await logger.dispose();
Transports
ConsoleTransport
Writes logs to the console. The message includes an ISO date, namespace, and level.
import { ConsoleTransport } from 'rn-structured-logger';
initLogger({
transports: [ConsoleTransport],
});
FileTransport
Writes logs to a file using react-native-fs
. Supports rotation when the file exceeds a size threshold.
import { FileTransport } from 'rn-structured-logger';
initLogger({
transports: [
FileTransport({
fileName: 'app.log',
maxBytes: 1024 * 1024, // 1MB
}),
],
});
SentryTransport
Sends error and fatal logs to Sentry.
import { SentryTransport } from 'rn-structured-logger';
initLogger({
transports: [SentryTransport()],
});
HttpTransport
Sends logs to a custom HTTP endpoint.
import { HttpTransport } from 'rn-structured-logger';
initLogger({
transports: [
HttpTransport({
url: 'https://your-logging-endpoint.com/logs',
headers: { Authorization: 'Bearer your-token' },
}),
],
});
Custom Transports
Implement your own transport:
const customTransport = {
name: 'CustomTransport',
write: (records: LogRecord[]) => {
// Send logs to your custom destination
console.log('Custom transport received:', records);
},
flush: async () => {
// Optional: flush any buffered data
},
dispose: async () => {
// Optional: clean up resources
},
};
initLogger({
transports: [customTransport],
});
Configuration Options
LoggerConfig
interface LoggerConfig {
level?: LogLevel; // 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal'
transports?: Transport[];
redactor?: Redactor;
sampling?: { rate: number }; // 0.0 to 1.0
rateLimit?: { maxPerMin: number };
batch?: { size: number; intervalMs: number };
device?: Record<string, unknown>;
patchConsole?: boolean;
}
Documentation
Full documentation for this project is hosted as a Docusaurus site and can be found at:
Use the documentation site for API details, guides, and examples.
Examples
Expo App with File Logging
import { initLogger, ConsoleTransport, FileTransport, makeRedactor } from 'rn-structured-logger';
import * as Device from 'expo-device';
import { Platform } from 'react-native';
const device = {
platform: Platform.OS,
model: Device.modelName,
osVersion: Device.osVersion,
};
initLogger({
level: 'info',
transports: Platform.OS === 'web' ? [ConsoleTransport] : [ConsoleTransport, FileTransport({ fileName: 'expo-app.log' })],
redactor: makeRedactor(['password', 'token']),
device,
});
Production Setup with Sentry
import { initLogger, ConsoleTransport, SentryTransport, makeRedactor } from 'rn-structured-logger';
initLogger({
level: 'warn',
transports: [ConsoleTransport, SentryTransport()],
redactor: makeRedactor(['password', 'token', 'email', 'ssn']),
sampling: { rate: 0.1 },
rateLimit: { maxPerMin: 100 },
batch: { size: 20, intervalMs: 5000 },
});
Troubleshooting
Module Resolution Errors
If you encounter "Cannot find module 'rn-structured-logger'", ensure the package is installed and the local path is correct for development.
File Transport Not Working
- Ensure
react-native-fs
is installed and linked. - Check file permissions on the device.
- Verify the file path is writable.
Console Patching Issues
If patchConsole
causes issues with other libraries, set it to false
and manually use the logger.
Performance Issues
- Increase batch size or interval to reduce I/O.
- Use sampling in production to reduce log volume.
- Avoid logging large objects or frequent debug logs.
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Run
npm test
- Submit a pull request
License
Apache License 2.0
Documentation
- 📚 API Documentation - Generated TypeDoc documentation for all classes, interfaces, and functions.
- Demo App - Bare React Native demo application showcasing the library features.