Skip to content

Logger System - @xcons/common

The XCons Common Package logger system provides comprehensive logging capabilities with package-based logging control and global configuration support.

🚀 Quick Start

html
<!DOCTYPE html>
<html>
<head>
    <title>My Application</title>
    
    <!-- STEP 1: Define global configuration BEFORE loading the package -->
    <script>
        window.__XCONS_LOGGER_CONFIG__ = {
            '@xcons/widget': {
                enabled: true,
                level: 3,  // DEBUG level (0=ERROR, 1=WARN, 2=INFO, 3=DEBUG, 4=TRACE)
                prefix: 'WIDGET',
                timestamp: true,
                colors: true
            },
            '@xcons/grid': {
                enabled: true,
                level: 2  // INFO level
            },
            '@xcons/datasource': {
                enabled: false  // Completely disabled
            }
        };
    </script>
    
    <!-- STEP 2: Load the package -->
    <script src="https://unpkg.com/@xcons/common@latest/core.js"></script>
</head>
<body>
    <script>
        // STEP 3: Use the logger
        const { logger, ComponentLogLevel } = XConsCommon;
        
        const myLogger = logger.createChild(
            '@xcons/widget',
            'COMPONENT-NAME',
            ComponentLogLevel.BASIC
        );
        
        myLogger.info('Application started!');
        myLogger.debug('Debug information');
    </script>
</body>
</html>

Usage with NPM/Node.js

bash
npm install @xcons/common
javascript
import { logger, LoggerRegistry, LoggerLogLevel } from '@xcons/common';

// Package logging configuration
LoggerRegistry.registerPackage('@xcons/widget', {
    enabled: true,
    level: LoggerLogLevel.DEBUG
});

// Create and use logger
const widgetLogger = logger.createChild('@xcons/widget', 'CORE');
widgetLogger.info('Widget initialized!');

✨ Key Features

  • 🌍 Global Configuration - Set logging rules before code loads
  • 🔒 Protected Settings - Global configuration cannot be overwritten (unless force: true)
  • 📦 Package-based Control - Enable/disable logging per package
  • 🎯 TypeScript - Full TypeScript support
  • 🚀 Universal - Works in Browser and Node.js
  • 🔧 Child Loggers - Component-specific logging with namespace
  • Lightweight - Minimal dependencies
  • 🎨 Configurable - Log levels and settings per package

🔧 Global Configuration (Priority System)

⚠️ Priority Rules

CRITICAL: Global configuration ALWAYS has the highest priority!

Priority Order (Highest to Lowest):
1. ✅ Global config (window.__XCONS_LOGGER_CONFIG__) - CANNOT BE OVERWRITTEN
2. ✅ Package registration - Merged with global config
3. ✅ Runtime updates - Cannot change global (unless force: true)

Setting Global Configuration

Method 1: HTML (Before Package Load)

html
<!DOCTYPE html>
<html>
<head>
    <!-- Define BEFORE @xcons/common loads -->
    <script>
        window.__XCONS_LOGGER_CONFIG__ = {
            '@xcons/widget': {
                enabled: true,
                level: 3,        // DEBUG (0=ERROR, 1=WARN, 2=INFO, 3=DEBUG, 4=TRACE)
                prefix: 'WIDGET',
                timestamp: true,
                colors: true
            },
            '@xcons/grid': {
                enabled: true,
                level: 2         // INFO
            },
            '@xcons/datasource': {
                enabled: false   // Completely disabled
            }
        };
    </script>
    
    <!-- Now load the package -->
    <script src="https://unpkg.com/@xcons/common@latest/core.js"></script>
</head>

Method 2: Programmatic (Runtime)

javascript
import { LoggerRegistry, LoggerLogLevel } from '@xcons/common';

// Set global configuration
LoggerRegistry.setGlobalConfig({
    '@xcons/widget': {
        enabled: true,
        level: LoggerLogLevel.DEBUG,
        prefix: 'WIDGET'
    },
    '@xcons/grid': {
        enabled: false
    }
});

// This automatically reloads and applies to all packages

Log Levels Reference

javascript
LoggerLogLevel.ERROR   // 0 - Errors only
LoggerLogLevel.WARN    // 1 - Errors + warnings
LoggerLogLevel.INFO    // 2 - Errors + warnings + info
LoggerLogLevel.DEBUG   // 3 - All of the above + debug
LoggerLogLevel.TRACE   // 4 - Most detailed logs

Configuration Options

typescript
interface LoggerConfig {
    enabled: boolean;      // Enable/disable logging
    level: LoggerLogLevel; // Minimum log level (0-4)
    prefix: string;        // Log prefix (e.g., 'WIDGET')
    timestamp: boolean;    // Show timestamp
    colors: boolean;       // Enable colored output
}

📦 Package-based Logging

Registering Packages

javascript
import { LoggerRegistry, LoggerLogLevel } from '@xcons/common';

// Enable detailed logging for widgets
LoggerRegistry.registerPackage('@xcons/widget', {
    enabled: true,
    level: LoggerLogLevel.DEBUG,
    prefix: 'WIDGET'
});

// Disable grid logging in production
LoggerRegistry.registerPackage('@xcons/grid', {
    enabled: false,
    level: LoggerLogLevel.ERROR
});

// Only errors and warnings for datasource
LoggerRegistry.registerPackage('@xcons/datasource', {
    enabled: true,
    level: LoggerLogLevel.WARN
});

Using Package Loggers

javascript
import { logger, ComponentLogLevel } from '@xcons/common';

// Create logger for @xcons/widget package
const widgetLogger = logger.createChild(
    '@xcons/widget',              // package namespace
    'WIDGET-DECORATOR',           // component name
    ComponentLogLevel.DETAILED    // component log level
);

// Logs respect package configuration
widgetLogger.info('Widget created');
widgetLogger.debug('Configuration loaded', { config });
widgetLogger.trace('Detailed trace'); // Only at DETAILED level

Dynamic Configuration

javascript
// Standard update (respects global config)
LoggerRegistry.updatePackage('@xcons/grid', {
    enabled: true,
    level: LoggerLogLevel.INFO
});
// ⚠️ If global config exists, it will be preserved

// Force update (override global config)
LoggerRegistry.updatePackage('@xcons/grid', {
    enabled: true,
    level: LoggerLogLevel.INFO
}, true);  // force=true
// ✅ This overrides global config

// Check if package has global protection
if (LoggerRegistry.hasGlobalConfig('@xcons/widget')) {
    console.log('Widget is protected by global config');
}

// Get global config for specific package
const globalConfig = LoggerRegistry.getGlobalPackageConfig('@xcons/widget');

// Clear global protection
LoggerRegistry.clearGlobalConfig('@xcons/widget');
// Now package can be freely configured

// Check registration
if (LoggerRegistry.hasPackage('@xcons/widget')) {
    console.log('Widget package is registered');
}

// Get package config
const config = LoggerRegistry.getPackageConfig('@xcons/widget');

// List all packages
const packages = LoggerRegistry.getRegisteredPackages();

// Get all configs
const allConfigs = LoggerRegistry.getAllConfigs();

🎯 Basic Usage

Simple Logging

javascript
import { logger } from '@xcons/common';

logger.info('Application started');
logger.warn('Warning message');
logger.error('Error occurred', error);
logger.debug('Debug data', { userId: 123 });

Child Loggers

javascript
// Without package (uses parent config)
const simpleLogger = logger.createChild('ComponentName');

// With package namespace
const packageLogger = logger.createChild('@xcons/widget', 'CORE');

// With component log level
const detailedLogger = logger.createChild(
    '@xcons/widget',
    'UI',
    ComponentLogLevel.DETAILED
);

Component Log Levels

javascript
import { ComponentLogLevel } from '@xcons/common';

ComponentLogLevel.OFF       // 0 - No component logging
ComponentLogLevel.BASIC     // 1 - Basic component logs
ComponentLogLevel.DETAILED  // 2 - Detailed component logs

🔥 Advanced Features

Performance Timing

javascript
const perfLogger = logger.createChild('@xcons/widget', 'PERF');

perfLogger.time('render');
// ... render logic
perfLogger.timeEnd('render'); // Logs: [@xcons/widget:PERF] render: 45.2ms

Table Logging

javascript
const dataLogger = logger.createChild('@xcons/datasource', 'LOADER');

dataLogger.table([
    { id: 1, name: 'Item A', status: 'active' },
    { id: 2, name: 'Item B', status: 'inactive' }
]);

Grouped Logging

javascript
const widgetLogger = logger.createChild('@xcons/widget', 'MANAGER');

widgetLogger.group('Widget Initialization');
widgetLogger.info('Loading configuration');
widgetLogger.debug('Parsing options');
widgetLogger.groupEnd();

🌍 Environment Setup

Development Environment

javascript
import { LoggerRegistry, LoggerLogLevel } from '@xcons/common';

// Development - detailed logging
LoggerRegistry.registerPackage('@xcons/widget', {
    enabled: true,
    level: LoggerLogLevel.TRACE,
    colors: true,
    timestamp: true
});

LoggerRegistry.registerPackage('@xcons/grid', {
    enabled: true,
    level: LoggerLogLevel.DEBUG
});

Production Environment

javascript
// Production - minimal logging
LoggerRegistry.registerPackage('@xcons/widget', {
    enabled: true,
    level: LoggerLogLevel.WARN,  // Only warnings and errors
    colors: false
});

LoggerRegistry.registerPackage('@xcons/grid', {
    enabled: false  // Completely disabled
});

Environment-based Configuration

html
<script>
    // Environment detection
    const isDev = window.location.hostname === 'localhost' || 
                  window.location.hostname === '127.0.0.1';
    
    // Configure based on environment
    window.__XCONS_LOGGER_CONFIG__ = isDev ? {
        // Development settings
        '@xcons/widget': { enabled: true, level: 3 },
        '@xcons/grid': { enabled: true, level: 3 },
        '@xcons/datasource': { enabled: true, level: 3 }
    } : {
        // Production settings
        '@xcons/widget': { enabled: true, level: 1 },
        '@xcons/grid': { enabled: false, level: 0 },
        '@xcons/datasource': { enabled: false, level: 0 }
    };
</script>

💼 Real World Example

javascript
import { 
    logger, 
    LoggerRegistry, 
    LoggerLogLevel,
    ComponentLogLevel 
} from '@xcons/common';

// Register package with global config
LoggerRegistry.registerPackage('@xcons/widget', {
    enabled: true,
    level: LoggerLogLevel.DEBUG
});

// Widget class with package logger
export class Widget {
    private logger = logger.createChild(
        '@xcons/widget',
        'WIDGET-CORE',
        ComponentLogLevel.BASIC
    );

    constructor(private id: string) {
        this.logger.info('Widget created', { id });
    }

    async initialize() {
        this.logger.debug('Initializing widget');
        
        this.logger.time('init');
        try {
            await this.loadConfig();
            await this.setupUI();
            this.logger.info('Widget ready');
        } catch (error) {
            this.logger.error('Initialization failed', error);
            throw error;
        } finally {
            this.logger.timeEnd('init');
        }
    }

    private async loadConfig() {
        this.logger.debug('Loading configuration');
        // Config loading logic
    }

    private async setupUI() {
        this.logger.debug('Setting up UI');
        // UI setup logic
    }
}

// Usage
const widget = new Widget('widget-1');
await widget.initialize();

🔍 Debug and Global Access

Browser Console

javascript
// Access logger registry
window.__XCONS_LOGGER_REGISTRY__

// Display all package configs
LoggerRegistry.getAllConfigs()

// Display global config
LoggerRegistry.getGlobalConfigSnapshot()

// Enable package instantly (if not protected)
LoggerRegistry.updatePackage('@xcons/grid', { 
    enabled: true,
    level: 3 
})

// Force enable (override global config)
LoggerRegistry.updatePackage('@xcons/grid', { 
    enabled: true,
    level: 3 
}, true)

// List registered packages
LoggerRegistry.getRegisteredPackages()

// Check global protection
LoggerRegistry.hasGlobalConfig('@xcons/widget')

// Clear global protection
LoggerRegistry.clearGlobalConfig('@xcons/widget')

Node.js

javascript
// Access global logger
global.__XCONS_LOGGER_REGISTRY__

📚 Complete HTML Example

html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>XCons Common - Complete Example</title>
    
    <!-- STEP 1: Global Configuration -->
    <script>
        // Environment detection
        const isDev = location.hostname === 'localhost';
        
        // Global logger configuration
        window.__XCONS_LOGGER_CONFIG__ = {
            '@xcons/widget': {
                enabled: true,
                level: isDev ? 3 : 1,  // DEBUG in dev, WARN in prod
                prefix: 'WIDGET',
                timestamp: true,
                colors: true
            },
            '@xcons/grid': {
                enabled: isDev,  // Only in development
                level: 3,
                prefix: 'GRID'
            },
            '@xcons/datasource': {
                enabled: true,
                level: 2,  // INFO level
                prefix: 'DS'
            }
        };
    </script>
    
    <!-- STEP 2: Load Package -->
    <script src="https://unpkg.com/@xcons/common@latest/core.js"></script>
</head>
<body>
    <h1>XCons Common Logger Example</h1>
    <button onclick="testLogs()">Test Logs</button>
    <button onclick="showConfigs()">Show Configs</button>
    
    <script>
        // STEP 3: Import and Usage
        const { 
            logger, 
            LoggerRegistry,
            LoggerLogLevel,
            ComponentLogLevel 
        } = XConsCommon;
        
        // Create loggers for different packages
        const widgetLogger = logger.createChild(
            '@xcons/widget',
            'UI-COMPONENT',
            ComponentLogLevel.BASIC
        );
        
        const gridLogger = logger.createChild(
            '@xcons/grid',
            'DATA-GRID',
            ComponentLogLevel.DETAILED
        );
        
        const dsLogger = logger.createChild(
            '@xcons/datasource',
            'API-CLIENT'
        );
        
        // Test function
        function testLogs() {
            console.clear();
            
            // Widget logs (level: WARN in prod, DEBUG in dev)
            widgetLogger.error('Widget error message');
            widgetLogger.warn('Widget warning message');
            widgetLogger.info('Widget info message');
            widgetLogger.debug('Widget debug message');
            
            // Grid logs (disabled in production)
            gridLogger.info('Grid initialized');
            gridLogger.debug('Grid rendering data');
            
            // Datasource logs (INFO level)
            dsLogger.info('Fetching data from API');
            dsLogger.debug('API response received');
        }
        
        // Show configurations
        function showConfigs() {
            console.group('📋 Logger Configurations');
            
            console.log('Global Config:', 
                LoggerRegistry.getGlobalConfigSnapshot());
            
            console.log('All Configs:', 
                LoggerRegistry.getAllConfigs());
            
            console.log('Registered Packages:', 
                LoggerRegistry.getRegisteredPackages());
            
            console.groupEnd();
        }
        
        // Run automatically on load
        window.addEventListener('load', () => {
            widgetLogger.info('Application loaded successfully! 🎉');
            showConfigs();
        });
    </script>
</body>
</html>

📖 API Reference

LoggerRegistry

MethodDescription
setGlobalConfig(config)Set global configuration programmatically
getGlobalConfigSnapshot()Get current global configuration
registerPackage(name, config, force?)Register package with config
getPackageConfig(name)Get package configuration
hasPackage(name)Check if package is registered
hasGlobalConfig(name)Check if package has global protection
getGlobalPackageConfig(name)Get global config for specific package
clearGlobalConfig(name)Clear global protection for package
clearAllGlobalConfigs()Clear all global protections
unregisterPackage(name)Remove package from registry
updatePackage(name, config, force?)Update package configuration
getRegisteredPackages()Get all registered packages
getAllConfigs()Get all package configs
reloadFromGlobal()Reload from global config
clear()Clear all packages

CoreLogger

MethodDescription
createChild(namespace, component?, level?)Create child logger with package support
configure(config)Update logger configuration
setLevel(level)Set minimum log level
enable() / disable()Enable/disable logging
getConfig()Get current configuration

ChildLogger

MethodDescription
info(message, ...data)Info level logging
warn(message, ...data)Warning level logging
error(message, ...data)Error level logging
debug(message, ...data)Debug level logging
trace(message, ...data)Trace level logging
group(title) / groupEnd()Group related logs
time(label) / timeEnd(label)Measure execution time
table(data)Display data in table format
getNamespace()Get package namespace
getComponentName()Get component name

🌍 Browser Support

  • Chrome 60+
  • Firefox 55+
  • Safari 12+
  • Edge 79+

🔧 Node.js Support

  • Node.js 16+

💡 Tips and Best Practices

1. Global Configuration Priority

javascript
// ✅ GOOD: Define global config before package loads
window.__XCONS_LOGGER_CONFIG__ = { /* ... */ };
// <script src="@xcons/common"></script>

// ❌ BAD: Try to change after package loads (requires force)
LoggerRegistry.updatePackage('@xcons/widget', config); // Global config is preserved

2. Environment Based Configuration

javascript
// Different settings for Development and Production
const logConfig = process.env.NODE_ENV === 'production' ? {
    level: LoggerLogLevel.WARN,
    colors: false
} : {
    level: LoggerLogLevel.TRACE,
    colors: true
};

3. Package Naming

javascript
// ✅ GOOD: Consistent package naming
'@xcons/widget'
'@xcons/grid'
'@xcons/datasource'

// ❌ BAD: Inconsistent naming
'widget-package'
'GridModule'
'DS_SOURCE'

4. Component Log Levels

javascript
// OFF for performance critical components
const perfCritical = logger.createChild('@xcons/widget', 'RENDER', ComponentLogLevel.OFF);

// DETAILED for components that need debugging
const debugComponent = logger.createChild('@xcons/widget', 'DEBUG', ComponentLogLevel.DETAILED);

💡 Tip: The logger system automatically detects browser and Node.js environments and applies appropriate formatting. Colored outputs during development, optimized logs in production.

🔗 Global Access: You can always access the logger instance via window.__XCONS_LOGGER_REGISTRY__ (browser) or global.__XCONS_LOGGER_REGISTRY__ (Node.js).