dvander@370: /** dvander@370: * =============================================================== dvander@370: * SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved. dvander@370: * =============================================================== dvander@370: * dvander@370: * This file is not open source and may not be copied without explicit dvander@370: * written permission of AlliedModders LLC. This file may not be redistributed dvander@370: * in whole or significant part. dvander@370: * For information, see LICENSE.txt or http://www.sourcemod.net/license.php dvander@370: * dvander@370: * Version: $Id$ dvander@370: */ dvander@370: dvander@300: #include dvander@300: #include "sourcemod.h" dvander@300: #include "sourcemm_api.h" faluco@266: #include "CLogger.h" dvander@351: #include "systems/LibrarySys.h" dvander@300: #include "sm_version.h" faluco@266: faluco@266: CLogger g_Logger; faluco@266: dvander@347: /** dvander@347: * :TODO: This should be creating the log folder if it doesn't exist dvander@347: */ dvander@347: faluco@281: void CLogger::OnSourceModStartup(bool late) faluco@281: { faluco@281: //:TODO: read these options from a file, dont hardcode them dvander@292: InitLogger(LoggingMode_Daily, true); faluco@281: } faluco@281: faluco@281: void CLogger::OnSourceModAllShutdown() faluco@281: { faluco@281: CloseLogger(); faluco@281: } faluco@281: faluco@266: void CLogger::_NewMapFile() faluco@266: { faluco@266: if (!m_Active) faluco@266: { faluco@266: return; faluco@266: } faluco@266: faluco@266: char _filename[256]; faluco@266: int i = 0; faluco@266: faluco@266: time_t t; faluco@266: time(&t); faluco@266: tm *curtime = localtime(&t); faluco@266: faluco@266: while (true) faluco@266: { dvander@347: g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/logs_%02d%02d%03d.log", curtime->tm_mon + 1, curtime->tm_mday, i); faluco@266: FILE *fp = fopen(_filename, "r"); faluco@266: if (!fp) faluco@266: { faluco@266: break; faluco@266: } faluco@266: fclose(fp); faluco@266: i++; faluco@266: } faluco@266: m_NrmFileName.assign(_filename); faluco@266: faluco@266: FILE *fp = fopen(m_NrmFileName.c_str(), "w"); faluco@266: if (!fp) faluco@266: { dvander@307: g_SMAPI->ConPrint("[SM] Unexpected fatal logging error. SourceMod logging disabled.\n"); faluco@266: m_Active = false; faluco@274: return; faluco@266: } else { faluco@266: char date[32]; faluco@266: strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); dvander@347: fprintf(fp, "L %s: SourceMod log file started (file \"logs_%02d%02d%03d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, i, SOURCEMOD_VERSION); faluco@266: fclose(fp); faluco@266: } faluco@266: } faluco@266: faluco@266: void CLogger::_CloseFile() faluco@266: { faluco@266: if (!m_Active) faluco@266: { faluco@266: return; faluco@266: } faluco@266: faluco@266: FILE *fp = NULL; faluco@266: if (!m_NrmFileName.empty()) faluco@266: { faluco@266: fp = fopen(m_NrmFileName.c_str(), "r+"); faluco@266: if (fp) faluco@266: { faluco@266: fseek(fp, 0, SEEK_END); faluco@266: LogMessage("Log file closed."); faluco@266: fclose(fp); faluco@266: } faluco@266: m_NrmFileName.clear(); faluco@266: } faluco@266: faluco@266: if (!m_ErrMapStart) faluco@266: { faluco@266: return; faluco@266: } faluco@266: fp = fopen(m_ErrFileName.c_str(), "r+"); faluco@266: if (fp) faluco@266: { faluco@266: fseek(fp, 0, SEEK_END); dvander@271: LogError("Error log file session closed."); faluco@266: fclose(fp); faluco@266: } faluco@266: m_ErrFileName.clear(); faluco@266: } faluco@266: faluco@266: void CLogger::InitLogger(LoggingMode mode, bool startlogging) faluco@266: { faluco@266: m_mode = mode; faluco@266: m_Active = startlogging; faluco@266: faluco@266: time_t t; faluco@266: time(&t); faluco@266: tm *curtime = localtime(&t); faluco@266: m_CurDay = curtime->tm_mday; faluco@266: faluco@266: char _filename[256]; dvander@317: g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%02d%02d%02d.log", curtime->tm_mon + 1, curtime->tm_mday, curtime->tm_year - 100); faluco@266: m_ErrFileName.assign(_filename); faluco@266: faluco@266: switch (m_mode) faluco@266: { faluco@266: case LoggingMode_PerMap: faluco@266: { faluco@266: if (!startlogging) faluco@266: { faluco@266: m_DelayedStart = true; faluco@266: } faluco@266: break; faluco@266: } faluco@266: case LoggingMode_Daily: faluco@266: { dvander@347: g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/logs_%02d%02d.log", curtime->tm_mon + 1, curtime->tm_mday); faluco@266: m_NrmFileName.assign(_filename); faluco@266: m_DailyPrintHdr = true; faluco@266: break; faluco@266: } dvander@351: default: dvander@351: { dvander@351: /* do nothing... */ dvander@351: break; dvander@351: } faluco@266: } faluco@266: } faluco@266: faluco@266: void CLogger::CloseLogger() faluco@266: { faluco@266: _CloseFile(); faluco@266: } faluco@266: faluco@266: void CLogger::LogMessage(const char *vafmt, ...) faluco@266: { faluco@266: if (!m_Active) faluco@266: { faluco@266: return; faluco@266: } faluco@266: faluco@266: if (m_mode == LoggingMode_HL2) faluco@266: { faluco@274: va_list ap; faluco@274: va_start(ap, vafmt); faluco@274: _PrintToHL2Log(vafmt, ap); faluco@274: va_end(ap); faluco@266: return; faluco@266: } faluco@266: faluco@266: if (m_DelayedStart) faluco@266: { faluco@266: m_DelayedStart = false; faluco@266: _NewMapFile(); faluco@266: } faluco@266: faluco@274: char msg[3072]; faluco@266: va_list ap; faluco@266: va_start(ap, vafmt); faluco@266: vsnprintf(msg, sizeof(msg), vafmt, ap); faluco@266: va_end(ap); faluco@266: faluco@266: char date[32]; faluco@266: time_t t; faluco@266: time(&t); faluco@266: tm *curtime = localtime(&t); faluco@266: strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); faluco@266: faluco@266: FILE *fp = NULL; faluco@266: if (m_mode == LoggingMode_PerMap) faluco@266: { faluco@266: fp = fopen(m_NrmFileName.c_str(), "a+"); faluco@266: if (!fp) faluco@266: { faluco@266: _NewMapFile(); faluco@266: fp = fopen(m_NrmFileName.c_str(), "a+"); faluco@266: if (!fp) faluco@266: { faluco@266: goto print_error; faluco@266: } faluco@266: } faluco@266: } else { faluco@266: if (m_CurDay != curtime->tm_mday) faluco@266: { faluco@266: char _filename[256]; dvander@347: g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/logs_%02d%02d.log", curtime->tm_mon + 1, curtime->tm_mday); faluco@266: m_NrmFileName.assign(_filename); faluco@266: m_CurDay = curtime->tm_mday; faluco@266: m_DailyPrintHdr = true; faluco@266: } faluco@266: fp = fopen(m_NrmFileName.c_str(), "a+"); faluco@266: } faluco@266: faluco@266: if (fp) faluco@266: { faluco@266: if (m_DailyPrintHdr) faluco@266: { faluco@266: m_DailyPrintHdr = false; dvander@347: fprintf(fp, "L %s: SourceMod log file session started (file \"logs_%02d%02d.log\") (Version \"%s\")\n", date, curtime->tm_mon + 1, curtime->tm_mday, SOURCEMOD_VERSION); faluco@266: } faluco@266: fprintf(fp, "L %s: %s\n", date, msg); faluco@266: fclose(fp); faluco@266: } else { faluco@266: goto print_error; faluco@266: } faluco@266: faluco@266: g_SMAPI->ConPrintf("L %s: %s\n", date, msg); faluco@270: return; faluco@266: print_error: dvander@307: g_SMAPI->ConPrint("[SM] Unexpected fatal logging error. SourceMod logging disabled.\n"); faluco@266: m_Active = false; faluco@266: } faluco@266: dvander@271: void CLogger::LogError(const char *vafmt, ...) faluco@266: { faluco@266: if (!m_Active) faluco@266: { faluco@266: return; faluco@266: } faluco@266: faluco@266: time_t t; faluco@266: time(&t); faluco@266: tm *curtime = localtime(&t); faluco@266: faluco@266: char date[32]; faluco@266: strftime(date, sizeof(date), "%m/%d/%Y - %H:%M:%S", curtime); faluco@266: faluco@266: if (curtime->tm_mday != m_CurDay) faluco@266: { faluco@266: char _filename[256]; dvander@317: g_SourceMod.BuildPath(Path_SM, _filename, sizeof(_filename), "logs/errors_%02d%02d%02d.log", curtime->tm_mon + 1, curtime->tm_mday, curtime->tm_year - 100); faluco@266: m_ErrFileName.assign(_filename); faluco@266: m_CurDay = curtime->tm_mday; faluco@266: m_ErrMapStart = false; faluco@266: } faluco@266: faluco@274: char msg[3072]; faluco@266: va_list ap; faluco@266: va_start(ap, vafmt); faluco@266: vsnprintf(msg, sizeof(msg), vafmt, ap); faluco@266: va_end(ap); faluco@266: faluco@266: FILE *fp = fopen(m_ErrFileName.c_str(), "a+"); faluco@266: if (fp) faluco@266: { faluco@266: if (!m_ErrMapStart) faluco@266: { faluco@266: fprintf(fp, "L %s: SourceMod error session started\n", date); faluco@266: fprintf(fp, "L %s: Info (map \"%s\") (log file \"errors_%02d%02d%02d.log\")\n", date, m_CurMapName.c_str(), curtime->tm_mon + 1, curtime->tm_mday, curtime->tm_year - 100); faluco@266: m_ErrMapStart = true; faluco@266: } faluco@266: fprintf(fp, "L %s: %s\n", date, msg); faluco@266: fclose(fp); faluco@266: } else { dvander@307: g_SMAPI->ConPrint("[SM] Unexpected fatal logging error. SourceMod logging disabled.\n"); faluco@266: m_Active = false; faluco@274: return; faluco@266: } faluco@266: faluco@266: g_SMAPI->ConPrintf("L %s: %s\n", date, msg); faluco@266: } faluco@266: faluco@266: void CLogger::MapChange(const char *mapname) faluco@266: { faluco@266: m_CurMapName.assign(mapname); faluco@266: faluco@266: switch (m_mode) faluco@266: { faluco@266: case LoggingMode_Daily: faluco@266: { faluco@266: LogMessage("-------- Mapchange to %s --------", mapname); faluco@266: break; faluco@266: } faluco@266: case LoggingMode_PerMap: faluco@266: { faluco@266: _NewMapFile(); faluco@266: break; faluco@266: } dvander@351: default: dvander@351: { dvander@351: /* Do nothing... */ dvander@351: break; dvander@351: } faluco@266: } faluco@266: faluco@266: if (m_ErrMapStart) faluco@266: { dvander@271: LogError("Error log file session closed."); faluco@266: } faluco@266: m_ErrMapStart = false; faluco@266: } faluco@266: faluco@274: void CLogger::_PrintToHL2Log(const char *fmt, va_list ap) faluco@266: { faluco@274: char msg[3072]; faluco@266: size_t len; faluco@266: faluco@274: len = vsnprintf(msg, sizeof(msg)-2, fmt, ap); faluco@274: len = (len >= sizeof(msg)) ? (sizeof(msg) - 2) : len; faluco@274: faluco@266: msg[len++] = '\n'; faluco@266: msg[len] = '\0'; faluco@266: faluco@266: engine->LogPrint(msg); dvander@300: } dvander@300: dvander@300: const char *CLogger::GetLogFileName(LogType type) const dvander@300: { dvander@300: switch (type) dvander@300: { dvander@300: case LogType_Normal: dvander@300: { dvander@300: return m_NrmFileName.c_str(); dvander@300: } dvander@300: case LogType_Error: dvander@300: { dvander@300: return m_ErrFileName.c_str(); dvander@300: } dvander@300: default: dvander@300: { dvander@300: return ""; dvander@300: } dvander@300: } dvander@300: } dvander@300: dvander@300: LoggingMode CLogger::GetLoggingMode() const dvander@300: { dvander@300: return m_mode; dvander@300: } dvander@300: dvander@300: void CLogger::EnableLogging() dvander@300: { dvander@300: if (m_Active) dvander@300: { dvander@300: return; dvander@300: } dvander@300: m_Active = true; dvander@300: LogMessage("Logging enabled manually by user."); dvander@300: } dvander@300: dvander@300: void CLogger::DisableLogging() dvander@300: { dvander@300: if (!m_Active) dvander@300: { dvander@300: return; dvander@300: } dvander@300: LogMessage("Logging disabled manually by user."); dvander@300: m_Active = false; dvander@300: }