I would like to be able to tell the JVM to stop logging certain level of messages at some point in the execution chain. At some point I want to only log messages with SEVERE level, so I was thinking of doing this:
for(Enumeration<String> loggerNames = logManager.getLoggerNames(); loggerNames.hasMoreElements();){
String name = loggerNames.nextElement();
Logger nextLogger = logManager.getLogger(name);
if(nextLogger != null)
nextLogger.setLevel(Level.SEVERE);
}
Is there a cleaner way to achieve the same logic i.e. set a global variable that would stop printing to log unless SEVERE? I need to distinguish between Console output (in test) and file output in live, so I could potentially set these level on the handler (console and File)?
ANSWERING MY OWN QUESTION:
This is exactly what I needed:
Handler[] handlers =
Logger.getLogger( "" ).getHandlers();
for ( int index = 0; index < handlers.length; index++ ) {
handlers[index].setLevel( Level.SEVERE);
}
To control you application configuration dynamically, a common way is to use JMX.
JConsole, part of the jdk, allows you to control MBeans manually but you could also access them programatically.
You can use JMX to control MBeans as described in this page.
With log4j you can change the level of the root logger.
This may work:
logManager.getLogger( "" ).setLevel(Level.SEVERE);
or use Logger.getParent() to find the root logger
Related
I'd like to use java util logging in my applet, at log level FINE and below.
I've put a logging.properties file in my applet's jar which says
handlers= java.util.logging.ConsoleHandler
.level= FINE
java.util.logging.ConsoleHandler.level = FINE
and in my applet class, I feed it to the log manager using
logManager.readConfiguration(getClass().getResourceAsStream("logging.properties"));
This successfully causes my debug logging to appear in the applet's console window, however as I should've expected, the java platform also begins to log its FINE level messages to the console.
Worse, the act of logging a message to the Java console, of itself, causes more AWT logging(!) This generates an infinite loop of messages in my console along the lines of
20:31:55 java.awt.mixing.Component FINE: this = javax.swing.JTextArea[...]
20:31:55 java.awt.mixing.Container FINE: this = javax.swing.JViewport[...]
I thought this should be easy to fix by adding
java.level=INFO
javax.level=INFO
sun.level=INFO
to my logging.properties file.
However, this does not work. The platform logging keeps spewing out, no matter what I write in the properties file.
I've dived into the source code. The LogManager appears to be keeping two different LoggingContexts. One for the user, one system context. My logging.properties file only affects the Loggers in the user LoggingContext, and therefore cannot influence the platform logging's settings.
The LogManager does share the rootLogger between the user LoggingContext and the system LoggingContext. And when I set its level to FINE, I get the infinite stream of awt blurb as a side effect.
So my question is: How can I get my user context's Loggers to log at level FINE by default but keep the system loggers at INFO level?
I had tried to do the same thing, but in a web start application. I needed to have java.util.logging set to FINEST in order to find some problems in the application. It didn't matter what I did, the Swing logging just kept on spewing.
Your question, and investigation that you had done helped me solving the problem, albeit in a very ugly way, but I only needed it temporarily. I grabbed the system loggers using reflection:
public static void tryToChangeSystemLogContextLoggers() {
try {
Field systemContextField = LogManager.class.getDeclaredField("systemContext");
systemContextField.setAccessible(true);
Object systemContext = systemContextField.get(LogManager.getLogManager());
Method demandLoggerMethod = systemContext.getClass().getDeclaredMethod("demandLogger", String.class, String.class);
demandLoggerMethod.setAccessible(true);
java.util.logging.Logger logger = (java.util.logging.Logger)demandLoggerMethod.invoke(systemContext, "java.awt", null);
logger.setLevel(java.util.logging.Level.WARNING);
logger.setUseParentHandlers(false);
logger = (java.util.logging.Logger)demandLoggerMethod.invoke(systemContext, "sun.awt", null);
logger.setLevel(java.util.logging.Level.WARNING);
logger.setUseParentHandlers(false);
logger = (java.util.logging.Logger)demandLoggerMethod.invoke(systemContext, "javax.swing", null);
logger.setLevel(java.util.logging.Level.WARNING);
logger.setUseParentHandlers(false);
} catch (Exception e) {
//Well, I tried
}
}
The code is fragile, and might not work in all java version.
I need to write my own logging handler on GAE/J. I have Android code that I'm trying to adapt such that it can be shared between GAE/J and Android. The GAE code I'm trying to write would allow the log statements in my existing code to work on GAE.
The docs say that I can just print to system.out and system.err, and it works, but badly. My logging shows up in the log viewer with too much extraneous text:
2013-03-08 19:37:11.355 [s~satethbreft22/1.365820955097965155].: [my_log_msg]
So, I started looking at the GAE log API. This looked hopeful initially: I can construct an AppLogLine and set the log records for a RequestLogs object.
However, there is no way to get the RequestLogs instance for the current request - the docs say so explicitly here:
Note: Currently, App Engine doesn't support the use of the request ID to directly look up the related logs.
I guess I could invent a new requestID and add log lines to that, but it is starting to look like this is just not meant to be?
Has anyone used this API to create their own log records, or otherwise managed to do their own logging to the log console.
Also, where can I find the source for GAE's java.util.logging? Is this public? I would like to see how that works if I can.
If what I'm trying to do is impossible then I will need to consider other options, e.g. writing my log output to a FusionTable.
I ended up just layering my logging code on top of GAE's java.util.logging. This feels non-optimal since it increases the complexity and overhead of my logging, but I guess this is what any 3rd logging framework for GAE must do (unless it is OK with the extra cruft that gets added when you just print to stdout).
Here is the crux of my code:
public int println(int priority, String msg) {
Throwable t = new Throwable();
StackTraceElement[] stackTrace = t.getStackTrace();
// Optional: translate from Android log levels to GAE log levels.
final Level[] levels = { Level.FINEST, Level.FINER, Level.FINE, Level.CONFIG,Level.INFO, Level.WARNING, Level.SEVERE, Level.SEVERE };
Level level = levels[priority];
LogRecord lr = new LogRecord(level, msg);
if (stackTrace.length > 2) { // should always be true
lr.setSourceClassName(stackTrace[2].getClassName());
lr.setSourceMethodName(stackTrace[2].getMethodName());
}
log.log(lr);
return 0;
}
Note that I use a stack depth of 2, but that # will depend on the 'depth' of your logging code.
I hope that Google will eventually support getting the current com.google.appengine.api.log.RequestLogs instance and inserting our own AppLogLine instances into it. (The API's are actually there to do that, but they explicitly don't support it, as above.)
I have a log4j logger that I instantiate like this:
logger = Logger.getLogger("EQUIP(" + id + ")");
Doing so, when I call logger.info("message"), I should get an output like this (with some date formatting):
13/11/12 15:08:27 INFO: EQUIP(1): message
But I'm only getting:
13/11/12 15:08:27 INFO: message
I'm also printing logger.getName() to the console for debugging and it gives me back the correct "EQUIP(1)" name. This behaviour is happening in some cases in my program, where I have several loggers like this, but mostly in this specific class. I want to know if I'm doing something wrong, if this name should be only the class/package name, or if it can be anything (it works well in 80+% of my loggers). I need to print the ID of each equipment because I have several of them working simultaneous, and tracking them without this would be next to impossible.
How should I fix this, preferably without resourcing to changing all my log calls to include this prefix?
The output format depends on the pattern you've configured for the appender. If the pattern string includes %c then you'll get the logger name included, if it doesn't then you won't.
An alternative approach might be to use the mapped diagnostic context, which is designed to disambiguate between log output from different threads writing to the same logger.
I'm trying to figure out why I'm generating multiple versions of my log files (.1, .2 ,etc). My project has a need for 3 separate loggers, I'm using java.util.log and setting up my loggers as follows:
logger = Logger.getLogger("Logger");
logger.addHandler(new FileHandler(logFileName));
statsLogger = Logger.getLogger("StatsLogger");
statsLogger.addHandler(new FileHandler(statsLogFileName));
alarmLogger = Logger.getLogger("AlarmLogger");
alarmLogger.addHandler(new FileHandler(alarmLogFileName));
my logging properties file:
handlers=java.util.logging.ConsoleHandler java.util.logging.FileHandler
java.util.logging.FileHandler.append=true
java.util.logging.FileHandler.level=INFO
java.util.logging.ConsoleHandler.level=INFO
java.util.logging.ConsoleHandler.formatter=com.package.LogFormatter
java.util.logging.FileHandler.formatter=com.package.LogFormatter
This seems to work, well as far as I can tell anyway... things seem to be getting logged to the correct log files. Any ideas on what could be causing this?
Thanks for any ideas
According to the FileHandler javadoc
http://docs.oracle.com/javase/1.4.2/docs/api/java/util/logging/FileHandler.html#FileHandler
Normally the "%u" unique field is set to 0. However, if the
FileHandler tries to open the filename and finds the file is currently
in use by another process it will increment the unique number field
and try again. This will be repeated until FileHandler finds a file
name that is not currently in use. If there is a conflict and no "%u"
field has been specified, it will be added at the end of the filename
after a dot. (This will be after any automatically added generation
number.)
Have you got multiple processes running that are using the same log configuration ? Also check that any old test processes are not showing up in windows process viewer or top.
What is the difference between logger.debug and logger.info ?
When will logger.debug be printed?
I suggest you look at the article called "Short Introduction to log4j". It contains a short explanation of log levels and demonstrates how they can be used in practice. The basic idea of log levels is that you want to be able to configure how much detail the logs contain depending on the situation. For example, if you are trying to troubleshoot an issue, you would want the logs to be very verbose. In production, you might only want to see warnings and errors.
The log level for each component of your system is usually controlled through a parameter in a configuration file, so it's easy to change. Your code would contain various logging statements with different levels. When responding to an Exception, you might call Logger.error. If you want to print the value of a variable at any given point, you might call Logger.debug. This combination of a configurable logging level and logging statements within your program allow you full control over how your application will log its activity.
In the case of log4j at least, the ordering of log levels is:
DEBUG < INFO < WARN < ERROR < FATAL
Here is a short example from that article demonstrating how log levels work.
// get a logger instance named "com.foo"
Logger logger = Logger.getLogger("com.foo");
// Now set its level. Normally you do not need to set the
// level of a logger programmatically. This is usually done
// in configuration files.
logger.setLevel(Level.INFO);
Logger barlogger = Logger.getLogger("com.foo.Bar");
// This request is enabled, because WARN >= INFO.
logger.warn("Low fuel level.");
// This request is disabled, because DEBUG < INFO.
logger.debug("Starting search for nearest gas station.");
// The logger instance barlogger, named "com.foo.Bar",
// will inherit its level from the logger named
// "com.foo" Thus, the following request is enabled
// because INFO >= INFO.
barlogger.info("Located nearest gas station.");
// This request is disabled, because DEBUG < INFO.
barlogger.debug("Exiting gas station search");
This will depend on the logging configuration. The default value will depend on the framework being used. The idea is that later on by changing a configuration setting from INFO to DEBUG you will see a ton of more (or less if the other way around) lines printed without recompiling the whole application.
If you think which one to use then it boils down to thinking what you want to see on which level. For other levels for example in Log4J look at the API, http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Level.html
Just a clarification about the set of all possible levels, that are:
ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
Basically it depends on how your loggers are configured. Typically you'd have debug output written out during development but turned off in production - or possibly have selected debug categories writing out while debugging a particular area.
The point of having different priorities is to allow you to turn up/down the level of detail on a particular component in a reasonably fine-grained way - and only needing to change the logging configuration (rather than code) to see the difference.
INFO is used to log the information your program is working as expected.
DEBUG is used to find the reason in case your program is not working as expected or an exception has occurred. it's in the interest of the developer.
This is a very old question, but i don't see my understanding here so I will add my 2 cents:
Every level corresponds/maps to a type of user:
debug : developer - manual debugging
trace : automated logging and step tracer - for 3rd level support
info : technician / support level 1 /2
warn : technician / user error : automated alert / support level 1
critical/fatal : depends on your setup - local IT
It depends on which level you selected in your log4j configuration file.
<Loggers>
<Root level="info">
...
If your level is "info" (by default), logger.debug(...) will not be printed in your console.
However, if your level is "debug", it will.
Depending on the criticality level of your code, you should use the most accurate level among the following ones :
ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
Info Messages are something which we would like to see even if the application is in best of state.
Debug messages are usually something that we would like to see while debugging some problem.
What is the difference between logger.debug and logger.info?
These are only some default level already defined. You can define your own levels if you like.
The purpose of those levels is to enable/disable one or more of them, without making any change in your code.
When logger.debug will be printed ??
When you have enabled the debug or any higher level in your configuration.