revamping frontend logging system and reorganising documentation

This commit is contained in:
2025-10-28 21:07:26 +01:00
parent 5c80ba17c5
commit b0cc0385f8
68 changed files with 3481 additions and 624 deletions

View File

@@ -69,6 +69,7 @@ const Icons = {
'folder-open': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 19a2 2 0 01-2-2V7a2 2 0 012-2h4l2 2h4a2 2 0 012 2v1M5 19h14a2 2 0 002-2v-5a2 2 0 00-2-2H9a2 2 0 00-2 2v5a2 2 0 01-2 2z"/></svg>`,
'download': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"/></svg>`,
'upload': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12"/></svg>`,
'save': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4"/></svg>`,
// Settings & Tools
'cog': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/></svg>`,
@@ -77,6 +78,10 @@ const Icons = {
'moon': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"/></svg>`,
'sun': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"/></svg>`,
// Design & Theming
'palette': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01"/></svg>`,
'color-swatch': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 21a4 4 0 01-4-4V5a2 2 0 012-2h4a2 2 0 012 2v12a4 4 0 01-4 4zm0 0h12a2 2 0 002-2v-4a2 2 0 00-2-2h-2.343M11 7.343l1.657-1.657a2 2 0 012.828 0l2.829 2.829a2 2 0 010 2.828l-8.486 8.485M7 17h.01"/></svg>`,
// Location
'location-marker': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"/><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"/></svg>`,
'globe': `<svg class="{{classes}}" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2 2 2 0 012 2v2.945M8 3.935V5.5A2.5 2.5 0 0010.5 8h.5a2 2 0 012 2 2 2 0 104 0 2 2 0 012-2h1.064M15 20.488V18a2 2 0 012-2h3.064M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/></svg>`,

View File

@@ -0,0 +1,490 @@
// static/shared/js/log-config.js
/**
* Centralized Logging Configuration for ALL Frontends
*
* This file provides a consistent logging system across:
* - Admin Frontend
* - Vendor Frontend
* - Shop Frontend
*
* Each frontend can customize log levels while sharing the same logging infrastructure.
*
* Usage in any frontend:
* ```javascript
* // Use the global logger
* log.info('Page loaded');
* log.error('Something went wrong', error);
*
* // Or use a pre-configured logger
* const vendorLog = window.LogConfig.loggers.vendors;
* vendorLog.info('Vendors loaded');
*
* // Or create a custom logger
* const pageLog = window.LogConfig.createLogger('MY-PAGE', 3);
* pageLog.info('Page initialized');
* ```
*/
// ============================================================================
// LOG LEVELS
// ============================================================================
const LOG_LEVELS = {
ERROR: 1, // Only errors
WARN: 2, // Errors and warnings
INFO: 3, // Errors, warnings, and info (default)
DEBUG: 4 // Everything including debug messages
};
// ============================================================================
// FRONTEND DETECTION
// ============================================================================
/**
* Detect which frontend we're in based on URL path
* @returns {string} 'admin' | 'vendor' | 'shop' | 'unknown'
*/
function detectFrontend() {
const path = window.location.pathname;
if (path.startsWith('/admin')) return 'admin';
if (path.startsWith('/vendor')) return 'vendor';
if (path.startsWith('/shop')) return 'shop';
return 'unknown';
}
// ============================================================================
// ENVIRONMENT DETECTION
// ============================================================================
/**
* Detect environment based on hostname
* @returns {string} 'development' | 'production'
*/
function detectEnvironment() {
const hostname = window.location.hostname;
// Development environments
if (hostname === 'localhost' ||
hostname === '127.0.0.1' ||
hostname.startsWith('192.168.') ||
hostname.endsWith('.local')) {
return 'development';
}
return 'production';
}
// ============================================================================
// LOG LEVEL CONFIGURATION
// ============================================================================
/**
* Default log levels per frontend
* Can be overridden by environment
*/
const DEFAULT_LOG_LEVELS = {
admin: {
development: LOG_LEVELS.DEBUG, // Show everything in development
production: LOG_LEVELS.WARN // Only warnings and errors in production
},
vendor: {
development: LOG_LEVELS.DEBUG,
production: LOG_LEVELS.INFO // Vendors might need more logging
},
shop: {
development: LOG_LEVELS.DEBUG,
production: LOG_LEVELS.ERROR // Shop frontend: minimal logging in production
},
unknown: {
development: LOG_LEVELS.DEBUG,
production: LOG_LEVELS.WARN
}
};
// ============================================================================
// ACTIVE LOG LEVEL DETERMINATION
// ============================================================================
const CURRENT_FRONTEND = detectFrontend();
const CURRENT_ENVIRONMENT = detectEnvironment();
const ACTIVE_LOG_LEVEL = DEFAULT_LOG_LEVELS[CURRENT_FRONTEND][CURRENT_ENVIRONMENT];
// ============================================================================
// LOGGING UTILITIES
// ============================================================================
/**
* Create a logger with a specific prefix and log level
*
* @param {string} prefix - Logger prefix (e.g., 'VENDORS', 'THEME', 'PRODUCTS')
* @param {number} level - Log level (1-4, defaults to ACTIVE_LOG_LEVEL)
* @param {string} context - Optional frontend context (defaults to CURRENT_FRONTEND)
* @returns {Object} Logger object with error, warn, info, debug methods
*/
function createLogger(prefix = 'APP', level = ACTIVE_LOG_LEVEL, context = CURRENT_FRONTEND) {
const frontendPrefix = context.toUpperCase();
const formatPrefix = (emoji, label) => `${emoji} [${frontendPrefix}:${prefix} ${label}]`;
return {
error: (...args) => {
if (level >= LOG_LEVELS.ERROR) {
console.error(formatPrefix('❌', 'ERROR'), ...args);
}
},
warn: (...args) => {
if (level >= LOG_LEVELS.WARN) {
console.warn(formatPrefix('⚠️', 'WARN'), ...args);
}
},
info: (...args) => {
if (level >= LOG_LEVELS.INFO) {
console.info(formatPrefix('', 'INFO'), ...args);
}
},
debug: (...args) => {
if (level >= LOG_LEVELS.DEBUG) {
console.log(formatPrefix('🔍', 'DEBUG'), ...args);
}
},
// Additional utility methods
group: (label) => {
if (level >= LOG_LEVELS.INFO) {
console.group(formatPrefix('📂', 'GROUP') + ' ' + label);
}
},
groupEnd: () => {
if (level >= LOG_LEVELS.INFO) {
console.groupEnd();
}
},
table: (data) => {
if (level >= LOG_LEVELS.DEBUG) {
console.table(data);
}
},
time: (label) => {
if (level >= LOG_LEVELS.DEBUG) {
console.time(formatPrefix('⏱️', 'TIME') + ' ' + label);
}
},
timeEnd: (label) => {
if (level >= LOG_LEVELS.DEBUG) {
console.timeEnd(formatPrefix('⏱️', 'TIME') + ' ' + label);
}
}
};
}
// ============================================================================
// DEFAULT GLOBAL LOGGER
// ============================================================================
/**
* Default logger for general operations
* Automatically prefixed with current frontend
*/
const log = createLogger('APP', ACTIVE_LOG_LEVEL);
// ============================================================================
// PRE-CONFIGURED LOGGERS FOR ADMIN FRONTEND
// ============================================================================
const adminLoggers = {
// Vendor management
vendors: createLogger('VENDORS', ACTIVE_LOG_LEVEL),
vendorTheme: createLogger('THEME', ACTIVE_LOG_LEVEL),
vendorUsers: createLogger('VENDOR-USERS', ACTIVE_LOG_LEVEL),
// Product management
products: createLogger('PRODUCTS', ACTIVE_LOG_LEVEL),
inventory: createLogger('INVENTORY', ACTIVE_LOG_LEVEL),
// Order management
orders: createLogger('ORDERS', ACTIVE_LOG_LEVEL),
// User management
users: createLogger('USERS', ACTIVE_LOG_LEVEL),
// Admin operations
audit: createLogger('AUDIT', ACTIVE_LOG_LEVEL),
dashboard: createLogger('DASHBOARD', ACTIVE_LOG_LEVEL),
// Import operations
imports: createLogger('IMPORTS', ACTIVE_LOG_LEVEL)
};
// ============================================================================
// PRE-CONFIGURED LOGGERS FOR VENDOR FRONTEND
// ============================================================================
const vendorLoggers = {
// Vendor dashboard
dashboard: createLogger('DASHBOARD', ACTIVE_LOG_LEVEL),
// Product management
products: createLogger('PRODUCTS', ACTIVE_LOG_LEVEL),
inventory: createLogger('INVENTORY', ACTIVE_LOG_LEVEL),
// Order management
orders: createLogger('ORDERS', ACTIVE_LOG_LEVEL),
// Theme customization
theme: createLogger('THEME', ACTIVE_LOG_LEVEL),
// Settings
settings: createLogger('SETTINGS', ACTIVE_LOG_LEVEL),
// Analytics
analytics: createLogger('ANALYTICS', ACTIVE_LOG_LEVEL)
};
// ============================================================================
// PRE-CONFIGURED LOGGERS FOR SHOP FRONTEND
// ============================================================================
const shopLoggers = {
// Product browsing
catalog: createLogger('CATALOG', ACTIVE_LOG_LEVEL),
product: createLogger('PRODUCT', ACTIVE_LOG_LEVEL),
search: createLogger('SEARCH', ACTIVE_LOG_LEVEL),
// Shopping cart
cart: createLogger('CART', ACTIVE_LOG_LEVEL),
checkout: createLogger('CHECKOUT', ACTIVE_LOG_LEVEL),
// User account
account: createLogger('ACCOUNT', ACTIVE_LOG_LEVEL),
orders: createLogger('ORDERS', ACTIVE_LOG_LEVEL),
// Wishlist
wishlist: createLogger('WISHLIST', ACTIVE_LOG_LEVEL)
};
// ============================================================================
// SMART LOGGER SELECTION
// ============================================================================
/**
* Get the appropriate logger set for current frontend
*/
function getLoggers() {
switch (CURRENT_FRONTEND) {
case 'admin':
return adminLoggers;
case 'vendor':
return vendorLoggers;
case 'shop':
return shopLoggers;
default:
return {}; // Empty object, use createLogger instead
}
}
// Export frontend-specific loggers
const loggers = getLoggers();
// ============================================================================
// API CALL LOGGING
// ============================================================================
/**
* Log API calls with consistent formatting
*
* @param {string} method - HTTP method (GET, POST, PUT, DELETE)
* @param {string} url - API endpoint URL
* @param {*} data - Request/response data (optional)
* @param {string} status - 'request' or 'response'
*/
function logApiCall(method, url, data = null, status = 'request') {
const apiLogger = createLogger('API', ACTIVE_LOG_LEVEL);
const emoji = status === 'request' ? '📤' : '📥';
const message = `${emoji} ${method} ${url}`;
if (ACTIVE_LOG_LEVEL >= LOG_LEVELS.DEBUG) {
if (data) {
apiLogger.debug(message, data);
} else {
apiLogger.debug(message);
}
} else if (ACTIVE_LOG_LEVEL >= LOG_LEVELS.INFO) {
apiLogger.info(message);
}
}
// ============================================================================
// ERROR LOGGING
// ============================================================================
/**
* Log errors with stack traces
*
* @param {Error} error - Error object
* @param {string} context - Context where error occurred
*/
function logError(error, context = 'Unknown') {
const errorLogger = createLogger('ERROR', ACTIVE_LOG_LEVEL);
errorLogger.error(`Error in ${context}:`, error.message);
if (ACTIVE_LOG_LEVEL >= LOG_LEVELS.DEBUG && error.stack) {
console.error('Stack trace:', error.stack);
}
}
// ============================================================================
// PERFORMANCE LOGGING
// ============================================================================
/**
* Log performance metrics
*
* @param {string} operation - Operation name
* @param {number} duration - Duration in milliseconds
*/
function logPerformance(operation, duration) {
const perfLogger = createLogger('PERF', ACTIVE_LOG_LEVEL);
if (ACTIVE_LOG_LEVEL >= LOG_LEVELS.DEBUG) {
const emoji = duration < 100 ? '⚡' : duration < 500 ? '⏱️' : '🐌';
perfLogger.debug(`${emoji} ${operation} took ${duration}ms`);
}
}
// ============================================================================
// EXPORTS (for modules)
// ============================================================================
// For pages that use module imports
if (typeof module !== 'undefined' && module.exports) {
module.exports = {
LOG_LEVELS,
log,
loggers,
createLogger,
logApiCall,
logError,
logPerformance,
detectFrontend,
detectEnvironment
};
}
// ============================================================================
// GLOBAL ACCESS (for inline scripts)
// ============================================================================
// Make available globally for inline scripts
window.LogConfig = {
LOG_LEVELS,
log,
loggers,
createLogger,
logApiCall,
logError,
logPerformance,
// Expose frontend/environment info
frontend: CURRENT_FRONTEND,
environment: CURRENT_ENVIRONMENT,
logLevel: ACTIVE_LOG_LEVEL
};
// ============================================================================
// INITIALIZATION
// ============================================================================
// Log that logging system is initialized
if (ACTIVE_LOG_LEVEL >= LOG_LEVELS.INFO) {
const frontendName = CURRENT_FRONTEND.charAt(0).toUpperCase() + CURRENT_FRONTEND.slice(1);
const envName = CURRENT_ENVIRONMENT.charAt(0).toUpperCase() + CURRENT_ENVIRONMENT.slice(1);
const levelName = Object.keys(LOG_LEVELS).find(k => LOG_LEVELS[k] === ACTIVE_LOG_LEVEL);
console.log(
`%c🎛 ${frontendName} Frontend Logging System Initialized`,
'font-weight: bold; font-size: 14px; color: #6366f1;'
);
console.log(
`%c Environment: ${envName}`,
'color: #8b5cf6;'
);
console.log(
`%c Log Level: ${ACTIVE_LOG_LEVEL} (${levelName})`,
'color: #8b5cf6;'
);
}
// ============================================================================
// USAGE EXAMPLES (for developers)
// ============================================================================
/*
EXAMPLE 1: Use global logger
=============================
window.LogConfig.log.info('Application started');
window.LogConfig.log.error('Failed to load data', error);
EXAMPLE 2: Use pre-configured logger (RECOMMENDED)
===================================================
// In admin frontend
const themeLog = window.LogConfig.loggers.vendorTheme;
themeLog.info('Theme editor loaded');
// In vendor frontend
const dashLog = window.LogConfig.loggers.dashboard;
dashLog.info('Dashboard initialized');
// In shop frontend
const cartLog = window.LogConfig.loggers.cart;
cartLog.info('Cart updated');
EXAMPLE 3: Create custom logger
================================
const myLog = window.LogConfig.createLogger('MY-FEATURE', 4);
myLog.info('Feature initialized');
EXAMPLE 4: Check current frontend
==================================
if (window.LogConfig.frontend === 'admin') {
// Admin-specific code
}
EXAMPLE 5: API call logging
============================
window.LogConfig.logApiCall('GET', '/api/vendors', null, 'request');
const data = await apiClient.get('/api/vendors');
window.LogConfig.logApiCall('GET', '/api/vendors', data, 'response');
EXAMPLE 6: Performance logging
===============================
const start = performance.now();
await loadData();
const duration = performance.now() - start;
window.LogConfig.logPerformance('Load Data', duration);
EXAMPLE 7: Error logging
=========================
try {
await saveData();
} catch (error) {
window.LogConfig.logError(error, 'Save Operation');
}
*/