501 lines
13 KiB
JavaScript
501 lines
13 KiB
JavaScript
/*
|
|
* @project: TERA
|
|
* @version: Development (beta)
|
|
* @license: MIT (not for evil)
|
|
* @copyright: Yuriy Ivanov (Vtools) 2017-2019 [progr76@gmail.com]
|
|
* Web: https://terafoundation.org
|
|
* Twitter: https://twitter.com/terafoundation
|
|
* Telegram: https://t.me/terafoundation
|
|
*/
|
|
|
|
require("./constant.js");
|
|
var fs = require('fs');
|
|
require("./log-strict.js");
|
|
var file_name_info = GetDataPath("info.log");
|
|
var file_name_infoPrev = GetDataPath("info-prev.log");
|
|
CheckSizeLogFile(file_name_info, file_name_infoPrev);
|
|
var file_name_log = GetDataPath("log.log");
|
|
var file_name_logPrev = GetDataPath("log-prev.log");
|
|
CheckSizeLogFile(file_name_log, file_name_logPrev);
|
|
var file_name_log_web = GetDataPath("web.log");
|
|
var file_name_log_webPrev = GetDataPath("web-prev.log");
|
|
CheckSizeLogFile(file_name_log_web, file_name_log_webPrev);
|
|
var file_name_error = GetDataPath("err.log");
|
|
var file_name_errorPrev = GetDataPath("err-prev.log");
|
|
CheckSizeLogFile(file_name_error, file_name_errorPrev);
|
|
var file_name_error_tx = GetDataPath("err-tx.log");
|
|
var file_name_error_txPrev = GetDataPath("err-tx-prev.log");
|
|
CheckSizeLogFile(file_name_error_tx, file_name_error_txPrev);
|
|
global.ToLog = function (Str,Level)
|
|
{
|
|
if(Level === undefined)
|
|
Level = 1;
|
|
if(Level && Level > global.LOG_LEVEL)
|
|
return ;
|
|
if(global.ALL_LOG_TO_CLIENT)
|
|
ToLogClient(Str, undefined, undefined);
|
|
else
|
|
ToLogFile(file_name_log, Str);
|
|
};
|
|
global.WEB_LOG = 0;
|
|
global.ToLogWeb = function (Str)
|
|
{
|
|
if(global.WEB_LOG)
|
|
{
|
|
SaveToLogFileSync(file_name_log_web, Str);
|
|
}
|
|
};
|
|
global.SmallAddr = function (Str)
|
|
{
|
|
return Str.substr(0, 5);
|
|
};
|
|
global.ToErrorTrace = function (Str)
|
|
{
|
|
ToError("" + Str + ":" + new Error().stack);
|
|
};
|
|
global.ToLogTrace = function (Str)
|
|
{
|
|
ToErrorTrace(Str);
|
|
};
|
|
global.ToInfo = function (Str)
|
|
{
|
|
ToLogFile(file_name_info, Str, 1);
|
|
};
|
|
global.ToError = function (Str)
|
|
{
|
|
ToLogFile(file_name_error, Str);
|
|
};
|
|
global.ToErrorTx = function (Str)
|
|
{
|
|
SaveToLogFileSync(file_name_error_tx, Str);
|
|
ToLog(Str);
|
|
};
|
|
|
|
function ToLogFile(file_name,Str,bNoFile)
|
|
{
|
|
if(Str instanceof Error)
|
|
{
|
|
Str = Str.message + "\n" + Str.stack;
|
|
}
|
|
if(!global.START_SERVER)
|
|
Str = global.PROCESS_NAME + ": " + Str;
|
|
if(global.PROCESS_NAME !== "MAIN" && process.send)
|
|
{
|
|
process.send({cmd:"log", message:Str});
|
|
return ;
|
|
}
|
|
else
|
|
{
|
|
console.log("" + START_PORT_NUMBER + ": " + GetStrOnlyTime() + ": " + Str);
|
|
}
|
|
if(bNoFile)
|
|
return ;
|
|
SaveToLogFileSync(file_name, Str);
|
|
};
|
|
global.ArrLogClient = [];
|
|
|
|
function ToLogClient(Str,StrKey,bFinal)
|
|
{
|
|
if(!Str)
|
|
return ;
|
|
ToLogFile(file_name_log, Str);
|
|
if(!StrKey)
|
|
StrKey = "";
|
|
ArrLogClient.push({text:GetStrOnlyTime() + " " + Str, key:StrKey, final:bFinal, });
|
|
if(ArrLogClient.length > 13)
|
|
ArrLogClient.shift();
|
|
};
|
|
global.ToLogClient = ToLogClient;
|
|
global.ToLogClient0 = ToLogClient;
|
|
var StartStatTime;
|
|
var CONTEXT_STATS = {Total:{}, Interval:[]};
|
|
var CONTEXT_ERRORS = {Total:{}, Interval:[]};
|
|
var CurStatIndex = 0;
|
|
global.PrepareStatEverySecond = function ()
|
|
{
|
|
CurStatIndex++;
|
|
var index = GetCurrentStatIndex();
|
|
CopyStatInterval(CONTEXT_STATS, index);
|
|
CopyStatInterval(CONTEXT_ERRORS, index);
|
|
};
|
|
global.TO_ERROR_LOG = function (Module,ErrNum,Str,type,data1,data2)
|
|
{
|
|
if(Str instanceof Error)
|
|
{
|
|
Str = Str.message + "\n";
|
|
}
|
|
if(type === "rinfo")
|
|
Str += " from: " + data1.address + ':' + data1.port;
|
|
else
|
|
if(type === "node")
|
|
Str += " from: " + data1.ip + ':' + data1.port;
|
|
var Key = Module + ":" + ErrNum;
|
|
ToError(" ==ERROR== " + Key + " " + Str);
|
|
AddToStatContext(CONTEXT_ERRORS, Key);
|
|
ADD_TO_STAT("ERRORS");
|
|
};
|
|
|
|
function GetCurrentStatIndex()
|
|
{
|
|
var DefMaxStatPeriod = MAX_STAT_PERIOD * 2 + 2;
|
|
return CurStatIndex % DefMaxStatPeriod;
|
|
};
|
|
global.HASH_RATE = 0;
|
|
global.ADD_HASH_RATE = function (Count)
|
|
{
|
|
Count = Count / 1000000;
|
|
global.HASH_RATE += Count;
|
|
ADD_TO_STAT("HASHRATE", Count);
|
|
};
|
|
global.GET_STAT = function (Key)
|
|
{
|
|
var Val = CONTEXT_STATS.Total[Key];
|
|
if(!Val)
|
|
Val = 0;
|
|
return Val;
|
|
};
|
|
global.ADD_TO_STAT_TIME = function (Name,startTime,bDetail)
|
|
{
|
|
if(global.STAT_MODE)
|
|
{
|
|
if(bDetail && global.STAT_MODE !== 2)
|
|
return ;
|
|
var Time = process.hrtime(startTime);
|
|
var deltaTime = Time[0] * 1000 + Time[1] / 1e6;
|
|
ADD_TO_STAT(Name, deltaTime);
|
|
}
|
|
};
|
|
global.ADD_TO_STAT = function (Key,Count,bDetail)
|
|
{
|
|
if(global.STAT_MODE)
|
|
{
|
|
if(bDetail && global.STAT_MODE !== 2)
|
|
return ;
|
|
AddToStatContext(CONTEXT_STATS, Key, Count);
|
|
}
|
|
};
|
|
global.GET_STATDIAGRAMS = function (Keys)
|
|
{
|
|
var now = GetCurrentTime();
|
|
var index = GetCurrentStatIndex();
|
|
if(!Keys || !Keys.length)
|
|
return [];
|
|
var Data = [];
|
|
for(var i = 0; i < Keys.length; i++)
|
|
{
|
|
var name = Keys[i];
|
|
var Value = GetDiagramData(CONTEXT_STATS, name);
|
|
Data.push({name:name, maxindex:index, arr:Value, starttime:(StartStatTime - 0), steptime:1});
|
|
}
|
|
var MinLength = undefined;
|
|
for(var i = 0; i < Data.length; i++)
|
|
{
|
|
var arr = Data[i].arr;
|
|
if(arr.length > 0 && (MinLength === undefined || arr.length < MinLength))
|
|
MinLength = arr.length;
|
|
}
|
|
var MaxSizeArr = 500;
|
|
for(var i = 0; i < Data.length; i++)
|
|
{
|
|
var ItemServer = Data[i];
|
|
var arr = ItemServer.arr;
|
|
if(MinLength && arr.length > MinLength)
|
|
{
|
|
arr = arr.slice(arr.length - MinLength);
|
|
}
|
|
if(MinLength)
|
|
if(",POWER_MY_WIN,POWER_BLOCKCHAIN,".indexOf("," + ItemServer.name + ",") >= 0)
|
|
{
|
|
arr = SERVER.GetStatBlockchain(ItemServer.name, MinLength);
|
|
}
|
|
var AvgValue = 0;
|
|
for(var j = 0; j < arr.length; j++)
|
|
{
|
|
if(arr[j])
|
|
AvgValue += arr[j];
|
|
}
|
|
if(arr.length > 0)
|
|
AvgValue = AvgValue / arr.length;
|
|
var StepTime = 1;
|
|
if(ItemServer.name.substr(0, 4) === "MAX:")
|
|
{
|
|
while(arr.length >= MaxSizeArr)
|
|
{
|
|
arr = ResizeArrMax(arr);
|
|
StepTime = StepTime * 2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while(arr.length >= MaxSizeArr)
|
|
{
|
|
arr = ResizeArrAvg(arr);
|
|
StepTime = StepTime * 2;
|
|
}
|
|
}
|
|
ItemServer.AvgValue = AvgValue;
|
|
ItemServer.steptime = StepTime;
|
|
ItemServer.arr = arr.slice(1);
|
|
}
|
|
return Data;
|
|
};
|
|
global.GET_STATS = function (Key)
|
|
{
|
|
var now = GetCurrentTime();
|
|
var index = GetCurrentStatIndex();
|
|
var stats = {Counter:CONTEXT_STATS.Total, Counter10S:CalcInterval(CONTEXT_STATS, index, 10), Counter10M:CalcInterval(CONTEXT_STATS,
|
|
index, 10 * 60), };
|
|
var errors = {Counter:CONTEXT_ERRORS.Total, Counter10S:CalcInterval(CONTEXT_ERRORS, index, 10), Counter10M:CalcInterval(CONTEXT_ERRORS,
|
|
index, 10 * 60), };
|
|
var Period = (now - StartStatTime) / 1000;
|
|
return {stats:stats, errors:errors, period:Period, Confirmation:[]};
|
|
};
|
|
global.StartCommonStat = function ()
|
|
{
|
|
for(var key in CONTEXT_STATS.Total)
|
|
return ;
|
|
ClearCommonStat();
|
|
};
|
|
global.ClearCommonStat = function ()
|
|
{
|
|
CurStatIndex = 0;
|
|
StartStatTime = undefined;
|
|
CONTEXT_STATS = {Total:{}, Interval:[]};
|
|
CONTEXT_ERRORS = {Total:{}, Interval:[]};
|
|
global.HASH_RATE = 0;
|
|
SERVER.ClearStat();
|
|
};
|
|
|
|
function ResizeArrMax(arr)
|
|
{
|
|
var arr2 = [];
|
|
var Count2 = Math.trunc(arr.length / 2);
|
|
for(var i = 0; i < Count2; i++)
|
|
{
|
|
arr2[i] = Math.max(arr[i * 2], arr[i * 2 + 1]);
|
|
}
|
|
return arr2;
|
|
};
|
|
|
|
function ResizeArrAvg(arr)
|
|
{
|
|
var arr2 = [];
|
|
var Count2 = Math.trunc(arr.length / 2);
|
|
for(var i = 0; i < Count2; i++)
|
|
{
|
|
arr2[i] = (arr[i * 2] + arr[i * 2 + 1]) / 2;
|
|
}
|
|
return arr2;
|
|
};
|
|
|
|
function ResizeArr(arr)
|
|
{
|
|
var arr2 = [];
|
|
var Count2 = Math.trunc(arr.length / 2);
|
|
for(var i = 0; i < Count2; i++)
|
|
{
|
|
arr2[i] = arr[i * 2];
|
|
}
|
|
return arr2;
|
|
};
|
|
global.ResizeArrAvg = ResizeArrAvg;
|
|
global.ResizeArrMax = ResizeArrMax;
|
|
|
|
function GetDiagramData(Context,Key)
|
|
{
|
|
var DefMaxStatPeriod = MAX_STAT_PERIOD * 2 + 2;
|
|
var IsMax;
|
|
if(Key.substr(0, 4) === "MAX:")
|
|
IsMax = true;
|
|
else
|
|
IsMax = false;
|
|
var delta = MAX_STAT_PERIOD;
|
|
var index2 = GetCurrentStatIndex();
|
|
var index1 = (index2 - delta + DefMaxStatPeriod) % DefMaxStatPeriod;
|
|
var Total = Context.Total;
|
|
var Counter1;
|
|
var arr = [];
|
|
var PrevValue = undefined;
|
|
for(var i = index1; i < index1 + delta; i++)
|
|
{
|
|
var index3 = i % DefMaxStatPeriod;
|
|
Counter1 = Context.Interval[index3];
|
|
if(Counter1)
|
|
{
|
|
var Value = Counter1[Key];
|
|
if(Value !== undefined)
|
|
{
|
|
if(!IsMax)
|
|
{
|
|
if(PrevValue !== undefined)
|
|
{
|
|
arr.push(Value - PrevValue);
|
|
}
|
|
else
|
|
{
|
|
arr.push(Value);
|
|
}
|
|
PrevValue = Value;
|
|
}
|
|
else
|
|
{
|
|
arr.push(Value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
arr.push(0);
|
|
}
|
|
}
|
|
}
|
|
return arr;
|
|
};
|
|
|
|
function CalcInterval(Context,index2,delta)
|
|
{
|
|
var DefMaxStatPeriod = MAX_STAT_PERIOD * 2 + 2;
|
|
var Res = {};
|
|
var index1 = (index2 - delta + DefMaxStatPeriod) % DefMaxStatPeriod;
|
|
var Total = Context.Total;
|
|
var Counter1;
|
|
for(var i = index1; i < index1 + delta; i++)
|
|
{
|
|
var index3 = i % DefMaxStatPeriod;
|
|
Counter1 = Context.Interval[index3];
|
|
if(Counter1)
|
|
break;
|
|
}
|
|
if(Counter1)
|
|
for(var Key in Total)
|
|
{
|
|
if(Key.substr(0, 4) === "MAX:")
|
|
Res[Key] = 0;
|
|
else
|
|
{
|
|
if(Counter1[Key] === undefined)
|
|
Res[Key] = Total[Key];
|
|
else
|
|
Res[Key] = Total[Key] - Counter1[Key];
|
|
}
|
|
}
|
|
return Res;
|
|
};
|
|
|
|
function AddToStatContext(Context,Key,AddValue)
|
|
{
|
|
if(AddValue === undefined)
|
|
AddValue = 1;
|
|
var Val = Context.Total[Key];
|
|
if(!Val)
|
|
Val = 0;
|
|
if(Key.substr(0, 4) === "MAX:")
|
|
Val = Math.max(Val, AddValue);
|
|
else
|
|
Val = Val + AddValue;
|
|
Context.Total[Key] = Val;
|
|
if(!StartStatTime)
|
|
StartStatTime = GetCurrentTime(0);
|
|
};
|
|
|
|
function CopyStatInterval(Context,index)
|
|
{
|
|
var Counter = Context.Interval[index];
|
|
if(!Counter)
|
|
{
|
|
Counter = {};
|
|
Context.Interval[index] = Counter;
|
|
}
|
|
var Total = Context.Total;
|
|
for(var Key in Total)
|
|
{
|
|
Counter[Key] = Total[Key];
|
|
if(Key.substr(0, 4) === "MAX:")
|
|
Total[Key] = 0;
|
|
}
|
|
};
|
|
if(DEBUG_MODE)
|
|
global.TO_DEBUG_LOG = function (Str,type,data1,data2)
|
|
{
|
|
if(!DEBUG_MODE)
|
|
return ;
|
|
if(type === "rinfo")
|
|
Str += " from: " + data1.address + ':' + data1.port + ' - ' + data2.length;
|
|
ToLog(Str);
|
|
};
|
|
else
|
|
global.TO_DEBUG_LOG = function (Str,type,data1,data2)
|
|
{
|
|
};
|
|
|
|
function SaveToLogFileAsync(fname,Str)
|
|
{
|
|
fs.open(fname, "a", undefined, function (err,file_handle)
|
|
{
|
|
if(!err)
|
|
{
|
|
var StrLog = GetStrTime() + " : " + Str + "\r\n";
|
|
fs.write(file_handle, StrLog, null, 'utf8', function (err,written)
|
|
{
|
|
if(!err)
|
|
{
|
|
fs.close(file_handle, function (err)
|
|
{
|
|
if(err)
|
|
console.log(err);
|
|
});
|
|
}
|
|
else
|
|
{
|
|
console.log("Ошибка записи в лог-файл ошибок!");
|
|
}
|
|
});
|
|
}
|
|
else
|
|
{
|
|
console.log("Ошибка открытия лог-файла ошибок");
|
|
}
|
|
});
|
|
};
|
|
|
|
function SaveToLogFileSync(fname,Str)
|
|
{
|
|
try
|
|
{
|
|
var StrLog = GetStrTime() + " : " + Str + "\r\n";
|
|
var file_handle = fs.openSync(fname, "a");
|
|
fs.writeSync(file_handle, StrLog, null, 'utf8');
|
|
fs.closeSync(file_handle);
|
|
}
|
|
catch(err)
|
|
{
|
|
console.log(err.message);
|
|
}
|
|
};
|
|
global.GetStrOnlyTime = function (now)
|
|
{
|
|
if(!global.GetCurrentTime)
|
|
return ":::";
|
|
if(!now)
|
|
now = GetCurrentTime();
|
|
var Str = "" + now.getHours().toStringZ(2);
|
|
Str = Str + ":" + now.getMinutes().toStringZ(2);
|
|
Str = Str + ":" + now.getSeconds().toStringZ(2);
|
|
Str = Str + "." + now.getMilliseconds().toStringZ(3);
|
|
return Str;
|
|
};
|
|
global.GetStrTime = function (now)
|
|
{
|
|
if(!global.GetCurrentTime)
|
|
return ":::";
|
|
if(!now)
|
|
now = GetCurrentTime();
|
|
var Str = "" + now.getDate().toStringZ(2);
|
|
Str = Str + "." + (1 + now.getMonth()).toStringZ(2);
|
|
Str = Str + "." + now.getFullYear();
|
|
Str = Str + " " + now.getHours().toStringZ(2);
|
|
Str = Str + ":" + now.getMinutes().toStringZ(2);
|
|
Str = Str + ":" + now.getSeconds().toStringZ(2);
|
|
Str = Str + "." + now.getMilliseconds().toStringZ(3);
|
|
return Str;
|
|
};
|