Time output in Eclipse console - java

is there any possibility to add timestamp to every line which is printed in Eclipse console? For example when code like
System.out.println("Hello World");
is executed I would like to have something like this in console:
[yy-mm-dd hh-mm-ss] Hello World
Thank you in advance for any sugestions.

I am not sure if third party library straightaway provides it. But you can create custom print method to achieve it and use it across the project
public void customPrint(String inputToPrint){
SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date now = new Date();
String strDate = sdfDate.format(now);
System.out.println("[" + strDate + "] " + inputToPrint);
}

This kind of goal is usually satisfied automatically by logging libraries like Logback. With a logging library you would instantiate a logger at the class level
private static final Logger LOG = LoggerFactory.getLogger(MyClass.class);
and then write your log messages through the logger:
LOG.debug("Here's my log message")
The output format is configurable, but one example of output is this:
2013-12-14 11:21:05.985 ["http-bio-8080"-exec-5] DEBUG c.s.m.i.MyClass - Here's my log message

Related

Java: Formatting a Date inside of a string

I know I'm probably doing something wrong, but I am trying to format a Date that is currently stored inside of a string but it won't let me parse it to a String because it doesn't recognize it as a Date (because it's in a String variable) and won't let me format it because it cannot format it in its current state. For reference, I am making a time clock application.
I apologize if I'm doing something stupid but I am fairly new to this and have never used SimpleDateFormat before. I put some snippets of code below:
ArrayList<String> punchHistoryTimes = new ArrayList<String>();
SimpleDateFormat sdf =new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
public void updatePunchHistory(Sheet sheet){
for(int rowNum:rowNumbers){
punchHistoryTimes.add(sheet.getRow(rowNum).getCell(1).getStringCellValue());
punchHistory.add(new JLabel(sheet.getRow(rowNum).getCell(0).getRichStringCellValue().getString()+ " " + sheet.getRow(rowNum).getCell(1).getRichStringCellValue().getString()+ " " + sheet.getRow(rowNum).getCell(2).getRichStringCellValue().getString()));
}
}
//other code is above this but not relevant to the issue
currentEmployee.setEndTime(sdf.format(currentDate));
if(punchHistory.get(punchHistory.size()-1).getText().contains("Clocked In")){
calcTimeWorked(punchHistory.get(punchHistoryTimes.size()-1).getText(),currentEmployee.getEndTime());
}else{
//This line below is where the error is happening
//value of currentEmployee.getStartTime() at error: 1654653731536
//value of currentEmployee.getEndTime() at error: 07-06-2022 21:02:12
//Both currentEmployee.getStartTime() and currentEmployee.getEndTime() are stored as Strings
calcTimeWorked(currentEmployee.getStartTime(),currentEmployee.getEndTime());
}
currentEmployee.setHoursWorked(differenceInTime);
I tried using the debugger and it shows the error is that it cannot parse 1654653731536. I understand the issue but cannot get a solution. I believe the issue is because when it stores the value in the excel file it is storing the date as a string but then when it pulls the date back out of the excel later (the application would have been closed between these events) it views it as a string and does not recognize that there is a Date inside of the String. Is there any way to cast the String 1654653731536 to a Date?

DBunit - Unable to typecast <1997/02/14> to TimeStamp

I'm doing an integration testing with DBUnit (2.49) + Hibernate (4.1.3) following this tutorial.
Production database : Oracle 10
Test database : Hsqldb 2.3.3
Context
My data contains the current format of date : yyyy/MM/dd. However,according to DBUnit faq, DBUnit only supports this format yyyy-mm-dd hh:mm:ss.fffffffff, so I had to create a new format for TimeStamp.
How I tried to fix it
I created a CustomTimeStampDataType based on this tutorial. I changed this part:
String formats[] = {"yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm a", "yyyy-MM-dd HH:mm:ss.fffffffff"};
into this one:
String formats[] = {"yyyy/MM/dd"};
I created a CustomeDataTypeFactory following the same tutorial. I only make it extend Oracle10DataTypeFactory rather than DefaultDatatTypeFactory.
In HibernateDBUnitTestCase, I override setDatabaseConfig() with the following:
#Override
protected void setUpDatabaseConfig(DatabaseConfig config){
config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new CustomDataTypeFactory());
}
But I got new errors
I ran a unit test and got this error.
org.dbunit.dataset.datatype.TypeCastException: Unable to typecast value <1997/02/14> of type <java.lang.String> to TIMESTAMP
at org.dbunit.dataset.datatype.TimestampDataType.typeCast(TimestampDataType.java:120)
at org.dbunit.dataset.datatype.TimestampDataType.setSqlValue(TimestampDataType.java:176)
at org.dbunit.database.statement.SimplePreparedStatement.addValue(SimplePreparedStatement.java:73)
at org.dbunit.operation.RefreshOperation$RowOperation.execute(RefreshOperation.java:189)
at org.dbunit.operation.RefreshOperation.execute(RefreshOperation.java:113)
at org.dbunit.AbstractDatabaseTester.executeOperation(AbstractDatabaseTester.java:190)
at org.dbunit.AbstractDatabaseTester.onSetup(AbstractDatabaseTester.java:103)
at org.dbunit.DatabaseTestCase.setUp(DatabaseTestCase.java:156)
at test.HibernateDbUnitTestCase.setUp(HibernateDbUnitTestCase.java:85)
at test.PlayerTest.setUp(PlayerTest.java:117)
Caused by: java.lang.IllegalArgumentException: Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]
at java.sql.Timestamp.valueOf(Unknown Source)
at org.dbunit.dataset.datatype.TimestampDataType.typeCast(TimestampDataType.java:116)
... 20 more
That was weird, it seemed like my CustomTimeStamp was not called, so I changed the date in the dataset using the default format : 1997-02-14 00:00:00.0, and ran the unit test again. Then I got:
org.dbunit.dataset.datatype.TypeCastException: Unable to typecast value <1997-02-14 00:00:00.0> of type <java.lang.String> to TIMESTAMP
at test.CustomTimestampDataType.typeCast(CustomTimestampDataType.java:69)
at test.CustomTimestampDataType.setSqlValue(CustomTimestampDataType.java:84)
at org.dbunit.database.statement.SimplePreparedStatement.addValue(SimplePreparedStatement.java:73)
at org.dbunit.operation.RefreshOperation$RowOperation.execute(RefreshOperation.java:189)
at org.dbunit.operation.RefreshOperation.execute(RefreshOperation.java:113)
at org.dbunit.AbstractDatabaseTester.executeOperation(AbstractDatabaseTester.java:190)
at org.dbunit.AbstractDatabaseTester.onSetup(AbstractDatabaseTester.java:103)
at org.dbunit.DatabaseTestCase.setUp(DatabaseTestCase.java:156)
at test.HibernateDbUnitTestCase.setUp(HibernateDbUnitTestCase.java:85)
at test.PlayerTest.setUp(PlayerTest.java:117)
That means CustomTimeStamp was actually called. Seems like, the problem stemed from DatabaseTestCase.setUp which somehow called the wrong TimeStampDataType.
How could I fix this issue?
My first option was to replace every yyyy/MM/dd into yyyy-mm-dd in the dataset using regular expressions. This worked fine, until I had to test a method that selected a date based on a request (so the format is yyyy-mm-dd) and compared it to the current date. ( so the format is yyyy / mm / dd). Hsqldb can't compare two dates with different format.
My second option was to decompile dbunit.jar, rewrite TimeStampDataType based on the tutorial. I'm unfamiliar with bytecode writing so before entering uncharted waters, I wanted to know if you had another solution.
Thank you in advance
Fixed it!
So I ended up using my second option.
This is the detailed path for those who need it.
Download dbUnit.2.2.source.jar
Unzip the jar
Go to Eclipse, File > New > Java Project
Uncheck "Use default location"
In Location : specify the path to the new folder created from the jar
Click on Finish
Modify the TimestampDataType.java (if needed)
Instead of ts = java.sql.Timestamp.valueOf(stringValue); use the code below
String formats[] =
{"dd/MM/yyyy HH:mm:ss.SS"}; //and more depending on your need
Timestamp ts = null;
for (int i = 0; i < formats.length; i++)
{
SimpleDateFormat sdf = new SimpleDateFormat(formats[i]);
try {
java.util.Date date = sdf.parse(stringValue);
ts = new Timestamp(date.getTime());
return ts;
}
catch( ParseException e) {
}
Modify the DateDataType.java (if needed)
Instead of return java.sql.Date.valueOf(stringValue); , use the code below
String formats[] =
{"dd/MM/yyyy"}; //and more depending on your need
for (int i = 0; i < formats.length; i++)
{
SimpleDateFormat sdf = new SimpleDateFormat(formats[i]);
try {
java.util.Date date = sdf.parse(stringValue);
java.sql.Date datesql = new java.sql.Date(date.getTime());
return datesql;
}
catch( ParseException e) {
}
}
Right-click on your project, then Export
Select JAR file, then Next
Fill the export destination then Finish.
You just have to add this new jar to the library to make it work.

Java: how to format string with logging-like pattern?

Sometimes it's required to compose a string using logging-like pattern:
Something went wrong, detailA={}, detailB={}
but not in order to log it, but for other purposes (e.g. send over network).
Sometimes it's causing code duplication, like this:
logger.info("Something went wrong, detailA={}, detailB={}", detailA, detailB));
otherSystem.info(String.format("Something went wrong, detailA=%s, detailB=%s",
detailA, detailB);
Which is highly inconvenient and error-prone. How to format a string using logging pattern and logging-like API?
If you using slf4j, you can use its MessageFormatter.arrayFormat which returns a FormattingTuple,
FormattingTuple ft = MessageFormatter.arrayFormat(format, argArray);
And then convert it to a string.
String msg = ft.getMessage();
Which means you can add a utility method for that
static String format(String format,String...params){
FormattingTuple ft = MessageFormatter.arrayFormat(format,params);
String message = ft.getMessage();
return message;
}
System.out.println(format("hi {}, you {}","there","rock"));

java.util.logging custom formatter not working as expected

I am using Java 6. I have created a custom formatter which creates only the time and the message, but it always prints null class name and method name and the log level besides the time and the message in two lines:
Mar 8, 2015 6:48:09 PM null null
ALL: This is a message
Also, the log files generated are in the following format, where I expected it to start with xxx.log.0 first, once it is full, then xxx.log.1, but it generated all 10 files at the same time.
xxxx.log.0.9
xxxx.log.0.8
xxxx.log.0.7
xxxx.log.0.6
xxxx.log.0.5
xxxx.log.0.4
xxxx.log.0.3
Can someone let me know how I can log only the time and the message and how I correct the log file extensions? Much appreciated!
public class MyFormatter extends Formatter {
public String format(LogRecord record)
{
String recordStr = new Date() + " " + formatMessage(record)
return recordStr;
}
}
The code which uses MyFormatter:
Logger fileLogger = Logger.getLogger(xxxx.class.getPackage().getName());
FileHandler handler = new FileHandler(pattern, limit, numLogFiles, true);
MyFormatter formatter = new MyFormatter();
handler.setFormatter(formatter);
fileLogger.addHandler(handler);
Level logLevel = java.util.logging.Level.ALL;
fileLogger.log(new LogRecord(logLevel, "This is a message"));
I am using Java 6. I have created a custom formatter which creates only the time and the message, but it always prints null class name and method name and the log level besides the time and the message in two lines:
That output is from the java.util.logging.SimpleFormatter which has support for printing just the date and message. The following pattern can be used to change the SimpleFormatter to work like your custom formatter:
-Djava.util.logging.SimpleFormatter.format="[%1$tc] %5$s%n"
The code that uses your formatter is not setting the method name, class name, or logger name. Calling the Logger.log(Level,String) method will compute the call site for you.
private static final Logger fileLogger = Logger.getLogger(xxxx.class.getPackage().getName());
private static void initLogging() throws IOException {
FileHandler handler = new FileHandler(pattern, limit, numLogFiles, true);
MyFormatter formatter = new MyFormatter();
handler.setFormatter(formatter);
fileLogger.addHandler(handler);
fileLogger.log(Level.ALL, "This is a message");
}
Not sure if it is intended but, you should use the event time of the LogRecord and not the current time.
Also, the log files generated are in the following format, where I expected it to start with xxx.log.0 first, once it is full, then xxx.log.1, but it generated all 10 files at the same time.
For every FileHandler you create, you have to be sure it is closed by your code before you create a new one with the same pattern. By default the LogManager will close any attached handlers on shutdown. You also have to make sure that you hold a strong reference to the logger that holds the attached handler. Method local references like what is used in your example doesn't count.

How do I get java logging output to appear on a single line?

At the moment a default entry looks something like this:
Oct 12, 2008 9:45:18 AM myClassInfoHere
INFO: MyLogMessageHere
How do I get it to do this?
Oct 12, 2008 9:45:18 AM myClassInfoHere - INFO: MyLogMessageHere
Clarification I'm using java.util.logging
As of Java 7, java.util.logging.SimpleFormatter supports getting its format from a system property, so adding something like this to the JVM command line will cause it to print on one line:
-Djava.util.logging.SimpleFormatter.format='%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s %2$s %5$s%6$s%n'
Alternatively, you can also add this to your logger.properties:
java.util.logging.SimpleFormatter.format='%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s %2$s %5$s%6$s%n'
Similar to Tervor, But I like to change the property on runtime.
Note that this need to be set before the first SimpleFormatter is created - as was written in the comments.
System.setProperty("java.util.logging.SimpleFormatter.format",
"%1$tF %1$tT %4$s %2$s %5$s%6$s%n");
1) -Djava.util.logging.SimpleFormatter.format
Java 7 supports a property with the java.util.Formatter format string syntax.
-Djava.util.logging.SimpleFormatter.format=...
See here.
My favorite is:
-Djava.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$-6s %2$s %5$s%6$s%n
which makes output like:
2014-09-02 16:44:57 SEVERE org.jboss.windup.util.ZipUtil unzip: Failed to load: foo.zip
2) Putting it to IDEs
IDEs typically let you set system properties for a project.
E.g. in NetBeans, instead of adding -D...=... somewhere, add the property in the action dialog, in a form of java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-... - without any quotes. The IDE should figure out.
3) Putting that to Maven - Surefire
For your convenience, Here is how to put it to Surefire:
<!-- Surefire -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<systemPropertyVariables>
<!-- Set JUL Formatting -->
<java.util.logging.SimpleFormatter.format>%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$-6s %2$s %5$s%6$s%n</java.util.logging.SimpleFormatter.format>
</systemPropertyVariables>
</configuration>
</plugin>
4) Hand-made
I have a library with few java.util.logging related classes. Amongst them, it's SingleLineFormatter.
Downloadable jar here.
public class SingleLineFormatter extends Formatter {
Date dat = new Date();
private final static String format = "{0,date} {0,time}";
private MessageFormat formatter;
private Object args[] = new Object[1];
// Line separator string. This is the value of the line.separator
// property at the moment that the SimpleFormatter was created.
//private String lineSeparator = (String) java.security.AccessController.doPrivileged(
// new sun.security.action.GetPropertyAction("line.separator"));
private String lineSeparator = "\n";
/**
* Format the given LogRecord.
* #param record the log record to be formatted.
* #return a formatted log record
*/
public synchronized String format(LogRecord record) {
StringBuilder sb = new StringBuilder();
// Minimize memory allocations here.
dat.setTime(record.getMillis());
args[0] = dat;
// Date and time
StringBuffer text = new StringBuffer();
if (formatter == null) {
formatter = new MessageFormat(format);
}
formatter.format(args, text, null);
sb.append(text);
sb.append(" ");
// Class name
if (record.getSourceClassName() != null) {
sb.append(record.getSourceClassName());
} else {
sb.append(record.getLoggerName());
}
// Method name
if (record.getSourceMethodName() != null) {
sb.append(" ");
sb.append(record.getSourceMethodName());
}
sb.append(" - "); // lineSeparator
String message = formatMessage(record);
// Level
sb.append(record.getLevel().getLocalizedName());
sb.append(": ");
// Indent - the more serious, the more indented.
//sb.append( String.format("% ""s") );
int iOffset = (1000 - record.getLevel().intValue()) / 100;
for( int i = 0; i < iOffset; i++ ){
sb.append(" ");
}
sb.append(message);
sb.append(lineSeparator);
if (record.getThrown() != null) {
try {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
record.getThrown().printStackTrace(pw);
pw.close();
sb.append(sw.toString());
} catch (Exception ex) {
}
}
return sb.toString();
}
}
Like Obediah Stane said, it's necessary to create your own format method. But I would change a few things:
Create a subclass directly derived from Formatter, not from SimpleFormatter. The SimpleFormatter has nothing to add anymore.
Be careful with creating a new Date object! You should make sure to represent the date of the LogRecord. When creating a new Date with the default constructor, it will represent the date and time the Formatter processes the LogRecord, not the date that the LogRecord was created.
The following class can be used as formatter in a Handler, which in turn can be added to the Logger. Note that it ignores all class and method information available in the LogRecord.
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
public final class LogFormatter extends Formatter {
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
#Override
public String format(LogRecord record) {
StringBuilder sb = new StringBuilder();
sb.append(new Date(record.getMillis()))
.append(" ")
.append(record.getLevel().getLocalizedName())
.append(": ")
.append(formatMessage(record))
.append(LINE_SEPARATOR);
if (record.getThrown() != null) {
try {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
record.getThrown().printStackTrace(pw);
pw.close();
sb.append(sw.toString());
} catch (Exception ex) {
// ignore
}
}
return sb.toString();
}
}
This is what I'm using.
public class VerySimpleFormatter extends Formatter {
private static final String PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
#Override
public String format(final LogRecord record) {
return String.format(
"%1$s %2$-7s %3$s\n",
new SimpleDateFormat(PATTERN).format(
new Date(record.getMillis())),
record.getLevel().getName(), formatMessage(record));
}
}
You'll get something like...
2016-08-19T17:43:14.295+09:00 INFO Hey~
2016-08-19T17:43:16.068+09:00 SEVERE Seriously?
2016-08-19T17:43:16.068+09:00 WARNING I'm warning you!!!
Per screenshot, in Eclipse select "run as" then "Run Configurations..." and add the answer from Trevor Robinson with double quotes instead of quotes. If you miss the double quotes you'll get "could not find or load main class" errors.
I've figured out a way that works. You can subclass SimpleFormatter and override the format method
public String format(LogRecord record) {
return new java.util.Date() + " " + record.getLevel() + " " + record.getMessage() + "\r\n";
}
A bit surprised at this API I would have thought that more functionality/flexibility would have been provided out of the box
If you log in a web application using tomcat add:
-Djava.util.logging.ConsoleHandler.formatter = org.apache.juli.OneLineFormatter
On VM arguments
This logging is specific to your application and not a general Java feature. What application(s) are you running?
It might be that this is coming from a specific logging library that you are using within your own code. If so, please post the details of which one you are using.
if you're using java.util.logging, then there is a configuration file that is doing this to log contents (unless you're using programmatic configuration). So, your options are
1) run post -processor that removes the line breaks
2) change the log configuration AND remove the line breaks from it. Restart your application (server) and you should be good.

Categories

Resources