I have small application that is uploading pictures to another website via webservice.
My current problem is, that Axis is logging the whole xml message (including the binary data of the picture!) via STDOUT and I can't seem to figure out, how to disable it.
My log4j settings for jboss (jboss-log4j.xml) includes an appender for normal STDOUT Info loggings, and I tried to disable axis with different category settings:
<appender name="STDLOG" class="org.jboss.logging.appender.RollingFileAppender">
<errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
<param name="File" value="${jboss.server.log.dir}/myapplication.log"/>
<param name="Append" value="true"/>
<param name="MaxFileSize" value="5MB"/>
<param name="MaxBackupIndex" value="10"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n"/>
</layout>
</appender>
using this setting for STDOUT:
<category name="STDOUT">
<priority value="DEBUG"/>
<appender-ref ref="STDLOG"/>
</category>
I tried these category settings without any change in the result:
<category name="log4j.logger.org.apache.axis" additivity="false">
<priority value="ERROR"/>
</category>
<category name="org.apache.axis">
<priority value="ERROR"/>
</category>
Some sample log output looks like this:
2009-08-07 10:29:43,911 INFO [STDOUT] (http-127.0.0.1-8080-1) =======================================================
= Elapsed: 2190 milliseconds
= In message: <?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<addVehicleImage xmlns="urn:VMgrWebService">
<id xmlns="">APP-T4QKR3U</id>
<idType xmlns="">chiffre</idType>
<data xmlns="">9j4AAQSkZJRgABAQAAAQABAAD2wBDAAUDBAQEAwUEBAQFB
QUGBww0TDMnrXAfKlLjnNJZcciiAOtqk9NG99qhZJKuyYq5k3G
8P2bVSOpT7rVddRP2Z/yqidRuMMKaO2CXRQNWP2jfOo4S4Bo3W
removed rest of image data...
IBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGe1UqaZJJy0jSHPGQ
2009-08-07 10:29:43,927 INFO [STDOUT] (http-127.0.0.1-8080-1) Upload result: true for image mypicture.JPG
Update
I checked the axis-1.4.jar and there is a file called simplelog.properties:
# Logging detail level,
# Must be one of ("trace", "debug", "info", "warn", "error", or "fatal").
org.apache.commons.logging.simplelog.defaultlog=info
Setting this to error within the jar, or as a category in jboss-log4j.xml didn't help at all.
Anyone any idea how I can turn off the Axis logging or at least set it to ERROR level?
Cheers
Frank
This might be a bit late in the day, but the problem does not seem to be that logging itself is done in Axis (via System.out and Commons Logging), but rather that the LogHandler is present in the handler chain. That is how the elapsed time is getting logged.
You can disable this handler from the Axis configuration file(s) - server-config.wsdd and/or client-config.wsdd, depending on whether you are using Axis as a server or a client.
The reason why you are seeing messages in your console is probably due to the LogHandler.writeToConsole property being set to true. If you set LogHandler.writeToConsole to false, it should write into a file as defined by the LogHandler.fileName property. By default, the file name is axis.log.
Ok, after trying to find a better solution, the only real way was to check the old legacy code and turn all System.out calls into real logging statements (much better anyway), and then simply filter the remaining STDOUT messages into a different log file.
One of the main reasons seems to be Jboss itself. This discussion from the axis2 mailing list explains why:
Ahh, but you didn't mention you are using jboss! It pretty much forces
you to use their parent log4 config . Ignore the axis2 logging in this
case, and see:
~/jboss/server/default/conf/log4j.xml
There you have to limit the categories. For example, you have:
<category name="org.apache">
<priority value="INFO"/>
</category>
You could leave that as is and just get your logs out of server.log .
I tried setting the category, without success. I assume this is because of differences between axis and axis2. So the only solution left was to go the good coding way and just don't use STDOUT in your own code ;-)
First off, you'll want to check that your log4j configuration is actually the one being read - I recall that in the past, at least one axis jar (I think it may have been axis-ant.jar) was guilty of bundling their own log4j.properties. It may be that log4j is reading a different configuration file than yours, making your efforts at tweaking the configuration pointless!
You can enable the system properties -Dlog4j.debug to have log4j print to standard out which configuration file is being read. If necessary, you can use -Dlog4j.configuration=<file> to point to your own file.
Also, I don't think this is causing your issues, but why are you setting additivity to false?
The problem is that Axis is not using Log4j to log that message, so attempting to change the log4j logging level on that class isn't relevant. Axis is using a System.out.println.
The only thing I can think of (which is really not nice given the side effects) is to turn the STDOUT logging off altogether. Probably setting the priority to off will do.
The only real solution is to fix Axis and patch the code to not pump the xml to System.out but rather use the logging mechanism instead - then you could control it.
It is very important to know which log4j.properties file or log4j.xml is being read. and as Matt pointed out, this is crucial in knowing why your tweaking efforts are not working.
Related
Context: Java web application running in Tomcat, Log4j 2 version 2.5. Logging set up to go to one Sentry instance using the Raven connector and one ELK (ElasticSearch + Logstash + Kibana) instance.
Configuration looks like this (anonymized):
<configuration>
<appenders>
<Raven name="Sentry">
<dsn>https://foo#bar.baz/1</dsn>
</Raven>
<Socket name="Logstash" host="1.2.3.4" port="1234">
<SerializedLayout />
</Socket>
</appenders>
<loggers>
<root level="info">
<appender-ref ref="Sentry" level="warn" />
<appender-ref ref="Logstash" />
</root>
</loggers>
</configuration>
Problem is that if Sentry or ELK starts acting up (long response times, unreachable, ...), the application threads get blocked trying to log and the application effectively dies.
Is there a preferred solution to this problem? Some kind of circuit breaker would be ideal here: after detecting a problem with the remote logging destination Log4j 2 would disable the appender for some time.
We use another appender wrapped in an <Async/> appender, but as far as I understand that is a good solution to make the logging... well, asynchronous, but not to fix the problem of unresponsive log destination.
In our system we have a special component called logs-forwarder that collects all the logs by log4j and other systems and forwards them to logstash / splunk etc. what might have you. So that's one valid option.
How can I use Logback to capture System.out messages in a Java program?
For example, I would like to use this code:
System.out.println("test: console out to file instead");
... and capture it's output to a file.
Can this be done using the logback.xml config file?
There's a little jar that does this for you: http://projects.lidalia.org.uk/sysout-over-slf4j/index.html
Please do read the FAQ: http://projects.lidalia.org.uk/sysout-over-slf4j/faq.html - If you use this module and configure logback to output to stdout, you'll get a stream of StackOverFlowErrors :D
If you want to do this yourself, you need to replace System.out and System.err with a custom PrintWriter (?I cannot fully remember the class name). This custom PrintWriter needs to forward the calls to logback in a semi intelligent manner, as print writters can also print character by character rather than by line.
The sysout-over-slf4j solutions answers the question 100%.
Just take note: If you setup the Java Util Logger -> SLF4j bridge (jul-to-slf4j), all the System.out.println messages will also be in you logback log file, along with all the messages printed to the Java util logger.
Here is how to set it up:
https://stackoverflow.com/a/43242620/2359435
Yes you can do it with some configuration similar to..
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<target>System.out</target>
<filter class="com.foo.StdOutFilter" />
...
</appender>
<logger name="mylogger" level="debug">
<appender-ref ref="stdout" />
</logger>
How do I filter log messages from external third party frameworks? I am using Hibernate and Spring framework and I would like to suppress the logs so that only my log4j logs appears.
In my log4j.properties file I set the root logger logging level to ERROR. Then for packages I specifically want to log, like my application code, I set the logging level to INFO or DEBUG.
log4j.rootLogger=ERROR, stdout
log4j.logger.com.initech.tps=DEBUG
log4j.logger.org.hibernate.SQL=INFO
I see co-workers who set root logging low and then end up listing everything they don't want to see, that just seems backward to me. I would rather list what I want to log than all the things I don't want to log.
BTW turning logging off entirely for a third-party component seems like a bad idea to me. For instance, Spring is relatively noisy and uses WARN for things I really don't need to know about, but if it logs an ERROR entry for something I want to see it.
You can do it by changing logger level in log4j.properties/log4j.xml file.
You need to set logger's <level value="off"/> if you want to filter logs from package but keep logger configuration for later use.
You could also set it to highest level to log only in case of error or fatal issue.
Following entries should be added to log4j.xml to turn off logging from hibernate and springframework packages:
<logger name="org.springframework">
<level value="off"/>
</logger>
<logger name="org.hibernate">
<level value="off"/>
</logger>
In log4j.properties you can define individual levels on a per logger basis:
log4j.logger.<name>=FATAL
In log4j.xml the syntax is
<logger name="<name>">
<level value="fatal"/>
</logger>
<name> is often the full qualified classname. You might want to use WARN or ERROR instead of FATAL
Just don't add those packages in your log4j.properties. For instance, you must have this for Spring in your properties file. Take it out if you have some entries like below (anything that starts with org.springframework). Same needs to be done for hibernate.
#Logs the SQL from Spring
log4j.logger.org.springframework.jdbc.core.JdbcTemplate=ERROR
#Logs the SQL parameters from Spring
log4j.logger.org.springframework.jdbc.core.StatementCreatorUtils=ERROR
Also as it was mentioned you should also set the following. I forgot to mention this.
log4j.rootLogger=FATAL
or
log4j.rootLogger=ERROR
I have a servlet. But it is not working as desired. Hence for debugging purposes, I want to print statements to the java console(the one that can be opened using the java icon in taskbar). However, if I use System.out.println("message"), it doesnt display in java console.
Is there any alternative way where I can display messages to the console from the servlet?
Or can anyone suggest me an alternative way to display messages to any other console?
In which console do you expect it to appear?
Depending on the servlet container (I assume Tomcat), the logs are stored in a logs folder. For Tomcat this is tomcat/logs (or more often referred to as CATALINA_HOME/logs). If you are running it from within an IDE - they should be in the IDE console.
As a sidenote, using System.out isn't advisable for a real product - use a logging framework (like log4j).
Servlet (HttpServlet) has a method log(String s) inherited from GenericServlet class.
So you can just include
log("output text")
in the servlet's code and see output.
If you use Eclipse log goes right into console.
If you use IntellijIdea log goes into Run --> "Tomcat Localhost Log" tab.
I want to print statements to the java console(the one that can be opened using the java icon in taskbar)
You need to realize that servlets actually runs at the server side, not at the client side. Those are in fact two physically different environments which communicates with each other through the network using the HTTP protocol. That Java console will only work for Java programs which runs at the client side, such as applets and JNLP.
In your case, you just need to read the server logs. That's where the stdout will by default print to, or use a better configureable logging framework such as logback. The server logs are usually found in a straightforward folder/file in the server installation directory, such as /logs in case of Tomcat.
Look for the log file in the log-folder of your servlet container (i.e. Tomcat).
As suggested use log4j to generate debug messages. This logging framework provides a configuration file where you can set things like where the logs should be written into or how the log messages should be formatted. As soon it's in place you can replace
System.out.println("message");
with
log.debug("your debug message");
or
log.info("in case of a message with info character");
log.error("routine foo has experienced an exception", e);
Now your code is much cleaner and there is even another benefit - when being placed correctly these logs act as documentation for your code segments.
You should use logging, e.g. java.util.logging or log4j
Example of relevant log4j configuration:
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p %c{1} - %m%n"/>
</layout>
</appender>
<root>
<priority value ="debug" />
<appender-ref ref="console" />
</root>
I have a several webapps which use java.util.logging. Tomcat 5.5 is configured to use the Juli logger so that each webapp has its own log file. The problem is that Juli does not have properties for maximum file size and file count. Using Juli the files will grow unbounded and only roll at the end of the day. Also, an unlimited number of log files are retained.
You can see the FileHandler properties on this page - Apache Tomcat 5.5 Documentation
There is no limit or count property (the following lines do nothing)
org.apache.juli.FileHandler.limit=102400
org.apache.juli.FileHandler.count=5
Without changing the webapps is there a way to get unique log files for each application with some type of bounds on the log file sizes?
UPDATE:
The solution I found was not use the Juli logger at all!
java.util.logging.FileHandler.limit=102400
java.util.logging.FileHandler.count=5
Thanks,
Greg
Update: I see your point now after reading more. "Tomcat's JULI implementation is not intended to be a fully-featured logging libary, only a simple bridge to those libraries. However, JULI does provide several properties for configuring the its handlers. These are listed below." Funny that they say that the default java.util.Logging implementation is too limited then they work around it by providing an even more limiting implementation.
FileHandler javadocs
java.util.logging.FileHandler.limit specifies an approximate maximum amount to write (in bytes) to any one file. If this is zero, then there is no limit. (Defaults to no limit).
java.util.logging.FileHandler.count specifies how many output files to cycle through (defaults to 1).
for the one file per web app, you probably want to separate it by the name of the logger and it depends on how the loggers are created for each app. If they're based off the package or class name then you can filter the logs based on that. It looks like the sample on the link you provided tells how to do this
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = \
2localhost.org.apache.juli.FileHandler
EDIT: Just realized you wanted per webapp logging which might not be possible with this setup...
My suggestion, assuming your are using Tomcat 6.0, is to compile the extra component for full commons-logging and use Log4j to configure rolling logs.
Building instructions here
http://tomcat.apache.org/tomcat-6.0-doc/building.html
Then replace the tomcat-juli.jar in the /bin directory of Tomcat and place the tomcat-juli-adapters.jar in the /lib directory along with log4j.jar and log4j.properties.
Then using something like:
<appender name="file" class="org.apache.log4j.RollingFileAppender">
<param name="File" value="logfile.log"/>
<param name="Threshold" value="INFO"/>
<param name="MaxFileSize" value="10MB"/>
<param name="MaxBackupIndex" value="3"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{ISO8601} %p %m%n"/>
</layout>
</appender>