It seems like Log4j is not logging any message containing "Task" using a ConsoleAppender.
public class Main
public static void main(String[] args)
{
Log log = LogFactory.getLog("Main");
log.info("'task' is logged, but");
log.info("'Task' is not logged ?!");
// wait for logging to finish
try
{
Thread.sleep(100);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
log4j.properties:
log4j.rootLogger = TRACE, CA
log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.conversionPattern=%d{HH:mm:ss.SSS} %-5p %c.%M - %m%n
I use commons-logging 1.2, log4j 1.2.17, openjdk version "13.0.2" 2020-01-14
Is this a bug? A FileAppender works normally. I can also System.out.println("Task") and see it on the console, so it is not my IDE filtering anything.
I would be happy if someone can try this and verify it, because I am super confused.
It turns out that my IntelliJ IDEA plugin Grep Console was filtering lines with .*Task.* due to import of the company configuration.
In IntelliJ, go to Settings > Other Settings > Grep Console > Input filtering. Check if there is any unexpected.
Related
In my app, I would like some way of formatting.
For that purpose, I wrote a SingleLineFormatter extends Formatter.
Now I am trying to set all Loggers to use it, but can't figure that out.
LogManager.getLogManager().readConfiguration((InputStream) configIS);
Collections.list(LogManager.getLogManager().getLoggerNames()).forEach(
loggerName -> {
List<Handler> handlers = Arrays.asList(Logger.getLogger(loggerName).getHandlers());
System.out.println(" * Logger " + loggerName + ": " + handlers.size());
handlers.forEach(handler -> System.out.println(" HF: " + handler.getFormatter()));
//handlers.forEach(handler -> handler.setFormatter(new SingleLineFormatter()));
}
);/**/
log.info("Logging test");
This reads the config, applies it to all handlers that are found.
Oct 02, 2018 10:42:10 PM cz.dynawest.logging.LoggingUtils initLogging
INFO: Log config file not found: #/logging.properties Using LoggingUtils' default.
* Logger cz.dynawest.csvcruncher.App: 0
* Logger global: 0
* Logger cz.dynawest.logging.LoggingUtils: 0
2018-10-02 22:42:10 INFO cz.dynawest.logging.LoggingUtils initLogging: Logging test
* Logger : 2
HF: cz.dynawest.logging.SingleLineFormatter#34c45dca
HF: cz.dynawest.logging.SingleLineFormatter#52cc8049
However the rest of the Loggers still use whatever they were configured with. Probably just JUL's default.
Oct 02, 2018 10:42:10 PM org.hsqldb.persist.Logger logInfoEvent
INFO: checkpointClose start
I know I can manage this from JUL's logging.properties within my JVM.
But I want to distribute the app, and want all the log messages to be formatted the same way.
How can I force all messages going to JUL to be formatted with my Formatter?
There is -Djava.util.logging.config.file=/path/to/app.properties, but that's out of scope for my particular case. (And doesn't work anyway.)
Update: It looks like the third party logging doesn't go through JUL. So the question is - if that's true, how do I configure the other frameworks?
Here is the file that's being loaded to LogManager. There are quite some experiments so not everythign is correct.
# Handlers
handlers = java.util.logging.ConsoleHandler java.util.logging.FileHandler
# Console
# The logging of the app actually reacts to this line.
java.util.logging.ConsoleHandler.formatter = cz.dynawest.logging.SingleLineFormatter
#java.util.logging.ConsoleHandler.formatter = cz.dynawest.logging.SimplestFormatter
java.util.logging.ConsoleHandler.level = ALL
# File
java.util.logging.FileHandler.level = ALL
java.util.logging.FileHandler.pattern = app.log
java.util.logging.FileHandler.formatter = cz.dynawest.logging.SingleLineFormatter
java.util.logging.FileHandler.limit = 0
java.util.logging.FileHandler.append = true
# Default global logging level.
.formatter = cz.dynawest.logging.SimplestFormatter
.level = INFO
#global.formatter = cz.dynawest.logging.SimplestFormatter
#root.formatter = cz.dynawest.logging.SimplestFormatter
#cz.dynawest.csvcruncher.App.formatter = cz.dynawest.logging.SimplestFormatter
#cz.dynawest.csvcruncher.App.handlers = java.util.logging.ConsoleHandler
#.useParentHandlers = false
# Various customizations.
org.apache.commons.beanutils.converters.level=INFO
In my app, I would like some way of formatting. For that purpose, I wrote a >SingleLineFormatter extends Formatter
Since JDK 7 the java.util.logging.SimpleFormatter supports a one line format.
This reads the config, applies it to all handlers that are found.
JUL will only load handlers when the logger is demanded by code. It is therefore possible to miss handlers because the loggers themselves haven't been created yet.
How can I force all messages going to JUL to be formatted with my Formatter?
There is -Djava.util.logging.config.file=/path/to/app.properties, but that's out of scope for my particular case. (And doesn't work anyway.)
You are already accessing the LogManager so you can set properties from Java like so:
private static void loadProperties() {
Properties props = new Properties();
props.put("java.util.logging.ConsoleHandler.formatter", "cz.dynawest.logging.SingleLineFormatter");
props.put("org.apache.commons.beanutils.converters.level", "INFO");
try(ByteArrayOutputStream out = new ByteArrayOutputStream()) {
props.store(out, "");
LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(out.toByteArray()));
} catch (IOException ioe) {
throw new AssertionError(ioe);
}
}
If you are running JDK 9 or newer then you should use LogManager.updateConfiguration(java.util.function.Function) instead.
It looks like the third party logging doesn't go through JUL. So the question is - if that's true, how do I configure the other frameworks?
You'll have to determine if the frameworks are routing to one another. You should only have to change the format of the framework that is publishing records to a output source.
In attempts to conform to what the lib might want me to use for logging, I switched to SLF4J and Logback. Didn't help.
So I looked at the particular library that causes the logging issues - HSQLDB.
The problem is that it does some attempts to master all common frameworks and bypasses my attempts to configure it externally. Here is an example: FrameworkLogger
Then I found in the HSQLDB manual:
HyperSQL also supports log4J and JDK logging. The same event information that is passed to the internal log, is passed to external logging frameworks. These frameworks are typically configured outside HyperSQL. The log messages include the string "hsqldb.db." followed by the unique id (a 16 character string) of the database that generated the message, so they can be identified in a multi-database server context.
As the default JDK logging framework has several shortcomings, HyperSQL configures this logging framework for better operation. If you do not want HyperSQL to configure the JDK logging framework, you should include the system level property hsqldb.reconfig_logging=false in your environment.
I tried setting the hsqldb.db. Logger but that didn't work.
So I guess I'll stick with JUL, and turn off the hsqldb.reconfig_logging=false.
By the way, here is a good review of JUL config.
One way is to a static String across application such as
private static Logger logger = Logger.getLogger("some_value");
I'm trying to configure Logback (in Grails using Groovy configuration) so that:
any errors (from anywhere) are logged to a rolling file and send an email
all debug output from my classes is sent to the rolling file
This is what I have so far:
appender("ROLLING", RollingFileAppender) { ... }
appender("EMAIL", SMTPAppender) { ... }
logger("my.package", DEBUG, ["ROLLING"], false)
root(ERROR, ["ROLLING", "EMAIL"])
It seems that the rolling file gets what I expect (debug from my package at least) but the EMAIL appender gets nothing.
How can I send the errors to the EMAIL appender?
I am working in Grails application and want to log messages in different files. I want to log exceptions, normal and API logs in different files. But according to Log4j general roles, If we set logger level to 'Info' then warn and error messages will also start logging in this file while I want to log error messages in different file. So, thus my error messages will be logged twicely in error file and in info file too. While I want that 'info' logger log just 'info' level messages not 'error' level messages too. And 'error' logger just log error messages.
Below is my Log4j Configuration:
log4j = {
def layoutPattern = new PatternLayout("[%d{ISO8601}] %m \r\n")
def dailyRollingInfoFile = new DailyRollingFileAppender(
name:"rollingInfoFileAppender",
layout: layoutPattern,
//Path of the Log File
fileName:"C:\\MS-Logs\\Application\\MSLogs.log",
datePattern: "'.'dd-MM-yyyy")
def dailyRollingExceptionFile = new DailyRollingFileAppender(
name:"rollingExceptionFileAppender",
layout: layoutPattern,
//Path of the Log File
fileName:"C:\\MS-Logs\\Exceptions\\ExceptionLogs.log",
datePattern: "'.'dd-MM-yyyy")
def dailyRollingExceptionAPIFile = new DailyRollingFileAppender(
name:"rollingAPIFileAppender",
layout: layoutPattern,
//Path of the Log File
fileName:"C:\\MS-Logs\\API\\MS-NotificationsLogs.log",
datePattern: "'.'dd-MM-yyyy")
//For logging exceptions stack trace
appenders {
appender dailyRollingInfoFile
appender dailyRollingExceptionFile
appender dailyRollingExceptionAPIFile
}
root {
info 'rollingInfoFileAppender', additivity: false
debug 'rollingAPIFileAppender', additivity: false
error 'rollingExceptionFileAppender'
}
}
And Now, this is how I add filters:
dailyRollingExceptionFile.addFilter(new org.apache.log4j.varia.LevelMatchFilter(levelToMatch:'ERROR', acceptOnMatch: true))
dailyRollingExceptionFile.addFilter(new org.apache.log4j.varia.DenyAllFilter())
//To make it sure that It will just Log, Messages by Info Logger
dailyRollingInfoFile.addFilter(new org.apache.log4j.varia.LevelMatchFilter(levelToMatch:'INFO', acceptOnMatch: true))
dailyRollingInfoFile.addFilter(new org.apache.log4j.varia.DenyAllFilter())
//To make it sure that It will just Log, Messages by API Logger
dailyRollingAPIFile.addFilter(new org.apache.log4j.varia.LevelMatchFilter(levelToMatch:'DEBUG', acceptOnMatch: true))
dailyRollingAPIFile.addFilter(new org.apache.log4j.varia.DenyAllFilter())
How, It may be possible to avoid same message being logged twicely in different files ? How can we log messages in different files without being repeating it in other file ?
Thanks for your Time :)
I believe Log4j's LevelMatchFilter allows you to do what you're after:
def dailyRollingInfoFile = new DailyRollingFileAppender(...)
dailyRollingInfoFile.addFilter(new org.apache.log4j.varia.LevelMatchFilter(levelToMatch:'INFO', acceptOnMatch: true))
dailyRollingInfoFile.addFilter(new org.apache.log4j.varia.DenyAllFilter())
The DenyAllFilter drops the messages that the LevelMatchFilter does not match (ie. everything other than level INFO)
Inmy research about JMS Appenders I've found turorial1 and tutorial2 . I've tried to follow them, but I couldn't run example program.
Fistly I created file log4j.properties
log4j.rootLogger=INFO, stdout, jms
#
log4j.logger.org.apache.activemq=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %-5p %c - %m%n
#
log4j.appender.jms=org.apache.log4j.net.JMSAppender
log4j.appender.jms.InitialContextFactoryName=org.apache.activemq.jndi.ActiveMQInitialContextFactory
log4j.appender.jms.ProviderURL=tcp://localhost:61616
log4j.appender.jms.TopicBindingName=logTopic
log4j.appender.jms.TopicConnectionFactoryBindingName=ConnectionFactory
and jndi.properties
topic.logTopic=logTopic
Then I added Receiver.java to my project
public class Receiver implements MessageListener {
public Receiver() throws Exception {
ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
Connection conn = factory.createConnection();
Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
conn.start();
MessageConsumer consumer = sess.createConsumer(sess.createTopic("logTopic"));
consumer.setMessageListener(this);
Logger log = Logger.getLogger(Receiver.class);
log.info("Test log");
Thread.sleep(1000);
consumer.close();
sess.close();
conn.close();
System.exit(1);
}
public static void main(String[] args) throws Exception {
new Receiver();
}
#Override
public void onMessage(Message message) {
try {
// receive log event in your consumer
LoggingEvent event = (LoggingEvent)((ActiveMQObjectMessage)message).getObject();
System.out.println("Received log [" + event.getLevel() + "]: "+ event.getMessage());
} catch (Exception e) {
e.printStackTrace();
}
}
}
I need make Receiver to gather all logs from project, but I cannot even run this simple example. Probably I don't know how to configure it correctly, because I get this output:
log4j:WARN No appenders could be found for logger (org.apache.activemq.transport.WireFormatNegotiator).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Did I miss adding some lines in code or some files to classpath? I'm new to log4j.
EDIT:
I set Logger in AspectJ class. But I think that also in Receiver Logger is created and log is sent, so probably it should be done in Receiver, not in other class in my project.
static final Logger logger = Logger.getLogger(ReportingAspect.class);
#Before("setLoggingFile()")
public void setProperties() {
PropertyConfigurator.configure("log4j.properties");
}
ProjectJMS
|
\_ src
| \_ packages...
\_jndi.propeties
\_log4j.properties
To configure log4j use :
-Dlog4j.configuration= path to config file
Path to conf file CAN be:
À file in a path outside of classpath , if so préfix it with file:/// , example:
-Dlog4j.configuration=file:/c:/foobar.lcf
Else in classpath in That case:
-Dlog4j.configuration=foobar.lcf where foobar.lcf is at root of your source folder
See:
http://logging.apache.org/log4j/1.2/manual.html
For jms:
-Add jms.jar at least to classpath
ensure you have a JMS broker running ( activemq for example)
Regards
Philippe
You need to move the log4j.properties under 'src' folder so it'll be included in the classpath, since it's not there it is not being loaded.
Have you validated, that your Method setProperties() is called before you used your logger?
Usually that kind of error only pops up, when either the configuration file (log4j.properties) was not found while initializing log4j by PropertyConfigurator, or you tried to log something before you initialized log4j with your PropertyConfigurator.
First your should make sure, that setProperties() is called the way you expect it to be called and if this should work you could try to validate if the configuration can be loaded. From what I see, I guess your configuration file should be found. To validate this, you could load the configuration in several steps to make sure, it was found:
Properties props = new Properties();
props.load( new FileInputStream( "log4j.properties" ) );
PropertyConfigurator.configure( props );
If your configuration will not be found, you'll receive a FileNotFoundException.
If I set the log level to DEBUG, All messages with log level >= DEBUG will be logged/printed.
But can I set log level to only DEBUG, such that messages with log level only with DEBUG will be printed. Or can give a range like print all messages whose log level is >=DEBUG but < ERROR?
Maybe you can use a LevelMatchFilter?
At some situation, You have to write logs to different outputs according to the level. how can it be done by simply configuration of Log4j? There are some methods below.
http://wiki.apache.org/logging-log4j/LogToAppenderByLevel
As said Jarle you have to use LevelMatchFilter.
I will demonstrate it with one simple exam:
log4j.rootLogger = WARN, admin
log4j.appender.admin=org.apache.log4j.rolling.RollingFileAppender
log4j.appender.admin.rollingPolicy = org.apache.log4j.rolling.TimeBasedRollingPolicy
log4j.appender.admin.rollingPolicy.FileNamePattern = Files\\TestLevels-%d{dd-MM-yyy}.txt
log4j.appender.admin.layout = org.apache.log4j.PatternLayout
log4j.appender.admin.layout.ConversionPattern = Date: %d{dd-MM-yyyy} Time: %d{HH:mm:ss} Message [%m]%n
log4j.appender.admin.filter.01=org.apache.log4j.varia.LevelMatchFilter
log4j.appender.admin.filter.01.LevelToMatch=FATAL
log4j.appender.admin.filter.01.AcceptOnMatch=false
log4j.appender.admin.filter.02=org.apache.log4j.varia.LevelMatchFilter
log4j.appender.admin.filter.02.LevelToMatch=ERROR
log4j.appender.admin.filter.02.AcceptOnMatch=true
log4j.appender.admin.filter.03=org.apache.log4j.varia.LevelMatchFilter
log4j.appender.admin.filter.03.LevelToMatch=WARN
log4j.appender.admin.filter.03.AcceptOnMatch=false
In my source I append only ERROR messages to file with name TestLevels.txt