/*
* ALMA - Atacama Large Millimiter Array
* (c) European Southern Observatory, 2002
* Copyright by ESO (in the framework of the ALMA collaboration),
* All rights reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
package alma.acs.logging.formatters;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.Map;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
import org.omg.CORBA.Any;
import alma.ACSLoggingLog.LogBinaryRecord;
import alma.ACSLoggingLog.LogBinaryRecordHelper;
import alma.ACSLoggingLog.NameValue;
import alma.acs.logging.AcsLogLevel;
import alma.acs.logging.AcsLogRecord;
import alma.acs.logging.LogParameterUtil;
import alma.acs.logging.level.AcsLogLevelDefinition;
import alma.acs.util.IsoDateFormat;
/**
* @author cparedes
*
* Class that is responsible for formatting the log records/elements of different levels
* as well as assigning the right values to their attributes.
*/
public class AcsBinLogFormatter extends AcsLogFormatter
{
/**
* This is the method used by ACS, for all AcsLogFormatters.
*/
public Any formatAny( Any anyLogRecord, LogRecord logRecord){
LogBinaryRecord binLogRecord = formatBinary(logRecord);
LogBinaryRecordHelper.insert(anyLogRecord,binLogRecord);
return anyLogRecord;
}
LogBinaryRecord formatBinary(LogRecord logRecord){
LogBinaryRecord rLog = new LogBinaryRecord();
// log level
AcsLogLevel acsLevel = AcsLogLevel.getNativeLevel(logRecord.getLevel());
if (acsLevel == null) {
return null;
}
final AcsLogLevelDefinition acsCoreLevel = acsLevel.getAcsLevel();
// get date
Date date = new Date(logRecord.getMillis());
String TimeStamp = IsoDateFormat.formatDate(date);
LogParameterUtil logParamUtil = new LogParameterUtil(logRecord);
rLog.type = (short) acsCoreLevel.value;
rLog.TimeStamp = TimeStamp;
String file = logRecord.getSourceClassName();
if (file == null)
{
if (acsCoreLevel == AcsLogLevelDefinition.DEBUG)
rLog.File = "unknown";
}
else
rLog.File = file;
long line = logParamUtil.extractLongProperty(LogParameterUtil.PARAM_LINE, -1);
if (line < 0)
{
if (acsCoreLevel == AcsLogLevelDefinition.TRACE || acsCoreLevel == AcsLogLevelDefinition.DEBUG)
rLog.Line = 0;
}
else
rLog.Line = (int)line;
String Routine = logRecord.getSourceMethodName();
if (Routine == null) {
if (acsCoreLevel == AcsLogLevelDefinition.TRACE) {
rLog.Routine = "unknown";
}
}
else {
rLog.Routine = Routine;
}
// host name: may be different from local host if ErrorTrace gets logged
String hostName = logParamUtil.extractStringProperty(LogParameterUtil.PARAM_HOSTNAME, null);
if (hostName == null || hostName.length() == 0) {
hostName = getLocalHostName();
}
rLog.Host = hostName;
// String process = logParamUtil.extractStringProperty(LogParameterUtil.PARAM_PROCESSNAME, null);
// if (process != null)
// rLog.Process = process;
// else{
String process = logRecord.getLoggerName();
if(process != null) rLog.Process = "LoggerName: " + process;
else rLog.Process = "";
// }
// source object: the container name or component name
String sourceObject = logRecord.getLoggerName();
if (sourceObject != null) {
rLog.SourceObject = sourceObject;
}else rLog.SourceObject = "";
// add thread ID, or name if given
String threadName = logParamUtil.extractStringProperty(LogParameterUtil.PARAM_THREAD_NAME, null);
if (threadName != null && threadName.length() > 0)
rLog.Thread = threadName;
else if (logRecord.getThreadID() >= 0)
rLog.Thread = ""+logRecord.getThreadID();
else rLog.Thread = "";
// add context
String context = logParamUtil.extractStringProperty("Context", null);
if (context != null)
rLog.LogContext = context;
else rLog.LogContext = "";
// add stack info
rLog.StackId="";
rLog.StackLevel = 0;
if (acsCoreLevel.compareTo(AcsLogLevelDefinition.WARNING) >= 0) {
// add stack id
String stackId = logParamUtil.extractStringProperty(LogParameterUtil.PARAM_STACK_ID, null);
if (stackId == null)
rLog.StackId="unknown";
else
rLog.StackId=stackId;
// add stack idlevel
long stackLevel = logParamUtil.extractLongProperty(LogParameterUtil.PARAM_STACK_LEVEL, -1);
if (stackLevel > 0)
rLog.StackLevel = (int)stackLevel;
}
// add log id
long logId = logRecord.getSequenceNumber();
if (logId >= 0)
rLog.LogId = "" +logId;
else rLog.LogId = "";
// add URI
String uri = logParamUtil.extractStringProperty(LogParameterUtil.PARAM_URI, null);
if (uri != null)
rLog.Uri = uri;
else rLog.Uri = "";
// add priority
// to be written only different as entry priority
long priority = logParamUtil.extractLongProperty(LogParameterUtil.PARAM_PRIORITY, acsCoreLevel.value);
if (priority != acsCoreLevel.value)
rLog.Priority = (int)priority;
else rLog.Priority = -1;
// the log message becomes the text in our XML record
if (logRecord.getMessage() != null)
{
rLog.MsgData = logRecord.getMessage();
}else rLog.MsgData = "";
//add Audience, Array and Antenna, if applicable
if (logRecord instanceof AcsLogRecord) {
rLog.Audience = ((AcsLogRecord) logRecord).getAudience();
rLog.Array = ((AcsLogRecord) logRecord).getArray();
rLog.Antenna = ((AcsLogRecord) logRecord).getAntenna();
}
// <Data> elements: logged exception or error trace, and log parameters
//NameValue a;
//rLog.log_data = new NameValue[propertiesMap.size() + 1];
//TODO: see why there are not attributes here
rLog.attributes = new NameValue[0];
NameValue [] log_data = new NameValue[257];
//rLog.log_data = new NameValue[257];
int i = 0;
try {
// logged exception
Throwable loggedThrowable = logRecord.getThrown();
if (loggedThrowable != null) {
StringWriter exWriter = new StringWriter();
loggedThrowable.printStackTrace(new PrintWriter(exWriter));
log_data[i++] = new NameValue("LoggedException", exWriter.toString());
}
// log parameters (except for the special properties which were used already to set specific fields)
for (Object param : logParamUtil.getNonSpecialPropertiesMapParameters()) {
if(i>=255) break;
if (param instanceof Map) {
// any map that is not the special properties map we interpret as name-value pairs.
Map propertiesMap = (Map) param;
for (Object keyName : propertiesMap.keySet()) {
String value = propertiesMap.get(keyName).toString();
log_data[i++] = new NameValue(keyName.toString(), value);
}
}
else {
// a single parameter was logged, but we have to fit it into our name-value scheme using a fake name
String value = param.toString();
log_data[i++] = new NameValue("LoggedParameter", value);
}
}
}
catch (Exception e) {
// expected not to happen often at all, thus no try blocks inside every loop, so we may lose some <Data>
String value = e.toString();
log_data[i++] = new NameValue("DataConstructionError", value);
}
rLog.log_data = new NameValue[i];
for(int j=0; j<i;j++) {
rLog.log_data[j] = log_data[j];
}
// end tag of BIN record
return rLog;
}
/**
* This method should never be called. We only add it to support the inheritance of
* {@link AcsLogFormatter} from {@link Formatter} which is useful for text-based subclasses.
*/
public String format(LogRecord record) {
return "Error: only binary format available!";
}
}