Study guide

2.2 AEM Custom Logging, Logback Configurations & Request Tracing

Adobe Certified Professional - AEM Sites Developer AD0-E128

Track your progress as you read

Finished sections get a check mark.

1 Chapter 1: Dispatcher Farm & Multi-Site Configuration

1.1 AEM Dispatcher Configuration & Caching Fundamentals 1.2 Multi-Site Management (MSM) & Blueprint/Live Copy Architecture 1.3 OSGi Configuration Management & Run Modes (.cfg.json)

2 Chapter 2: Oak Indexing & Custom Logging

2.1 Custom Oak Index Definitions & Lucene Query Optimization 2.2 AEM Custom Logging, Logback Configurations & Request Tracing

3 Chapter 3: Component Architecture, HTL & Client Libraries

3.1 Core Components & Proxy Component Pattern 3.2 HTL (HTML Template Language) Block Statements & Context-Aware Escaping 3.3 Client-Side Libraries (Clientlibs) Architecture & Management

4 Chapter 4: Sling Models & OSGi Declarative Services

4.1 Sling Models Framework, Injectors & Model Exporter 4.2 OSGi Declarative Services, Component Lifecycle & Service Rankings

5 Chapter 5: Templates, Fragments & Business Workflows

5.1 Editable Templates, Structure, Initial Content & Content Policies 5.2 Content Fragments, Experience Fragments & Headless Delivery 5.3 AEM Workflows, Custom Process Steps & Launchers

6 Chapter 6: Build, Packaging & Cloud Manager CI/CD

6.1 Maven Project Structure & AEM Project Archetype 6.2 Content Package Types, Packaging Rules & FileVault Validation 6.3 Cloud Manager CI/CD Pipelines & Quality Gates 6.4 Rapid Development Environments (RDE) & Sling Repoinit Scripts

7 Chapter 7: Environment Maintenance & Content Distribution

7.1 AEM Maintenance Releases & Cloud Service Version Updates 7.2 AEM Deployment Topologies & Cloud Architecture 7.3 Replication Agents & Sling Content Distribution 7.4 Repository Maintenance: Revision Cleanup, Compaction & Purge Tasks

8 Chapter 8: Analyzing, Debugging & Diagnostic Tools

8.1 System Log Analysis & Diagnostic Tooling 8.2 Debugging Client-Side Libraries & Granite Dumplibs 8.3 Dispatcher Caching Diagnostics, X-Cache-Info & Local Validation 8.4 Environment Troubleshooting, Web Console & Developer Console

2.2 AEM Custom Logging, Logback Configurations & Request Tracing

Key Takeaways Explain This Topic AI

Apache Sling Logging delegates directly to Logback Classic, allowing dynamic OSGi configuration through Sling LogManager factory configurations without JVM restarts.

Custom application loggers must be configured via OSGi .cfg.json files named org.apache.sling.commons.log.LogManager.factory.config~identifier.cfg.json stored in the ui.config module.

Setting org.apache.sling.commons.log.additiv to false isolates custom loggers and prevents log entries from bubbling up and duplicating inside the root error.log.

Sling request.log records incoming requests with '->' and outgoing responses with '<-', correlating transactions via request IDs and displaying exact processing duration in milliseconds.

SLF4J parameterized logging with placeholders ({}) prevents unnecessary String concatenation overhead, and expensive parameter evaluations must be guarded with log.isDebugEnabled().

Last updated: September 2026

2.2 AEM Custom Logging, Logback Configurations & Request Tracing

Core Principle: Robust logging and request tracing form the foundation of enterprise observability in Adobe Experience Manager. By leveraging the Apache Sling Commons Log framework and Logback Classic , developers configure isolated project log files, monitor request processing lifecycles via request.log , and diagnose performance bottlenecks using diagnostic consoles and SLF4J best practices.

1. Sling Logging Architecture & Logback Integration

In Adobe Experience Manager, logging is governed by Apache Sling Commons Log , which embeds and extends the industry-standard Logback Classic and Logback Core libraries. +----------------------------------------------------------------------+

  • | Application Layer (Java / OSGi) |
  • | org.slf4j.Logger LOG = LoggerFactory.getLogger(...) |
  • +----------------------------------------------------------------------+
  • |
  • v
  • +----------------------------------------------------------------------+
  • | SLF4J API (Simple Logging Facade for Java) |
  • +----------------------------------------------------------------------+
  • |
  • v
  • +----------------------------------------------------------------------+
  • | Sling Commons Log & Logback Core |
  • | (Dynamic OSGi Configuration Management via LogManager) |
  • +----------------------------------------------------------------------+
  • | |
  • v v
  • +------------------------------------+ +-----------------------------+
  • | OSGi Factory Configurations | | Built-in Log Appenders |
  • | LogManager.factory.config~*.cfg.json| | error.log, stdout.log |
  • +------------------------------------+ +-----------------------------+
  • | |
  • +---------------------+---------------------+
  • |
  • v
  • +----------------------------------------------------------------------+
  • | Target Log Files under crx-quickstart/logs/ |
  • | error.log | request.log | access.log | myproject.log |
  • +----------------------------------------------------------------------+
  • The SLF4J Abstraction

All AEM code (OSGi services, Sling Models, workflow processes, servlets) interacts solely with the SLF4J interface ( org.slf4j.Logger , org.slf4j.LoggerFactory ). Code remains completely decoupled from the underlying Logback implementation.

Dynamic OSGi Configuration

Unlike traditional standalone Java applications that require editing static logback.xml files on disk, Sling exposes the Sling LogManager ( org.apache.sling.commons.log.LogManager ) as an OSGi service. Loggers, appenders, log levels, and file destinations are managed dynamically via OSGi configuration admin. Modifications take effect immediately in the running JVM without restarting the AEM instance or redeploying bundles.

2. Sling LogManager Factory Configurations ( .cfg.json )

In modern AEM projects, custom logging configurations are authored as OSGi factory configurations using the .cfg.json format and deployed via the ui.config Maven module.

File Naming Convention & Path

OSGi factory configurations require a tilde ( ~ ) separator followed by a unique semantic identifier:

ui.config/src/main/content/jcr_root/apps/myproject/osgiconfig/config/org.apache.sling.commons.log.LogManager.factory.config~myproject.cfg.json

Run-mode specific configurations can be targeted to distinct environments by placing files in run-mode folders:

  • config.author (applied only to author instances)
  • config.publish (applied only to publish instances)
  • config.stage or config.prod (Cloud Service environment tiers)
  • Complete Configuration Example
  • Below is a production-ready .cfg.json configuration for a custom application log: {
  • "org.apache.sling.commons.log.file": "logs/myproject.log",
  • "org.apache.sling.commons.log.level": "INFO",
  • "org.apache.sling.commons.log.pattern": "%d{dd.MM.yyyy HH:mm:ss.SSS} *%level* [%thread] %logger %msg%n",
  • "org.apache.sling.commons.log.names": [
  • "com.myproject",
  • "com.myproject.core.services",
  • "com.myproject.core.models"
  • ],
  • "org.apache.sling.commons.log.additiv": false,
  • "org.apache.sling.commons.log.file.size": "20MB",
  • "org.apache.sling.commons.log.file.number": 5
  • }
  • Configuration Property Breakdown

Property Key Type Description & Production Guidance

org.apache.sling.commons.log.file String File path for log output. Relative paths are resolved against crx-quickstart/ (e.g., logs/myproject.log ).

org.apache.sling.commons.log.level String Minimum logging threshold. Allowed values: TRACE , DEBUG , INFO , WARN , ERROR . Production default: INFO or WARN .

org.apache.sling.commons.log.names Array[String] Array of Java package names or fully qualified class names routed to this appender. All sub-packages are automatically included.

org.apache.sling.commons.log.pattern String Logback formatting pattern. Standard pattern: %d{dd.MM.yyyy HH:mm:ss.SSS} *%level* [%thread] %logger %msg%n .

org.apache.sling.commons.log.additiv Boolean Crucial Setting . Controls logger additivity. When false , messages written to myproject.log are not duplicated in error.log . Default is false in modern configs.

org.apache.sling.commons.log.file.size String Maximum size of an individual log file before triggering rotation (e.g., 10MB , 50MB ).

org.apache.sling.commons.log.file.number Integer Number of rotated historical archive files to retain on disk before oldest files are purged.

  • 3. Log Appenders, Rolling Policies & MDC Tracing
  • Log File Rolling Policies

Sling Commons Log supports both size-based and time-based rolling policies:

Size-Based Rolling : Configured via org.apache.sling.commons.log.file.size and org.apache.sling.commons.log.file.number . When myproject.log reaches 20MB, Sling renames it to myproject.log.0 , shifting older files up to myproject.log.4 , and purges older files.

Time-Based (Date) Rolling : Configured by specifying a date pattern in quotes as the file property or appending a date pattern: logs/myproject.log.yyyy-MM-dd . Files rotate daily at midnight.

Mapped Diagnostic Context (MDC) Tracing

In high-volume concurrent environments, multiple threads execute simultaneously, interleaving log statements across different user requests. Mapped Diagnostic Context (MDC) allows developers to trace an entire user journey across multiple OSGi services.

MDC values are available only when the request pipeline or application code populates them. Do not assume every AEM log pattern automatically exposes %X{request.id} or %X{sling.userId} . If end-to-end correlation is required, define and propagate a correlation value deliberately and include it in the project logger pattern.

Configuring MDC in the log pattern: %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [req:%X{request.id}] [user:%X{sling.userId}] %-5level %logger{36} - %msg%n

Log output with MDC: 2026-09-23 14:10:05.122 [127.0.0.1 [1695478205122] GET /content/wknd/us/en.html HTTP/1.1] [req:1042] [user:anonymous] INFO c.m.c.s.CatalogService - Cache miss for product 4421

4. Request Tracing: request.log and access.log Architecture

AEM maintains two distinct request tracing log files under crx-quickstart/logs/ : +------------------------------------------------------------------------+

  • | Incoming Client Request |
  • +------------------------------------------------------------------------+
  • | |
  • v v
  • +-------------------------------+ +-------------------------------+
  • | access.log | | request.log |
  • | (NCSA Combined Access Log) | | (Sling Engine Internal Trace)|
  • +-------------------------------+ +-------------------------------+
  • | - Remote Client IP Address | | - Inbound Marker (->) |
  • | - HTTP Method & Target URL | | - Request ID (e.g., [1042]) |
  • | - HTTP Status Code | | - Outbound Marker (<-) |
  • | - Bytes Transferred | | - Response Status & MIME Type |
  • | - User-Agent & Referer | | - Internal Duration in ms |
  • +-------------------------------+ +-------------------------------+
  • Anatomy of request.log Entries

The Sling Request Logger records two distinct lines for every single HTTP transaction: an inbound entry upon request arrival, and an outbound entry upon response completion.

  • 1. Inbound Entry ( -> ) 23/Sep/2026:14:10:05 +0000 [1042] -> GET /content/wknd/us/en.html HTTP/1.1
  • Timestamp : 23/Sep/2026:14:10:05 +0000
  • Request ID : [1042] (unique integer assigned to this request thread)
  • Direction : -> (inbound request arriving at Sling)
  • HTTP Details : GET /content/wknd/us/en.html HTTP/1.1
  • 2. Outbound Entry ( <- ) 23/Sep/2026:14:10:05 +0000 [1042] <- 200 text/html;charset=UTF-8 84ms
  • Timestamp : 23/Sep/2026:14:10:05 +0000
  • Request ID : [1042] (matches the inbound entry ID)
  • Direction : <- (outbound response returned to client/Dispatcher)
  • HTTP Status Code : 200
  • Content-Type : text/html;charset=UTF-8
  • Elapsed Time : 84ms (exact total processing time inside the AEM JVM)
  • Diagnostic Techniques with request.log

Identifying Slow Requests : Filtering for durations exceeding performance budgets (e.g., > 500ms or 1000ms): grep '<-' request.log | awk '$NF > 500 {print $0}'

Detecting Hung or Crashed Threads : If an inbound request ( -> ) appears in request.log without a corresponding outbound entry ( <- ), the thread either encountered an infinite loop, hung waiting on a deadlocked JCR session lock, or was killed by a JVM crash.

Analyzing Concurrent Load : Matching timestamps and request ID gaps indicates peak concurrency and request queues.

access.log vs. request.log

access.log : Formatted according to the standard NCSA Combined Log Format. Records external client IP, authenticated user, byte volume, and browser User-Agent. Ideal for traffic analysis and external DDoS detection.

request.log : Sling-specific operational log. Records internal millisecond execution time and ties directly to Sling script resolution and OSGi thread execution.

  • 5. Runtime Logger Management & Web Console Diagnostics
  • The Apache Felix Web Console ( /system/console/slinglog )

On local SDK environments and on-premise/AMS AEM instances, developers can inspect and manipulate loggers in real time via the Sling Log Support console:

Navigate to http://localhost:4502/system/console/slinglog .

Review all active logger configurations, their assigned log levels, appenders, and package categories.

Click Add new Logger to configure a temporary logger:

  • Log Level: DEBUG
  • Log File: logs/debug-workflow.log
  • Logger: com.myproject.core.workflow

The new logger activates instantly in memory without restarting bundles.

Warning

Operational Guardrail: Changes made through /system/console/slinglog are stored either in transient memory or in the local OSGi ConfigAdmin repository. In enterprise CI/CD workflows and AEM as a Cloud Service, any manual Web Console change will be wiped upon the next deployment. All durable loggers must be committed to Git as .cfg.json files.

Logging in AEM as a Cloud Service

In AEM as a Cloud Service, direct access to /system/console/slinglog is restricted on cloud environments. Developers manage and inspect logs through two primary mechanisms:

Adobe I/O CLI ( aio ) : Developers stream live logs directly to their local terminal: aio cloudmanager:tail-logs 12345 publish aemerror

aio cloudmanager:tail-logs 12345 author aemrequest

Cloud Manager Log Downloads : Download full compressed archives of aemerror , aemrequest , and httpdaccess logs from the Cloud Manager Environment details page.

6. SLF4J Best Practices in OSGi Services & Sling Models

Writing clean, efficient logging code is critical to preventing CPU bottlenecks and memory allocation pressure in high-throughput AEM applications.

1. Logger Initialization Pattern

Always declare the logger as a private static final field at the class level: package com.myproject.core.services.impl;

  • import org.osgi.service.component.annotations.Component;
  • import org.slf4j.Logger;
  • import org.slf4j.LoggerFactory;
  • @Component(service = CatalogService.class)
  • public class CatalogServiceImpl implements CatalogService {
  • // CORRECT: Class-level static final logger
  • private static final Logger LOG = LoggerFactory.getLogger(CatalogServiceImpl.class);

// ...

}

Avoid creating non-static logger instances in Sling Models; Sling Models are instantiated frequently, and recreating logger instances consumes unnecessary heap allocations.

2. Parameterized Logging (Avoid String Concatenation)

Never use String concatenation ( + ) inside log statements: // INCORRECT (ANTI-PATTERN): Allocates StringBuilder even if DEBUG is disabled!

LOG.debug("Fetching product details for SKU " + sku + " in category " + category);

  • // CORRECT: Defers string formatting until level check passes
  • LOG.debug("Fetching product details for SKU {} in category {}", sku, category);
  • 3. Guarding Expensive Parameter Construction

When computing a log argument requires significant processing (such as serializing a large object to JSON or iterating a JCR collection), wrap the statement in log.isDebugEnabled() or log.isTraceEnabled() : // CORRECT: Prevents expensive JSON serialization when DEBUG is disabled

  • if (LOG.isDebugEnabled()) {
  • LOG.debug("Serialized payload response: {}", complexObjectSerializer.toJson(order));
  • }
  • 4. Proper Exception Logging

When catching exceptions, pass the Throwable object as the final unparameterized argument to allow SLF4J to print the complete stack trace: try {

  • remoteService.syncInventory(storeId);
  • } catch (RemoteConnectionException ex) {
  • // CORRECT: Automatically appends complete stack trace to error.log
  • LOG.error("Failed to sync inventory for store {}", storeId, ex);
  • // INCORRECT: Destroys the stack trace and root cause
  • LOG.error("Error occurred: " + ex.getMessage());
  • // INCORRECT: Bypasses logging framework and writes to stderr
  • ex.printStackTrace();
  • }
  • 5. Loop Hygiene

Never log inside tight loops over repository nodes or collections. Logging thousands of lines per second saturates the disk write buffer and causes thread lock contention. Instead, aggregate metrics and log periodic summaries: int count = 0;

  • for (Resource item : pageResource.getChildren()) {
  • processItem(item);
  • if (++count % 1000 == 0) {
  • LOG.info("Processed {} items so far...", count);
  • }
  • }
  • LOG.info("Completed processing total {} items.", count);
  • 7. AEM Standard Log Files Quick Reference

Log File Default Path Primary Contents Diagnostic Use Case

error.log crx-quickstart/logs/error.log Uncaught exceptions, system startup messages, OSGi bundle errors. Primary troubleshooting log for Java runtime failures and syntax exceptions.

request.log crx-quickstart/logs/request.log Inbound ( -> ) and outbound ( <- ) HTTP requests with execution duration in ms. Diagnosing slow rendering servlets, unindexed queries, and hung worker threads.

access.log crx-quickstart/logs/access.log NCSA Combined HTTP access logs (client IP, HTTP status, bytes). Traffic analysis, IP rate limiting, external security monitoring.

stdout.log crx-quickstart/logs/stdout.log JVM standard output and unhandled native crash dumps. Detecting JVM OutOfMemory errors and garbage collection pauses.

history.log crx-quickstart/logs/history.log Replication agent transmissions and package activations. Troubleshooting content distribution failures between Author and Publish.