A React TypeScript library for logging UI interactions and events
npm install dynamic-ui-loggerbash
Using npm
npm install dynamic-ui-logger
Using yarn
yarn add dynamic-ui-logger
Using pnpm
pnpm add dynamic-ui-logger
`
$3
Ensure you have React 17 or 18 installed:
`bash
npm install react react-dom
`
---
π Quick Start
$3
First, create a custom logger configuration file:
`typescript
// logger.ts
import { useUILogger } from 'dynamic-ui-logger';
const getLogger = () => {
return useUILogger({
apiUrl: 'https://your-logging-api.com/logs',
maxLogSize: 50, // Buffer size before auto-flush
idleTime: 30000, // 30 seconds idle timeout
sendDebugLogToApi: true, // Enable debug log sending
sendErrorLogToApi: true, // Enable error log sending
});
};
export default getLogger;
`
$3
`tsx
// App.tsx
import React, { useState } from 'react';
import getLogger from './logger';
const App: React.FC = () => {
const { log, error, flush } = getLogger();
const [counter, setCounter] = useState(0);
const handleClick = () => {
setCounter(prev => prev + 1);
log(Button clicked - Counter: ${counter + 1});
};
const handleError = () => {
try {
throw new Error('Something went wrong!');
} catch (err) {
error(err as Error);
}
};
return (
);
};
export default App;
`
---
βοΈ Configuration Options
The useUILogger hook accepts a configuration object with the following options:
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| apiUrl | string | '' | The endpoint URL where logs will be sent |
| apiHeader | Record | {} | Custom headers to include with API requests |
| maxLogSize | number | 20 | Maximum number of logs to buffer before auto-flush |
| idleTime | number | 30000 | Milliseconds of user inactivity before auto-flush (default: 30s) |
| sendDebugLogToApi | boolean | false | Whether to send debug logs to the API on flush |
| sendErrorLogToApi | boolean | false | Whether to immediately send error logs to the API |
| enableTimestamps | boolean | true | Include timestamps in log entries |
| autoCaptureEvents | boolean | false | Enable automatic UI event capturing (errors, rejections) |
| autoCaptureAPI | boolean | false | Enable automatic API call interception for error context |
$3
`typescript
const logger = useUILogger({
apiUrl: 'https://api.yourservice.com/v1/logs',
apiHeader: {
'Authorization': 'Bearer your-api-token',
'X-App-Version': '1.0.0',
},
maxLogSize: 100,
idleTime: 60000, // 1 minute
sendDebugLogToApi: true,
sendErrorLogToApi: true,
});
`
---
π API Reference
$3
Creates and returns a logger instance. The instance is a singleton - multiple calls return the same instance.
#### Returns: UILoggerInstance
| Method | Signature | Description |
|--------|-----------|-------------|
| log | (message: string) => void | Log a debug/info message |
| error | (error: string \| Error) => void | Log an error message or Error object |
| flush | () => void | Manually flush all buffered logs to the API |
---
ποΈ Architecture
$3
`
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Main Thread β
β ββββββββββββββββ βββββββββββββββββββ ββββββββββββββββ β
β β Your React βββββΆβ useUILogger βββββΆβ postMessage β β
β β Components β β Hook β β to Worker β β
β ββββββββββββββββ βββββββββββββββββββ ββββββββββββββββ β
β β β β
β βΌ β β
β βββββββββββββββββββ β β
β β Idle Timer β β β
β β Detection β β β
β βββββββββββββββββββ β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Web Worker Thread β
β ββββββββββββββββ βββββββββββββββββββ ββββββββββββββββ β
β β Log Buffer βββββΆβ Log Processing βββββΆβ API Fetch β β
β β (In-Memory) β β & Formatting β β Request β β
β ββββββββββββββββ βββββββββββββββββββ ββββββββββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
`
$3
1. Main Thread (logger.ts)
- Provides the useUILogger hook for React components
- Integrates with react-idle-timer for activity detection
- Registers global error handlers
- Communicates with the Web Worker via postMessage
2. Web Worker (log.worker.ts)
- Runs in a separate thread for non-blocking operation
- Maintains an in-memory log buffer
- Handles log batching and API submission
- Supports different log types: log, error, and flush
3. Idle Detection
- Uses react-idle-timer to detect user inactivity
- Automatically flushes logs when the user becomes idle
- Resets the timer on each new log entry
---
π Global Error Handling
Dynamic UI Logger automatically captures:
- Unhandled Errors: JavaScript errors that bubble up to the window level
- Unhandled Promise Rejections: Promises that reject without a .catch() handler
- API Context: If autoCaptureAPI is enabled, the last intercepted API call (fetch or XHR) is included in the error log for better debugging context.
`typescript
// Enable auto-capture in config
const logger = useUILogger({
autoCaptureEvents: true,
autoCaptureAPI: true,
// ...
});
// Automatically captured with context!
throw new Error('Uncaught error');
`
---
π§ API Payload Format
When logs are flushed to your API, they are sent in the following format:
Standard Log:
`json
{
"header": {
"action": "auditClientLogs",
"corrId": "auditClientLogs-1705927385123",
// ...your custom headers
},
"logs": "[\"Log message 1\", \"Log message 2\"]",
"timestamp": 1705927385123
}
`
Error Log (with API Context):
`json
{
"header": { ... },
"logs": "[{ \"error\": \"Failed to fetch data\", \"stack\": \"...\", \"lastApiCall\": { \"url\": \"/api/data\", \"method\": \"GET\", \"status\": 500, \"timestamp\": ... } }]",
"timestamp": 1705927385123
}
`
---
π Development vs Production
Dynamic UI Logger automatically detects the environment:
| Environment | Behavior |
|-------------|----------|
| Development (localhost) | Logs are printed to console only, no API calls |
| Production | Logs are buffered and sent to the configured API endpoint |
---
π TypeScript Types
`typescript
// Configuration interface
export interface UILoggerConfig {
maxLogSize?: number; // Buffer size limit
enableTimestamps?: boolean; // Enable timestamps
autoCaptureEvents?: boolean; // Auto-capture UI events
autoCaptureAPI?: boolean; // Auto-capture API calls
apiUrl?: string; // API endpoint URL
apiHeader?: Record; // Custom headers
idleTime?: number; // Idle timeout (ms)
sendDebugLogToApi?: boolean; // Send debug logs
sendErrorLogToApi?: boolean; // Send error logs
}
// API Log Entry (captured context)
export interface APILogEntry {
url: string;
method: string;
status?: number;
timestamp: number;
payload?: any;
response?: any;
}
// Logger instance interface
export interface UILoggerInstance {
log: (log: string) => void;
error: (error: string | Error) => void;
flush: () => void;
}
// Log entry structure
export interface UILogEntry {
id: string;
timestamp: number;
type: 'click' | 'input' | 'navigation' | 'custom';
target?: string;
value?: string | number | boolean;
metadata?: Record;
}
`
---
π§ͺ Example Project
The repository includes a complete example application demonstrating all features:
`bash
Clone the repository
git clone https://github.com/your-username/dynamic-ui-logger.git
Navigate to the project
cd dynamic-ui-logger
Install dependencies
npm install
Run the development server
npm run dev
`
$3
- β
Logging button clicks
- β
Logging input changes
- β
Logging navigation events
- β
Error handling (try/catch and custom errors)
- β
Manual log flushing
- β
Idle detection
---
π Scripts
| Script | Description |
|--------|-------------|
| npm run dev | Start development server |
| npm run build | Build the library for production |
| npm run type-check | Run TypeScript type checking |
---
π¦ Publishing to npm
`bash
Build the package
npm run build
Login to npm (if not already logged in)
npm login
Publish the package
npm publish
`
---
π€ Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
1. Fork the repository
2. Create your feature branch (git checkout -b feature/AmazingFeature)
3. Commit your changes (git commit -m 'Add some AmazingFeature')
4. Push to the branch (git push origin feature/AmazingFeature`)