package alma.contLogTest.TestLogLevelsCompImpl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import com.cosylab.logging.engine.log.ILogEntry;
import alma.acs.logging.engine.LogReceiver;
import alma.acs.logging.engine.LogReceiver.DelayedLogEntry;
import alma.acs.logging.engine.LogReceiver.ReceivedLogRecord;
/**
* Helper class for tests that must receive log records from the Log service.
*/
public class LogSeriesExpectant
{
private LogReceiver logReceiver;
/**
* @param logReceiver an already initialized LogReceiver from which logs will be fetched.
* This class will not {@link LogReceiver#stop() stop} the logReceiver,
* which therefore remains the task of the calling class.
* @throws IllegalArgumentException if logReceiver is not initialized.
*/
LogSeriesExpectant(LogReceiver logReceiver) {
if (!logReceiver.isInitialized()) {
throw new IllegalArgumentException("The given logReceiver must be initialized!");
}
this.logReceiver = logReceiver;
}
/**
* Call this method before the logs that we are interested in get produced.
*/
public void clearLogs() {
logReceiver.getLogQueue().clear();
}
/**
* Call this method after the logs that should be received have been produced.
* Then the call may take up to <code>logRoundtripTimeSeconds</code> seconds to return.
*
* @param loggerName The name of the logger whose records are to be collected.
* Filtering of arriving log records will be done for the {@link ILogEntry.Field#SOURCEOBJECT} field.
* @param logRoundtripTimeSeconds Maximum roundtrip time of a log record
* (incl. caching by container, sending to Log service, processing by Log service, arrival at LogReceiver).
*/
LogList awaitLogRecords(String loggerName, int logRoundtripTimeSeconds) {
int sortingTimeWindowSeconds = 0; // doesn't look like we need a running time windows to sort log records as long as we sort the list in the end.
long endTimeMillis = System.currentTimeMillis() + (logRoundtripTimeSeconds + sortingTimeWindowSeconds) * 1000;
LogList logRecords = new LogList();
logReceiver.setDelayMillis(sortingTimeWindowSeconds * 1000);
BlockingQueue<DelayedLogEntry> queue = logReceiver.getLogQueue();
long waitTimeMillis = -1;
while ((waitTimeMillis = endTimeMillis - System.currentTimeMillis()) > 0) {
DelayedLogEntry delayedLogEntry = null;
try {
delayedLogEntry = queue.poll(waitTimeMillis, TimeUnit.MILLISECONDS);
} catch (InterruptedException ex) {
// continue
}
if (delayedLogEntry != null) { // timeout yields a null
ReceivedLogRecord logRecord = delayedLogEntry.getLogRecord();
String sourceObjectName = logRecord.getSourceObject();
if (sourceObjectName != null && sourceObjectName.equals(loggerName)) {
// printing this could be useful for debugging the test
System.out.println("TEST DEBUG: " + logRecord.getMessage());
if (logRecord.getMessage() == null) {
System.out.println("BUG: got a null log-message from " + sourceObjectName);
continue;
}
// Filter out python trace-logs (which could make it or not, depending on timing)
if (logRecord.getMessage().startsWith("initialize -") ||
logRecord.getMessage().startsWith("getLevels -") ||
logRecord.getMessage().startsWith("cleanUp -")) {
//System.out.println("Dropping this log: "+ logRecord.getMessage());
continue;
}
// Filter out messages which are a work-around for a python issue
if (!logRecord.getMessage().endsWith("===packet fill-up message===")) {
logRecords.add(logRecord);
}
}
else {
// printing this could be useful for debugging the test
//System.out.println("Dropped log message from " + sourceObjectName + ": " + logRecord.getMessage());
//System.out.println("Dropped log message from " + sourceObjectName + ": " + logEntry.getField(ILogEntry.Field.LOGMESSAGE));
}
}
}
// sort by timestamp
Collections.sort(logRecords, new Comparator<ReceivedLogRecord>() {
public int compare(ReceivedLogRecord o1, ReceivedLogRecord o2) {
return o1.getTimestamp().compareTo(o2.getTimestamp()) ;
}
});
return logRecords;
}
// /**
// * Sleeps as long as the granularity of OS time makes {@link System#currentTimeMillis()} return the same value.
// * Calling this method between sending of two logs guarantees that the log records carry different time stamps.
// */
// public void awaitSystimeChange() {
// long t1 = System.currentTimeMillis();
// while (System.currentTimeMillis() == t1) {
// try {
// Thread.sleep(20);
// } catch (InterruptedException ex) {
// ex.printStackTrace();
// }
// }
// }
public static class LogList extends ArrayList<ReceivedLogRecord> {
public int getMinLogLevel() {
int minLevel = Integer.MAX_VALUE;
for (ReceivedLogRecord logRecord : this) {
minLevel = Math.min(minLevel, logRecord.getLevel().acsCoreLevel.value);
}
return minLevel;
}
public int getMaxLogLevel() {
int maxLevel = -1;
for (ReceivedLogRecord logRecord : this) {
maxLevel = Math.max(maxLevel, logRecord.getLevel().acsCoreLevel.value);
}
return maxLevel;
}
}
}