npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dynamic-ui-logger

v1.1.1

Published

A React TypeScript library for logging UI interactions and events

Downloads

24

Readme

🚀 Dynamic UI Logger

npm version License: MIT TypeScript

A lightweight, high-performance React TypeScript library for logging UI interactions and events in your applications. Dynamic UI Logger uses Web Workers for non-blocking log processing and features intelligent idle detection for automatic log flushing.


✨ Features

| Feature | Description | |---------|-------------| | 🔄 Web Worker Processing | Log processing happens in a separate thread, ensuring zero UI blocking | | ⏰ Idle Detection | Automatically flushes logs after configurable periods of user inactivity | | �️ Global Error Capture | Automatically captures unhandled errors and promise rejections | | � API Integration | Seamlessly send logs to your backend with customizable headers | | 📝 TypeScript First | Full TypeScript support with complete type definitions | | ⚡ Lightweight | Minimal footprint with only essential dependencies | | 🔧 Configurable | Extensive configuration options to fit your needs | | 🧪 Dev Mode Support | Console logging in development, API logging in production |


📦 Installation

# Using npm
npm install dynamic-ui-logger

# Using yarn
yarn add dynamic-ui-logger

# Using pnpm
pnpm add dynamic-ui-logger

Peer Dependencies

Ensure you have React 17 or 18 installed:

npm install react react-dom

🚀 Quick Start

1. Create a Logger Instance

First, create a custom logger configuration file:

// 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;

2. Use in Your Components

// 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 (
        <div>
            <button onClick={handleClick}>
                Click Me ({counter})
            </button>
            <button onClick={handleError}>
                Trigger Error
            </button>
            <button onClick={flush}>
                Flush Logs Now
            </button>
        </div>
    );
};

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<string, string> | {} | 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 |

Example Configuration

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

useUILogger(config: UILoggerConfig): UILoggerInstance

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

How It Works

┌────────────────────────────────────────────────────────────────┐
│                        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    │  │
│  └──────────────┘    └─────────────────┘    └──────────────┘  │
└────────────────────────────────────────────────────────────────┘

Key Components

  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.
// 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:

{
    "header": {
        "action": "auditClientLogs",
        "corrId": "auditClientLogs-1705927385123",
        // ...your custom headers
    },
    "logs": "[\"Log message 1\", \"Log message 2\"]",
    "timestamp": 1705927385123
}

Error Log (with API Context):

{
    "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

// 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<string, string>;  // 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<string, any>;
}

🧪 Example Project

The repository includes a complete example application demonstrating all features:

# 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

Example Features Demonstrated

  • ✅ 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

# 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)
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.


👨‍💻 Author

Subhasis Bhattacharya


🙏 Acknowledgments