Tomcat logging properties filtering - java

I have simplified tomcat's logging properties to just this:
handlers = java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format=%1$tF %1$TT.%1tL [::] %4$s %3$s %5$s %n
org.springframework.aop.framework.CglibAopProxy.level = ERROR
My issue is that the last line seems to be completely ignored and I keep seeing logs like this:
2018-05-09 10:40:33.159 [::] INFO org.springframework.aop.framework.CglibAopProxy
I am absolutely sure it comes from this logger thanks to the log format I set in the logging.properties.

My issue is that the last line seems to be completely ignored...
It is ignored because ERROR fails to be parsed as valid level. Per the docs:
Valid values are integers between Integer.MIN_VALUE and Integer.MAX_VALUE, and all known level names. Known names are the levels defined by this class (e.g., FINE, FINER, FINEST), or created by this class with appropriate package access, or new levels defined or created by subclasses.
Change your logging line to one of the valid levels that is higher than INFO. Choose one of the following log lines:
org.springframework.aop.framework.CglibAopProxy.level = OFF
org.springframework.aop.framework.CglibAopProxy.level = SEVERE
org.springframework.aop.framework.CglibAopProxy.level = WARNING

Related

Custom logging with log4j2 jdbc appender in java

I am trying to log my events in my database using log4j2. Specifically I am using log4j2 jdbc appender in my properties configuration file for that purpose. By using default log4j2 log levels everything works. The log values successfully get inserted in database.
This is my initial appender in my log4j2 properties file:
# JDBC appender
appender.db.type = Jdbc
appender.db.name = databaseAppender
appender.db.tableName = db_name.test
appender.db.cf.type = ConnectionFactory
appender.db.cf.class = com.myproject.ConnectionFactory
appender.db.cf.method = getConnection
appender.db.col2.type = Column
appender.db.col2.name = message
appender.db.col2.pattern = %m
appender.db.col3.type = Column
appender.db.col3.name = category
appender.db.col3.pattern = %M{1}
appender.db.col4.type = Column
appender.db.col4.name = timestamp
appender.db.col4.isEventTimestamp = true
appender.db.col5.type = Column
appender.db.col5.name = log_level
appender.db.col5.pattern = %-5p
appender.db.filter.threshold.type = ThresholdFilter
appender.db.filter.threshold.level = info
appender.db.filter.threshold.onMatch = Accept
appender.db.filter.threshold.onMismatch = Deny
But then I tried to create a custom log level following this log4j2 site https://logging.apache.org/log4j/2.x/manual/customloglevels.html
LOG.log(Level.forName("DIAG", 350), "a diagnostic message");
It successfully logs the event with the defined log level. And even places the data in database since threshold level is info in my jdbc appender. As info intLevel > diag intLevel.
My problem is if I changed the threshold level to diag in my jdbc appender it doesn't work at all i.e.
appender.db.filter.threshold.level = diag
Nothing is inserted in my database. So my first question is why it is not working and please give me any solution if possible.
Another thing is that I twitched around the intLevel of DIAG to 10 like:
LOG.log(Level.forName("DIAG", 10), "a diagnostic message");
And now it is inserting in database but also throws some errors.
2019-05-24 12:06:00,248 main WARN Error while converting string [diag] to type [class org.apache.logging.log4j.Level]. Using default value [null]. java.lang.IllegalArgumentException: Unknown level constant [DIAG].
at org.apache.logging.log4j.Level.valueOf(Level.java:320)
at org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$LevelConverter.convert(TypeConverters.java:288)
at org.apache.logging.log4j.core.config.plugins.convert.TypeConverters$LevelConverter.convert(TypeConverters.java:284)
at org.apache.logging.log4j.core.config.plugins.convert.TypeConverters.convert(TypeConverters.java:419)
at org.apache.logging.log4j.core.config.plugins.visitors.AbstractPluginVisitor.convert(AbstractPluginVisitor.java:149)
at org.apache.logging.log4j.core.config.plugins.visitors.PluginAttributeVisitor.visit(PluginAttributeVisitor.java:45)
at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.generateParameters(PluginBuilder.java:253)
at org.apache.logging.log4j.core.config.plugins.util.PluginBuilder.build(PluginBuilder.java:135)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createPluginObject(AbstractConfiguration.java:964)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:904)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:896)
at org.apache.logging.log4j.core.config.AbstractConfiguration.createConfiguration(AbstractConfiguration.java:896)
at org.apache.logging.log4j.core.config.AbstractConfiguration.doConfigure(AbstractConfiguration.java:514)
at org.apache.logging.log4j.core.config.AbstractConfiguration.initialize(AbstractConfiguration.java:238)
at org.apache.logging.log4j.core.config.AbstractConfiguration.start(AbstractConfiguration.java:250)
at org.apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:548)
at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:620)
at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:637)
at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:231)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:153)
at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:45)
at org.apache.logging.log4j.LogManager.getContext(LogManager.java:194)
at org.apache.logging.log4j.LogManager.getLogger(LogManager.java:581)
at com.myproject.Main.<clinit>(Main.java:35)
Any help would be greatly appreciated and thank you in advance.
Since you have not defined intLevel in log4j2.properties file so add
customLevel.DIAG =350
where 350 is the intLevel.
This may remove the error.

How to destroy log4j logger instances

I have a code that run concurrently, and for each run it need log something in file. Each execution - new story with unique file.
So, I can't just get the logger for classname, add file appender, write logs, close and remove appender, because when concurrect code run - logger will contains both appenders, and logs will be written to both files.
So, I can create a new logger instance for each execution Logger.getLogger(classname + counter), but how to mark it as garbage after work is done?
P.S. Moreover... I need somethimes print to console from all this loggers.
Maybe I do something wrong, maybe log4j not created for this pattern and I have to implement it. But log4j - priority choose for me, because it already widely used in this big application.
Thank you in advance, Andrei!
You can't destroy / clean up Appender instances. But you can improve the solution you have with Log4j2 toolbox.
Routing things to dynamic files in Log4j is possible, but most of the time a Marker in a file is sufficient, or at least a starting point for more complex routing.
Please do read up on its documentation. Especially the last paragraph is important to your case:
Some important rules about Markers must be considered when using them.
Markers must be unique. They are permanently registered by name so care should be taken to insure that Markers used in your application are distinct from those in the application's dependencies, unless that is what is desired.
Parent Markers can be added or removed dynamically. However, this is fairly expensive to do. Instead, it is recommended that the parents be identified when obtaining the Marker the first time as shown in the examples above. Specifically, the set method replaces all the markers in a single operation while add and remove act on only a single Marker at a time.
Evaluating Markers with multiple ancestors is much more expensive than Markers with no parents. For example, in one set of tests to evaluate whether a Marker matched its grandparent took 3 times longer than evaluating the Marker itself. Even then though, evaluating Markers is inexpensive compared to resolving the callers class name or line number.
Then you can use the marker in the configuration in places where a pattern is expected like this: $${marker:}. I haven't used that in a filename though and doubt that it works, but you can create routing based on the Marker.
I used this simple test script, please note the use of the Marker that is created for each line from the Scanner. In your case it would be created by config or from Servlet input or similar.
package toTest;
import java.util.Scanner;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Marker;
import org.apache.logging.log4j.MarkerManager;
public class TestMe {
private final Logger myOneAndOnlyLogger = LogManager.getLogger("MyCentralName");
public static void main(String[] args) {
new TestMe().doMyThing();
}
private void doMyThing() {
Scanner input = new Scanner(System.in);
String line = "";
while(!line.equals("QUIT")) {
System.out.println("Line: ");
line = input.nextLine();
Marker forThisRound = MarkerManager.getMarker(line);
myOneAndOnlyLogger.log(Level.ERROR, forThisRound, "1");
myOneAndOnlyLogger.log(Level.ERROR, forThisRound, "2");
System.out.println("Line done.");
}
}
}
and this log4j2.properties (a rolling file example I had at hand with marker in the pattern):
status = error
name = MarkerExample
#Make sure to change log file path as per your need
property.filename = /tmp/java/marker.log
filters = threshold
filter.threshold.type = ThresholdFilter
filter.threshold.level = debug
appenders = rolling
appender.rolling.type = RollingFile
appender.rolling.name = RollingFile
appender.rolling.fileName = ${filename}
appender.rolling.filePattern = /tmp/java/debug-backup-%d{MM-dd-yy-HH-mm-ss}-%i.log.gz
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} $${marker:} %-5p %c{1}:%L - %m%n
appender.rolling.policies.type = Policies
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
appender.rolling.policies.time.interval = 1
appender.rolling.policies.time.modulate = true
appender.rolling.policies.size.type = SizeBasedTriggeringPolicy
appender.rolling.policies.size.size=10MBONE
appender.rolling.strategy.type = DefaultRolloverStrategy
appender.rolling.strategy.max = 20
loggers = rolling
#Make sure to change the package structure as per your application
logger.rolling.name = MyCentralName
logger.rolling.level = debug
logger.rolling.additivity = false
logger.rolling.appenderRef.rolling.ref = RollingFile

Deeplearning4j Disable Logging

I have a deeplearning for java project which is producing huge amounts of logger output on STDO. I want to disable that but I cant seem to figure out how to do it.
I have a log4j.properties file in my src/main/resources folder which looks like this:
log4j.rootLogger=ERROR, Console
log4j.logger.play=WARN
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d{ABSOLUTE} %-5p ~ %m%n
log4j.appender.org.springframework=WARN
log4j.appender.org.nd4j=WARN
log4j.appender.org.canova=WARN
log4j.appender.org.datavec=WARN
log4j.appender.org.deeplearning4j=WARN
log4j.appender.opennlp.uima=OFF
log4j.appender.org.apache.uima=OFF
log4j.appender.org.cleartk=OFF
log4j.logger.org.springframework=WARN
log4j.logger.org.nd4j=WARN
log4j.logger.org.canova=WARN
log4j.logger.org.datavec=WARN
log4j.logger.org.deeplearning4j=WARN
log4j.logger.opennlp.uima.util=OFF
log4j.logger.org.apache.uima=OFF
log4j.logger.org.cleartk=OFF
log4j.logger.org.deeplearning4j.optimize.solvers.BaseOptimizer=OFF
slf4j.logger.org.deeplearning4j.optimize.solvers.BaseOptimizer=OFF
The specific output that is far too much is:
21:26:34.860 [main] DEBUG o.d.optimize.solvers.BaseOptimizer - Hit termination condition on iteration 0: score=1.2894165074915344E19, oldScore=1.2894191699433697E19, condition=org.deeplearning4j.optimize.terminations.EpsTermination#55f111f3
which happens multiple times a second while training.
The output of the log entry that you have provided look very much as the SLF4J output with Logback format (not LOG4J output).
Also dependencies of deeplearning4j-core advice SLF4J is used for logging.
Hence your log4j.properties have no effect on deeplearning4j logging. Try to add logback.xml configuration to the resources as well and switch to WARN or ERROR level for root logger, see https://logback.qos.ch/manual/configuration.html
There are some properties in the framework DL4J (1.0.0-beta7) that activate/deactivate the logs. I found some of them:
import org.nd4j.common.config.ND4JSystemProperties;
System.setProperty(ND4JSystemProperties.LOG_INITIALIZATION, "false");
System.setProperty(ND4JSystemProperties.ND4J_IGNORE_AVX, "true");
System.setProperty(ND4JSystemProperties.VERSION_CHECK_PROPERTY, "false");
Notice that this is an unconventional solution. On the other hand, there are some messages impossible to avoid:
MultiLayerNetwork.init()
In this method you can find a OneTimeLogger without validations:
OneTimeLogger.info(log, "Starting MultiLayerNetwork with WorkspaceModes set to [training: {}; inference: {}], cacheMode set to [{}]",
layerWiseConfigurations.getTrainingWorkspaceMode(),
layerWiseConfigurations.getInferenceWorkspaceMode(),
layerWiseConfigurations.getCacheMode());
If you find a better way to disable log messages inside DL4J please share it. There are some other ways outside the DL4J library.

Configure logging in Groovy

I am using java logging in Groovy and I wanted to modify the format string so I only have one line instead of two, but the methods I tried didn't work - I looked at this question:
How do I get java logging output to appear on a single line?
I tried passing the property to groovy, but it didn't change the format.
I passed it like this:
groovy myScript.groovy -Djava.util.logging.SimpleFormatter.format=%1$tF %1$tT
but it doesn't look like it was picked up.
Here is what I did - I added this code to my groovy:
System.setProperty("java.util.logging.SimpleFormatter.format",
'%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$-6s %5$s%6$s%n');
Logger log = Logger.getLogger("")
FileHandler fh = new FileHandler("../log/replication.log")
log.addHandler(fh)
SimpleFormatter formatter = new SimpleFormatter()
fh.setFormatter(formatter)
which didn't require me to modify the java properties in command line (I didn't want to create additional script to start my groovy script).
You can use JAVA_OPTS for that. For example,
import java.util.logging.*
Logger log = Logger.getLogger('test')
log.setLevel(Level.INFO)
log.info('Test info log')
log.warning('Test warning')
log.config('Test config')
log.fine('Test fine')
and setting (i.e. below for windows):
set JAVA_OPTS="-Djava.util.logging.SimpleFormatter.format=%1$tF %1$tT [%4$s] %5$s %n"
Running the above sample script yields:
> groovy testLoggingJavaUtil.groovy
2015-03-27 17:35:48 [INFO] Test info log
2015-03-27 17:35:48 [WARNING] Test warning

Selecting file logging level on package level

I have several log files logfile and debugLogFile. One - more debug info, second less, but still need to have some. In future I expect to have third file with info quantity something between of these two.
I'm asking log4j to log package MyPck in INFO level. This I need for logfile. But I need to have DEBUG level for MyPck for debugLogFile. This is a problem.
Both, logFile and debugLogFile have Threshold=ALL. I need to have possibility in each log file to write all level information. For example logfile will contain DEBUG level for MyPck and INFO for MyPck1 and debugLogFile will contain INFO level for MyPck and DEBUG for MyPck1. How to solve this problem?
log4j.rootLogger=ALL, logfile, debugLogFile
log4j.logger.MyPck=INFO
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.File=logFile.log
log4j.appender.logfile.Threshold=ALL
log4j.appender.debugLogFile=org.apache.log4j.RollingFileAppender
log4j.appender.debugLogFile.File=debugLogFile.log
log4j.appender.debugLogFile.Threshold=ALL
This should get you going in the right direction:
log4j.rootLogger=TRACE, defaultFile
log4j.appender.defaultFile=org.apache.log4j.RollingFileAppender
log4j.appender.defaultFile.File=defaultFile.log
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.File=logFile.log
log4j.appender.debugLogFile=org.apache.log4j.RollingFileAppender
log4j.appender.debugLogFile.File=debugLogFile.log
log4j.logger.MyPck=DEBUG,logFile
log4j.logger.MyPck1=INFO,logFile
log4j.logger.MyPck=INFO,debugLogFile
log4j.logger.MyPck1=DEBUG,debugLogFile
log4j.additivity.MyPck=false
log4j.additivity.MyPck1=false
The log4j.additivity.MyPck=false setting ensures that the output of MyPck does not appear in the rootLogger appender.
When you set the log level for MyPck to INFO, you actually set the threshold for this package to INFO, i.e. no message below that level will ever be emitted.
So you need to set the threshold of the package to the lowest common level you want to log.
The next step is then to configure the thresholds of the loggers to filter out any messages you don't want:
log4j.rootLogger=ALL, logfile, debugLogFile
log4j.logger.MyPck=DEBUG
log4j.appender.logfile=org.apache.log4j.RollingFileAppender
log4j.appender.logfile.File=logFile.log
log4j.appender.logfile.Threshold=INFO
log4j.appender.debugLogFile=org.apache.log4j.RollingFileAppender
log4j.appender.debugLogFile.File=debugLogFile.log
log4j.appender.debugLogFile.Threshold=DEBUG
Note that the second appender gets a copy of all messages of the first one.

Categories

Resources