I'm running a lamba on AWS, and using slf4j for logging
Part of the project requirements is that the log level can be set at runtime, using an environment variable, but I'm not sure if that's possible
I'm using the following code, but changing the environment variable "LOG_LEVEL" in the UI to "DEBUG" has no effect to what is added to the CloudWatch logs. Is this possible?
import org.apache.log4j.Level;
import org.apache.log4j.LogManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyLambdaHandler implements RequestHandler<Integer, String> {
private static final Logger LOGGER = LoggerFactory.getLogger(MyLambdaHandler.class);
static {
org.apache.log4j.Logger rootLogger = LogManager.getRootLogger();
String logLevel = (System.getenv("LOG_LEVEL") != null) ? System.getenv("LOG_LEVEL") : "INFO";
rootLogger.setLevel(Level.toLevel(logLevel));
}
public String myHandler(int myCount, Context context) {
LOGGER.debug("Entering myHandler lambda handler";
LOGGER.info("Handling myCount {}", myCount);
int returnValue = myCount * 2;
LOGGER.debug("MyHandler return value {}", returnValue);
return returnValue;
}
}
Yes it's possible! You need to take care of two things:
For the first problem, all you need to do is pass a lambda environment variable with name JAVA_TOOL_OPTIONS
and value "-DLOG_LEVEL=DEBUG"
.
For the second point, you can add this to your Java project src/main/resources/log4j.properties
with content something like
log4j.rootCategory=${LOG_LEVEL}, LAMBDA
LOG_LEVEL_PATTERN=%5p
LOG_PATTERN=[%d{yyyy-MM-dd HH:mm:ss.SSS}] boot%X{context} ${LOG_LEVEL_PATTERN} [%t] - %c{1}: %m%n
log4j.appender.LAMBDA=com.amazonaws.services.lambda.runtime.log4j.LambdaAppender
log4j.appender.LAMBDA.layout=org.apache.log4j.PatternLayout
log4j.appender.LAMBDA.layout.conversionPattern=${LOG_PATTERN}
And that's it!
If everything goes well you should soon see in your logs a line reading something like
Picked up JAVA_TOOL_OPTIONS: -DLOG_LEVEL=DEBUG
and hopefully start seeing some debug statements.
Notice how LOG_LEVEL
is embedded in the value of the lambda variable as opposed to being the variable name. This is a useful indirect way to feed JVM arguments down a lambda which you can then use as system properties.
Kudos to https://zenidas.wordpress.com/recipes/system-properties-for-a-java-lambda-function/