b2c-logging
Logging Skill
This skill guides you through implementing logging in B2C Commerce using the Logger and Log classes.
Overview
B2C Commerce provides a logging framework with:
| Feature | Description |
|---|---|
| Log Levels | debug, info, warn, error, fatal |
| Categories | Organize logs by functional area |
| Custom Files | Write to dedicated log files |
| NDC | Nested Diagnostic Context for tracing |
| BM Configuration | Enable/disable levels per category |
Log Levels
| Level | Method | Description | Default State |
|---|---|---|---|
debug |
debug() |
Detailed debugging information | Disabled (never on production) |
info |
info() |
General information | Disabled by default |
warn |
warn() |
Warning conditions | Always enabled |
error |
error() |
Error conditions | Always enabled |
fatal |
fatal() |
Critical failures | Always enabled, can send email |
Basic Logging
Using Logger (Static Methods)
The Logger class provides static methods for quick logging:
var Logger = require('dw/system/Logger');
// Simple messages
Logger.debug('Debug message');
Logger.info('Info message');
Logger.warn('Warning message');
Logger.error('Error message');
// Messages with parameters (Java MessageFormat syntax)
Logger.info('Processing order {0} for customer {1}', orderNo, customerEmail);
Logger.error('Failed to process {0}: {1}', productId, errorMessage);
Using Log (Instance Methods)
The Log class provides instance-based logging with categories:
var Logger = require('dw/system/Logger');
// Get logger for a category
var log = Logger.getLogger('checkout');
log.debug('Cart contents: {0}', JSON.stringify(cart));
log.info('Checkout started for basket {0}', basketId);
log.warn('Inventory low for product {0}', productId);
log.error('Payment failed: {0}', errorMessage);
log.fatal('Critical checkout failure: {0}', errorMessage);
Categories
Categories help organize and filter log messages:
var Logger = require('dw/system/Logger');
// Different categories for different areas
var checkoutLog = Logger.getLogger('checkout');
var paymentLog = Logger.getLogger('payment');
var inventoryLog = Logger.getLogger('inventory');
var integrationLog = Logger.getLogger('integration');
// Use appropriate logger
checkoutLog.info('Order {0} submitted', orderNo);
paymentLog.info('Payment authorized: {0}', transactionId);
inventoryLog.warn('Stock level below threshold for {0}', productId);
integrationLog.error('API call failed: {0}', serviceName);
Categories are configured in Business Manager under Administration > Operations > Custom Log Settings.
Custom Named Log Files
Write to dedicated log files instead of the standard custom log files:
var Logger = require('dw/system/Logger');
// Get logger with custom file prefix
var orderExportLog = Logger.getLogger('orderexport', 'export');
var feedLog = Logger.getLogger('productfeed', 'feed');
// Messages go to custom-orderexport-*.log
orderExportLog.info('Exporting order {0}', orderNo);
// Messages go to custom-productfeed-*.log
feedLog.info('Processing product {0}', productId);
File Name Rules
The fileNamePrefix parameter must follow these rules:
| Rule | Requirement |
|---|---|
| Length | 3-25 characters |
| Characters | a-z, A-Z, 0-9, -, _ |
| Start/End | Must start and end with alphanumeric |
| Not allowed | Cannot start or end with - or _ |
File Naming Pattern
Custom log files follow this pattern:
custom-<prefix>-<hostname>-appserver-<date>.log
Example: custom-orderexport-blade0-1-appserver-20240115.log
Quota
Maximum 200 different log file names per day per appserver.
Checking Log Level Status
Check if a log level is enabled before expensive operations:
var Logger = require('dw/system/Logger');
var log = Logger.getLogger('myCategory');
// Check before expensive string building
if (log.isDebugEnabled()) {
log.debug('Full cart contents: {0}', JSON.stringify(cart));
}
// Check before expensive calculations
if (log.isInfoEnabled()) {
var stats = calculateDetailedStats(); // expensive
log.info('Statistics: {0}', JSON.stringify(stats));
}
// Available checks
log.isDebugEnabled(); // true if debug logging enabled
log.isInfoEnabled(); // true if info logging enabled
log.isWarnEnabled(); // true if warn logging enabled
log.isErrorEnabled(); // true if error logging enabled
Static Level Checks
var Logger = require('dw/system/Logger');
if (Logger.isDebugEnabled()) {
Logger.debug('Debug message');
}
Message Formatting
Messages support Java MessageFormat syntax:
var Logger = require('dw/system/Logger');
var log = Logger.getLogger('order');
// Positional parameters
log.info('Order {0} has {1} items totaling {2}', orderNo, itemCount, total);
// Same parameter multiple times
log.info('Product {0}: {0} is out of stock', productId);
// Complex objects (use JSON.stringify for objects)
log.debug('Request: {0}', JSON.stringify(requestData));
Nested Diagnostic Context (NDC)
NDC helps trace related log messages across a request:
var Logger = require('dw/system/Logger');
var Log = require('dw/system/Log');
var log = Logger.getLogger('checkout');
var ndc = Log.getNDC();
function processOrder(orderId) {
// Push context onto the stack
ndc.push('Order:' + orderId);
try {
log.info('Starting order processing');
processPayment();
processShipping();
log.info('Order processing complete');
} finally {
// Always pop context when leaving scope
ndc.pop();
}
}
function processPayment() {
ndc.push('Payment');
try {
log.info('Processing payment'); // NDC shows: Order:123 Payment
} finally {
ndc.pop();
}
}
NDC Methods
| Method | Description |
|---|---|
push(message) |
Add context to the stack |
pop() |
Remove and return top context |
peek() |
View top context without removing |
remove() |
Clear entire context |
Best Practices
1. Use Categories
// Good: Organized by functional area
var log = Logger.getLogger('payment.processor');
var log = Logger.getLogger('inventory.sync');
var log = Logger.getLogger('order.export');
// Avoid: No category
Logger.info('Something happened');
2. Check Level Before Expensive Operations
// Good: Check before building expensive string
if (log.isDebugEnabled()) {
log.debug('Full response: {0}', JSON.stringify(largeObject));
}
// Avoid: Always building expensive strings
log.debug('Full response: {0}', JSON.stringify(largeObject));
3. Include Context in Messages
// Good: Includes relevant context
log.error('Payment failed for order {0}, customer {1}: {2}',
orderNo, customerId, errorMessage);
// Avoid: Missing context
log.error('Payment failed');
4. Use Appropriate Levels
// debug: Detailed technical information
log.debug('SQL query: {0}', query);
log.debug('API request body: {0}', JSON.stringify(body));
// info: Notable events
log.info('Order {0} placed successfully', orderNo);
log.info('Customer {0} logged in', customerId);
// warn: Potential issues
log.warn('Inventory low for product {0}: {1} remaining', productId, qty);
log.warn('Slow API response: {0}ms', responseTime);
// error: Failures that need attention
log.error('Payment declined for order {0}: {1}', orderNo, reason);
log.error('Failed to connect to service {0}: {1}', serviceName, error);
// fatal: Critical system failures
log.fatal('Database connection lost');
log.fatal('Critical configuration missing: {0}', configKey);
5. Use Custom Log Files for Integration
// Dedicated files for each integration
var erpLog = Logger.getLogger('erp-sync', 'erp');
var omsLog = Logger.getLogger('oms-export', 'oms');
var crmLog = Logger.getLogger('crm-sync', 'crm');
6. Don't Log Sensitive Data
// Good: Mask sensitive data
log.info('Payment processed for card ending in {0}', cardNumber.slice(-4));
// Avoid: Logging sensitive data
log.info('Payment processed for card {0}', cardNumber);
Business Manager Configuration
Configure custom logging in Administration > Operations > Custom Log Settings:
| Setting | Description |
|---|---|
| Log to File | Enable file logging for each level |
| Receive Email | Email addresses for fatal notifications |
| Root Category | Default settings for all categories |
| Custom Categories | Override settings per category |
Configuring Categories
- Go to Custom Log Settings
- Click Add Category
- Enter category name (e.g.,
checkout,payment) - Set log levels to enable
Log Output Format
Log entries follow this format:
[timestamp] [level] [category] message
Example:
[2024-01-15 10:30:45.123 GMT] [INFO] [checkout] Order ORD123 placed successfully
Detailed Reference
- Log Files - Log file types, locations, and retention
Script API Classes
| Class | Description |
|---|---|
dw.system.Logger |
Static logging methods and logger factory |
dw.system.Log |
Logger instance with category support |
dw.system.LogNDC |
Nested Diagnostic Context for tracing |
More from salesforcecommercecloud/b2c-developer-tooling
b2c-docs
Search and read B2C Commerce Script API documentation and XSD schemas using the b2c CLI. Use this skill whenever the user needs to look up class methods, understand API signatures, find available properties on commerce objects (baskets, orders, products, customers), or check XML schema formats for imports. Also use when writing server-side scripts and needing API reference — even if they just say "what methods does Basket have" or "what fields can I import for products".
116b2c-webdav
List, upload, download, and manage files on B2C Commerce instances via WebDAV. Use this skill whenever the user needs to upload files to IMPEX directories, download exports from an instance, list remote files, create or delete directories, or zip/unzip files on the server. Also use when managing file transfers to sandboxes or browsing instance file systems -- even if they just say 'upload a file to the instance' or 'check what's in the IMPEX folder'.
103b2c-slas-auth-patterns
Implement SLAS authentication patterns in B2C Commerce including passwordless login (email OTP, SMS OTP, passkeys), session bridging between PWA Kit/Storefront Next and SFRA, hybrid authentication (B2C 25.3+), token refresh flows, trusted system on behalf of (TSOB), and JWT validation. Use this skill whenever the user asks about shopper authentication beyond basic login, token exchange flows, passwordless or biometric auth, keeping sessions alive across storefronts, handling 409 Conflict errors on token endpoints, refreshing shopper tokens, or validating JWTs — even if they don't mention SLAS by name.
90b2c-config
Inspect and debug CLI configuration, instance connections, and authentication. Use this skill whenever the user needs to check which dw.json or credentials are active, manage multiple instance profiles, retrieve OAuth tokens for scripting, troubleshoot authentication failures or connection errors, or integrate with VS Code or other editors. Also use when environment variables override config or the wrong sandbox is being targeted -- even if they just say 'why is it connecting to the wrong instance' or 'get me an access token'.
90b2c-controllers
Create storefront controllers using SFRA or classic patterns with server.get/post, middleware chains, and res.render/json. Use this skill whenever the user needs to build a page route, handle form submissions, create AJAX endpoints, extend or override existing controllers, or add middleware to a request pipeline. Also use when debugging route registration or response rendering -- even if they just say 'new page endpoint' or 'handle a POST request'.
86b2c-scapi-schemas
Browse and retrieve SCAPI OpenAPI schema specifications. Use this skill whenever the user needs to list available SCAPI APIs, inspect endpoint paths or request/response shapes, explore data models for products or orders, check which fields an API returns, or understand SCAPI versioning. Also use when looking up API details before building an integration -- even if they just say 'what fields does the product API return' or 'show me the SCAPI endpoints'.
84