package dailyBot.control;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import dailyBot.control.connection.ChatConnection;
import dailyBot.control.connection.EmailConnection;
import dailyBot.model.Strategy.StrategyId;
public class DailyLog
{
private static volatile int hour = 0;
private static volatile int errorCount = 0;
private static volatile String acummulatedInfo = "";
private static volatile String acummulatedError = "";
private static volatile boolean acummulate = false;
public static void logError(String error)
{
if(!acummulate)
sendMessage("DailyBot-error", error, true, true);
else
acummulatedError += error + "\n";
ChatConnection.sendMessage(error, true, ChatConnection.ADMINS | ChatConnection.WATCHERS);
checkHourErrors();
}
public static void logInfo(String info)
{
if(!acummulate)
sendMessage("DailyBot-info", info, true, false);
else
acummulatedInfo += info + "\n";
}
public static void sendAcummulated()
{
if(!acummulatedInfo.trim().isEmpty())
sendMessage("DailyBot-info", acummulatedInfo, true, false);
if(!acummulatedError.trim().isEmpty())
sendMessage("DailyBot-error", acummulatedError, true, true);
acummulatedInfo = "";
acummulatedError = "";
acummulate = false;
}
public static void acummulateLog()
{
acummulate = true;
}
public static void logErrorToDisk(String error)
{
sendMessage("DailyBot-error", error, false, true);
if(!error.contains("quota") && !error.contains("Daily"))
checkHourErrors();
}
private static final Map <String, StringBuffer> rangeMapWatchers = Collections.synchronizedMap(new HashMap <String, StringBuffer> ());
private static final Map <String, StringBuffer> rangeMapAll = Collections.synchronizedMap(new HashMap <String, StringBuffer> ());
private static StringBuffer getStringBuffer(String title, boolean all)
{
final Map <String, StringBuffer> rangeMap = all ? rangeMapAll : rangeMapWatchers;
if(!rangeMap.containsKey(title))
rangeMap.put(title, new StringBuffer(""));
return rangeMap.get(title);
}
private static String format(int number)
{
String answer = number + "";
while(answer.length() < 2)
answer = "0" + answer;
return answer;
}
public static synchronized void addRangeInfo(String title, String info)
{
Calendar calendar = Calendar.getInstance();
getStringBuffer(title, false).append(format(calendar.get(Calendar.MONTH) + 1) + "/" + format(calendar.get(Calendar.DAY_OF_MONTH)) + " " + format(calendar.get(Calendar.HOUR_OF_DAY)) + ":" + format(calendar.get(Calendar.MINUTE)) + " - " + info + "\n");
getStringBuffer(title, true).append(format(calendar.get(Calendar.MONTH) + 1) + "/" + format(calendar.get(Calendar.DAY_OF_MONTH)) + " " + format(calendar.get(Calendar.HOUR_OF_DAY)) + ":" + format(calendar.get(Calendar.MINUTE)) + " - " + info + "\n");
}
public static synchronized String getRangeInfo(boolean all)
{
final Map <String, StringBuffer> rangeMap = all ? rangeMapAll : rangeMapWatchers;
try
{
boolean notFirst = false;
StringBuffer sb = new StringBuffer("");
for(Map.Entry <String, StringBuffer> e : rangeMap.entrySet())
{
if(notFirst)
sb.append("\n");
notFirst = true;
sb.append(e.getKey() + ":\n");
sb.append(e.getValue().toString());
}
return sb.toString();
}
finally
{
for(StringBuffer sb : rangeMap.values())
sb.setLength(0);
}
}
private static void sendMessage(String title, String message, boolean email, boolean chat)
{
try
{
if(!email && !DailyProperties.isTesting())
{
Calendar calendar = Calendar.getInstance();
String number = calendar.get(Calendar.YEAR) + "" + (calendar.get(Calendar.MONTH) + 1) + "" + calendar.get(Calendar.DATE);
FileWriter fileWriter = new FileWriter(new File("logs/log" + number + ".txt"), true);
fileWriter.write(message);
fileWriter.write(System.getProperty("line.separator"));
fileWriter.close();
}
if(email)
EmailConnection.sendEmail(title, message, EmailConnection.ADMINS | EmailConnection.WATCHERS | EmailConnection.SUPERADMINS);
}
catch(Exception e)
{
System.out.println("Error en el gestionador de errores");
}
}
private static void checkHourErrors()
{
Calendar calendar = Calendar.getInstance();
int currentHour = calendar.get(Calendar.HOUR_OF_DAY);
int lastErrorCount;
synchronized(DailyLog.class.getClass())
{
if(hour == currentHour)
errorCount++;
else
{
hour = currentHour;
errorCount = 1;
}
lastErrorCount = errorCount;
}
if(lastErrorCount == 200)
{
sendMessage("DailyBot-error", "200 errores en una hora, reiniciando", true, true);
tryReboot();
}
}
public static void tryReboot()
{
ExecutorService executor = Executors.newSingleThreadExecutor();
for(final StrategyId strategyId : StrategyId.values())
{
Future <Boolean> writer = executor.submit(new Callable <Boolean>()
{
@Override
public Boolean call() throws Exception
{
strategyId.strategy().writePersistency();
return true;
}
});
try
{
writer.get(10, TimeUnit.SECONDS);
}
catch(Exception e1)
{
DailyLog.logError("Al reiniciar imposible escribir " + strategyId);
}
}
reboot();
}
public static void tryInmediateReboot()
{
reboot();
}
private static void reboot()
{
try
{
String message = "Reiniciando, stack:\n";
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
if(stackTrace != null)
for(StackTraceElement stackTraceElement : stackTrace)
message += stackTraceElement + "\n";
DailyLog.logError(message);
sendAcummulated();
DailyUtils.sleep(180000);
Runtime.getRuntime().exec("service dailybot restart");
System.exit(0);
throw(new RuntimeException());
}
catch(IOException e)
{
DailyLog.logError("Error reiniciando equipo " + e.getMessage());
reboot();
}
}
}