/*
* Copyright 2014, The Sporting Exchange Limited
* Copyright 2015, Simon Matić Langford
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.betfair.cougar.logging.records;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.TimeZone;
import java.util.logging.Level;
import com.betfair.cougar.api.LoggableEvent;
public final class EventLogRecord extends CougarLogRecord {
private static final String fieldSeperator = ",";
private static final String collectionStart = "[";
private static String collectionSeperator = "|";
private static final String collectionEnd = "]";
private static final String TAB = "\t";
private static final ThreadLocal<DateFormat> dateFormatter = new ThreadLocal<DateFormat>();
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
public static void setCollectionSeperator(String collectionSeperator) {
EventLogRecord.collectionSeperator = collectionSeperator;
}
private static String[] NON_LOGGABLE_STRINGS = new String[]{
LINE_SEPARATOR, TAB, fieldSeperator, collectionSeperator
};
private String messageString;
private final LoggableEvent event;
private final Object[] xFields;
public EventLogRecord(LoggableEvent event, Object[] extensionFields) {
super(event.getLogName(), Level.INFO, null);
this.event = event;
this.xFields = extensionFields == null ? new Object[]{} : extensionFields;
}
/* (non-Javadoc)
* @see com.betfair.cougar.logging.records.LoggableEvent#renderMessageString()
*/
public final void renderMessageString() {
Object[] coreFields = event.getFieldsToLog();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < coreFields.length + xFields.length; ++i) {
if (i > 0) {
sb.append(fieldSeperator);
}
Object field = i < coreFields.length ? coreFields[i] : xFields[i - coreFields.length];
renderObject(sb, field);
}
messageString = sb.toString();
}
// Do not allow the getMessage method to be overloaded so that the message
// is correctly written from the result of the setEventRecord call. The pre
// render is available so that the message can be rendered before the logging
// synchronised blocking write is entered.
public final String getMessage() {
if (messageString == null) {
renderMessageString();
}
return messageString;
}
// Return a byte array for binary logging. Dummy implementation
/* (non-Javadoc)
* @see com.betfair.cougar.logging.records.LoggableEvent#getBytes()
*/
public final byte[] getBytes() throws IOException {
return getMessage().getBytes();
}
private DateFormat getDateFormatter() {
if (dateFormatter.get() == null) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
dateFormatter.set(dateFormat);
}
return dateFormatter.get();
}
private void renderObject(StringBuilder sb, Object o) {
if (o == null) {
return;
}
if (o instanceof Date) {
sb.append(getDateFormatter().format((Date)o));
return;
}
if (o instanceof Loggable) {
((Loggable)o).writeTo(sb);
return;
}
if (o instanceof Object[]) {
o = Arrays.asList((Object[])o);
}
if (o instanceof Iterable<?>) {
sb.append(collectionStart);
boolean first = true;
for (Object obj : (Iterable<?>)o) {
if (first) {
first = false;
} else {
sb.append(collectionSeperator);
}
renderObject(sb, obj);
}
sb.append(collectionEnd);
return;
}
if (o instanceof Boolean) {
sb.append(((Boolean)o) ? "Y" : "N");
return;
}
sb.append(cleanse(o));
}
private String cleanse(Object obj) {
if(obj == null)
return "";
String stringToLog = obj.toString();
for (String string : NON_LOGGABLE_STRINGS) {
stringToLog = stringToLog.replace(string, " ");
}
return stringToLog;
}
}