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

@voicenter-team/socketio-storage-logger

v2.0.8

Published

Logger that allows you to save logged information into your storage and emit stored logs via socket.io

Readme

socketio-storage-logger

socketio-storage-logger is a library that allows you to log data into storage and periodically emit stored logs to the server using socket.io-client or HTTP requests.

The library uses a storage worker pattern that provides a consistent interface for different storage backends. You must provide a storage worker appropriate for your environment - the library does not make assumptions about the runtime environment.

Features

  • Cross-platform - Works in browsers, Node.js, service workers, etc.
  • Flexible storage - Support for any storage backend via storage workers
  • Auto migration - Automatically recovers orphaned logs from previous sessions
  • Dual transport - Send logs via WebSocket or HTTP requests
  • Console overload - Optionally intercept global console methods
  • Log levels - Filter logs by severity level
  • TypeScript - Full TypeScript support with type definitions

Install with NPM

npm install @voicenter-team/socketio-storage-logger --save

Configuration Parameters

| Parameter | Description | |-----------------|---------------------------------------------------------------------------------------------------------| | socket | SocketIO connection / undefined default: undefined. Defines the initialized socket.io connection. | | url | string / undefined default: undefined. Defines the socket connection URL. | | requestUrl | string / undefined default: undefined. Defines the URL for HTTP log requests. | | socketOptions | object. Defines configuration options for socket.io connection. | | loggerOptions | LoggerOptions. Required. Defines the configuration options for logger. |

LoggerOptions Interface

| Parameter | Description | |-------------------------|--------------------------------------------------------------------------------------------| | logToConsole | boolean default: true. Whether logger should log data to console. | | overloadGlobalConsole | boolean default: false. Whether to overload global console methods. | | system | string Required. System identifier for storage keys. Must be unique across projects. | | socketEmitInterval | number default: 60000. Interval for sending logs in milliseconds. | | storageWorker | StorageWorkerConstructor Required. Storage worker class for your environment. | | loggerLevel | Level default: 'debug'. Minimum log level to process. | | staticObject | LoggerDataPartial. Static data included in every log. | | debugPrefix | string. Prefix for internal debug logs. |

Storage Workers

The library provides a LocalStorageWorker for browser environments. For other environments, you can create custom storage workers by extending BaseStorageWorker.

Available Storage Workers

  • LocalStorageWorker - For browser environments using localStorage

Usage

Basic Browser Usage

import StorageLogger, { LocalStorageWorker } from "@voicenter-team/socketio-storage-logger"

const logger = new StorageLogger({
    url: "https://your-server-domain.com",
    socketOptions: {
        reconnection: true,
        reconnectionDelay: 5000,
        reconnectionAttempts: 10,
        upgrade: false,
        transports: ['websocket'],
        debug: false
    },
    loggerOptions: {
        system: "my-web-app",
        storageWorker: LocalStorageWorker,
        logToConsole: true,
        overloadGlobalConsole: false,
        socketEmitInterval: 10000
    }
})

Using HTTP Requests Instead of WebSocket

import StorageLogger, { LocalStorageWorker } from "@voicenter-team/socketio-storage-logger"

const logger = new StorageLogger({
    requestUrl: "https://your-server-domain.com/api/logs",
    loggerOptions: {
        system: "my-web-app",
        storageWorker: LocalStorageWorker,
        logToConsole: true,
        socketEmitInterval: 30000
    }
})

Using Existing Socket Connection

import StorageLogger, { LocalStorageWorker } from "@voicenter-team/socketio-storage-logger"
import io from "socket.io-client"

const socket = io("https://your-server-domain.com", {
    reconnection: true,
    reconnectionDelay: 5000,
    reconnectionAttempts: 10,
    transports: ['websocket']
})

const logger = new StorageLogger({
    socket,
    loggerOptions: {
        system: "my-web-app",
        storageWorker: LocalStorageWorker,
        logToConsole: true,
        socketEmitInterval: 10000
    }
})

Logging Messages

// Log different severity levels
logger.log({ message: "User logged in", userId: 123 })
logger.warn({ message: "API rate limit approaching", requests: 95 })
logger.error({ message: "Database connection failed", error: "Timeout" })
logger.debug({ message: "Processing user data", step: "validation" })

Console Overloading

Enable console overloading to automatically capture all console calls:

const logger = new StorageLogger({
    url: "https://your-server-domain.com",
    loggerOptions: {
        system: "my-app",
        storageWorker: LocalStorageWorker,
        logToConsole: true,
        overloadGlobalConsole: true, // Enable console overloading
        socketEmitInterval: 10000
    }
})

// Now these console calls will be captured and sent to the server
console.log("This will be captured by the logger")
console.warn("This warning will be stored and sent") 
console.error("This error will be stored and sent")
console.debug("This debug info will be stored and sent")

// The original console behavior is preserved - logs still appear in browser console
// But they're also stored and sent to your server

Custom Storage Workers

Node.js File System Example

import StorageLogger, { BaseStorageWorker, DebugLogFunction } from "@voicenter-team/socketio-storage-logger"
import fs from 'fs/promises'
import path from 'path'

class FileSystemStorageWorker extends BaseStorageWorker {
    private logDir = './logs'

    constructor(debugLog: DebugLogFunction) {
        super(debugLog)
        this.ensureLogDir()
    }

    private async ensureLogDir() {
        try {
            await fs.mkdir(this.logDir, { recursive: true })
        } catch (error) {
            this.debugLog('Error creating log directory:', error)
        }
    }

    async getItem(key: string): Promise<string | null> {
        try {
            const filePath = path.join(this.logDir, `${key}.json`)
            const data = await fs.readFile(filePath, 'utf8')
            return data
        } catch (error: any) {
            if (error.code === 'ENOENT') return null
            throw error
        }
    }

    async setItem(key: string, value: string): Promise<void> {
        const filePath = path.join(this.logDir, `${key}.json`)
        await fs.writeFile(filePath, value, 'utf8')
    }

    async removeItem(key: string): Promise<void> {
        try {
            const filePath = path.join(this.logDir, `${key}.json`)
            await fs.unlink(filePath)
        } catch (error: any) {
            if (error.code !== 'ENOENT') throw error
        }
    }

    async getAllKeys(): Promise<string[]> {
        try {
            const files = await fs.readdir(this.logDir)
            return files
                .filter(file => file.endsWith('.json'))
                .map(file => file.replace('.json', ''))
        } catch (error) {
            return []
        }
    }
}

const logger = new StorageLogger({
    requestUrl: "https://your-server-domain.com/api/logs",
    loggerOptions: {
        system: "my-node-app",
        storageWorker: FileSystemStorageWorker,
        socketEmitInterval: 30000
    }
})

Chrome Extension Background Script

import StorageLogger, { BaseStorageWorker, DebugLogFunction } from "@voicenter-team/socketio-storage-logger"

class ChromeStorageWorker extends BaseStorageWorker {
    constructor(debugLog: DebugLogFunction) {
        super(debugLog)
    }

    async getItem(key: string): Promise<string | null> {
        this.debugLog(`[ChromeStorage] Getting item for key: ${key}`)
        
        const results = await chrome.storage.local.get(key)
        return results[key] || null
    }

    async setItem(key: string, value: string): Promise<void> {
        this.debugLog(`[ChromeStorage] Setting item for key: ${key}`)
        
        await chrome.storage.local.set({ [key]: value })
    }

    async removeItem(key: string): Promise<void> {
        this.debugLog(`[ChromeStorage] Removing item for key: ${key}`)
        
        await chrome.storage.local.remove(key)
    }

    async getAllKeys(): Promise<string[]> {
        this.debugLog('[ChromeStorage] Getting all keys')
        
        const allItems = await chrome.storage.local.get(null)
        return Object.keys(allItems)
    }
}

const logger = new StorageLogger({
    url: "https://your-server-domain.com",
    loggerOptions: {
        system: "my-extension",
        storageWorker: ChromeStorageWorker,
        logToConsole: true,
        socketEmitInterval: 10000
    }
})

Redis Storage Example

import StorageLogger, { BaseStorageWorker, DebugLogFunction } from "@voicenter-team/socketio-storage-logger"
import Redis from 'ioredis'

class RedisStorageWorker extends BaseStorageWorker {
    private redis: Redis

    constructor(debugLog: DebugLogFunction, redisUrl: string) {
        super(debugLog)
        this.redis = new Redis(redisUrl)
    }

    async getItem(key: string): Promise<string | null> {
        this.debugLog(`[Redis] Getting item for key: ${key}`)
        return await this.redis.get(key)
    }

    async setItem(key: string, value: string): Promise<void> {
        this.debugLog(`[Redis] Setting item for key: ${key}`)
        await this.redis.set(key, value)
    }

    async removeItem(key: string): Promise<void> {
        this.debugLog(`[Redis] Removing item for key: ${key}`)
        await this.redis.del(key)
    }

    async getAllKeys(): Promise<string[]> {
        this.debugLog('[Redis] Getting all keys')
        return await this.redis.keys('*')
    }
}

const logger = new StorageLogger({
    requestUrl: "https://your-server-domain.com/api/logs",
    loggerOptions: {
        system: "my-microservice",
        storageWorker: (debugLog) => new RedisStorageWorker(debugLog, 'redis://localhost:6379'),
        socketEmitInterval: 15000
    }
})

Advanced Features

Debug Logging

Enable internal debug logging to see what the logger is doing:

const logger = new StorageLogger({
    // ... configuration
    loggerOptions: {
        system: "my-app",
        storageWorker: LocalStorageWorker,
        debugPrefix: "MyApp" // Custom debug prefix
    }
})

// Enable debug logging
logger.toggleDebugLogging(true)

// Now you'll see internal debug messages in the console
logger.log({ message: "Test log" })

Log Levels

Control which logs are processed and sent to the server:

const logger = new StorageLogger({
    // ... configuration
    loggerOptions: {
        system: "my-app",
        storageWorker: LocalStorageWorker,
        loggerLevel: "warning" // Only warning and error logs will be sent
    }
})

// These will be ignored (below warning level)
logger.debug({ message: "Debug info" })  // Ignored
logger.log({ message: "Info message" })  // Ignored

// These will be processed and sent
logger.warn({ message: "Warning message" })  // Sent ✅
logger.error({ message: "Error occurred" })  // Sent ✅

// Change log level at runtime
logger.changeLogLevel("debug") // Now all logs will be sent

Static Fields

Add data that will be included in every log:

// Set static fields that appear in every log
logger.setupStaticFields({
    version: "1.2.3",
    environment: "production",
    userId: "user123"
})

// Update static fields
logger.updateStaticFields({
    sessionId: "session456"
})

// Now every log will include these fields
logger.log({ message: "Button clicked" })
// Sent log will include: version, environment, userId, sessionId + message

Manual Control

// Stop the logger (useful for cleanup)
await logger.stop()

// Restart the logger
await logger.start()

// Manually emit logs (force send now)
await logger.emitLogs()

// Reset storage (clear all stored logs)
await logger.resetStorage()

Migration & Recovery

The logger automatically handles log migration when the page refreshes or the application restarts. It will:

  1. Find old log storage keys from previous sessions
  2. Migrate all logs to the current session's storage
  3. Clean up old storage keys to prevent bloat
  4. Preserve original log structure for seamless processing

This ensures no logs are ever lost due to page refreshes or application restarts.

TypeScript Support

The library is written in TypeScript and provides full type definitions:

import StorageLogger, { 
    LocalStorageWorker, 
    BaseStorageWorker, 
    DebugLogFunction,
    LoggerOptions,
    ConfigOptions 
} from "@voicenter-team/socketio-storage-logger"

// Fully typed configuration
const config: ConfigOptions = {
    url: "https://example.com",
    loggerOptions: {
        system: "my-app",
        storageWorker: LocalStorageWorker,
        loggerLevel: "info"
    }
}

const logger = new StorageLogger(config)