* Logging:
- Limit buffer size; block and wakeup writer when full - Limit errors written to system log - Add method to force a log below the current level
This commit is contained in:
@ -117,6 +117,17 @@ public class Log {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Always log this messge with the given priority, ignoring current minimum priority level.
|
||||
* This allows an INFO message about changing port numbers, for example, to always be logged.
|
||||
* @since 0.8.2
|
||||
*/
|
||||
public void logAlways(int priority, String msg) {
|
||||
_manager.addRecord(new LogRecord(_class, _name,
|
||||
Thread.currentThread().getName(), priority,
|
||||
msg, null));
|
||||
}
|
||||
|
||||
public void debug(String msg) {
|
||||
log(DEBUG, msg);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.TreeMap;
|
||||
@ -78,6 +79,9 @@ public class LogManager {
|
||||
|
||||
/** the config file */
|
||||
private File _locationFile;
|
||||
|
||||
/** max to LogRecords to buffer in memory before we start blocking */
|
||||
private static final int MAX_BUFFER = 1024;
|
||||
/** Ordered list of LogRecord elements that have not been written out yet */
|
||||
private final LinkedBlockingQueue<LogRecord> _records;
|
||||
/** List of explicit overrides of log levels (LogLimit objects) */
|
||||
@ -119,7 +123,7 @@ public class LogManager {
|
||||
public LogManager(I2PAppContext context) {
|
||||
_displayOnScreen = true;
|
||||
_alreadyNoticedMissingConfig = false;
|
||||
_records = new LinkedBlockingQueue();
|
||||
_records = new LinkedBlockingQueue(MAX_BUFFER);
|
||||
_limits = new ConcurrentHashSet();
|
||||
_logs = new ConcurrentHashMap(128);
|
||||
_defaultLimit = Log.ERROR;
|
||||
@ -221,25 +225,26 @@ public class LogManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by Log to add records to the queue
|
||||
*
|
||||
* Used by Log to add records to the queue.
|
||||
* This is generally nonblocking and unsyncrhonized but may block when under
|
||||
* massive logging load as a way of throttling logging threads.
|
||||
*/
|
||||
void addRecord(LogRecord record) {
|
||||
if ((!_context.isRouterContext()) && _writer == null)
|
||||
startLogWriter();
|
||||
|
||||
_records.offer(record);
|
||||
/**** don't burden the logging thread with counting
|
||||
int numRecords = _records.size();
|
||||
|
||||
if (numRecords > 100) {
|
||||
boolean success = _records.offer(record);
|
||||
if (!success) {
|
||||
// the writer waits 10 seconds *or* until we tell them to wake up
|
||||
// before rereading the config and writing out any log messages
|
||||
synchronized (_writer) {
|
||||
_writer.notifyAll();
|
||||
}
|
||||
// block as a way of slowing down out-of-control loggers (a little)
|
||||
try {
|
||||
_records.put(record);
|
||||
} catch (InterruptedException ie) {}
|
||||
}
|
||||
****/
|
||||
}
|
||||
|
||||
/**
|
||||
@ -605,10 +610,13 @@ public class LogManager {
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
List<LogRecord> _removeAll() {
|
||||
List<LogRecord> vals = new LinkedList();
|
||||
_records.drainTo(vals);
|
||||
return vals;
|
||||
/**
|
||||
* Zero-copy.
|
||||
* For the LogWriter
|
||||
* @since 0.8.2
|
||||
*/
|
||||
Queue<LogRecord> getQueue() {
|
||||
return _records;
|
||||
}
|
||||
|
||||
public char[] getFormat() {
|
||||
|
@ -15,7 +15,7 @@ import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.List;
|
||||
import java.util.Queue;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
|
||||
@ -38,6 +38,8 @@ class LogWriter implements Runnable {
|
||||
private LogManager _manager;
|
||||
|
||||
private boolean _write;
|
||||
private static final int MAX_DISKFULL_MESSAGES = 8;
|
||||
private int _diskFullMessageCount;
|
||||
|
||||
private LogWriter() { // nop
|
||||
}
|
||||
@ -61,7 +63,7 @@ class LogWriter implements Runnable {
|
||||
}
|
||||
//System.err.println("Done writing");
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error writing the logs: " + e.getMessage());
|
||||
System.err.println("Error writing the log: " + e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
closeFile();
|
||||
@ -70,16 +72,19 @@ class LogWriter implements Runnable {
|
||||
public void flushRecords() { flushRecords(true); }
|
||||
public void flushRecords(boolean shouldWait) {
|
||||
try {
|
||||
List<LogRecord> records = _manager._removeAll();
|
||||
// zero copy, drain the manager queue directly
|
||||
Queue<LogRecord> records = _manager.getQueue();
|
||||
if (records == null) return;
|
||||
if (!records.isEmpty()) {
|
||||
for (LogRecord rec : records) {
|
||||
LogRecord rec;
|
||||
while ((rec = records.poll()) != null) {
|
||||
writeRecord(rec);
|
||||
}
|
||||
try {
|
||||
_currentOut.flush();
|
||||
} catch (IOException ioe) {
|
||||
System.err.println("Error writing the router log");
|
||||
if (++_diskFullMessageCount < MAX_DISKFULL_MESSAGES)
|
||||
System.err.println("Error writing the router log - disk full? " + ioe);
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
@ -138,6 +143,7 @@ class LogWriter implements Runnable {
|
||||
} catch (Throwable t) {
|
||||
if (!_write)
|
||||
return;
|
||||
if (++_diskFullMessageCount < MAX_DISKFULL_MESSAGES)
|
||||
System.err.println("Error writing log, disk full? " + t);
|
||||
//t.printStackTrace();
|
||||
}
|
||||
|
Reference in New Issue
Block a user