/* * psplog.cpp -- Christophe Painchaud aka Atanor, DaSH * * Copyright (C) 2001 Atomic Blue (info@planeshift.it, http://www.atomicblue.org) * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation (version 2 of the License) * This program 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 General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include #include #include "util/consoleout.h" #include "util/log.h" #include namespace pslog { iObjectRegistry* logger; bool disp_flag[MAX_FLAGS]; uint32 filters_id[MAX_FLAGS]; char *flagnames[] = { "LOG_ANY", "LOG_WEATHER", "LOG_SPAWN", "LOG_CELPERSIST", "LOG_PAWS", "LOG_GROUP", "LOG_CHEAT", "LOG_LINMOVE", "LOG_SPELLS", "LOG_NEWCHAR", "LOG_SUPERCLIENT", "LOG_EXCHANGES", "LOG_ADMIN", "LOG_STARTUP", "LOG_CHARACTER", "LOG_CONNECTIONS", "LOG_CHAT", "LOG_NET", "LOG_LOAD", "LOG_NPC", "LOG_TRADE", "LOG_SOUND", "LOG_COMBAT", "LOG_SKILLXP", "LOG_QUESTS", "LOG_SCRIPT", "LOG_MARRIAGE", "LOG_MESSAGES", "LOG_CACHE", "LOG_PETS", "LOG_USER", "LOG_LOOT", "LOG_DUELS", "LOG_TRIBES" }; // End of flagnames char *flagsetting[] = { "Planeshift.Log.Any", "Planeshift.Log.Weather", "Planeshift.Log.Spawn", "Planeshift.Log.Cel", "Planeshift.Log.PAWS", "Planeshift.Log.Group", "Planeshift.Log.Cheat", "Planeshift.Log.Linmove", "Planeshift.Log.Spells", "Planeshift.Log.Newchar", "Planeshift.Log.Superclient", "Planeshift.Log.Exchanges", "Planeshift.Log.Admin", "Planeshift.Log.Startup", "Planeshift.Log.Character", "Planeshift.Log.Connections", "Planeshift.Log.Chat", "Planeshift.Log.Net", "Planeshift.Log.Load", "Planeshift.Log.NPC", "Planeshift.Log.Trade", "Planeshift.Log.Sound", "Planeshift.Log.Combat", "Planeshift.Log.SkillXP", "Planeshift.Log.Quests", "Planeshift.Log.Script", "Planeshift.Log.Marriage", "Planeshift.Log.Messages", "Planeshift.Log.Cache", "Planeshift.Log.Pets", "Planeshift.Log.User", "Planeshift.Log.Loot", "Planeshift.Log.Duels", "Planeshift.Log.Tribes" }; // End of flagsettings bool DoLog(int severity, LOG_TYPES type, uint32 filter_id) { if (logger == 0) return false; if (!disp_flag[type] && severity > CS_REPORTER_SEVERITY_WARNING) return false; if (filters_id[type]!=0 && filter_id!=0 && filters_id[type]!=filter_id) return false; return true; } void LogMessage (const char* file, int line, const char* function, int severity, LOG_TYPES type, uint32 filter_id, const char* msg, ...) { if (!DoLog(severity,type,filter_id)) return; va_list arg; ConsoleOutMsgClass con = CON_SPAM; switch (severity) { case CS_REPORTER_SEVERITY_WARNING: con = CON_WARNING; break; case CS_REPORTER_SEVERITY_NOTIFY: con = CON_NOTIFY; break; case CS_REPORTER_SEVERITY_ERROR: con = CON_ERROR; break; case CS_REPORTER_SEVERITY_BUG: con = CON_BUG; break; case CS_REPORTER_SEVERITY_DEBUG: con = CON_DEBUG; break; } va_start(arg, msg); CPrintfLog (con, msg, arg); va_end(arg); if(con <= ConsoleOut::GetMaximumOutputClassStdout()) { char msgid[5000]; snprintf (msgid, 5000, "<%s:%d %s>", file, line, function); va_start(arg, msg); csReportV (logger, severity, msgid, msg, arg); va_end(arg); // Log errors to a file so they can be emailed to devs daily. if (severity == CS_REPORTER_SEVERITY_ERROR || severity == CS_REPORTER_SEVERITY_BUG) { FILE *f = fopen("errorlog.txt","a"); if (f) { fprintf(f,msgid); fprintf(f," "); va_start(arg, msg); vfprintf(f,msg,arg); va_end(arg); fclose(f); } } } } void Initialize(iObjectRegistry* object_reg) { logger = object_reg; static bool initialized = false; if (initialized) return; initialized = true; for (int i = 0; i < MAX_FLAGS; i++) { disp_flag[i] = false; } disp_flag[LOG_ANY] = true; disp_flag[LOG_CONNECTIONS] = true; disp_flag[LOG_CHAT] = true; disp_flag[LOG_NET] = true; disp_flag[LOG_CHARACTER] = true; disp_flag[LOG_NEWCHAR] = true; } void SetFlag(const char *name,bool flag, uint32 filter) { for (int i=0; iGetInt("Planeshift.LogCSV.MaxSize", 10*1024*1024); filename[CSV_PALADIN] = configmanager->GetStr("Planeshift.LogCSV.File.Paladin"); filename[CSV_EXCHANGES] = configmanager->GetStr("Planeshift.LogCSV.File.Exchanges"); filename[CSV_AUTHENT] = configmanager->GetStr("Planeshift.LogCSV.File.Authent"); filename[CSV_STATUS] = configmanager->GetStr("Planeshift.LogCSV.File.Status"); filename[CSV_ADVICE] = configmanager->GetStr("Planeshift.LogCSV.File.Advice"); filename[CSV_ECONOMY] = configmanager->GetStr("Planeshift.LogCSV.File.Economy"); filename[CSV_STUCK] = configmanager->GetStr("Planeshift.LogCSV.File.Stuck"); for(int i = 0;i < MAX_CSV;i++) { if(filename[i].IsEmpty()) { csvFile[i] = NULL; continue; } if (!(vfs->Exists(filename[i]))) { csvFile[i] = vfs->Open(filename[i],VFS_FILE_WRITE); switch(i) { case CSV_PALADIN: header = "Date/Time, Client, Type, Sector, Start pos (xyz), Maximum displacement, Real displacement, Start velocity, Angular velocity, Paladin version\n"; break; case CSV_EXCHANGES: header = "Date/Time, Source Client, Target Client, Type, Item, Quantity, Cost\n"; break; case CSV_AUTHENT: header = "Date/Time, Client, Client ID, Details\n"; break; case CSV_STATUS: header = "Date/Time, Status\n"; break; case CSV_ADVICE: header = "Date/Time, Source Client, Target Client, Message\n"; break; case CSV_ECONOMY: header = "Action, Count, Item, Quality, From, To, Price, Time\n"; break; case CSV_STUCK: header = "Date/Time, Client, Race, Gender, Sector, PosX, PosY," " PosZ, Direction\n"; break; } csvFile[i]->Write(header.GetData(), header.Length()); csvFile[i]->Flush(); } else { csvFile[i] = vfs->Open(filename[i],VFS_FILE_APPEND); if (csvFile[i] && csvFile[i]->GetSize() > maxSize) { CPrintf(CON_ERROR, "Log File %s is too big! Current size is: %u", filename[i].GetData(), csvFile[i]->GetSize()); csvFile[i] = vfs->Open(filename[i],VFS_FILE_WRITE); } } } } void LogCSV::Write(int type, csString& text) { if (!csvFile[type]) return; time_t curtime = time(NULL); struct tm *loctime; loctime = localtime (&curtime); csString buf(asctime(loctime)); buf.Truncate(buf.Length()-1); buf.Append(", "); buf.Append(text); buf.Append("\n"); csvFile[type]->Write(buf, buf.Length()); static unsigned count = 0; if (type == CSV_STATUS) csvFile[type]->Flush(); else { // Unfair flushing mechanism for the time being. count++; if(count % 5 == 0) { count = 0; csvFile[type]->Flush(); } } }