I'm trying to suppress output of the date line durinng logging when using the default logger in java.util.logging. For example, here is a typical output:
Jun 1, 2010 10:18:12 AM gamma.utility.application info
INFO: ping: db-time=2010-06-01 10:18:12.0, local-time=20100601t101812, duration=180000
Jun 1, 2010 10:21:12 AM gamma.utility.application info
INFO: ping: db-time=2010-06-01 10:21:12.0, local-time=20100601t102112, duration=180000
I would like to get rid of the Jun 1, 2010... lines, they just clutter my log output. How can I do this?
From Java SE 7 there is a new system property: java.util.logging.SimpleFormatter.format.
The same property is also configurable on the java.util.logging properties file (logging.properties).
If you are an Eclipse user, and you are annoyed by the double line message in the console output, you could change the jre logging.properties file (JDK_HOME/jre/lib/logging.properties) in this way:
java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n
Some example format is available here: http://docs.oracle.com/javase/7/docs/api/index.html?java/util/logging/SimpleFormatter.html.
The problem is caused by a handler in the parent log. The solution is to remove all handlers from the parent log, and then add own custom handler. This code removes handlers from the parent log:
for(Handler iHandler:log.getParent().getHandlers())
{
log.getParent().removeHandler(iHandler);
}
Write a custom formatter extending java.util.logging.Formatter class and implement the String format(LogRecord) method according to your needs. For example, the following formatter shows only the log message (and the throwable stacktrace if an exception is being logged):
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
class CustomRecordFormatter extends Formatter {
#Override
public String format(final LogRecord r) {
StringBuilder sb = new StringBuilder();
sb.append(formatMessage(r)).append(System.getProperty("line.separator"));
if (null != r.getThrown()) {
sb.append("Throwable occurred: "); //$NON-NLS-1$
Throwable t = r.getThrown();
PrintWriter pw = null;
try {
StringWriter sw = new StringWriter();
pw = new PrintWriter(sw);
t.printStackTrace(pw);
sb.append(sw.toString());
} finally {
if (pw != null) {
try {
pw.close();
} catch (Exception e) {
// ignore
}
}
}
}
return sb.toString();
}
}
This is how you use it:
import java.util.logging.ConsoleHandler;
import java.util.logging.Logger;
class A {
private static final Logger LOGGER = Logger.getLogger(A.class.getName());
static {
CustomRecordFormatter formatter = new CustomRecordFormatter();
ConsoleHandler consoleHandler = new ConsoleHandler();
consoleHandler.setFormatter(formatter);
LOGGER.addHandler(consoleHandler);
}
public void doSomething() {
LOGGER.info("something happened");
}
}
Related
i'd like to substitute all my system.out.println with a log.println in my web-app, in order insert all my log not in Eclipse console, but in an apposite file. I want that because i've deployed my web-app under a tomcat docker container.
I've found after some research this class:
import java.io.PrintWriter;
import java.io.FileOutputStream;
import java.util.Date;
public class Log{
private SettingsManager settings;
private String logFile;
private PrintWriter writer;
static Log theInstance = null;
/**
* Returns the only available instance of this class, if it exists...
* instantiates and returns it otherwise. LOg file name is retrieved
* through the SettingsManager
*
* #return
*/
public static Log getInstance() {
if (Log.theInstance == null) {
Log.theInstance = new Log();
}
return Log.theInstance;
}
private Log() {
this.settings = SettingsManager.getInstance();
this.logFile = settings.getString("settings.log.filename");
try {
this.writer = new PrintWriter(new FileOutputStream(this.logFile, true), true);
writer.println("*** Kerberos Logfile ***");
writer.println(" *** Logging started ***");
}catch(Exception ex) {
ex.printStackTrace();
}
}
public String getLogFile() {
return this.logFile;
}
public void println(String line) {
writer.println("[" + new Date().toString() + "]" + line);
}
}
Well, how can i modify this singleton class (I've no class named "SettingsManager") and substitute all my system.out.println with log.println? How can i set my log path?
Or.. can someone show me a simple log class and how to instanciate it?
Use some logging library like Log4j. Read tutorials/document and implement in your code. Do not copy exactly someone's code and then use.
You can check below tutorial for example:
http://www.vogella.com/tutorials/Logging/article.html
Ok, the case is simple. I need to be able to enable/disable logging for a JDK class (HttpURLConnection) programmatically.
public class HttpLoggingTest {
/**
Just a dummy to get some action from HttpURLConnection
*/
private static void getSomething(String urlStr) throws MalformedURLException, IOException {
System.out.println("----- " + urlStr);
HttpURLConnection conn = (HttpURLConnection) new URL("http://www.google.com").openConnection();
for (Entry<String, List<String>> header : conn.getHeaderFields().entrySet()) {
System.out.println(header.getKey() + "=" + header.getValue());
}
conn.disconnect();
}
public static void main(String[] args) throws MalformedURLException, IOException {
// HERE : Enable JDK logging for class
// sun.net.www.protocol.http.HttpURLConnection
getSomething("http://www.goodle.com");
// HERE: Disable JDK logging for class
// sun.net.www.protocol.http.HttpURLConnection
getSomething("http://www.microsoft.com");
}
}
In other words: before the first URL call the logging must be enabled and then disabled before the next call.
That is the challenge !
I'm unable to figure out how to do it.
Must work with Java 7.
Note:
I can do it by using configuration file, logging.properties :
sun.net.www.protocol.http.HttpURLConnection.level = ALL
but I want to have a programmatic solution.
UPDATE
Here's code that works in Java 6 but not in Java 7:
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.Map.Entry;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
public class HttpLoggingTest {
/**
Just a dummy to get some action from HttpURLConnection
*/
private static void getSomething(String urlStr) throws MalformedURLException, IOException {
System.out.println("----- " + urlStr);
HttpURLConnection conn = (HttpURLConnection) new URL("http://www.google.com").openConnection();
for (Entry<String, List<String>> header : conn.getHeaderFields().entrySet()) {
System.out.println(header.getKey() + "=" + header.getValue());
}
conn.disconnect();
}
private static void enableConsoleHandler() {
//get the top Logger
Logger topLogger = java.util.logging.Logger.getLogger("");
// Handler for console (reuse it if it already exists)
Handler consoleHandler = null;
//see if there is already a console handler
for (Handler handler : topLogger.getHandlers()) {
if (handler instanceof ConsoleHandler) {
//found the console handler
consoleHandler = handler;
break;
}
}
if (consoleHandler == null) {
//there was no console handler found, create a new one
consoleHandler = new ConsoleHandler();
topLogger.addHandler(consoleHandler);
}
consoleHandler.setLevel(Level.ALL);
}
public static void main(String[] args) throws MalformedURLException, IOException {
enableConsoleHandler();
final Logger httpLogger = Logger.getLogger("sun.net.www.protocol.http.HttpURLConnection");
// Enable JDK logging for class
//sun.net.www.protocol.http.HttpURLConnection
httpLogger.setLevel(java.util.logging.Level.FINE);
getSomething("http://www.goodle.com");
// Disable JDK logging for class
// sun.net.www.protocol.http.HttpURLConnection
httpLogger.setLevel(java.util.logging.Level.INFO);
getSomething("http://www.microsoft.com");
}
}
UPDATE2
In order to make sure that a solution only enables output from our target class (and not all sorts of other JDK internal classes) I've created this minimal JAXB example. Here JAXB is simply an example of 'something else', it could have been any other part of the JDK that also use PlatformLogger.
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* Minimal dummy JAXB example. Only purpose is to provoke
* some JAXB action. Non-prod quality!
*/
#XmlRootElement(name = "book")
public class Celebrity {
#XmlElement
public String getFirstName() {
return "Marilyn";
}
#XmlElement
public String getLastName() {
return "Monroe";
}
public void printXML() {
JAXBContext context;
try {
context = JAXBContext.newInstance(Celebrity.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(this, System.out);
} catch (JAXBException ex) {
}
}
}
Instantiate an instance of the Celebrity class and call printXML(). Put that into getSomething() method. This must not generate JAXB internal logging output ... or else you've enabled logging for more than you thought.
Stumbled over PlatformLoggingMXBean the other day. I'll need to try something like:
PlatformLoggingMXBean platformLoggingMXBean =
ManagementFactory.getPlatformMXBean(PlatformLoggingMXBean.class);
platformLoggingMXBean.setLoggerLevel(
"sun.net.www.protocol.http.HttpURLConnection", "FINE");
and see it it works.
Try:
java.util.logging.Logger logger =
java.util.logging.Logger.getLogger(
"sun.net.www.protocol.http.HttpURLConnection");
logger.setLevel(java.util.logging.Level.FINE);
I tried to go through the tutorial on the Java logging API:
www.vogella.com/articles/Logging/article.html
But the generated files are empty (tested in Netbeans, Eclipse as well as running the jar from cmd). The log messages are displayed in the console only.
The following are the files used in the project. What might be the reason for such behavior?
Project: de.vogella.logger
MyHtmlFormatter.java
package de.vogella.logger;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
//This custom formatter formats parts of a log record to a single line
class MyHtmlFormatter extends Formatter {
// This method is called for every log records
public String format(LogRecord rec) {
StringBuffer buf = new StringBuffer(1000);
// Bold any levels >= WARNING
buf.append("<tr>");
buf.append("<td>");
if (rec.getLevel().intValue() >= Level.WARNING.intValue()) {
buf.append("<b>");
buf.append(rec.getLevel());
buf.append("</b>");
} else {
buf.append(rec.getLevel());
}
buf.append("</td>");
buf.append("<td>");
buf.append(calcDate(rec.getMillis()));
buf.append(' ');
buf.append(formatMessage(rec));
buf.append('\n');
buf.append("<td>");
buf.append("</tr>\n");
return buf.toString();
}
private String calcDate(long millisecs) {
SimpleDateFormat date_format = new SimpleDateFormat("MMM dd,yyyy HH:mm");
Date resultdate = new Date(millisecs);
return date_format.format(resultdate);
}
// This method is called just after the handler using this
// formatter is created
public String getHead(Handler h) {
return "<HTML>\n<HEAD>\n" + (new Date())
+ "\n</HEAD>\n<BODY>\n<PRE>\n"
+ "<table width=\"100%\" border>\n "
+ "<tr><th>Level</th>" +
"<th>Time</th>" +
"<th>Log Message</th>" +
"</tr>\n";
}
// This method is called just after the handler using this
// formatter is closed
public String getTail(Handler h) {
return "</table>\n </PRE></BODY>\n</HTML>\n";
}
}
MyLogger.java
package de.vogella.logger;
import java.io.IOException;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
public class MyLogger {
static private FileHandler fileTxt;
static private SimpleFormatter formatterTxt;
static private FileHandler fileHTML;
static private Formatter formatterHTML;
static public void setup() throws IOException {
// Get the global logger to configure it
Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
logger.setLevel(Level.INFO);
fileTxt = new FileHandler("Logging.txt");
fileHTML = new FileHandler("Logging.html");
// Create txt Formatter
formatterTxt = new SimpleFormatter();
fileTxt.setFormatter(formatterTxt);
logger.addHandler(fileTxt);
// Create HTML Formatter
formatterHTML = new MyHtmlFormatter();
fileHTML.setFormatter(formatterHTML);
logger.addHandler(fileHTML);
}
}
UseLogger.java
package de.vogella.logger.test;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import de.vogella.logger.MyLogger;
public class UseLogger {
// Always use the classname, this way you can refactor
private final static Logger LOGGER = Logger.getLogger(UseLogger.class
.getName());
public void doSomeThingAndLog() {
// Image here some real work
// Now we demo the logging
// Set the LogLevel to Severe, only severe Messages will be written
LOGGER.setLevel(Level.SEVERE);
LOGGER.severe("Info Log");
LOGGER.warning("Info Log");
LOGGER.info("Info Log");
LOGGER.finest("Really not important");
// Set the LogLevel to Info, severe, warning and info will be written
// Finest is still not written
LOGGER.setLevel(Level.INFO);
LOGGER.severe("Info Log");
LOGGER.warning("Info Log");
LOGGER.info("Info Log");
LOGGER.finest("Really not important");
}
public static void main(String[] args) {
UseLogger tester = new UseLogger();
try {
MyLogger.setup();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException("Problems with creating the log files");
}
tester.doSomeThingAndLog();
}
}
Change the following line (in the method de.vogella.logger.MyLogger.setup()):
// Get the global logger to configure it
Logger logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
with:
// Get the global logger to configure it
Logger logger = Logger.getLogger("");
See more:
Java Logging
Java Logging: Configuration
Java Logging Framework
Here is my code, I am wondering why it isn't logging anything. When I type into the console it says:
Hello
Apr 08, 2013 10:13:47 PM java.util.logging.LogManager$RootLogger log
INFO: Hello
However, nothing is being logged to any files.
import java.io.IOException;
import java.util.Scanner;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
public class main {
public static void main(String[] args) throws IOException{
while (1 == 1) {
String text;
Scanner in = new Scanner(System.in);
text = in.nextLine();
FileHandler fileTxt;
SimpleFormatter formatterTxt;
Logger logger = Logger.getLogger("");
logger.setLevel(Level.INFO);
fileTxt = new FileHandler("../loggedText.txt");
formatterTxt = new SimpleFormatter();
fileTxt.setFormatter(formatterTxt);
logger.addHandler(fileTxt);
logger.info(text);
}
}
}
Your loop never terminates which means the JVM never performs a proper shutdown. The FileHandler is only closed and synched if all the logging shutdown hook executes normally. It is possible that the data was written but is never synched with the filesystem.
Let's create a corrected example that can terminate normally:
public class main {
private static final Logger logger = Logger.getLogger(""); //Prevent G.C.
public static void main(String[] args) throws IOException {
logger.setLevel(Level.INFO);
FileHandler fileTxt = new FileHandler("../loggedText.txt");
fileTxt.setFormatter(new SimpleFormatter());
logger.addHandler(fileTxt);
System.out.println("root.level " + logger.getLevel());
System.out.println("FileHandler.level " + fileTxt.getLevel());
Scanner in = new Scanner(System.in);
String text;
while (true) {
System.out.print("Enter text: ");
text = in.nextLine();
if (text != null && !text.isEmpty()
&& !"quit".equalsIgnoreCase(text)) {
logger.info(text);
} else {
System.out.println("Done!");
break;
}
}
}
}
Will output the following to the console:
root.level INFO
FileHandler.level ALL
Enter text: hello
Nov 22, 2016 10:39:19 AM java.util.logging.LogManager$RootLogger log
INFO: hello
Enter text: quit
Done!
On the filesystem is loggedText.txt containing:
Nov 22, 2016 10:39:19 AM java.util.logging.LogManager$RootLogger log
INFO: hello
If you can't terminate normally you need to explicitly call FileHandler.close() on the handlers you create.
Note: The logged class name and method name are incorrect which is known as JDK-8152389.
Hi I am trying to implement the java logging in my application. I want to use two handlers.
A file handler and my own console handler. Both of my handlers work fine. My logging is send to a file and to the console .
My logging is also sent to the default console handler, which i do not want. If you run my code you will see extra two line sent to the console. I don't want to use the default console handler. Does anyone know how to disable the default console handler.
I only want to use the two handlers I have created.
Handler fh = new FileHandler("test.txt");
fh.setFormatter(formatter);
logger.addHandler(fh);
Handler ch = new ConsoleHandler();
ch.setFormatter(formatter);
logger.addHandler(ch);
import java.util.Date;
import java.util.logging.ConsoleHandler;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
public class LoggingExample {
private static Logger logger = Logger.getLogger("test");
static {
try {
logger.setLevel(Level.INFO);
Formatter formatter = new Formatter() {
#Override
public String format(LogRecord arg0) {
StringBuilder b = new StringBuilder();
b.append(new Date());
b.append(" ");
b.append(arg0.getSourceClassName());
b.append(" ");
b.append(arg0.getSourceMethodName());
b.append(" ");
b.append(arg0.getLevel());
b.append(" ");
b.append(arg0.getMessage());
b.append(System.getProperty("line.separator"));
return b.toString();
}
};
Handler fh = new FileHandler("test.txt");
fh.setFormatter(formatter);
logger.addHandler(fh);
Handler ch = new ConsoleHandler();
ch.setFormatter(formatter);
logger.addHandler(ch);
LogManager lm = LogManager.getLogManager();
lm.addLogger(logger);
} catch (Throwable e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
logger.info("why does my test application use the standard console logger ?\n" + " I want only my console handler (Handler ch)\n " + "how can i turn the standard logger to the console off. ??");
}
}
Just do
LogManager.getLogManager().reset();
The default console handler is attached to the root logger, which is a parent of all other loggers including yours. So I see two ways to solve your problem:
If this is only affects this particular class of yours, the simplest solution would be to disable passing the logs up to the parent logger:
logger.setUseParentHandlers(false);
If you want to change this behaviour for your whole app, you could remove the default console handler from the root logger altogether before adding your own handlers:
Logger globalLogger = Logger.getLogger("global");
Handler[] handlers = globalLogger.getHandlers();
for(Handler handler : handlers) {
globalLogger.removeHandler(handler);
}
Note: if you want to use the same log handlers in other classes too, the best way is to move the log configuration into a config file in the long run.
This is strange but Logger.getLogger("global") does not work in my setup (as well as Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)).
However Logger.getLogger("") does the job well.
Hope this info also helps somebody...
Do a reset of the configuration and set the root level to OFF
LogManager.getLogManager().reset();
Logger globalLogger = Logger.getLogger(java.util.logging.Logger.GLOBAL_LOGGER_NAME);
globalLogger.setLevel(java.util.logging.Level.OFF);
You must instruct your logger not to send its messages on up to its parent logger:
...
import java.util.logging.*;
...
Logger logger = Logger.getLogger(this.getClass().getName());
logger.setUseParentHandlers(false);
...
However, this should be done before adding any more handlers to logger.