Expand my Community achievements bar.

Guidelines for the Responsible Use of Generative AI in the Experience Cloud Community.

Configure logback.xml file AEM 6.5

Avatar

Level 1

We are working on to have custom log file. And would like to configure custom appender. Where should I place my logback.xml file to work .

Trying to customize log message in access.log and request.log

 

https://logback.qos.ch/

 

14 Replies

Avatar

Level 10

Hi @cakayastha ,

To configure Logback in Adobe Experience Manager (AEM) 6.5, you need to place the logback.xml file in the appropriate location within your AEM project. Here's how you can do it:

  1. Create logback.xml: First, create your logback.xml file with your custom configuration. This file typically defines the loggers, appenders, and other configurations for Logback. You can refer to the Logback documentation (https://logback.qos.ch/) for details on configuring Logback.

  2. Determine Location: Decide where you want to place your logback.xml file within your AEM project. You have a few options:

    • CRX Repository: You can place the logback.xml file directly in the CRX repository. For example, you might place it under /apps/<your-app>/src/main/content/META-INF/vault/filter.xml if you're using a Maven project structure.

    • Bundle Configuration: You can also include the logback.xml file within your OSGi bundle. In this case, you would typically place it under src/main/resources in your Maven project structure.

  3. Package the Configuration: If you're placing the logback.xml file in the CRX repository, make sure it gets included in your AEM package. Update your Maven POM file or your package definition to ensure that the logback.xml file is included in your package.

  4. Deploy the Package: Deploy the AEM package containing the logback.xml file to your AEM instance. This will ensure that the Logback configuration is applied to your AEM instance.

  5. Restart AEM: After deploying the package, restart your AEM instance to apply the new Logback configuration.

  6. Verify: Once the AEM instance has restarted, verify that your custom Logback configuration is applied. You can check the logs to see if your custom appenders and loggers are working as expected.

By following these steps, you should be able to configure Logback in AEM 6.5 and customize your log files such as access.log and request.log according to your requirements.

Avatar

Level 1

@HrishikeshKa 

Thanks for your reply. As you suggested  both crx repo path and bundle configuration tried below but did not see logback getting in effect, please guide if  any miss at my end

logback.xml fie :

<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>/logs/SampleProject.log</file>
<append>true</append>
<immediateFlush>true</immediateFlush>
<encoder>
<pattern>%d %-5level %X{X-test-ID:-NA} [%thread] %logger{30} %marker- %msg %n</pattern>
</encoder>
</appender>
<logger name="com.test" level="INFO"/>
<root level="TRACE">
<appender-ref ref="FILE" />
</root>
</configuration>

 

 

----->  Added above logback.xml file to path :  ui.app -> src -> main -> content -> jcr_root -> test -> config -> logback.xml file 

 

------> ui.app -> src -> main -> content -> META-INF -> vault -> filter.xml file 

added include :

<include pattern="/apps/test/config(/.*)?"></include>

 

-------> Added configuration file path : 

config -> org.apache.sling.commons.log.LogManger.xml 

org.apache.sling.commons.log.configurationFile="/apps/test/config/logback.xml"

 

 

Avatar

Level 10

Hi @cakayastha ,

It seems like you've configured Logback properly, but there might be a few things to check to ensure it's working as expected:

  1. Check Log File Location: Ensure that the directory /logs exists in your application's environment and that the application has write permissions to it. Otherwise, Logback might fail silently.

  2. Bundle Configuration: Verify that your bundle configuration is correct. The LogManager configuration in org.apache.sling.commons.log.LogManager.xml should point to the correct path of your logback.xml file. Make sure there are no typos or incorrect paths.

  3. Bundle Activation: Confirm that your bundle is getting activated correctly. Check the logs or console to ensure that there are no errors during the activation of your OSGi bundle.

  4. Logger Configuration: Ensure that the logger configuration in logback.xml is correctly targeting the package or class you want to log. In your case, com.test is set to INFO level, so it should log messages of INFO level or higher.

  5. Override Logging Levels: Verify that there are no other configurations overriding your Logback settings. Sometimes, logging configurations can be overridden by other bundles or configurations.

  6. Restart the Application: After making changes, it's often necessary to restart your application to apply the new logging configurations.

If you've checked all of these and are still not seeing Logback in effect, consider looking at the logs for any error messages related to Logback initialization or configuration. Sometimes Logback itself might log error messages that can help diagnose the issue.

Avatar

Level 1

@HrishikeshKa 

Tried setting up console appender but did not see any log print in console either.

I also tried putting logback file in core -> src -> main -> resources -> logback.xml 

 

<configuration>
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>/logs/SampleProject.log</file>
<append>true</append>
<immediateFlush>true</immediateFlush>
<encoder>
<pattern>%d %-5level %X{X-App-ID:-NA} [%thread] %logger{30} %marker- %msg %n</pattern>
</encoder>
</appender>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d %-5level %X{X-app-ID:-NA} [%thread] %logger{30} %marker- %msg %n</pattern>
</encoder>
</appender>
<logger name="com.XXX.XXX.XXX.core" level="INFO"/>
<root level="TRACE">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE" />
</root>
</configuration>

Avatar

Level 1

My understanding is that you can't override org.apache.sling.commons.log.configurationFile property for a custom factory, but I may be mistaken. At least it says so here. https://sling.apache.org/documentation/development/logging.html

I tried and the field wouldn't render in my system console... (http://localhost:4503/system/console/configMgr)

williamm3434422_4-1723843315045.png

williamm3434422_1-1723842047312.png

I think you can only set the logback.xml on the Apache Sling Logging Configuration

which points to the following directory to find your logback.xml: C:\Users\XXXXXX\aem\aem\publish\crx-quickstart (${sling.home})

... or wherever you have installed your aem instance for development purposes.

williamm3434422_0-1723841700793.png

Also, change your root XML node to include the debug attribute as shown below. This will provide more information in the aem console on the bootup of the server with problems with your logback config.  

 

<configuration debug="true">
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>/logs/SampleProject.log</file>
<append>true</append>
<immediateFlush>true</immediateFlush>

....

I tried getting it working with Sentry... but Sentry is not part of the following repo or binding, so it wouldn't work as a custom appender. My error: Caused by: java.lang.ClassNotFoundException: io.sentry.logback.SentryAppender not found by org.apache.sling.commons.log [15]. 

williamm3434422_2-1723843198580.png

Logback Core and Logback Classic are part of the apache-sling-commons-log source so they should work.

https://mvnrepository.com/artifact/org.apache.sling/org.apache.sling.commons.log

Refer to the following for more info as well: https://www.baeldung.com/logback

 

I think I would have to branch off the repo... https://github.com/apache/sling-org-apache-sling-commons-log

and add sentry libraries as maven imports. Here was my logback.xml for reference.

 

 

 

 

<configuration debug="true">
  <!-- Configure the Sentry appender, overriding the logging threshold to the WARN level -->
  <appender name="Sentry" class="io.sentry.logback.SentryAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
    <options>
      <dsn>xxxxx</dsn>
    </options>
      <minimumEventLevel>WARN</minimumEventLevel>
  </appender>
  <!-- Enable the Console and Sentry appenders, Console is provided as an example
  of a non-Sentry logger that is set to a different logging threshold -->
  <root level="WARN">
    <appender-ref ref="Sentry" />
  </root>
</configuration>

 

 

 

I added Sentry via a servlet filter class and wrapped a chain method in a try-catch instead and configured a high ranking value so it would be executed first. At least we have coverage on our servlets.

 

 

 

package com.example.filters;
import io.sentry.Sentry;
import org.osgi.service.component.annotations.Component;
import javax.servlet.*;
import java.io.IOException;
import org.osgi.framework.Constants;
import com.example.services.SentryConfigService;
import org.osgi.service.component.annotations.Reference;
/**
 * This filter will run before every Servlet call and every other Filter
 * The objective of this Filter is to catch all unhandled exceptions and log them in sentry
 * If adding a new filter ensure it is less than the Sentry Filter Ranking value of 999
 */
@Component(
    service = Filter.class,
    property = {
        "sling.filter.scope=" + SentryFilter.REQUEST_FILTER_SCOPE,
        Constants.SERVICE_RANKING + ":Integer=999",
        "sling.filter.pattern=" + SentryFilter.CST_SERVLET_FILTER_PATTERN,
})
public class SentryFilter implements Filter {
    static final String REQUEST_FILTER_SCOPE = "request";
    static final String CST_SERVLET_FILTER_PATTERN = "/bin/example/api/.*";
    
    private SentryConfigService sentryConfigService;
    /**
     * Init is called at application start up of the AEM package. This method is executed regardless if a servlet call is made.
     * In addition, this means changes to the Sentry config values won't reflect at runtime or immediately. A build
     * or reboot of the application needs to be performed in order to re-execute the init function to apply the updated config values.
     */
    
    public void init(FilterConfig filterconfig) {
        if (sentryConfigService.isActive()) {
            Sentry.init(options -> {
                options.setDsn(sentryConfigService.getDsnKey());
                options.setTracesSampleRate(Double.valueOf(sentryConfigService.getTraceRateKey()));
            });
        }
    }
    
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            chain.doFilter(request, response);
        } catch (Throwable e) {
            Sentry.captureException(e);
            throw e;
        }
    }
    
    public void destroy() {
        // Is normal to do nothing
    }
}

 

 

 

Avatar

Level 1

I managed to get logback.xml working with Sentry but it was an extremely customized solution. I had to download the org.apache.sling.commons.log

source code (https://github.com/apache/sling-org-apache-sling-commons-log). Add sentry packages to the code. Ensure those packages were exported. Compile the Apache library. Uninstall the old org.apache.sling.commons.log from AEM Bundles and install the newly compiled version. I also had to configure the binding within AEM on the Apache Sling Logging Configuration page, and it magically worked! I will post a youtube video at a later time on how I did this step by step. I am still experimenting myself and not sure if my company wants to implement this in production. (More detail in next reply)

 

The major caveat with using logback.xml is that you are now responsible for all logging handling within the file itself. It will override all org.apache.sling.commons.log.LogManager.factory.config in your aem project and any built-in handlers within aem. (Work around in further replies)

 

Perhaps I could have exported the sentry libraries from my own source code and that might also make them available without having to modify the sling commons source. Still learning with Maven... (Update: I tried, it doesn't work)

Avatar

Level 1

I just jumped to level 100 in AEM forums on my first post despite being a lowly level one. Booyah!

Caused by: java.lang.ClassNotFoundException: io.sentry.logback.SentryAppender not found by org.apache.sling.commons.log [15]

io.sentry.logback*  and io.sentry* must be locally exported libraries within the context of org.apache.sling.commons.log as I previously implemented.

version 5.5.1

williamm3434422_0-1723948905967.png

williamm3434422_1-1723948928481.png

version 5.1.10, this is the pom.xml

williamm3434422_1-1724163262946.png

williamm3434422_0-1723948905967.png

 

0. Be sure to check your version of apache.sling.commons.log in aem and download that version from Git Hub and build that. If you get an ant build javascript engine exception you need to install Java 8 a.k.a Java 1.8 SDK and build the source code. My instance of AEM 6.5 has 5.1.10 installed so I had to use Java 8 to compile the souce. 

1. Make the changes as shown above. 

2. Compile the source code

3. Uninstall the existing bundle for org.apache.sling.commons.log here... (http://localhost:4503/system/console/bundles)

4. Install the newly compiled bundle, set activate and set the bundle start order to 1 (logging should start first)

5. Update the Sling Logging Configuration to point to the new bundle under the binding section. This will now be an input stream since you installed it manually. Before it was probably sling as this was the install at the time of setting up AEM and was installed from the file system.

williamm3434422_0-1724163219361.png

6. Configure logback.xml with sentry config appropriately to your threshold of logging

7. Reboot AEM and check logs for errors

 

The major caveat with using logback.xml is that you are now responsible for all logging handling within the file itself. It will override all org.apache.sling.commons.log.LogManager.factory.config files in your aem project and any built-in handlers within AEM. (Workaround in next reply)

 

Note that if you have multiple projects installed in AEM they will go to the same sentry DSN unless there is a way to filter based on logger configs. I haven't done this yet but in theory, you could configure multiple sentry appenders with various DSN endpoints. I have to test out still, but this is the idea...

Read more about loggers here: https://logback.qos.ch/manual/configuration.html

I believe the logger hierarchy will only manage exceptions or errors within the context of your source package and associated children.

 

<configuration debug="true">
  <!-- Configure the Sentry appender, overriding the logging threshold to the WARN level -->
  <appender name="SentryOne" class="io.sentry.logback.SentryAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
    <options>
      <dsn>xxxxx</dsn>
    </options>
      <minimumEventLevel>ERROR</minimumEventLevel>
  </appender>

  <appender name="SentryTwo" class="io.sentry.logback.SentryAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
    <options>
      <dsn>aaaaaaaa</dsn>
    </options>
      <minimumEventLevel>ERROR</minimumEventLevel>
  </appender>

  <logger name="com.example1.test">
    <appender-ref ref="SentryOne" />
  </logger>

  <logger name="com.example2.test">
    <appender-ref ref="SentryTwo" />
  </logger>
  <!-- Enable the Console and Sentry appenders, Console is provided as an example
  of a non-Sentry logger that is set to a different logging threshold -->
  <root level="INFO">
    <appender-ref ref="SentryOne" />
    <appender-ref ref="SentryTwo" />
  </root>
</configuration>

 

Avatar

Level 1

I found out how to use logback.xml while retaining factory configs and aem default log behavior. I pulled this from global file log manager config in apache.sling.commons.log source. After some experimenting, I realized you need to use the include node which will just add to the existing global config. Adding appenders in the main logback.xml overrides the default logging behavior of aem and corrupts any factory.configs one has implemented. 

 

<configuration debug="true">
  <!--
  This config file is used when LogBack is being configured from LogbackManager and no
  explicit config is provided. It provides global settings which are then merged with the
  OSGi config.
  -->
  <jmxConfigurator />
  <newRule pattern="*/configuration/osgi"
           actionClass="org.apache.sling.commons.log.logback.OsgiAction"/>
  <newRule pattern="*/configuration/appender-ref-osgi"
           actionClass="org.apache.sling.commons.log.logback.OsgiAppenderRefAction"/>
  <osgi/>
  <include file="${sling.home}\sentry.xml"/>
</configuration>

 

 and  sentry.xml or any other type of logback appending you want.

 

<included>
<appender name="Sentry" class="io.sentry.logback.SentryAppender">
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
    <options>
      <dsn>xxxxxx</dsn>
    </options>
  </appender>
  <logger name="com" level="ERROR">
      <appender-ref ref="Sentry" />
  </logger>
  <logger name="org" level="ERROR">
      <appender-ref ref="Sentry" />
  </logger>
</included>

 

 

If you update your logback.xml to include further files or any other changes in any child files you can reload them without turning off the aem server by clicking the update button on the org.apache.sling.commons.log bundle. This triggers a reset event and reloads the logback.xml at runtime via an event.

http://localhost:4503/system/console/bundles

williamm3434422_0-1724117526849.png

An OSGi event with the org/apache/sling/commons/log/RESET topic resets the Logback at runtime.

 

Avatar

Level 1

You can also accomplish the same through an aem service that loads a file or string and converts it to an input stream. You would have to test, but I believe the reset event may retrigger this source too, not sure. A deployment of your source doesn't retrigger this service but rather when AEM boots up.

 

package com.example

import org.apache.sling.commons.log.logback.ConfigProvider;
import org.osgi.service.component.annotations.Component;
import org.xml.sax.InputSource;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

@Component(service = ConfigProvider.class, immediate = true)
public class Sentry implements ConfigProvider {
    public InputSource getConfigSource() {
        String config = "<included>\n" +
            "  <appender name=\"FOOFILE\" class=\"io.sentry.logback.SentryAppender\">\n" +
            "    <options>\n" +
            "      <dsn>xxxxxx</dsn>\n" +
            "    </options>\n" +
            "    <encoder>\n" +
            "      <pattern>%d %-5level %logger{35} - %msg %n</pattern>\n" +
            "    </encoder>\n" +
            "  </appender>\n" +
            "\n" +
            "  <logger name=\"com\" level=\"ERROR\">\n" +
            "       <appender-ref ref=\"FOOFILE\" />\n" +
            "  </logger>\n" +
            "  <logger name=\"org\" level=\"ERROR\">\n" +
            "       <appender-ref ref=\"FOOFILE\" />\n" +
            "  </logger>\n" +
            "\n" +
            "</included>";
        InputStream stream = new ByteArrayInputStream(config.getBytes(StandardCharsets.UTF_8));
        return new InputSource(stream);
    }
}

 

 

Avatar

Level 1

I will try tomorrow with a log Manager.xml config. I think it will just create another root global sling logging configuration or update the existing. So everything I stated already may still very well apply. Just a different approach potentially. Not sure what kind of binding control it offers. Looks the same according to documentation potentially.

Avatar

Level 1

williamm3434422_0-1723996214673.png

I have no idea how to create another global sling config or set the above properties in it directly via a config file unless I modify the org.sling.apache.commons.log source code directly. I believe this is only a config that can manually be set through the user interface. I think you can only override the following as stated in the documentation.

williamm3434422_1-1723996353348.png

If someone knows how to set those properties via some sort of global config file or bundle config please share. I don't believe the previous comments to be true but I may be incorrect. 

 

Avatar

Administrator

@cakayastha Did you find the suggestions helpful? Please let us know if more information is required. Otherwise, please mark the answer as correct for posterity. If you have found out solution yourself, please share it with the community.



Kautuk Sahni

Avatar

Level 1

@kautuk_sahni  Noop, not yet,. Did try both suggested ways but neither one working.

Avatar

Level 1

The question has been answered in full. And the answer is now clear.