AWS Lambda运行时是否可以更改日志级别?

12

我在AWS上运行lambda,并使用slf4j进行日志记录。

项目要求之一是可以在运行时使用环境变量设置日志级别,但我不确定是否可行。

我正在使用以下代码,但在UI中更改环境变量“LOG_LEVEL”为“DEBUG”对添加到CloudWatch日志的内容没有影响。这是否可能?

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;

    }

}
2个回答

4

我能够通过使用amazon版本的log4j2并对log4j2.xml配置文件进行更改来解决这个问题。

在maven中添加以下依赖项:

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

在配置中使用logger级别的环境变量

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

最后,在lambda函数中使用log4j2记录器

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

public class MyLambdaHandler implements RequestHandler<Void, Void> {

    private static final Logger LOGGER = LogManager.getLogger(MyLambdaHandler .class);

    public Void handleRequest(Void myVoid, Context context) {

        LOGGER.error("Log info enabled: {}", LOGGER.isInfoEnabled());
        LOGGER.info("Info messge");
        LOGGER.error("Log error enabled: {}",  LOGGER.isErrorEnabled());
        LOGGER.error("Error Message");
        LOGGER.error("Log trace enabled: {}",  LOGGER.isTraceEnabled());
        LOGGER.trace("trace message");
        LOGGER.error("Log warning enabled: {}",  LOGGER.isWarnEnabled());
        LOGGER.warn("warn message");
        LOGGER.error("Log debug enabled: {}",  LOGGER.isDebugEnabled());
        LOGGER.debug("debug message");
        return null;

    }

}    

然后将LOG_LEVEL环境变量设置为适当的级别,以便在日志中查看相关条目。


你是否在使用Maven Shade插件来处理这个Lambda函数,并且也成功地使其工作了呢? - Darren
1
我已将代码添加到Github存储库中:https://github.com/tetsujin1979/aws-log-level - Joseph McCarthy
@JosephMcCarthy 我从你的git存储库创建了一个lambda函数,并将环境变量LOG_LEVEL设置为info,但我仍然看不到日志输出中的任何日志消息,我只看到以下内容(跳过开始请求和报告请求消息) %d [%thread] %-5level %logger - %msg%n%d [%thread] %-5level %logger - %msg%n%d [%thread] %-5level %logger - %msg%n%d [%thread] %-5level %logger - %msg%n%d [%thread] %-5level %logger - %msg%n%d [%thread] %-5level %logger - %msg%nEND RequestId: 4ecf66b5-480e-4068-a9c1-e32433e487d9 我有遗漏的地方吗? - abhishekmahawar
云监控日志还显示“ERROR StatusLogger Unrecognized format specifier [d]”和其他类似的消息。 - abhishekmahawar
好的,我通过使用此处定义的shade插件配置解决了问题:https://github.com/aws/aws-lambda-java-libs/tree/master/aws-lambda-java-log4j2 - abhishekmahawar
@JosephMcCarthy 你有确认日志是否被适当记录,即使当 LOG_LEVEL=INFO 时,所有内容都被记录下来了吗? - undefined

4

是的,这是可能的!您需要注意两件事:

  • 一、更新Lambda环境变量
  • 二、确保log4j将会接收到更新

对于第一个问题,您只需传递一个名为JAVA_TOOL_OPTIONS且值为"-DLOG_LEVEL=DEBUG"的lambda环境变量即可。

对于第二个问题,您可以将以下内容添加到Java项目的src/main/resources/log4j.properties文件中:

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}

好的,就这些!

如果一切顺利,很快你的日志中应该会看到一行类似于以下内容的记录:

Picked up JAVA_TOOL_OPTIONS: -DLOG_LEVEL=DEBUG

希望能看到一些调试语句。

请注意,LOG_LEVEL被嵌入到lambda变量的值中,而不是作为变量名。这是一种有用的间接方式,可以通过lambda传递JVM参数,然后将其用作系统属性。 感谢https://zenidas.wordpress.com/recipes/system-properties-for-a-java-lambda-function/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接