I'm developing an Alexa skill using Java to handle the intents.
The Java project is a maven project. One of the dependencies is on Apache's log4j2.
Here's a snapshot of the log file from my last test. I wish Amazon would allow you to download logs. Edited: I found a way to copy and paste part of the log.
START RequestId: 5077a4b9-f3ad-49f9-9f79-0c78e443bf41 Version: $LATEST
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.
END RequestId: 5077a4b9-f3ad-49f9-9f79-0c78e443bf41
REPORT RequestId: 5077a4b9-f3ad-49f9-9f79-0c78e443bf41 Duration: 2117.38 ms Billed Duration: 2200 ms Memory Size: 512 MB Max Memory Used: 155 MB Init Duration: 3143.46 ms
START RequestId: d3bff3f0-a270-4a02-8cbc-a2be3162741f Version: $LATEST
22:37:48.898 [main] ERROR com.ggl.bible.reader.ReadingTypeIntentHandler - Mode value: reading
22:37:48.916 [main] ERROR com.ggl.bible.reader.ReadingTypeIntentHandler - Reading decision value: reading
22:37:48.997 [main] ERROR com.ggl.bible.reader.ReadingTypeIntentHandler - Reading Decision reading not understood
END RequestId: d3bff3f0-a270-4a02-8cbc-a2be3162741f
I don't know if the image is clear enough, but the second line tells me that the log4j2 can't find the log4j2 configuration file.
I have a log4j.properties file in src/main/resources. It's not much, but it's all I need
log4j.rootLogger=INFO
As you can see from the image (I hope), lines 6 - 8 at 22:37:48 are logger output. For now, all of my logger output is written as ERROR. While this "works", I'd like to be able to distinguish the information from the actual error.
The first two logger lines are information. The third line is an actual error where Alexa didn't interpret the word as I would have liked.
I'd like to set up a working log4j properties file, and I'd like to know where the properties file is supposed to be placed in a maven project. Thanks for your help.
As requested in the comments, the Java class with the logger comments is too long to post in its entirety.
Here's the logger definition.
private static Logger logger = LogManager.getLogger(ReadingTypeIntentHandler.class);
Here's a few lines of logger methods.
if (modeValue.isPresent()) {
logger.error("Mode value: " + modeValue.get());
}
if (bookValue.isPresent()) {
logger.error("Book value: " + bookValue.get());
}
if (startChapterValue.isPresent()) {
logger.error("Start chapter value: " + startChapterValue.get());
}
The Java code works. The messages appear in the log file.
My pom dependency is here. If there's more than one needed, tell me what else I need. Maven isn't telling me I'm missing anything.
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
Edited again: Adding a pom dependency for log4j-api had no effect.
Adding a log4j2.xml file to src/main/resources got rid of the "No log4j2 configuration file found." message in the log. This was the practical answer for me.
Here's the log4j2.xml file I used. I hope this question helps future Alexa skills developers.
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="info">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
Related
I have a function which executes HTTP request/response and I would like to log the content of them.
Such code can be invoked multiple times within the same execution (classified by an "executionId") and each time can have a different "activityId".
What I would like to get is:
A new log file each time the executionId changes (so having execution1.log, execution2.log, execution3.log etc.)
To append into the potentially already existing file all logs for the same execution id (so if file execution1.log has already been created and I'm asked to log again something when executionId == execution1, then appending to that file).
With this purpose in mind, I have configured the following log4j2.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<properties>
<property name="logDir">logs/</property>
</properties>
<appenders>
<RollingFile name="HttpActivityTracingAppender" filePattern="${logDir}/http-logs/${ctx:executionId}.log" append="true">
<PatternLayout pattern="%d{ISO8601} [%t] %c [execution:%X{executionId},activity:%X{activityId}] : %p - %m%n"/>
<Policies>
<OnStartupTriggeringPolicy />
</Policies>
</RollingFile>
</appenders>
<loggers>
<logger name="HttpActivityTracing" level="trace">
<appender-ref ref="HttpActivityTracingAppender"/>
</logger>
</loggers>
</configuration>
... and then I'm invoking the logger as follows:
ThreadContext.put("id", UUID.randomUUID().toString());
ThreadContext.putAll(Map.of("executionId", ..., "activityId", ...);
ThreadContext.pop();
myLogger.trace("bla bla bla");
ThreadContext.clearAll();
The result is that the first time executionId is defined (let's say execution1), then a log file named execution1.log is created under logs/ as expected.
However, on consecutive executions with new values of executionId, I see the new executionId inside the log file but the name of the file used is still execution1.log.
So for example, inside execution1.log I will find stuff like:
2022-09-20T22:52:02,639 [main] HttpActivityTracing [execution:execution1,activity:activity1] : TRACE - ... (ok)
2022-09-20T22:52:02,639 [main] HttpActivityTracing [execution:execution1,activity:activity2] : TRACE - ... (ok)
2022-09-20T22:52:02,639 [main] HttpActivityTracing [execution:execution1,activity:activity3] : TRACE - ... (ok)
2022-09-20T22:52:02,639 [main] HttpActivityTracing [execution:execution2,activity:activity1] : TRACE - ... (NO, I WANT THIS INTO ANOTHER FILE "execution2.log")
2022-09-20T22:52:02,639 [main] HttpActivityTracing [execution:execution2,activity:activity2] : TRACE - ... (NO, I WANT THIS INTO ANOTHER FILE "execution2.log")
I have found several examples all over the web but I couldn't make this one work, I feel I'm not far but I can't make it work.
Can anyone please help?
P.s. I've tried to use fileName instead of filePattern in the RollingFile appender configuration, but it tries to create a file with the name ${ctx:executionId} in it which ends up being rejected by Windows because it contains an illegal character :.
I ended up solving the issue with the exact same configuration than illustrated in the question, plus the following two lines of code after the ThreadContext.pop():
LoggerContext context = (LoggerContext) LogManager.getContext(false);
context.reconfigure();
I have a Spring boot application deployed to GCP App Engine with logback as a logging framework. The problem which I am facing is that I can not find the logger messages which I put into my code. I found a similar post: Google App Engine - Can not find my logging messages. But it is pretty much older and the solutions are not working anymore. On this post, it is mentioned to set the logger level manually. On a similar line, I used logging.properties file to set the level as INFO. But still, it was of no use.
I thought the issue might be with the file permission on the App Engine. So, I specified the log file location at /tmp having full read-write permissions. It did not work. If there are any exception scenarios then stack traces are visible on Stackdriver Logging. Please suggest.
Here is how I managed to make the logs appear in Stackdriver under java.log.
I created a file myApp/src/main/resources/logback.xml and added this configuration:
<configuration>
<appender name="STDOUT" class="com.google.cloud.logging.logback.LoggingAppender">
</appender>
<root level="info">
<appender-ref ref="STDOUT"/>
</root>
</configuration>
I also added the dependency in the file myApp/pom.xml :
<dependencies>
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-logging-logback</artifactId>
<version>0.80.0-alpha</version>
</dependency>
<!-- other dependencies -->
</dependencies>
Then in my main.java I did logger.info("my info log") and logger.error("my error log") and the logs appeared in Stackdriver after a few seconds of accessing my web app.
I took the sample code from the GoogleCloudPlatform/getting-started-java repository to deploy my app.
As per the requirement and for security purpose I am updating Struts project. Before the Struts version is 2.3.24 and now I am updating it to 2.5.12. I have downloaded all the required jar files of Struts and applied to project but I am getting the below error
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.
But I am not using any logger in my project. I have added all the dependency jar files and I am not using Maven, but added related libraries in lib folder. Any suggestions please.
Struts framework is using a logging framework log4j second version.
Struts 2.3 to 2.5 migration
Please be aware that the framework is using Log4j2 now as a main logging layer, the existing old logging layer is deprecated and will be removed soon. Log4j2 supports many different logging implementations, please check documentations for more details.
The file log4j2.xml is required to bootstrap the logging framework. But it's missing from the classpath. It's also missing from the Struts framework.
You should find some log4j2.xml, i.e. from the struts-showcase application or read a step 4 in this tutorial How To Create A Struts 2 Web Application
Step 4 - Add Logging
To see what’s happening under the hood, the example application for this tutorial uses log4j2. You’ll need to add a dependency node for log4j2 to the pom:
pom.xml log4j dependency node
<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>
Using both log4j-core and log4j-api allows to use the latest version of Log4j2 without a clash with version provided by the framework. Setup a log4j2.xml configuration in the src/main/resources folder which contains the following
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<Console name="STDOUT" target="SYSTEM_OUT">
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
</Console>
</Appenders>
<Loggers>
<Logger name="com.opensymphony.xwork2" level="debug"/>
<Logger name="org.apache.struts2" level="debug"/>
<Root level="warn">
<AppenderRef ref="STDOUT"/>
</Root>
</Loggers>
</Configuration>
Note the above log4j2 configuration specifies the console as the log target.
No log4j2 configuration file found means log4j2.xml configuration file is not in your classpath.
Check your project jar contains log4j confuguration file or not.
Otherwise you can set log4j confuguration file path as system property in your build script.
<sysproperty key="log4j.configurationFile" value="file:///${basedir}/src/log4j2.xml" />
Check https://logging.apache.org/log4j/2.x/manual/configuration.html for log4j configuration
I've been banging my head over this one for a few days and can't get it figured out. Log4j2 is backwards compatible if you add the log4j1 compatibility library.
My web-inf\lib has:
slf-api
log4j-1.2-api (backwards compat. library)
log4j-api (log4j2)
log4j-core (log4j2)
log4j-web (auto-wiring for web applications)
My web.xml has:
<!-- log4j2 auto-wiring -->
<context-param>
<param-name>log4jConfiguration</param-name>
<param-value>file:///${catalina.base}/conf/log4j2.xml</param-value>
</context-param>
My [tomcat]/conf/log4j2.xml is:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug">
<Appenders>
<!-- Appends to CONSOLE -->
<Console name="consoleAppender" target="SYSTEM_OUT">
<ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY" />
<PatternLayout pattern="%5p (%F:%L) - %m%n" />
</Console>
</Appenders>
<Loggers>
<Logger name="com.mycompany.componentA" level="WARN" />
<Logger name="com.mycompany.componentA.QueryLogger" level="DEBUG" />
<Logger name="com.mycompany.mycode" level="DEBUG" />
<Root level="WARN">
<AppenderRef ref="consoleAppender" />
</Root>
</Loggers>
</Configuration>
I have upgraded code under my control (com.mycompany.mycode) to log4j2 APIs and they work/log flawlessly. Code that is not under my control but was written against log4j1 (com.mycompany.componentA) just simply fails to log at all. No errors, no debugs, nothing.
Something interesting though... when I start the application I get a log4j1 warning about incorrect configurations when the application starts. This also stumps me because there are no log4j1 libraries (except the compatibility API) in the WAR. Warning is:
log4j:WARN No appenders could be found for logger (com.mycompany.componentB)
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
EDIT: I (finally) figured out what's going on. One of my dependencies did a horribly bad thing and BUNDLED the log4j1 classes into it's final jar. So there are no log4j1 jars on the classpath, but there are log4j1 CLASSES on the classpath.
The only way I was able to get this working was to:
Create BOTH a log4j1 and log4j2 XML configuration files (even though the log4j2 configuration contained all the loggers I wanted)
Let Log4j2 auto-wire itself via the 'log4j-web' artifact + 'log4jConfiguration' web.xml parameter
Manually wire log4j1 by calling the deprecated Log4jConfigurer.initLogging(...) API on server startup
This is probably horribly incorrect, but as indicated above, it was the only way I got it working after weeks of fooling around.
My understanding of the lo4j1 bridge is that wiring up log4j2 and including the bridge is all that should be required (e.g. no need to manually wire log4j1). In practice, that does not seem to be occurring.
That error message means you still have the log4j-1.x jar in your application. Look for it in your WEB-INF/lib and remove it and then it should work.
If not in WEB-INF/lib, then perhaps in your web container (Tomcat?) shared lib folder? Ralph is right that this error message is generated by Log4j-1.2, so it is on the classpath somewhere... Try printing the value of System property java.class.path if necessary.
Update: another way to find the location of the Log4j1 jar is by printing the value of org.apache.log4j.AppenderSkeleton.class.getResource("/org/apache/log4j/AppenderSkeleton.class") from your application.
(I originally suggested Category but this also exists in the Log4j 1 bridge, so AppenderSkeleton is better.)
I use log4j2 in my project something like this:
logger.log(Level.ERROR, this.logData);
My configuration file looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="ERROR" DLog4jContextSelector="org.apache.logging.log4j.core.async.AsyncLoggerContextSelector">
<Appenders>
<!-- Async Loggers will auto-flush in batches, so switch off immediateFlush. -->
<RandomAccessFile name="RandomAccessFile" fileName="C:\\logs\\log1.log" immediateFlush="false" append="false">
<PatternLayout>
<Pattern>%d %p %c{1.} [%t] %m %ex%n</Pattern>
</PatternLayout>
</RandomAccessFile>
</Appenders>
<Loggers>
<Root level="error" includeLocation="false">
<AppenderRef ref="RandomAccessFile"/>
</Root>
</Loggers>
It creates my file, I log something to it, but it's still empty. When I trying to delete this file, OS told me that it in use (if app currently working), but even if I stop application, file still empty.
So which settings should I change to make it work correctly?
I suspect that asynchronous logging is not switched on correctly.
As of beta-9 it is not possible to switch on Async Loggers in the XML configuration, you must set the system property Log4jContextSelector to "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector".
The reason you are not seeing anything in the log is that your log messages are still in the buffer and have not been flushed to disk yet. If you switch on Async Loggers the log messages will be flushed to disk automatically.
I share a cleaner and easier solution.
https://stackoverflow.com/a/33467370/3397345
Add a file named log4j2.component.properties to your classpath. This can be done in most maven or gradle projects by saving it in src/main/resources.
Set the value for the context selector by adding the following line to the file.
Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
Log4j will attempt to read the system property first. If the system property is null, then it will fall back to the values stored in this file by default.