Claude Code Plugins

Community-maintained marketplace

Feedback

Guide for implementing logging in Salesforce B2C Commerce scripts

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name b2c-logging
description Implement logging in B2C Commerce scripts using dw.system.Logger. Use when adding debug output, error tracking, or custom log files to server-side code. Covers getLogger, log categories, log levels (debug, info, warn, error, fatal), and custom named log files.

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

  1. Go to Custom Log Settings
  2. Click Add Category
  3. Enter category name (e.g., checkout, payment)
  4. 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