1

I am using the following configurations in my code but cloudwatch logs are not getting generated. Log4j2.xml is present in main/resources. I am following the AWS documentation and some stack overflow but I am not getting the logs it says -

Cloudwatch Logs

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
START RequestId: e36-c827-46-93-a7 Version: $LATEST
Transforming org/apache/logging/log4j/core/lookup/JndiLookup (lambdainternal.CustomerClassLoader@433d)
2022-03-07T16:01:51.527+05:30   2022-03-07 10:31:51,526 main ERROR Error processing element Lambda ([Appenders: null]): CLASS_NOT_FOUND
2022-03-07T16:01:51.626+05:30   2022-03-07 10:31:51,626 main ERROR Unable to locate appender "Lambda" for logger config "root"

Log4j2.xml

<?xml version="1.0" encoding="UTF-8"?>
<Configuration packages="com.amazonaws.services.lambda.runtime.log4j2" status="WARN">
    <Appenders>
        <Lambda name="Lambda">
            <PatternLayout>
                <pattern>%d{yyyy-MM-dd HH:mm:ss} %X{AWSRequestId} %-5p %c{1}:%L - %m%n</pattern>
            </PatternLayout>
        </Lambda>
    </Appenders>
    <Loggers>
        <Root level="INFO">
            <AppenderRef ref="Lambda" />
        </Root>
        <Logger name="software.amazon.awssdk" level="WARN" />
        <Logger name="software.amazon.awssdk.request" level="DEBUG" />
    </Loggers>
</Configuration>

Gradle Dependencies used:

implementation 'org.apache.logging.log4j:log4j-api:2.17.2'
implementation 'org.apache.logging.log4j:log4j-core:2.17.2'
runtimeOnly 'org.apache.logging.log4j:log4j-slf4j18-impl:2.17.0'
runtimeOnly 'com.amazonaws:aws-lambda-java-log4j2:1.5.1'

Service class Logging Declaration

@Slf4j
public class ABC {
        
    public void method1(){
        log.info(" HELLO WORLD  ________ ");
    }
}

Please help.

Jens
  • 20,533
  • 11
  • 60
  • 86
satyam pandey
  • 43
  • 1
  • 7

4 Answers4

1

alternatively, You can use the Context object to get a logger like below

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;
import com.amazonaws.services.lambda.runtime.RequestHandler;
public class MyClass implements RequestHandler<Map<String, Object>, Void> {
   @Override
public Void handleRequest(Map<String, Object> inputRequest, Context context) {
LambdaLogger logger = context.getLogger();
logger.log("Hello ");
}}
Srinivas Nangana
  • 147
  • 1
  • 2
  • 16
  • 2
    Yes. I would also recommend to use the logger provider in the context or just print to stdout. I know it sounds weird, but using Log4J in Lambdas has little to no benefit. Even worse, if not configured properly, it will be worse. For example: CloudWatch automatically adds timestamps, if log4j does it as well you have redundant data and worse readability ... – Jens Mar 07 '22 at 11:40
  • @Jens I am aware of the LambdaLogger approach, I just want to understand if we can configure log4j logs for cloudwatch. I am following AWS documentation for achieving it but not sure where iam going wrong. – satyam pandey Mar 08 '22 at 05:22
  • @TheAccidentalCoder Then make sure that you deploy Log4J dependencies and configuration to the Lambda service. Looking at your post I'd say that you are not including the required dependencies in your Jar. (see `runtimeDependency` which means that the dependency is already available in the Lambda JVM, which I don't think it is). – Jens Mar 08 '22 at 07:44
0

Changing these lines:

runtimeOnly 'org.apache.logging.log4j:log4j-slf4j18-impl:2.17.0'    
runtimeOnly 'com.amazonaws:aws-lambda-java-log4j2:1.5.1'

To

implementation 'org.apache.logging.log4j:log4j-slf4j18-impl:2.17.0'
implementation 'com.amazonaws:aws-lambda-java-log4j2:1.5.1'

Solved this problem for me

0

Just add this dependencies:

            <dependency>
                <groupId>com.amazonaws</groupId>
                <artifactId>aws-lambda-java-log4j2</artifactId>
                <version>1.5.1</version>
            </dependency>
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-core</artifactId>
                <version>2.20.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-api</artifactId>
                <version>2.20.0</version>
            </dependency>
            <dependency>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-slf4j-impl</artifactId>
                <version>2.20.0</version>
            </dependency>

Be careful that any other logging packages are removed, also slf4j packages.

0

The issue that you are seeing with cloudwatch logs not being generated is an artifact of a known issue where log4j2 does not work correctly with shadowJar or a shaded jar. In order to correct this and get the log output you expect you need an additional transformation at build time.

Using Gradle

import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer

shadowJar{
    transform(Log4j2PluginsCacheFileTransformer)
}

To try to more quickly remediate this issue I have linked all the posts I used to correct this below.

Disclaimer: To the person who deleted my previous post - the posts that I posted on are not duplicates but they are similar, there is a nuanced difference between them and all of them helped understanding various aspects of the problem. It took a very long time to put together all these random pieces of info into a true fix and I stand by my answer as being relevant on this post. Please do not remove posts that are geared towards saving multiple hours of research for others. Especially when there is no way to contact you, no suggested edit system, and no way to dispute YOUR opinion. Please allow the community to decide how valuable a post is by the vote system.

Rhineb
  • 305
  • 3
  • 12