Skip to content

Commit

Permalink
logging memory
Browse files Browse the repository at this point in the history
  • Loading branch information
witek committed Nov 24, 2011
1 parent 5028192 commit c02e8ea
Show file tree
Hide file tree
Showing 11 changed files with 178 additions and 33 deletions.
22 changes: 22 additions & 0 deletions src/main/java/ilarkesto/core/base/Utl.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ public class Utl {

public static String language = "en";

public static int hashCode(Object... objects) {
int hashCode = 23;
for (Object object : objects) {
if (object == null) continue;
if (object instanceof Object[]) {
hashCode = hashCode * 37 + hashCode((Object[]) object);
} else {
hashCode = hashCode * 37 + object.hashCode();
}
}
return hashCode;
}

public static String getLanguage() {
return language;
}
Expand Down Expand Up @@ -56,6 +69,15 @@ public static <T> List<T> toList(T... elements) {
public static boolean equals(Object a, Object b) {
if (a == null && b == null) return true;
if (a == null || b == null) return false;
if (a instanceof Object[] && b instanceof Object[]) {
Object[] aa = (Object[]) a;
Object[] ba = (Object[]) b;
if (aa.length != ba.length) return false;
for (int i = 0; i < aa.length; i++) {
if (!equals(aa[i], ba[i])) return false;
}
return true;
}
return a.equals(b);
}

Expand Down
14 changes: 11 additions & 3 deletions src/main/java/ilarkesto/core/logging/Log.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public class Log {
private static final Log ANONYMOUS = new Log("?");
private static final Map<String, Log> LOGGERS = new HashMap<String, Log>();
private static boolean debugEnabled = true;
private static LogRecordHandler logRecordHandler = new PrintStreamLogDataHandler(System.err);
private static LogRecordHandler logRecordHandler = new PrintStreamLogRecordHandler(System.err);

private String name;

Expand Down Expand Up @@ -116,13 +116,21 @@ public static void DEBUG(Object... s) {
ANONYMOUS.debug(s);
}

public static void setLogRecordHandler(LogRecordHandler logDataHandler) {
Log.logRecordHandler = logDataHandler;
public static void setLogRecordHandler(LogRecordHandler handler) {
Log.logRecordHandler = handler;
}

public static enum Level {
DEBUG, INFO, WARN, ERROR, FATAL;

public boolean isInfo() {
return this == INFO;
}

public boolean isWarn() {
return this == WARN;
}

public boolean isWarnOrWorse() {
return isErrorOrWorse() || (this == WARN);
}
Expand Down
58 changes: 41 additions & 17 deletions src/main/java/ilarkesto/core/logging/LogRecord.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
/*
* Copyright 2011 Witoslaw Koczewsi <[email protected]>, Artjom Kochtchi
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option)
* any later version.
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero
* General Public License as published by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
* for more details.
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
package ilarkesto.core.logging;

import ilarkesto.core.base.Str;
import ilarkesto.core.base.Utl;
import ilarkesto.core.logging.Log.Level;

public class LogRecord {
Expand All @@ -24,7 +25,7 @@ public class LogRecord {
public final Object[] parameters;
public String context;

public LogRecord(String name, Level level, Object[] parameters) {
public LogRecord(String name, Level level, Object... parameters) {
super();
this.name = name;
this.level = level;
Expand All @@ -46,28 +47,51 @@ public String toString() {
sb.append(" ").append(nameFormated);

// text
StringBuilder text = new StringBuilder();
sb.append(Str.fillUpRight(getParametersAsString(), " ", 100));

// context
if (context != null) sb.append(" | ").append(context);

// extra line for high prio logs
if ((level != Level.DEBUG) && (level != Level.INFO)) sb.append('\n');

return sb.toString();
}

public String getParametersAsString() {
StringBuilder textSb = new StringBuilder();
if (parameters == null) {
text.append(" <null>");
textSb.append(" <null>");
} else {
for (Object parameter : parameters) {
text.append(' ');
textSb.append(' ');
if (parameter instanceof Throwable) {
text.append("\n").append(Str.getStackTrace((Throwable) parameter));
textSb.append("\n").append(Str.getStackTrace((Throwable) parameter));
} else {
text.append(Str.format(parameter));
textSb.append(Str.format(parameter));
}
}
}
sb.append(Str.fillUpRight(text.toString(), " ", 100));
String text = textSb.toString();
return text;
}

// context
if (context != null) sb.append(" | ").append(context);
private transient int hashcode;

// extra line for high prio logs
if ((level != Level.DEBUG) && (level != Level.INFO)) sb.append('\n');
@Override
public int hashCode() {
if (hashcode == 0) hashcode = Utl.hashCode(level, name, parameters);
return hashcode;
}

return sb.toString();
@Override
public boolean equals(Object obj) {
if (!(obj instanceof LogRecord)) return false;
LogRecord other = (LogRecord) obj;
if (level != other.level) return false;
if (!Utl.equals(name, other.name)) return false;
if (!Utl.equals(parameters, other.parameters)) return false;
return true;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@

import java.io.PrintStream;

public class PrintStreamLogDataHandler implements LogRecordHandler {
public class PrintStreamLogRecordHandler implements LogRecordHandler {

private PrintStream out;

public PrintStreamLogDataHandler(PrintStream out) {
public PrintStreamLogRecordHandler(PrintStream out) {
super();
this.out = out;
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/ilarkesto/di/app/AApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import ilarkesto.io.ExclusiveFileLock;
import ilarkesto.io.ExclusiveFileLock.FileLockedException;
import ilarkesto.io.IO;
import ilarkesto.logging.DefaultLogDataHandler;
import ilarkesto.logging.DefaultLogRecordHandler;
import ilarkesto.persistence.DaoListener;
import ilarkesto.persistence.DaoService;
import ilarkesto.persistence.EntityStore;
Expand Down Expand Up @@ -129,7 +129,7 @@ public void run() {
if (exclusiveFileLock != null) exclusiveFileLock.release();
Log.flush();
onShutdown();
DefaultLogDataHandler.stopLogging();
DefaultLogRecordHandler.stopLogging();
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/main/java/ilarkesto/di/app/ApplicationStarter.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import ilarkesto.di.BeanProvider;
import ilarkesto.di.MultiBeanProvider;
import ilarkesto.io.IO;
import ilarkesto.logging.DefaultLogDataHandler;
import ilarkesto.logging.DefaultLogRecordHandler;
import ilarkesto.logging.JavaLogging;
import ilarkesto.logging.Log4jLogging;

Expand All @@ -38,7 +38,7 @@ public static <A extends AApplication> A startApplication(Class<A> applicationCl
String... arguments) {

Sys.storeStartupTime();
DefaultLogDataHandler.activate();
DefaultLogRecordHandler.activate();
Log.setDebugEnabled(Sys.isDevelopmentMode());
Utl.language = Locale.getDefault().getLanguage();
LOG.info("********************************************************************************");
Expand All @@ -49,7 +49,7 @@ public static <A extends AApplication> A startApplication(Class<A> applicationCl
try {
A application = applicationClass.newInstance();
if (beanProvider != null) beanProvider.autowire(application);
DefaultLogDataHandler.setLogFile(new File(application.getApplicationDataDir() + "/error.log"));
DefaultLogRecordHandler.setLogFile(new File(application.getApplicationDataDir() + "/error.log"));
JavaLogging.redirectToLoggers();
try {
Log4jLogging.redirectToLoggers();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,32 @@
import java.io.FileWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

public class DefaultLogDataHandler implements LogRecordHandler {
public class DefaultLogRecordHandler implements LogRecordHandler {

private static final Log LOG = Log.get(DefaultLogDataHandler.class);
private static final Log LOG = Log.get(DefaultLogRecordHandler.class);
public static final DateFormat LOG_TIME_FORMAT = new SimpleDateFormat("EEE, dd. MMMM yyyy, HH:mm");
public static final DefaultLogDataHandler INSTANCE = new DefaultLogDataHandler();
public static final DefaultLogRecordHandler INSTANCE = new DefaultLogRecordHandler();

private BlockingQueue<LogRecord> queue = new LinkedBlockingQueue<LogRecord>();
private File logFile;
private Thread sysoutThread;
private boolean shutdown = false;

private LinkedList<LogRecord> latestRecords = new LinkedList<LogRecord>();

private LinkedList<LogRecord> errorRecords = new LinkedList<LogRecord>();

public static void activate() {}

private DefaultLogDataHandler() {
private DefaultLogRecordHandler() {
System.err.println("Initializing logging system");
sysoutThread = new Thread(new Runnable() {

Expand Down Expand Up @@ -84,10 +91,26 @@ public static void stopLogging() {
INSTANCE.flush();
INSTANCE.shutdown = true;
if (INSTANCE.sysoutThread != null) INSTANCE.sysoutThread.interrupt();
INSTANCE.latestRecords.clear();
}

@Override
public void log(LogRecord record) {

synchronized (latestRecords) {
latestRecords.add(record);
if (latestRecords.size() > 256) latestRecords.remove(0);
}

if (record.level.isWarnOrWorse()) {
synchronized (errorRecords) {
if (!errorRecords.contains(record)) {
errorRecords.add(record);
if (errorRecords.size() > 256) errorRecords.remove(0);
}
}
}

record.context = Thread.currentThread().getName();
try {
queue.put(record);
Expand Down Expand Up @@ -162,4 +185,16 @@ private void appendToFile(String record) {
}
}

public static List<LogRecord> getLatestRecords() {
synchronized (INSTANCE.latestRecords) {
return new ArrayList<LogRecord>(INSTANCE.latestRecords);
}
}

public static List<LogRecord> getErrors() {
synchronized (INSTANCE.errorRecords) {
return new ArrayList<LogRecord>(INSTANCE.errorRecords);
}
}

}
4 changes: 4 additions & 0 deletions src/main/java/ilarkesto/testng/ATest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ public class ATest extends Assert {

protected Log log = Log.get(getClass());

public static void assertNotEquals(Object a, Object b) {
assertFalse(a.equals(b), "Objects expected not to be equal: <" + a + "> and <" + b + ">");
}

public static void assertSize(Collection collection, int expectedSize) {
assertNotNull(collection, "Collection expected to be not null");
assertEquals(collection.size(), expectedSize, "Collection size expected to be <" + expectedSize + ">, but is <"
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/ilarkesto/webapp/AWebApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import ilarkesto.core.logging.Log;
import ilarkesto.di.app.AApplication;
import ilarkesto.gwt.server.AGwtConversation;
import ilarkesto.logging.DefaultLogDataHandler;
import ilarkesto.logging.DefaultLogRecordHandler;

import java.io.File;
import java.util.HashSet;
Expand Down Expand Up @@ -48,7 +48,7 @@ public abstract class AWebApplication extends AApplication {
@Override
protected void onStart() {
if (!isDevelopmentMode()) Sys.setHeadless(true);
DefaultLogDataHandler.setLogFile(new File(getApplicationDataDir() + "/error.log"));
DefaultLogRecordHandler.setLogFile(new File(getApplicationDataDir() + "/error.log"));
LOG.info("Initializing web application");
onStartWebApplication();
}
Expand Down
9 changes: 9 additions & 0 deletions src/test/java/ilarkesto/core/base/UtlTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@

public class UtlTest extends ATest {

@Test
public void equals() {
Object[] a = { "hello", "equals" };
Object[] b = { "hello", "equals" };
Object[] c = { "hello", "world" };
assertTrue(Utl.equals(a, b));
assertFalse(Utl.equals(a, c));
}

@Test
public void removeDuplicates() {
List<String> list = Utl.toList("a", "b", "b", "a");
Expand Down
43 changes: 43 additions & 0 deletions src/test/java/ilarkesto/core/logging/LogRecordTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright 2011 Witoslaw Koczewsi <[email protected]>
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero
* General Public License as published by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License along with this program. If not,
* see <http://www.gnu.org/licenses/>.
*/
package ilarkesto.core.logging;

import ilarkesto.core.logging.Log.Level;
import ilarkesto.testng.ATest;

import org.testng.annotations.Test;

public class LogRecordTest extends ATest {

@Test
public void hash() {
LogRecord a = new LogRecord("A", Level.INFO, "hello", "logger");
LogRecord b = new LogRecord("A", Level.INFO, "hello", "logger");
LogRecord c = new LogRecord("A", Level.INFO, "hello", "world");
assertEquals(a.hashCode(), b.hashCode());
assertNotEquals(a.hashCode(), c.hashCode());
}

@Test
public void equals() {
LogRecord a = new LogRecord("A", Level.INFO, "hello", "logger");
LogRecord b = new LogRecord("A", Level.INFO, "hello", "logger");
LogRecord c = new LogRecord("A", Level.INFO, "hello", "world");
assertEquals(a, a);
assertEquals(a, b);
assertNotEquals(a, c);
}

}

0 comments on commit c02e8ea

Please sign in to comment.