Debugging AEM SDK using logs

Accessing the AEM SDK’s logs, either the AEM SDK local quickstart Jar’s or Dispatcher Tools’ can provide key insights into debugging AEM applications.

AEM Logs

Let’s take a look at how we can use Java logging to help a local development and debugging. Needless to say, the efficacy of logging is wholly contingent on how well you use log statements in your code base. If you’ve logged the right information in the right places at the right log levels, the logs are invaluable. If not, all bets are off. The first thing to understand is AEM maintains log configurations as OSGi configurations in the AEM project. Since they’re OSGi configurations, they’re stored in the ui.apps project under apps, project name, config. The reason they live under the config folder is AEM as a cloud service, doesn’t have a local dev or dev OSGi run mode. So the configurations for local dev and dev are stored in the default config folder, and over in config.stage or as needed. Opening the config file, we see it’s pretty simple. The first line declares the Java packages to be logged. Typically, this is the root Java package for your OSGi bundle. In more complex projects, this may need to be set to multiple packages. The second line sets the log level. For development activities, debug is ideal. You might notice this file doesn’t declare a log file name, which means it will be output to the default error dialog. It’s important not to change this because Cloud Manager only exposes the error dialog. As mentioned previously, this config applies to both the local dev and AEM as a cloud service development environments. So if a custom log file is set, any log statements routed to this custom file will be unavailable in the cloud. Ideally, you want to keep the local dev and AEM as a cloud service dev environment logging configs as similar as possible to ensure the cloud dev environments are just as debuggable as local dev.
I’ve added a few log statements to the project’s ImageListImpl class at various log levels, warn, debug, and even trace. Since the loggers config level is set to debug, it will collect all debug log statements and higher, which includes debug, info, warn, and error. Because trace is lower than debug, you won’t see these statements in the log. But towards the end of this video, we’ll take a look at how to create Ad Hoc loggers in case we need to check these out. All right, let’s take a look at the logs. Logs are stored under your aem-sdk local run-times crx/quickstart/logs folder. Typically, it’s easiest to tail or stream the logs as they’re into. With MacOS or Linux ,the tail commands often used. Another popular app for MacOS is Apple’s Console App. And for Windows, you may need a third-party programmer plugin, or use PowerShell’s Get-Content command. Let’s invoke the ImageListImpl’s Java code by refreshing our apps website homepage, which should generate some log statements.
And as you can see, our projects debug statements are being logged.
AEM itself typically doesn’t log too much to the error log outside of errors. However, if irrelevant statements become distracting, you can always filter the log statements, using your Java package or class name as the filter criteria.
Let’s check out temporary Ad Hoc log configurations. This ability is only available on the local AEM-SDK Quickstart Jar. Remember the config file in our IDE is checked into get as part of the project, shared across team members, and deployed to AEM’s cloud service. Creating an Ad Hoc config allows logging to be configured directly in the local AEM runtime. Login as admin and navigate to Operations, Web console, Sling, Log support.
This console lists all the loggers in the system, and we can see the debug logger we deployed via our project. Let’s say we wanted to temporarily, in our local AEM runtime, see trace statements. We can edit the logger config, select Trace and Save.
Now, our log captures our trace statements as well.
Keep in mind, that when using the sling lock support console, the changes are written back to the configuration file in AEM.
Since we updated the logger configuration that we deployed to apps we can config. If we open that config file in the repository now, it’s apparent the log support console overrode the deployed config file.
This also means, that next time we deploy our project, it’s going to overwrite these changes with whatever’s in our AEM project. It’s also possible to create brand new loggers via the Add New Logger button.
The nuance with loggers created using this method is, since they don’t have an existing configuration file to update in the repository, a new config file is created for them under Apps, System, Config. And because AEM projects usually don’t, and probably shouldn’t ever deploy to App, System, Config, these new configs can live through project deployments. With a log support console provides a lot of flexibility, it’s best to try to normalize the state of logging across the development team using the OSGi configurations maintained in the project, as this helps establish expectations of what debug information is available across all development environments, both local and in the cloud. -

Logs act as the frontline for debugging AEM applications, but are dependent on adequate logging in the deployed AEM application. Adobe recommends keeping local development and AEM as a Cloud Service Dev logging configurations as similar a possible, as it normalizes log visibility on the AEM SDK’s local quickstart and AEM as a Cloud Service’s Dev environments, reducing configuration twiddling and re-deployment.

The AEM Project Archetype configures logging at the DEBUG level for your AEM application’s Java packages for local development via the Sling Logger OSGi configuration found at


which logs to the error.log.

If default logging is insufficient for local development, ad hoc logging can be configured via AEM SDK’s local quickstart’s Log Support web console, at (/system/console/slinglog), however it’s not recommended ad hoc changes are persisted to Git unless these same log configurations are needed on AEM as a Cloud Service Dev environments as well. Keep in mind, changes via the Log Support console, are persisted directly to the AEM SDK’s local quickstart’s repository.

Java log statements can be view in the error.log file:

$ ~/aem-sdk/author/crx-quickstart/logs/error.log

Often it it useful to “tail” the error.log which streams its output to the terminal.

Dispatcher logs

Dispatcher logs are output to stdout when bin/docker_run is invoked, however logs can be directly access with in the Docker contain.

Accessing logs in the Docker container dispatcher-tools-access-logs

Dispatcher logs can be directly accessing in the Docker container at /etc/httpd/logs.

$ docker ps

# locate the CONTAINER ID associated with "adobe/aem-ethos/dispatcher-publisher" IMAGE
CONTAINER ID        IMAGE                                       COMMAND                  CREATED             STATUS              PORTS                  NAMES
46127c9d7081        adobe/aem-ethos/dispatcher-publish:2.0.23   "/docker_entrypoint.…"   6 seconds ago       Up 5 seconds>80/tcp   wonderful_merkle

$ docker exec -it <CONTAINER ID> /bin/sh

/ #
/ # cd /etc/httpd/logs
/ # ls
    dispatcher.log          healthcheck_access_log  httpd_access.log        httpd_error.log

# When finished viewing the logs files, exit the Docker container's shell
/# exit

The <CONTAINER ID> in docker exec -it <CONTAINER ID> /bin/sh must be replaced with the target Docker CONTAINER ID listed from the docker ps command.

Copying the Docker logs to the local filesystem dispatcher-tools-copy-logs

Dispatcher logs can be copied out of the Docker container at /etc/httpd/logs to the local file system for inspection using your favorite log analysis tool. Note that this is a point-in-time copy, and does not provide real time updates to the logs.

$ docker ps

# locate the CONTAINER ID associated with "adobe/aem-ethos/dispatcher-publisher" IMAGE
CONTAINER ID        IMAGE                                       COMMAND                  CREATED             STATUS              PORTS                  NAMES
46127c9d7081        adobe/aem-ethos/dispatcher-publish:2.0.23   "/docker_entrypoint.…"   6 seconds ago       Up 5 seconds>80/tcp   wonderful_merkle

$ docker cp -L <CONTAINER ID>:/etc/httpd/logs logs
$ cd logs
$ ls
    dispatcher.log          healthcheck_access_log  httpd_access.log        httpd_error.log

The <CONTAINER_ID> in docker cp <CONTAINER_ID>:/var/log/apache2 ./ must be replaced with the target Docker CONTAINER ID listed from the docker ps command.