Search code examples
javaamazon-web-serviceslog4j2amazon-cloudwatchamazon-cloudwatchlogs

Helpme to get log4j2 correctly


I am newbie to implement log4j2 with my aws java lambda cloud watch. I need custom log instead of cloud watch logs. I am uploading a csv of large size record using step function.So the built in cloud watch logs the same thing repeatedly. So I am planning to add log4j2 with my java lambda. For this I added below dependency in my pom.xml

    <dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>aws-lambda-java-log4j2</artifactId>
    <version>1.0.0</version>
  </dependency>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.8.2</version>
  </dependency>
  <dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.8.2</version>
  </dependency>

Then added the log4j2.xml under src/main/resources. The log4j2.xml is like below

<?xml version="1.0" encoding="UTF-8"?>
<Configuration packages="com.amazonaws.services.lambda.runtime.log4j2.LambdaAppender">
  <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="debug">
      <AppenderRef ref="Lambda" />
    </Root>
  </Loggers>
</Configuration>

After that to check the log i have created one aws java lambda project and my code looks like below.

 package com.amazonaws.lambda.demo;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.S3Event;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.S3Object;

import com.amazonaws.services.stepfunctions.AWSStepFunctions;
import com.amazonaws.services.stepfunctions.AWSStepFunctionsClientBuilder;
import com.amazonaws.services.stepfunctions.model.StartExecutionRequest;

import com.amazonaws.services.lambda.runtime.Context;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class log4jTest implements RequestHandler<S3Event, String> {
    static final Logger logger = LogManager.getLogger(log4jTest.class); 
    private AmazonS3 s3 = AmazonS3ClientBuilder.standard().build();      
    public log4jTest() {}
    log4jTest(AmazonS3 s3) {
    this.s3 = s3;
    }
@Override
public String handleRequest(S3Event event, Context context) {
    String bucket = event.getRecords().get(0).getS3().getBucket().getName();
    String key = event.getRecords().get(0).getS3().getObject().getKey();
    try {
            for(int i=0;i<10;i++)
                {
                    if(i==10)
                        {
                            logger.error("log data Error");
                        }
                }

        } catch (Exception e) {

                            context.getLogger().log(String.format(
                                "Error getting object %s from bucket %s. Make sure they exist and"
                                    + " your bucket is in the same region as this function.", key, bucket));
                            }
                return null;
}
}

According to the aws document Logging (Java). Everything I did as the doc says. But when I am run the lambda I am getting an error like below

ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console. Set system property 'org.apache.logging.log4j.simplelog.StatusLogger.level' to TRACE to show Log4j2 internal initialization logging.

I am checking the log in lambda -> Monitoring -> jump to logs [Screen shot given below]

enter image description here

I googled and went through below sites.

No log4j2 configuration file found. Using default configuration: logging only errors to the console

No log4j2 configuration file found. Using default configuration: logging only errors to the console

But I dont know I can't fix this error anyway. Please anyone can help me on this. It would be really grateful if u can do this.

Thanks in advance


Solution

  • I found I did not have any luck placing my log4j2.xml file at either src/main/resources or at src/main/resources/path/to/my/Lambda/log4j2.xml. So I did a little digging. In my case, Lambda deploys my handler with a classpath whose first entry is a folder /var/task. The class files are rooted directly at /var/task - but the resource files are placed in /var/task/resources - so Log4J2 cannot find log4j2.xml in the classpath. The solution for me was to use the log4j.configurationFile property to specify the location of the file within the resources folder:

    static {
        // System.setProperty("org.apache.logging.log4j.simplelog.StatusLogger.level","TRACE");
        System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager");
        System.setProperty("log4j.configurationFile", "resources/lambda-log4j2.xml");
    }
    

    I also renamed the file "lambda-log4j2.xml" - to make sure it was reading my file, during debugging this... This static block is at the top of my handler class.