b2c-logging

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Logging Skill

日志实现技能

This skill guides you through implementing logging in B2C Commerce using the Logger and Log classes.
本技能将指导你使用Logger和Log类在B2C Commerce中实现日志功能。

Overview

概述

B2C Commerce provides a logging framework with:
FeatureDescription
Log Levelsdebug, info, warn, error, fatal
CategoriesOrganize logs by functional area
Custom FilesWrite to dedicated log files
NDCNested Diagnostic Context for tracing
BM ConfigurationEnable/disable levels per category
B2C Commerce提供的日志框架包含以下功能:
功能描述
日志级别debug、info、warn、error、fatal
日志分类按功能领域组织日志
自定义文件写入专用日志文件
NDC用于追踪的嵌套诊断上下文(Nested Diagnostic Context)
BM配置按分类启用/禁用不同级别

Log Levels

日志级别

LevelMethodDescriptionDefault State
debug
debug()
Detailed debugging informationDisabled (never on production)
info
info()
General informationDisabled by default
warn
warn()
Warning conditionsAlways enabled
error
error()
Error conditionsAlways enabled
fatal
fatal()
Critical failuresAlways enabled, can send email
级别方法描述默认状态
debug
debug()
详细的调试信息禁用(生产环境中始终关闭)
info
info()
常规信息默认禁用
warn
warn()
警告情况始终启用
error
error()
错误情况始终启用
fatal
fatal()
严重故障始终启用,可发送邮件

Basic Logging

基础日志实现

Using Logger (Static Methods)

使用Logger(静态方法)

The
Logger
class provides static methods for quick logging:
javascript
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);
Logger
类提供静态方法用于快速记录日志:
javascript
var Logger = require('dw/system/Logger');

// 简单消息
Logger.debug('Debug message');
Logger.info('Info message');
Logger.warn('Warning message');
Logger.error('Error message');

// 带参数的消息(Java MessageFormat语法)
Logger.info('Processing order {0} for customer {1}', orderNo, customerEmail);
Logger.error('Failed to process {0}: {1}', productId, errorMessage);

Using Log (Instance Methods)

使用Log(实例方法)

The
Log
class provides instance-based logging with categories:
javascript
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);
Log
类提供基于实例的日志记录,支持分类:
javascript
var Logger = require('dw/system/Logger');

// 获取指定分类的日志实例
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:
javascript
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.
日志分类有助于组织和过滤日志消息:
javascript
var Logger = require('dw/system/Logger');

// 为不同功能区域创建不同分类的日志实例
var checkoutLog = Logger.getLogger('checkout');
var paymentLog = Logger.getLogger('payment');
var inventoryLog = Logger.getLogger('inventory');
var integrationLog = Logger.getLogger('integration');

// 使用对应分类的日志实例
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);
日志分类可在Business Manager的Administration > Operations > Custom Log Settings中配置。

Custom Named Log Files

自定义命名日志文件

Write to dedicated log files instead of the standard custom log files:
javascript
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);
将日志写入专用日志文件,而非标准自定义日志文件:
javascript
var Logger = require('dw/system/Logger');

// 获取带自定义文件前缀的日志实例
var orderExportLog = Logger.getLogger('orderexport', 'export');
var feedLog = Logger.getLogger('productfeed', 'feed');

// 消息将写入custom-orderexport-*.log文件
orderExportLog.info('Exporting order {0}', orderNo);

// 消息将写入custom-productfeed-*.log文件
feedLog.info('Processing product {0}', productId);

File Name Rules

文件名规则

The
fileNamePrefix
parameter must follow these rules:
RuleRequirement
Length3-25 characters
Charactersa-z, A-Z, 0-9,
-
,
_
Start/EndMust start and end with alphanumeric
Not allowedCannot start or end with
-
or
_
fileNamePrefix
参数必须遵循以下规则:
规则要求
长度3-25个字符
允许字符a-z、A-Z、0-9、
-
_
首尾字符必须以字母或数字开头和结尾
禁止规则不能以
-
_
开头或结尾

File Naming Pattern

文件命名格式

Custom log files follow this pattern:
custom-<prefix>-<hostname>-appserver-<date>.log
Example:
custom-orderexport-blade0-1-appserver-20240115.log
自定义日志文件遵循以下命名格式:
custom-<prefix>-<hostname>-appserver-<date>.log
示例:
custom-orderexport-blade0-1-appserver-20240115.log

Quota

配额限制

Maximum 200 different log file names per day per appserver.
每个应用服务器每天最多支持200个不同的日志文件名。

Checking Log Level Status

检查日志级别状态

Check if a log level is enabled before expensive operations:
javascript
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
在执行高开销操作前,先检查对应日志级别是否启用:
javascript
var Logger = require('dw/system/Logger');
var log = Logger.getLogger('myCategory');

// 在构建高开销字符串前检查
if (log.isDebugEnabled()) {
    log.debug('Full cart contents: {0}', JSON.stringify(cart));
}

// 在执行高开销计算前检查
if (log.isInfoEnabled()) {
    var stats = calculateDetailedStats(); // 高开销操作
    log.info('Statistics: {0}', JSON.stringify(stats));
}

// 可用的检查方法
log.isDebugEnabled();  // 如果debug日志启用则返回true
log.isInfoEnabled();   // 如果info日志启用则返回true
log.isWarnEnabled();   // 如果warn日志启用则返回true
log.isErrorEnabled();  // 如果error日志启用则返回true

Static Level Checks

静态级别检查

javascript
var Logger = require('dw/system/Logger');

if (Logger.isDebugEnabled()) {
    Logger.debug('Debug message');
}
javascript
var Logger = require('dw/system/Logger');

if (Logger.isDebugEnabled()) {
    Logger.debug('Debug message');
}

Message Formatting

消息格式化

Messages support Java MessageFormat syntax:
javascript
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));
日志消息支持Java MessageFormat语法:
javascript
var Logger = require('dw/system/Logger');
var log = Logger.getLogger('order');

// 位置参数
log.info('Order {0} has {1} items totaling {2}', orderNo, itemCount, total);

// 重复使用同一参数
log.info('Product {0}: {0} is out of stock', productId);

// 复杂对象(使用JSON.stringify处理对象)
log.debug('Request: {0}', JSON.stringify(requestData));

Nested Diagnostic Context (NDC)

嵌套诊断上下文(NDC)

NDC helps trace related log messages across a request:
javascript
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有助于在请求链路中追踪相关日志消息:
javascript
var Logger = require('dw/system/Logger');
var Log = require('dw/system/Log');

var log = Logger.getLogger('checkout');
var ndc = Log.getNDC();

function processOrder(orderId) {
    // 将上下文推入栈中
    ndc.push('Order:' + orderId);

    try {
        log.info('Starting order processing');
        processPayment();
        processShipping();
        log.info('Order processing complete');
    } finally {
        // 离开作用域时务必弹出上下文
        ndc.pop();
    }
}

function processPayment() {
    ndc.push('Payment');
    try {
        log.info('Processing payment'); // NDC显示:Order:123 Payment
    } finally {
        ndc.pop();
    }
}

NDC Methods

NDC方法

MethodDescription
push(message)
Add context to the stack
pop()
Remove and return top context
peek()
View top context without removing
remove()
Clear entire context
方法描述
push(message)
将上下文添加到栈中
pop()
移除并返回栈顶上下文
peek()
查看栈顶上下文但不移除
remove()
清空整个上下文栈

Best Practices

最佳实践

1. Use Categories

1. 使用日志分类

javascript
// 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');
javascript
// 推荐:按功能领域分类
var log = Logger.getLogger('payment.processor');
var log = Logger.getLogger('inventory.sync');
var log = Logger.getLogger('order.export');

// 避免:不使用分类
Logger.info('Something happened');

2. Check Level Before Expensive Operations

2. 高开销操作前检查日志级别

javascript
// 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));
javascript
// 推荐:构建高开销字符串前先检查
if (log.isDebugEnabled()) {
    log.debug('Full response: {0}', JSON.stringify(largeObject));
}

// 避免:始终构建高开销字符串
log.debug('Full response: {0}', JSON.stringify(largeObject));

3. Include Context in Messages

3. 消息中包含上下文信息

javascript
// Good: Includes relevant context
log.error('Payment failed for order {0}, customer {1}: {2}',
    orderNo, customerId, errorMessage);

// Avoid: Missing context
log.error('Payment failed');
javascript
// 推荐:包含相关上下文
log.error('Payment failed for order {0}, customer {1}: {2}',
    orderNo, customerId, errorMessage);

// 避免:缺少上下文
log.error('Payment failed');

4. Use Appropriate Levels

4. 使用合适的日志级别

javascript
// 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);
javascript
// debug:详细技术信息
log.debug('SQL query: {0}', query);
log.debug('API request body: {0}', JSON.stringify(body));

// info:重要事件
log.info('Order {0} placed successfully', orderNo);
log.info('Customer {0} logged in', customerId);

// warn:潜在问题
log.warn('Inventory low for product {0}: {1} remaining', productId, qty);
log.warn('Slow API response: {0}ms', responseTime);

// error:需要关注的故障
log.error('Payment declined for order {0}: {1}', orderNo, reason);
log.error('Failed to connect to service {0}: {1}', serviceName, error);

// fatal:严重系统故障
log.fatal('Database connection lost');
log.fatal('Critical configuration missing: {0}', configKey);

5. Use Custom Log Files for Integration

5. 集成场景使用自定义日志文件

javascript
// 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');
javascript
// 为每个集成使用专用日志文件
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

6. 不要记录敏感数据

javascript
// 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);
javascript
// 推荐:掩码处理敏感数据
log.info('Payment processed for card ending in {0}', cardNumber.slice(-4));

// 避免:记录敏感数据
log.info('Payment processed for card {0}', cardNumber);

Business Manager Configuration

Business Manager配置

Configure custom logging in Administration > Operations > Custom Log Settings:
SettingDescription
Log to FileEnable file logging for each level
Receive EmailEmail addresses for fatal notifications
Root CategoryDefault settings for all categories
Custom CategoriesOverride settings per category
Administration > Operations > Custom Log Settings中配置自定义日志:
设置描述
Log to File为每个级别启用文件日志
Receive Email接收fatal级别通知的邮箱地址
Root Category所有分类的默认设置
Custom Categories按分类覆盖默认设置

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
  1. 进入Custom Log Settings
  2. 点击Add Category
  3. 输入分类名称(例如:
    checkout
    payment
  4. 设置要启用的日志级别

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
日志条目遵循以下格式:
[时间戳] [级别] [分类] 消息
示例:
[2024-01-15 10:30:45.123 GMT] [INFO] [checkout] Order ORD123 placed successfully

Detailed Reference

详细参考

  • Log Files - Log file types, locations, and retention
  • Log Files - 日志文件类型、位置和保留策略

Script API Classes

脚本API类

ClassDescription
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
描述
dw.system.Logger
静态日志方法和日志实例工厂
dw.system.Log
支持分类的日志实例
dw.system.LogNDC
用于追踪的嵌套诊断上下文