mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-02-03 02:53:48 +00:00
feat(Core/Logging): rework logging (#4692)
* feat(Core/Logging): rework logging * correct level for sql.sql * del unused config options * Correct build * correct after merge * whitespace 20:29:37 1. 'Player.cpp'. Replace (1) 20:29:37 2. 'ObjectMgr.cpp'. Replace (3) * 1 * correct logging * correct affter merge * 1 * 2 * LOG_LEVEL_WARN * #include "AppenderDB.h" * 3 * 4 * 5 * 1. 'WorldSocket.cpp'. Replace (1) * 6 * 1
This commit is contained in:
@@ -4,12 +4,17 @@
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
*/
|
||||
|
||||
#include "Config.h"
|
||||
#include "MapManager.h"
|
||||
#include "MMapManager.h"
|
||||
#include "Log.h"
|
||||
#include "StringFormat.h"
|
||||
|
||||
namespace MMAP
|
||||
{
|
||||
static char const* const MAP_FILE_NAME_FORMAT = "%s/mmaps/%03i.mmap";
|
||||
static char const* const TILE_FILE_NAME_FORMAT = "%s/mmaps/%03i%02i%02i.mmtile";
|
||||
|
||||
// ######################## MMapManager ########################
|
||||
MMapManager::~MMapManager()
|
||||
{
|
||||
@@ -27,17 +32,14 @@ namespace MMAP
|
||||
return true;
|
||||
|
||||
// load and init dtNavMesh - read parameters from file
|
||||
uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i.mmap") + 1;
|
||||
char* fileName = new char[pathLen];
|
||||
snprintf(fileName, pathLen, (sWorld->GetDataPath() + "mmaps/%03i.mmap").c_str(), mapId);
|
||||
std::string fileName = acore::StringFormat(MAP_FILE_NAME_FORMAT, sConfigMgr->GetOption<std::string>("DataDir", ".").c_str(), mapId);
|
||||
|
||||
FILE* file = fopen(fileName, "rb");
|
||||
FILE* file = fopen(fileName.c_str(), "rb");
|
||||
if (!file)
|
||||
{
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||
sLog->outDebug(LOG_FILTER_MAPS, "MMAP:loadMapData: Error: Could not open mmap file '%s'", fileName);
|
||||
LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not open mmap file '%s'", fileName.c_str());
|
||||
#endif
|
||||
delete [] fileName;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -47,7 +49,6 @@ namespace MMAP
|
||||
if (count != 1)
|
||||
{
|
||||
;//TC_LOG_DEBUG(LOG_FILTER_MAPS, "MMAP:loadMapData: Error: Could not read params from file '%s'", fileName);
|
||||
delete [] fileName;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -56,15 +57,12 @@ namespace MMAP
|
||||
if (DT_SUCCESS != mesh->init(¶ms))
|
||||
{
|
||||
dtFreeNavMesh(mesh);
|
||||
sLog->outError("MMAP:loadMapData: Failed to initialize dtNavMesh for mmap %03u from file %s", mapId, fileName);
|
||||
delete [] fileName;
|
||||
LOG_ERROR("server", "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap %03u from file %s", mapId, fileName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
delete [] fileName;
|
||||
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||
sLog->outDetail("MMAP:loadMapData: Loaded %03i.mmap", mapId);
|
||||
LOG_DEBUG("server", "MMAP:loadMapData: Loaded %03i.mmap", mapId);
|
||||
#endif
|
||||
|
||||
// store inside our map list
|
||||
@@ -85,7 +83,7 @@ namespace MMAP
|
||||
Map* map = sMapMgr->FindBaseMap(mapId);
|
||||
if (!map)
|
||||
{
|
||||
sLog->outMisc("ZOMG! MoveMaps: BaseMap not found!");
|
||||
LOG_INFO("misc", "ZOMG! MoveMaps: BaseMap not found!");
|
||||
return this->MMapLock;
|
||||
}
|
||||
|
||||
@@ -108,38 +106,31 @@ namespace MMAP
|
||||
uint32 packedGridPos = packTileID(x, y);
|
||||
if (mmap->mmapLoadedTiles.find(packedGridPos) != mmap->mmapLoadedTiles.end())
|
||||
{
|
||||
sLog->outError("MMAP:loadMap: Asked to load already loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y);
|
||||
LOG_ERROR("server", "MMAP:loadMap: Asked to load already loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y);
|
||||
return false;
|
||||
}
|
||||
|
||||
// load this tile :: mmaps/MMMXXYY.mmtile
|
||||
uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile") + 1;
|
||||
char* fileName = new char[pathLen];
|
||||
snprintf(fileName, pathLen, (sWorld->GetDataPath() + "mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y);
|
||||
|
||||
FILE* file = fopen(fileName, "rb");
|
||||
std::string fileName = acore::StringFormat(TILE_FILE_NAME_FORMAT, sConfigMgr->GetOption<std::string>("DataDir", ".").c_str(), mapId, x, y);
|
||||
FILE* file = fopen(fileName.c_str(), "rb");
|
||||
if (!file)
|
||||
{
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||
sLog->outDebug(LOG_FILTER_MAPS, "MMAP:loadMap: Could not open mmtile file '%s'", fileName);
|
||||
#endif
|
||||
delete [] fileName;
|
||||
LOG_DEBUG("maps", "MMAP:loadMap: Could not open mmtile file '%s'", fileName.c_str());
|
||||
return false;
|
||||
}
|
||||
delete [] fileName;
|
||||
|
||||
// read header
|
||||
MmapTileHeader fileHeader;
|
||||
if (fread(&fileHeader, sizeof(MmapTileHeader), 1, file) != 1 || fileHeader.mmapMagic != MMAP_MAGIC)
|
||||
{
|
||||
sLog->outError("MMAP:loadMap: Bad header in mmap %03u%02i%02i.mmtile", mapId, x, y);
|
||||
LOG_ERROR("server", "MMAP:loadMap: Bad header in mmap %03u%02i%02i.mmtile", mapId, x, y);
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fileHeader.mmapVersion != MMAP_VERSION)
|
||||
{
|
||||
sLog->outError("MMAP:loadMap: %03u%02i%02i.mmtile was built with generator v%i, expected v%i",
|
||||
LOG_ERROR("server", "MMAP:loadMap: %03u%02i%02i.mmtile was built with generator v%i, expected v%i",
|
||||
mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION);
|
||||
fclose(file);
|
||||
return false;
|
||||
@@ -151,7 +142,7 @@ namespace MMAP
|
||||
size_t result = fread(data, fileHeader.size, 1, file);
|
||||
if (!result)
|
||||
{
|
||||
sLog->outError("MMAP:loadMap: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, x, y);
|
||||
LOG_ERROR("server", "MMAP:loadMap: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, x, y);
|
||||
fclose(file);
|
||||
return false;
|
||||
}
|
||||
@@ -173,13 +164,13 @@ namespace MMAP
|
||||
++loadedTiles;
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||
dtMeshHeader* header = (dtMeshHeader*)data;
|
||||
sLog->outDetail("MMAP:loadMap: Loaded mmtile %03i[%02i,%02i] into %03i[%02i,%02i]", mapId, x, y, mapId, header->x, header->y);
|
||||
LOG_DEBUG("server", "MMAP:loadMap: Loaded mmtile %03i[%02i,%02i] into %03i[%02i,%02i]", mapId, x, y, mapId, header->x, header->y);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog->outError("MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y);
|
||||
LOG_ERROR("server", "MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y);
|
||||
dtFree(data);
|
||||
return false;
|
||||
}
|
||||
@@ -196,7 +187,7 @@ namespace MMAP
|
||||
{
|
||||
// file may not exist, therefore not loaded
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||
sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMap: Asked to unload not loaded navmesh map. %03u%02i%02i.mmtile", mapId, x, y);
|
||||
LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map. %03u%02i%02i.mmtile", mapId, x, y);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -209,7 +200,7 @@ namespace MMAP
|
||||
{
|
||||
// file may not exist, therefore not loaded
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||
sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMap: Asked to unload not loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y);
|
||||
LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -228,7 +219,7 @@ namespace MMAP
|
||||
// this is technically a memory leak
|
||||
// if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used
|
||||
// we cannot recover from this error - assert out
|
||||
sLog->outError("MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y);
|
||||
LOG_ERROR("server", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y);
|
||||
ABORT();
|
||||
}
|
||||
else
|
||||
@@ -236,7 +227,7 @@ namespace MMAP
|
||||
mmap->mmapLoadedTiles.erase(packedGridPos);
|
||||
--loadedTiles;
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||
sLog->outDetail("MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, x, y, mapId);
|
||||
LOG_DEBUG("server", "MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, x, y, mapId);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@@ -252,7 +243,7 @@ namespace MMAP
|
||||
{
|
||||
// file may not exist, therefore not loaded
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||
sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMap: Asked to unload not loaded navmesh map %03u", mapId);
|
||||
LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map %03u", mapId);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -271,12 +262,12 @@ namespace MMAP
|
||||
}
|
||||
|
||||
if (status != DT_SUCCESS)
|
||||
sLog->outError("MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y);
|
||||
LOG_ERROR("server", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y);
|
||||
else
|
||||
{
|
||||
--loadedTiles;
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||
sLog->outDetail("MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, x, y, mapId);
|
||||
LOG_DEBUG("server", "MMAP:unloadMap: Unloaded mmtile %03i[%02i,%02i] from %03i", mapId, x, y, mapId);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -284,7 +275,7 @@ namespace MMAP
|
||||
delete mmap;
|
||||
loadedMMaps.erase(mapId);
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||
sLog->outDetail("MMAP:unloadMap: Unloaded %03i.mmap", mapId);
|
||||
LOG_DEBUG("server", "MMAP:unloadMap: Unloaded %03i.mmap", mapId);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@@ -299,7 +290,7 @@ namespace MMAP
|
||||
{
|
||||
// file may not exist, therefore not loaded
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||
sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map %03u", mapId);
|
||||
LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map %03u", mapId);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -308,7 +299,7 @@ namespace MMAP
|
||||
if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
|
||||
{
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||
sLog->outDebug(LOG_FILTER_MAPS, "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %03u instanceId %u", mapId, instanceId);
|
||||
LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %03u instanceId %u", mapId, instanceId);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -318,7 +309,7 @@ namespace MMAP
|
||||
dtFreeNavMeshQuery(query);
|
||||
mmap->navMeshQueries.erase(instanceId);
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||
sLog->outDetail("MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId);
|
||||
LOG_DEBUG("server", "MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@@ -351,12 +342,12 @@ namespace MMAP
|
||||
if (DT_SUCCESS != query->init(mmap->navMesh, 1024))
|
||||
{
|
||||
dtFreeNavMeshQuery(query);
|
||||
sLog->outError("MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
|
||||
LOG_ERROR("server", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||
sLog->outDetail("MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
|
||||
LOG_DEBUG("server", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
|
||||
#endif
|
||||
mmap->navMeshQueries.insert(std::pair<uint32, dtNavMeshQuery*>(instanceId, query));
|
||||
}
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
#ifndef _MMAP_MANAGER_H
|
||||
#define _MMAP_MANAGER_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "DetourAlloc.h"
|
||||
#include "DetourNavMesh.h"
|
||||
#include "DetourExtended.h"
|
||||
#include "World.h"
|
||||
#include <unordered_map>
|
||||
#include <shared_mutex>
|
||||
|
||||
|
||||
@@ -270,12 +270,12 @@ namespace VMAP
|
||||
WorldModel* worldmodel = new WorldModel();
|
||||
if (!worldmodel->readFile(basepath + filename + ".vmo"))
|
||||
{
|
||||
sLog->outError("VMapManager2: could not load '%s%s.vmo'", basepath.c_str(), filename.c_str());
|
||||
LOG_ERROR("server", "VMapManager2: could not load '%s%s.vmo'", basepath.c_str(), filename.c_str());
|
||||
delete worldmodel;
|
||||
return nullptr;
|
||||
}
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||
sLog->outDebug(LOG_FILTER_MAPS, "VMapManager2: loading file '%s%s'", basepath.c_str(), filename.c_str());
|
||||
LOG_DEBUG("maps", "VMapManager2: loading file '%s%s'", basepath.c_str(), filename.c_str());
|
||||
#endif
|
||||
model = iLoadedModelFiles.insert(std::pair<std::string, ManagedModel>(filename, ManagedModel())).first;
|
||||
model->second.setModel(worldmodel);
|
||||
@@ -291,13 +291,13 @@ namespace VMAP
|
||||
ModelFileMap::iterator model = iLoadedModelFiles.find(filename);
|
||||
if (model == iLoadedModelFiles.end())
|
||||
{
|
||||
sLog->outError("VMapManager2: trying to unload non-loaded file '%s'", filename.c_str());
|
||||
LOG_ERROR("server", "VMapManager2: trying to unload non-loaded file '%s'", filename.c_str());
|
||||
return;
|
||||
}
|
||||
if (model->second.decRefCount() == 0)
|
||||
{
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||
sLog->outDebug(LOG_FILTER_MAPS, "VMapManager2: unloading file '%s'", filename.c_str());
|
||||
LOG_DEBUG("maps", "VMapManager2: unloading file '%s'", filename.c_str());
|
||||
#endif
|
||||
delete model->second.getModel();
|
||||
iLoadedModelFiles.erase(model);
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
*/
|
||||
|
||||
#include "MapTree.h"
|
||||
#include "Common.h"
|
||||
#include "ModelInstance.h"
|
||||
#include "VMapManager2.h"
|
||||
#include "VMapDefinitions.h"
|
||||
#include "Log.h"
|
||||
#include "Errors.h"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
@@ -45,7 +45,7 @@ namespace VMAP
|
||||
void operator()(const Vector3& point, uint32 entry)
|
||||
{
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) && defined(VMAP_DEBUG)
|
||||
sLog->outDebug(LOG_FILTER_MAPS, "AreaInfoCallback: trying to intersect '%s'", prims[entry].name.c_str());
|
||||
LOG_DEBUG("maps", "AreaInfoCallback: trying to intersect '%s'", prims[entry].name.c_str());
|
||||
#endif
|
||||
prims[entry].intersectPoint(point, aInfo);
|
||||
}
|
||||
@@ -61,7 +61,7 @@ namespace VMAP
|
||||
void operator()(const Vector3& point, uint32 entry)
|
||||
{
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) && defined(VMAP_DEBUG)
|
||||
sLog->outDebug(LOG_FILTER_MAPS, "LocationInfoCallback: trying to intersect '%s'", prims[entry].name.c_str());
|
||||
LOG_DEBUG("maps", "LocationInfoCallback: trying to intersect '%s'", prims[entry].name.c_str());
|
||||
#endif
|
||||
if (prims[entry].GetLocationInfo(point, locInfo))
|
||||
result = true;
|
||||
@@ -338,7 +338,7 @@ namespace VMAP
|
||||
}
|
||||
if (!iTreeValues)
|
||||
{
|
||||
sLog->outError("StaticMapTree::LoadMapTile() : tree has not been initialized [%u, %u]", tileX, tileY);
|
||||
LOG_ERROR("server", "StaticMapTree::LoadMapTile() : tree has not been initialized [%u, %u]", tileX, tileY);
|
||||
return false;
|
||||
}
|
||||
bool result = true;
|
||||
@@ -364,7 +364,7 @@ namespace VMAP
|
||||
// acquire model instance
|
||||
WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name);
|
||||
if (!model)
|
||||
sLog->outError("StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u, %u]", tileX, tileY);
|
||||
LOG_ERROR("server", "StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u, %u]", tileX, tileY);
|
||||
|
||||
// update tree
|
||||
uint32 referencedVal;
|
||||
@@ -376,7 +376,7 @@ namespace VMAP
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) && defined(VMAP_DEBUG)
|
||||
if (referencedVal > iNTreeValues)
|
||||
{
|
||||
sLog->outDebug(LOG_FILTER_MAPS, "StaticMapTree::LoadMapTile() : invalid tree element (%u/%u)", referencedVal, iNTreeValues);
|
||||
LOG_DEBUG("maps", "StaticMapTree::LoadMapTile() : invalid tree element (%u/%u)", referencedVal, iNTreeValues);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
@@ -388,9 +388,9 @@ namespace VMAP
|
||||
++iLoadedSpawns[referencedVal];
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) && defined(VMAP_DEBUG)
|
||||
if (iTreeValues[referencedVal].ID != spawn.ID)
|
||||
sLog->outDebug(LOG_FILTER_MAPS, "StaticMapTree::LoadMapTile() : trying to load wrong spawn in node");
|
||||
LOG_DEBUG("maps", "StaticMapTree::LoadMapTile() : trying to load wrong spawn in node");
|
||||
else if (iTreeValues[referencedVal].name != spawn.name)
|
||||
sLog->outDebug(LOG_FILTER_MAPS, "StaticMapTree::LoadMapTile() : name collision on GUID=%u", spawn.ID);
|
||||
LOG_DEBUG("maps", "StaticMapTree::LoadMapTile() : name collision on GUID=%u", spawn.ID);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -414,7 +414,7 @@ namespace VMAP
|
||||
loadedTileMap::iterator tile = iLoadedTiles.find(tileID);
|
||||
if (tile == iLoadedTiles.end())
|
||||
{
|
||||
sLog->outError("StaticMapTree::UnloadMapTile() : trying to unload non-loaded tile - Map:%u X:%u Y:%u", iMapID, tileX, tileY);
|
||||
LOG_ERROR("server", "StaticMapTree::UnloadMapTile() : trying to unload non-loaded tile - Map:%u X:%u Y:%u", iMapID, tileX, tileY);
|
||||
return;
|
||||
}
|
||||
if (tile->second) // file associated with tile
|
||||
@@ -448,7 +448,7 @@ namespace VMAP
|
||||
else
|
||||
{
|
||||
if (!iLoadedSpawns.count(referencedNode))
|
||||
sLog->outError("StaticMapTree::UnloadMapTile() : trying to unload non-referenced model '%s' (ID:%u)", spawn.name.c_str(), spawn.ID);
|
||||
LOG_ERROR("server", "StaticMapTree::UnloadMapTile() : trying to unload non-referenced model '%s' (ID:%u)", spawn.name.c_str(), spawn.ID);
|
||||
else if (--iLoadedSpawns[referencedNode] == 0)
|
||||
{
|
||||
iTreeValues[referencedNode].setUnloaded();
|
||||
|
||||
@@ -44,14 +44,14 @@ void LoadGameObjectModelList()
|
||||
FILE* model_list_file = fopen((sWorld->GetDataPath() + "vmaps/" + VMAP::GAMEOBJECT_MODELS).c_str(), "rb");
|
||||
if (!model_list_file)
|
||||
{
|
||||
sLog->outError("Unable to open '%s' file.", VMAP::GAMEOBJECT_MODELS);
|
||||
LOG_ERROR("server", "Unable to open '%s' file.", VMAP::GAMEOBJECT_MODELS);
|
||||
return;
|
||||
}
|
||||
|
||||
char magic[8];
|
||||
if (fread(magic, 1, 8, model_list_file) != 8 || memcmp(magic, VMAP::VMAP_MAGIC, 8) != 0)
|
||||
{
|
||||
sLog->outError("File '%s' has wrong header, expected %s.", VMAP::GAMEOBJECT_MODELS, VMAP::VMAP_MAGIC);
|
||||
LOG_ERROR("maps", "File '%s' has wrong header, expected %s.", VMAP::GAMEOBJECT_MODELS, VMAP::VMAP_MAGIC);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -72,13 +72,13 @@ void LoadGameObjectModelList()
|
||||
|| fread(&v1, sizeof(Vector3), 1, model_list_file) != 1
|
||||
|| fread(&v2, sizeof(Vector3), 1, model_list_file) != 1)
|
||||
{
|
||||
sLog->outError("File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS);
|
||||
LOG_ERROR("server", "File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS);
|
||||
break;
|
||||
}
|
||||
|
||||
if (v1.isNaN() || v2.isNaN())
|
||||
{
|
||||
sLog->outError("File '%s' Model '%s' has invalid v1%s v2%s values!",
|
||||
LOG_ERROR("maps", "File '%s' Model '%s' has invalid v1%s v2%s values!",
|
||||
VMAP::GAMEOBJECT_MODELS, std::string(buff, name_length).c_str(), v1.toString().c_str(), v2.toString().c_str());
|
||||
continue;
|
||||
}
|
||||
@@ -87,8 +87,9 @@ void LoadGameObjectModelList()
|
||||
}
|
||||
|
||||
fclose(model_list_file);
|
||||
sLog->outString(">> Loaded %u GameObject models in %u ms", uint32(model_list.size()), GetMSTimeDiffToNow(oldMSTime));
|
||||
sLog->outString();
|
||||
|
||||
LOG_INFO("server", ">> Loaded %u GameObject models in %u ms", uint32(model_list.size()), GetMSTimeDiffToNow(oldMSTime));
|
||||
LOG_INFO("server", " ");
|
||||
}
|
||||
|
||||
GameObjectModel::~GameObjectModel()
|
||||
@@ -107,7 +108,7 @@ bool GameObjectModel::initialize(const GameObject& go, const GameObjectDisplayIn
|
||||
// ignore models with no bounds
|
||||
if (mdl_box == G3D::AABox::zero())
|
||||
{
|
||||
sLog->outError("GameObject model %s has zero bounds, loading skipped", it->second.name.c_str());
|
||||
LOG_ERROR("server", "GameObject model %s has zero bounds, loading skipped", it->second.name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace
|
||||
{
|
||||
if (!replace)
|
||||
{
|
||||
sLog->outError("> Config: Option '%s' is exist! Option key - '%s'", optionName.c_str(), itr->second.c_str());
|
||||
LOG_ERROR("server", "> Config: Option '%s' is exist! Option key - '%s'", optionName.c_str(), itr->second.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
sLog->outError("> Config: %s", e.what());
|
||||
LOG_ERROR("server", "> Config: %s", e.what());
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -134,7 +134,7 @@ T ConfigMgr::GetValueDefault(std::string const& name, T const& def, bool showLog
|
||||
{
|
||||
if (showLogs)
|
||||
{
|
||||
sLog->outError("> Config: Missing name %s in config, add \"%s = %s\"",
|
||||
LOG_ERROR("server", "> Config: Missing name %s in config, add \"%s = %s\"",
|
||||
name.c_str(), name.c_str(), acore::ToString(def).c_str());
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ T ConfigMgr::GetValueDefault(std::string const& name, T const& def, bool showLog
|
||||
{
|
||||
if (showLogs)
|
||||
{
|
||||
sLog->outError("> Config: Bad value defined for name '%s', going to use '%s' instead",
|
||||
LOG_ERROR("server", "> Config: Bad value defined for name '%s', going to use '%s' instead",
|
||||
name.c_str(), acore::ToString(def).c_str());
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ std::string ConfigMgr::GetValueDefault<std::string>(std::string const& name, std
|
||||
{
|
||||
if (showLogs)
|
||||
{
|
||||
sLog->outError("> Config: Missing name %s in config, add \"%s = %s\"",
|
||||
LOG_ERROR("server", "> Config: Missing name %s in config, add \"%s = %s\"",
|
||||
name.c_str(), name.c_str(), def.c_str());
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ bool ConfigMgr::GetOption<bool>(std::string const& name, bool const& def, bool s
|
||||
{
|
||||
if (showLogs)
|
||||
{
|
||||
sLog->outError("> Config: Bad value defined for name '%s', going to use '%s' instead",
|
||||
LOG_ERROR("server", "> Config: Bad value defined for name '%s', going to use '%s' instead",
|
||||
name.c_str(), def ? "true" : "false");
|
||||
}
|
||||
|
||||
@@ -299,13 +299,13 @@ bool ConfigMgr::LoadModulesConfigs()
|
||||
return false;
|
||||
|
||||
// Print modules configurations
|
||||
sLog->outString();
|
||||
sLog->outString("Using modules configuration:");
|
||||
LOG_INFO("server", " ");
|
||||
LOG_INFO("server", "Using modules configuration:");
|
||||
|
||||
for (auto const& itr : moduleConfigFiles)
|
||||
sLog->outString("> %s", itr.c_str());
|
||||
LOG_INFO("server", "> %s", itr.c_str());
|
||||
|
||||
sLog->outString("");
|
||||
LOG_INFO("server", " ");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -19,14 +19,14 @@ DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool<T>& pool, std::st
|
||||
std::string const dbString = sConfigMgr->GetOption<std::string>(name + "DatabaseInfo", "");
|
||||
if (dbString.empty())
|
||||
{
|
||||
sLog->outSQLDriver("Database %s not specified in configuration file!", name.c_str());
|
||||
LOG_INFO("sql.driver", "Database %s not specified in configuration file!", name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8 const asyncThreads = sConfigMgr->GetOption<uint8>(name + "Database.WorkerThreads", 1);
|
||||
if (asyncThreads < 1 || asyncThreads > 32)
|
||||
{
|
||||
sLog->outSQLDriver("%s database: invalid number of worker threads specified. Please pick a value between 1 and 32.", name.c_str());
|
||||
LOG_INFO("sql.driver", "%s database: invalid number of worker threads specified. Please pick a value between 1 and 32.", name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool<T>& pool, std::st
|
||||
|
||||
auto sleepThread = [&]()
|
||||
{
|
||||
sLog->outSQLDriver("> Retrying after %u seconds", durationSecs.count());
|
||||
LOG_INFO("sql.driver", "> Retrying after %u seconds", static_cast<uint32>(durationSecs.count()));
|
||||
std::this_thread::sleep_for(durationSecs);
|
||||
};
|
||||
|
||||
@@ -72,7 +72,7 @@ DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool<T>& pool, std::st
|
||||
// If the error wasn't handled quit
|
||||
if (error)
|
||||
{
|
||||
sLog->outSQLDriver("DatabasePool %s NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile for specific errors", name.c_str());
|
||||
LOG_ERROR("sql.driver", "DatabasePool %s NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile for specific errors", name.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,7 @@ DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool<T>& pool, std::st
|
||||
{
|
||||
if (!pool.PrepareStatements())
|
||||
{
|
||||
sLog->outSQLDriver("Could not prepare statements of the %s database, see log for details.", name.c_str());
|
||||
LOG_ERROR("sql.driver", "Could not prepare statements of the %s database, see log for details.", name.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,8 +38,8 @@ uint32 DatabaseWorkerPool<T>::Open()
|
||||
{
|
||||
WPFatal(_connectionInfo.get(), "Connection info was not set!");
|
||||
|
||||
sLog->outSQLDriver("Opening DatabasePool '%s'. Asynchronous connections: %u, synchronous connections: %u.",
|
||||
GetDatabaseName(), _async_threads, _synch_threads);
|
||||
LOG_INFO("sql.driver", "Opening DatabasePool '%s'. Asynchronous connections: %u, synchronous connections: %u.",
|
||||
GetDatabaseName(), _async_threads, _synch_threads);
|
||||
|
||||
uint32 error = OpenConnections(IDX_ASYNC, _async_threads);
|
||||
|
||||
@@ -52,17 +52,19 @@ uint32 DatabaseWorkerPool<T>::Open()
|
||||
|
||||
if (!error)
|
||||
{
|
||||
sLog->outSQLDriver("DatabasePool '%s' opened successfully. %u total connections running.",
|
||||
GetDatabaseName(), (_connectionCount[IDX_SYNCH] + _connectionCount[IDX_ASYNC]));
|
||||
LOG_INFO("sql.driver", "DatabasePool '%s' opened successfully. %u total connections running.",
|
||||
GetDatabaseName(), (_connectionCount[IDX_SYNCH] + _connectionCount[IDX_ASYNC]));
|
||||
}
|
||||
|
||||
LOG_INFO("sql.driver", " ");
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void DatabaseWorkerPool<T>::Close()
|
||||
{
|
||||
sLog->outSQLDriver("Closing down DatabasePool '%s'.", GetDatabaseName());
|
||||
LOG_INFO("sql.driver", "Closing down DatabasePool '%s'.", GetDatabaseName());
|
||||
|
||||
//! Shuts down delaythreads for this connection pool by underlying deactivate().
|
||||
//! The next dequeue attempt in the worker thread tasks will result in an error,
|
||||
@@ -78,8 +80,8 @@ void DatabaseWorkerPool<T>::Close()
|
||||
t->Close(); //! Closes the actualy MySQL connection.
|
||||
}
|
||||
|
||||
sLog->outSQLDriver("Asynchronous connections on DatabasePool '%s' terminated. Proceeding with synchronous connections.",
|
||||
GetDatabaseName());
|
||||
LOG_INFO("sql.driver", "Asynchronous connections on DatabasePool '%s' terminated. Proceeding with synchronous connections.",
|
||||
GetDatabaseName());
|
||||
|
||||
//! Shut down the synchronous connections
|
||||
//! There's no need for locking the connection, because DatabaseWorkerPool<>::Close
|
||||
@@ -92,7 +94,7 @@ void DatabaseWorkerPool<T>::Close()
|
||||
delete _queue;
|
||||
delete _mqueue;
|
||||
|
||||
sLog->outSQLDriver("All connections on DatabasePool '%s' closed.", GetDatabaseName());
|
||||
LOG_INFO("sql.driver", "All connections on DatabasePool '%s' closed.", GetDatabaseName());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@@ -125,7 +127,7 @@ uint32 DatabaseWorkerPool<T>::OpenConnections(InternalIndex type, uint8 numConne
|
||||
{
|
||||
if (mysql_get_server_version(t->GetHandle()) < MIN_MYSQL_SERVER_VERSION)
|
||||
{
|
||||
sLog->outSQLDriver("Not support MySQL versions below 5.7");
|
||||
LOG_ERROR("sql.driver", "Not support MySQL versions below 5.7");
|
||||
error = 1;
|
||||
}
|
||||
}
|
||||
@@ -299,10 +301,10 @@ void DatabaseWorkerPool<T>::CommitTransaction(SQLTransaction transaction)
|
||||
switch (transaction->GetSize())
|
||||
{
|
||||
case 0:
|
||||
sLog->outSQLDriver("Transaction contains 0 queries. Not executing.");
|
||||
LOG_INFO("sql.driver", "Transaction contains 0 queries. Not executing.");
|
||||
return;
|
||||
case 1:
|
||||
sLog->outSQLDriver("Warning: Transaction only holds 1 query, consider removing Transaction context in code.");
|
||||
LOG_INFO("sql.driver", "Warning: Transaction only holds 1 query, consider removing Transaction context in code.");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
#ifdef ACORE_DEBUG
|
||||
if (!IsType(MYSQL_TYPE_TINY))
|
||||
{
|
||||
sLog->outSQLDriver("Warning: GetUInt8() on non-tinyint field. Using type: %s.", FieldTypeToString(data.type));
|
||||
LOG_INFO("sql.driver", "Warning: GetUInt8() on non-tinyint field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -50,7 +50,7 @@ public:
|
||||
#ifdef ACORE_DEBUG
|
||||
if (!IsType(MYSQL_TYPE_TINY))
|
||||
{
|
||||
sLog->outSQLDriver("Warning: GetInt8() on non-tinyint field. Using type: %s.", FieldTypeToString(data.type));
|
||||
LOG_INFO("sql.driver", "Warning: GetInt8() on non-tinyint field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -75,7 +75,7 @@ public:
|
||||
#ifdef ACORE_DEBUG
|
||||
if (!IsType(MYSQL_TYPE_SHORT) && !IsType(MYSQL_TYPE_YEAR))
|
||||
{
|
||||
sLog->outSQLDriver("Warning: GetUInt16() on non-smallint field. Using type: %s.", FieldTypeToString(data.type));
|
||||
LOG_INFO("sql.driver", "Warning: GetUInt16() on non-smallint field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -93,7 +93,7 @@ public:
|
||||
#ifdef ACORE_DEBUG
|
||||
if (!IsType(MYSQL_TYPE_SHORT) && !IsType(MYSQL_TYPE_YEAR))
|
||||
{
|
||||
sLog->outSQLDriver("Warning: GetInt16() on non-smallint field. Using type: %s.", FieldTypeToString(data.type));
|
||||
LOG_INFO("sql.driver", "Warning: GetInt16() on non-smallint field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -111,7 +111,7 @@ public:
|
||||
#ifdef ACORE_DEBUG
|
||||
if (!IsType(MYSQL_TYPE_INT24) && !IsType(MYSQL_TYPE_LONG))
|
||||
{
|
||||
sLog->outSQLDriver("Warning: GetUInt32() on non-(medium)int field. Using type: %s.", FieldTypeToString(data.type));
|
||||
LOG_INFO("sql.driver", "Warning: GetUInt32() on non-(medium)int field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -129,7 +129,7 @@ public:
|
||||
#ifdef ACORE_DEBUG
|
||||
if (!IsType(MYSQL_TYPE_INT24) && !IsType(MYSQL_TYPE_LONG))
|
||||
{
|
||||
sLog->outSQLDriver("Warning: GetInt32() on non-(medium)int field. Using type: %s.", FieldTypeToString(data.type));
|
||||
LOG_INFO("sql.driver", "Warning: GetInt32() on non-(medium)int field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -147,7 +147,7 @@ public:
|
||||
#ifdef ACORE_DEBUG
|
||||
if (!IsType(MYSQL_TYPE_LONGLONG) && !IsType(MYSQL_TYPE_BIT))
|
||||
{
|
||||
sLog->outSQLDriver("Warning: GetUInt64() on non-bigint field. Using type: %s.", FieldTypeToString(data.type));
|
||||
LOG_INFO("sql.driver", "Warning: GetUInt64() on non-bigint field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -165,7 +165,7 @@ public:
|
||||
#ifdef ACORE_DEBUG
|
||||
if (!IsType(MYSQL_TYPE_LONGLONG) && !IsType(MYSQL_TYPE_BIT))
|
||||
{
|
||||
sLog->outSQLDriver("Warning: GetInt64() on non-bigint field. Using type: %s.", FieldTypeToString(data.type));
|
||||
LOG_INFO("sql.driver", "Warning: GetInt64() on non-bigint field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -183,7 +183,7 @@ public:
|
||||
#ifdef ACORE_DEBUG
|
||||
if (!IsType(MYSQL_TYPE_FLOAT))
|
||||
{
|
||||
sLog->outSQLDriver("Warning: GetFloat() on non-float field. Using type: %s.", FieldTypeToString(data.type));
|
||||
LOG_INFO("sql.driver", "Warning: GetFloat() on non-float field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0.0f;
|
||||
}
|
||||
#endif
|
||||
@@ -201,7 +201,7 @@ public:
|
||||
#ifdef ACORE_DEBUG
|
||||
if (!IsType(MYSQL_TYPE_DOUBLE))
|
||||
{
|
||||
sLog->outSQLDriver("Warning: GetDouble() on non-double field. Using type: %s.", FieldTypeToString(data.type));
|
||||
LOG_INFO("sql.driver", "Warning: GetDouble() on non-double field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return 0.0f;
|
||||
}
|
||||
#endif
|
||||
@@ -219,7 +219,7 @@ public:
|
||||
#ifdef ACORE_DEBUG
|
||||
if (IsNumeric())
|
||||
{
|
||||
sLog->outSQLDriver("Error: GetCString() on numeric field. Using type: %s.", FieldTypeToString(data.type));
|
||||
LOG_INFO("sql.driver", "Error: GetCString() on numeric field. Using type: %s.", FieldTypeToString(data.type));
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
@@ -331,7 +331,7 @@ protected:
|
||||
MYSQL_TYPE_SET:
|
||||
*/
|
||||
default:
|
||||
sLog->outSQLDriver("SQL::SizeForType(): invalid field type %u", uint32(field->type));
|
||||
LOG_INFO("sql.driver", "SQL::SizeForType(): invalid field type %u", uint32(field->type));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,4 +93,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
|
||||
PrepareStatement(LOGIN_INS_CHAR_IP_LOGGING, "INSERT INTO logs_ip_actions (account_id,character_guid,type,ip,systemnote,unixtime,time) VALUES (?, ?, ?, ?, ?, unix_timestamp(NOW()), NOW())", CONNECTION_ASYNC);
|
||||
// 0: string, 1: string, 2: string // Complete name: "Login_Insert_Failed_Account_Login_due_password_IP_Logging"
|
||||
PrepareStatement(LOGIN_INS_FALP_IP_LOGGING, "INSERT INTO logs_ip_actions (account_id,character_guid,type,ip,systemnote,unixtime,time) VALUES ((SELECT id FROM account WHERE username = ?), 0, 1, ?, ?, unix_timestamp(NOW()), NOW())", CONNECTION_ASYNC);
|
||||
|
||||
// DB logging
|
||||
PrepareStatement(LOGIN_INS_LOG, "INSERT INTO logs (time, realm, type, level, string) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||
}
|
||||
|
||||
@@ -111,6 +111,8 @@ enum LoginDatabaseStatements
|
||||
LOGIN_SEL_ACCOUNT_MUTE_INFO,
|
||||
LOGIN_DEL_ACCOUNT_MUTED,
|
||||
|
||||
LOGIN_INS_LOG,
|
||||
|
||||
MAX_LOGINDATABASE_STATEMENTS
|
||||
};
|
||||
|
||||
|
||||
35
src/common/Database/Logging/AppenderDB.cpp
Normal file
35
src/common/Database/Logging/AppenderDB.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#include "AppenderDB.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "LogMessage.h"
|
||||
#include "PreparedStatement.h"
|
||||
|
||||
AppenderDB::AppenderDB(uint8 id, std::string const& name, LogLevel level, AppenderFlags /*flags*/, std::vector<std::string_view> const& /*args*/)
|
||||
: Appender(id, name, level), realmId(0), enabled(false) { }
|
||||
|
||||
AppenderDB::~AppenderDB() { }
|
||||
|
||||
void AppenderDB::_write(LogMessage const* message)
|
||||
{
|
||||
// Avoid infinite loop, PExecute triggers Logging with "sql.sql" type
|
||||
if (!enabled || (message->type.find("sql") != std::string::npos))
|
||||
return;
|
||||
|
||||
PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_LOG);
|
||||
stmt->setUInt64(0, message->mtime);
|
||||
stmt->setUInt32(1, realmId);
|
||||
stmt->setString(2, message->type);
|
||||
stmt->setUInt8(3, uint8(message->level));
|
||||
stmt->setString(4, message->text);
|
||||
LoginDatabase.Execute(stmt);
|
||||
}
|
||||
|
||||
void AppenderDB::setRealmId(uint32 _realmId)
|
||||
{
|
||||
enabled = true;
|
||||
realmId = _realmId;
|
||||
}
|
||||
28
src/common/Database/Logging/AppenderDB.h
Normal file
28
src/common/Database/Logging/AppenderDB.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#ifndef APPENDERDB_H
|
||||
#define APPENDERDB_H
|
||||
|
||||
#include "Appender.h"
|
||||
|
||||
class AppenderDB : public Appender
|
||||
{
|
||||
public:
|
||||
static constexpr AppenderType type = APPENDER_DB;
|
||||
|
||||
AppenderDB(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& args);
|
||||
~AppenderDB();
|
||||
|
||||
void setRealmId(uint32 realmId) override;
|
||||
AppenderType getType() const override { return type; }
|
||||
|
||||
private:
|
||||
uint32 realmId;
|
||||
bool enabled;
|
||||
void _write(LogMessage const* message) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -68,7 +68,7 @@ uint32 MySQLConnection::Open()
|
||||
MYSQL* mysqlInit = mysql_init(nullptr);
|
||||
if (!mysqlInit)
|
||||
{
|
||||
sLog->outError("Could not initialize Mysql connection to database `%s`", m_connectionInfo.database.c_str());
|
||||
LOG_ERROR("sql.sql", "Could not initialize Mysql connection to database `%s`", m_connectionInfo.database.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -121,18 +121,17 @@ uint32 MySQLConnection::Open()
|
||||
{
|
||||
if (!m_reconnecting)
|
||||
{
|
||||
sLog->outSQLDriver("MySQL client library: %s", mysql_get_client_info());
|
||||
sLog->outSQLDriver("MySQL server ver: %s ", mysql_get_server_info(m_Mysql));
|
||||
LOG_INFO("sql.sql", "MySQL client library: %s", mysql_get_client_info());
|
||||
LOG_INFO("sql.sql", "MySQL server ver: %s ", mysql_get_server_info(m_Mysql));
|
||||
|
||||
if (mysql_get_server_version(m_Mysql) != mysql_get_client_version())
|
||||
{
|
||||
sLog->outSQLDriver("[WARNING] MySQL client/server version mismatch; may conflict with behaviour of prepared statements.");
|
||||
LOG_WARN("sql.sql", "[WARNING] MySQL client/server version mismatch; may conflict with behaviour of prepared statements.");
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||
sLog->outDetail("Connected to MySQL database at %s", m_connectionInfo.host.c_str());
|
||||
#endif
|
||||
LOG_INFO("sql.sql", "Connected to MySQL database at %s", m_connectionInfo.host.c_str());
|
||||
|
||||
mysql_autocommit(m_Mysql, 1);
|
||||
|
||||
// set connection properties to UTF8 to properly handle locales for different
|
||||
@@ -141,7 +140,7 @@ uint32 MySQLConnection::Open()
|
||||
return 0;
|
||||
}
|
||||
|
||||
sLog->outError("Could not connect to MySQL database at %s: %s", m_connectionInfo.host.c_str(), mysql_error(mysqlInit));
|
||||
LOG_ERROR("sql.sql", "Could not connect to MySQL database at %s: %s", m_connectionInfo.host.c_str(), mysql_error(mysqlInit));
|
||||
uint32 errorCode = mysql_errno(mysqlInit);
|
||||
mysql_close(mysqlInit);
|
||||
return errorCode;
|
||||
@@ -158,29 +157,23 @@ bool MySQLConnection::Execute(const char* sql)
|
||||
if (!m_Mysql)
|
||||
return false;
|
||||
|
||||
uint32 _s = getMSTime();
|
||||
|
||||
if (mysql_query(m_Mysql, sql))
|
||||
{
|
||||
uint32 _s = 0;
|
||||
if (sLog->GetSQLDriverQueryLogging())
|
||||
_s = getMSTime();
|
||||
uint32 lErrno = mysql_errno(m_Mysql);
|
||||
|
||||
if (mysql_query(m_Mysql, sql))
|
||||
{
|
||||
uint32 lErrno = mysql_errno(m_Mysql);
|
||||
LOG_ERROR("sql.sql", "SQL: %s", sql);
|
||||
LOG_ERROR("sql.sql", "ERROR: [%u] %s", lErrno, mysql_error(m_Mysql));
|
||||
|
||||
sLog->outSQLDriver("SQL: %s", sql);
|
||||
sLog->outSQLDriver("ERROR: [%u] %s", lErrno, mysql_error(m_Mysql));
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return Execute(sql); // Try again
|
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return Execute(sql); // Try again
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (sLog->GetSQLDriverQueryLogging())
|
||||
{
|
||||
sLog->outSQLDriver("[%u ms] SQL: %s", getMSTimeDiff(_s, getMSTime()), sql);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_DEBUG("sql.sql", "[%u ms] SQL: %s", getMSTimeDiff(_s, getMSTime()), sql);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -201,14 +194,12 @@ bool MySQLConnection::Execute(PreparedStatement* stmt)
|
||||
MYSQL_STMT* msql_STMT = m_mStmt->GetSTMT();
|
||||
MYSQL_BIND* msql_BIND = m_mStmt->GetBind();
|
||||
|
||||
uint32 _s = 0;
|
||||
if (sLog->GetSQLDriverQueryLogging())
|
||||
_s = getMSTime();
|
||||
uint32 _s = getMSTime();
|
||||
|
||||
if (mysql_stmt_bind_param(msql_STMT, msql_BIND))
|
||||
{
|
||||
uint32 lErrno = mysql_errno(m_Mysql);
|
||||
sLog->outSQLDriver("SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT));
|
||||
LOG_ERROR("sql.sql", "SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT));
|
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return Execute(stmt); // Try again
|
||||
@@ -220,7 +211,7 @@ bool MySQLConnection::Execute(PreparedStatement* stmt)
|
||||
if (mysql_stmt_execute(msql_STMT))
|
||||
{
|
||||
uint32 lErrno = mysql_errno(m_Mysql);
|
||||
sLog->outSQLDriver("SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT));
|
||||
LOG_ERROR("sql.sql", "SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT));
|
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return Execute(stmt); // Try again
|
||||
@@ -229,8 +220,7 @@ bool MySQLConnection::Execute(PreparedStatement* stmt)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sLog->GetSQLDriverQueryLogging())
|
||||
sLog->outSQLDriver("[%u ms] SQL(p): %s", getMSTimeDiff(_s, getMSTime()), m_mStmt->getQueryString(m_queries[index].first).c_str());
|
||||
LOG_DEBUG("sql.sql", "[%u ms] SQL(p): %s", getMSTimeDiff(_s, getMSTime()), m_mStmt->getQueryString(m_queries[index].first).c_str());
|
||||
|
||||
m_mStmt->ClearParameters();
|
||||
return true;
|
||||
@@ -254,14 +244,12 @@ bool MySQLConnection::_Query(PreparedStatement* stmt, MYSQL_RES** pResult, uint6
|
||||
MYSQL_STMT* msql_STMT = m_mStmt->GetSTMT();
|
||||
MYSQL_BIND* msql_BIND = m_mStmt->GetBind();
|
||||
|
||||
uint32 _s = 0;
|
||||
if (sLog->GetSQLDriverQueryLogging())
|
||||
_s = getMSTime();
|
||||
uint32 _s = getMSTime();
|
||||
|
||||
if (mysql_stmt_bind_param(msql_STMT, msql_BIND))
|
||||
{
|
||||
uint32 lErrno = mysql_errno(m_Mysql);
|
||||
sLog->outSQLDriver("SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT));
|
||||
LOG_ERROR("sql.sql", "SQL(p): %s\n [ERROR]: [%u] %s", m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT));
|
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return _Query(stmt, pResult, pRowCount, pFieldCount); // Try again
|
||||
@@ -273,8 +261,8 @@ bool MySQLConnection::_Query(PreparedStatement* stmt, MYSQL_RES** pResult, uint6
|
||||
if (mysql_stmt_execute(msql_STMT))
|
||||
{
|
||||
uint32 lErrno = mysql_errno(m_Mysql);
|
||||
sLog->outSQLDriver("SQL(p): %s\n [ERROR]: [%u] %s",
|
||||
m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT));
|
||||
LOG_ERROR("sql.sql", "SQL(p): %s\n [ERROR]: [%u] %s",
|
||||
m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT));
|
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return _Query(stmt, pResult, pRowCount, pFieldCount); // Try again
|
||||
@@ -283,8 +271,7 @@ bool MySQLConnection::_Query(PreparedStatement* stmt, MYSQL_RES** pResult, uint6
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sLog->GetSQLDriverQueryLogging())
|
||||
sLog->outSQLDriver("[%u ms] SQL(p): %s", getMSTimeDiff(_s, getMSTime()), m_mStmt->getQueryString(m_queries[index].first).c_str());
|
||||
LOG_DEBUG("sql.sql", "[%u ms] SQL(p): %s", getMSTimeDiff(_s, getMSTime()), m_mStmt->getQueryString(m_queries[index].first).c_str());
|
||||
|
||||
m_mStmt->ClearParameters();
|
||||
|
||||
@@ -318,32 +305,28 @@ bool MySQLConnection::_Query(const char* sql, MYSQL_RES** pResult, MYSQL_FIELD**
|
||||
return false;
|
||||
|
||||
{
|
||||
uint32 _s = 0;
|
||||
if (sLog->GetSQLDriverQueryLogging())
|
||||
_s = getMSTime();
|
||||
uint32 _s = getMSTime();
|
||||
|
||||
if (mysql_query(m_Mysql, sql))
|
||||
{
|
||||
uint32 lErrno = mysql_errno(m_Mysql);
|
||||
sLog->outSQLDriver("SQL: %s", sql);
|
||||
sLog->outSQLDriver("ERROR: [%u] %s", lErrno, mysql_error(m_Mysql));
|
||||
LOG_ERROR("sql.sql", "SQL: %s", sql);
|
||||
LOG_ERROR("sql.sql", "ERROR: [%u] %s", lErrno, mysql_error(m_Mysql));
|
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return _Query(sql, pResult, pFields, pRowCount, pFieldCount); // We try again
|
||||
|
||||
return false;
|
||||
}
|
||||
else if (sLog->GetSQLDriverQueryLogging())
|
||||
{
|
||||
sLog->outSQLDriver("[%u ms] SQL: %s", getMSTimeDiff(_s, getMSTime()), sql);
|
||||
}
|
||||
|
||||
LOG_DEBUG("sql.sql", "[%u ms] SQL: %s", getMSTimeDiff(_s, getMSTime()), sql);
|
||||
|
||||
*pResult = mysql_store_result(m_Mysql);
|
||||
*pRowCount = mysql_affected_rows(m_Mysql);
|
||||
*pFieldCount = mysql_field_count(m_Mysql);
|
||||
}
|
||||
|
||||
if (!*pResult )
|
||||
if (!*pResult)
|
||||
return false;
|
||||
|
||||
if (!*pRowCount)
|
||||
@@ -392,7 +375,7 @@ bool MySQLConnection::ExecuteTransaction(SQLTransaction& transaction)
|
||||
ASSERT(stmt);
|
||||
if (!Execute(stmt))
|
||||
{
|
||||
sLog->outSQLDriver("[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size());
|
||||
LOG_INFO("sql.driver", "[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size());
|
||||
RollbackTransaction();
|
||||
return false;
|
||||
}
|
||||
@@ -404,7 +387,7 @@ bool MySQLConnection::ExecuteTransaction(SQLTransaction& transaction)
|
||||
ASSERT(sql);
|
||||
if (!Execute(sql))
|
||||
{
|
||||
sLog->outSQLDriver("[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size());
|
||||
LOG_INFO("sql.driver", "[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size());
|
||||
RollbackTransaction();
|
||||
return false;
|
||||
}
|
||||
@@ -427,7 +410,7 @@ MySQLPreparedStatement* MySQLConnection::GetPreparedStatement(uint32 index)
|
||||
ASSERT(index < m_stmts.size());
|
||||
MySQLPreparedStatement* ret = m_stmts[index];
|
||||
if (!ret)
|
||||
sLog->outSQLDriver("ERROR: Could not fetch prepared statement %u on database `%s`, connection type: %s.",
|
||||
LOG_INFO("sql.driver", "ERROR: Could not fetch prepared statement %u on database `%s`, connection type: %s.",
|
||||
index, m_connectionInfo.database.c_str(), (m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous");
|
||||
|
||||
return ret;
|
||||
@@ -453,16 +436,16 @@ void MySQLConnection::PrepareStatement(uint32 index, const char* sql, Connection
|
||||
MYSQL_STMT* stmt = mysql_stmt_init(m_Mysql);
|
||||
if (!stmt)
|
||||
{
|
||||
sLog->outSQLDriver("[ERROR]: In mysql_stmt_init() id: %u, sql: \"%s\"", index, sql);
|
||||
sLog->outSQLDriver("[ERROR]: %s", mysql_error(m_Mysql));
|
||||
LOG_INFO("sql.driver", "[ERROR]: In mysql_stmt_init() id: %u, sql: \"%s\"", index, sql);
|
||||
LOG_INFO("sql.driver", "[ERROR]: %s", mysql_error(m_Mysql));
|
||||
m_prepareError = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mysql_stmt_prepare(stmt, sql, static_cast<unsigned long>(strlen(sql))))
|
||||
{
|
||||
sLog->outSQLDriver("[ERROR]: In mysql_stmt_prepare() id: %u, sql: \"%s\"", index, sql);
|
||||
sLog->outSQLDriver("[ERROR]: %s", mysql_stmt_error(stmt));
|
||||
LOG_INFO("sql.driver", "[ERROR]: In mysql_stmt_prepare() id: %u, sql: \"%s\"", index, sql);
|
||||
LOG_INFO("sql.driver", "[ERROR]: %s", mysql_stmt_error(stmt));
|
||||
mysql_stmt_close(stmt);
|
||||
m_prepareError = true;
|
||||
}
|
||||
@@ -506,9 +489,9 @@ bool MySQLConnection::_HandleMySQLErrno(uint32 errNo)
|
||||
mysql_close(GetHandle());
|
||||
if (this->Open()) // Don't remove 'this' pointer unless you want to skip loading all prepared statements....
|
||||
{
|
||||
sLog->outSQLDriver("Connection to the MySQL server is active.");
|
||||
LOG_INFO("sql.driver", "Connection to the MySQL server is active.");
|
||||
if (oldThreadId != mysql_thread_id(GetHandle()))
|
||||
sLog->outSQLDriver("Successfully reconnected to %s @%s:%s (%s).",
|
||||
LOG_INFO("sql.driver", "Successfully reconnected to %s @%s:%s (%s).",
|
||||
m_connectionInfo.database.c_str(), m_connectionInfo.host.c_str(), m_connectionInfo.port_or_socket.c_str(),
|
||||
(m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous");
|
||||
|
||||
@@ -531,17 +514,17 @@ bool MySQLConnection::_HandleMySQLErrno(uint32 errNo)
|
||||
// Outdated table or database structure - terminate core
|
||||
case ER_BAD_FIELD_ERROR:
|
||||
case ER_NO_SUCH_TABLE:
|
||||
sLog->outError("Your database structure is not up to date. Please make sure you've executed all queries in the sql/updates folders.");
|
||||
LOG_ERROR("server", "Your database structure is not up to date. Please make sure you've executed all queries in the sql/updates folders.");
|
||||
std::this_thread::sleep_for(10s);
|
||||
std::abort();
|
||||
return false;
|
||||
case ER_PARSE_ERROR:
|
||||
sLog->outError("Error while parsing SQL. Core fix required.");
|
||||
LOG_ERROR("server", "Error while parsing SQL. Core fix required.");
|
||||
std::this_thread::sleep_for(10s);
|
||||
std::abort();
|
||||
return false;
|
||||
default:
|
||||
sLog->outError("Unhandled MySQL errno %u. Unexpected behaviour possible.", errNo);
|
||||
LOG_ERROR("server", "Unhandled MySQL errno %u. Unexpected behaviour possible.", errNo);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ void PreparedStatement::BindParameters()
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
if (i < m_stmt->m_paramCount)
|
||||
sLog->outSQLDriver("[WARNING]: BindParameters() for statement %u did not bind all allocated parameters", m_index);
|
||||
LOG_INFO("sql.driver", "[WARNING]: BindParameters() for statement %u did not bind all allocated parameters", m_index);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -246,7 +246,7 @@ void MySQLPreparedStatement::ClearParameters()
|
||||
|
||||
static bool ParamenterIndexAssertFail(uint32 stmtIndex, uint8 index, uint32 paramCount)
|
||||
{
|
||||
sLog->outError("Attempted to bind parameter %u%s on a PreparedStatement %u (statement has only %u parameters)", uint32(index) + 1, (index == 1 ? "st" : (index == 2 ? "nd" : (index == 3 ? "rd" : "nd"))), stmtIndex, paramCount);
|
||||
LOG_ERROR("server", "Attempted to bind parameter %u%s on a PreparedStatement %u (statement has only %u parameters)", uint32(index) + 1, (index == 1 ? "st" : (index == 2 ? "nd" : (index == 3 ? "rd" : "nd"))), stmtIndex, paramCount);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ bool MySQLPreparedStatement::CheckValidIndex(uint8 index)
|
||||
ASSERT(index < m_paramCount || ParamenterIndexAssertFail(m_stmt->m_index, index, m_paramCount));
|
||||
|
||||
if (m_paramsSet[index])
|
||||
sLog->outSQLDriver("[WARNING] Prepared Statement (id: %u) trying to bind value on already bound index (%u).", m_stmt->m_index, index);
|
||||
LOG_INFO("sql.driver", "[WARNING] Prepared Statement (id: %u) trying to bind value on already bound index (%u).", m_stmt->m_index, index);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ bool SQLQueryHolder::SetQuery(size_t index, const char* sql)
|
||||
{
|
||||
if (m_queries.size() <= index)
|
||||
{
|
||||
sLog->outError("Query index (%u) out of range (size: %u) for query: %s", uint32(index), (uint32)m_queries.size(), sql);
|
||||
LOG_ERROR("server", "Query index (%u) out of range (size: %u) for query: %s", uint32(index), (uint32)m_queries.size(), sql);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ bool SQLQueryHolder::SetPQuery(size_t index, const char* format, ...)
|
||||
{
|
||||
if (!format)
|
||||
{
|
||||
sLog->outError("Query (index: %u) is empty.", uint32(index));
|
||||
LOG_ERROR("server", "Query (index: %u) is empty.", uint32(index));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ bool SQLQueryHolder::SetPQuery(size_t index, const char* format, ...)
|
||||
|
||||
if (res == -1)
|
||||
{
|
||||
sLog->outError("SQL Query truncated (and not execute) for format: %s", format);
|
||||
LOG_ERROR("server", "SQL Query truncated (and not execute) for format: %s", format);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ bool SQLQueryHolder::SetPreparedQuery(size_t index, PreparedStatement* stmt)
|
||||
{
|
||||
if (m_queries.size() <= index)
|
||||
{
|
||||
sLog->outError("Query index (%u) out of range (size: %u) for prepared statement", uint32(index), (uint32)m_queries.size());
|
||||
LOG_ERROR("server", "Query index (%u) out of range (size: %u) for prepared statement", uint32(index), (uint32)m_queries.size());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ PreparedResultSet::PreparedResultSet(MYSQL_STMT* stmt, MYSQL_RES* result, uint64
|
||||
//- This is where we store the (entire) resultset
|
||||
if (mysql_stmt_store_result(m_stmt))
|
||||
{
|
||||
sLog->outSQLDriver("%s:mysql_stmt_store_result, cannot bind result from MySQL server. Error: %s", __FUNCTION__, mysql_stmt_error(m_stmt));
|
||||
LOG_INFO("sql.driver", "%s:mysql_stmt_store_result, cannot bind result from MySQL server. Error: %s", __FUNCTION__, mysql_stmt_error(m_stmt));
|
||||
delete[] m_rBind;
|
||||
delete[] m_isNull;
|
||||
delete[] m_length;
|
||||
@@ -77,7 +77,7 @@ PreparedResultSet::PreparedResultSet(MYSQL_STMT* stmt, MYSQL_RES* result, uint64
|
||||
//- This is where we bind the bind the buffer to the statement
|
||||
if (mysql_stmt_bind_result(m_stmt, m_rBind))
|
||||
{
|
||||
sLog->outSQLDriver("%s:mysql_stmt_bind_result, cannot bind result from MySQL server. Error: %s", __FUNCTION__, mysql_stmt_error(m_stmt));
|
||||
LOG_INFO("sql.driver", "%s:mysql_stmt_bind_result, cannot bind result from MySQL server. Error: %s", __FUNCTION__, mysql_stmt_error(m_stmt));
|
||||
delete[] m_rBind;
|
||||
delete[] m_isNull;
|
||||
delete[] m_length;
|
||||
|
||||
80
src/common/Logging/Appender.cpp
Normal file
80
src/common/Logging/Appender.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#include "Appender.h"
|
||||
#include "LogMessage.h"
|
||||
#include "StringFormat.h"
|
||||
#include <sstream>
|
||||
|
||||
Appender::Appender(uint8 _id, std::string const& _name, LogLevel _level /* = LOG_LEVEL_DISABLED */, AppenderFlags _flags /* = APPENDER_FLAGS_NONE */):
|
||||
id(_id), name(_name), level(_level), flags(_flags) { }
|
||||
|
||||
Appender::~Appender() { }
|
||||
|
||||
uint8 Appender::getId() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
std::string const& Appender::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
LogLevel Appender::getLogLevel() const
|
||||
{
|
||||
return level;
|
||||
}
|
||||
|
||||
AppenderFlags Appender::getFlags() const
|
||||
{
|
||||
return flags;
|
||||
}
|
||||
|
||||
void Appender::setLogLevel(LogLevel _level)
|
||||
{
|
||||
level = _level;
|
||||
}
|
||||
|
||||
void Appender::write(LogMessage* message)
|
||||
{
|
||||
if (!level || level < message->level)
|
||||
return;
|
||||
|
||||
std::ostringstream ss;
|
||||
|
||||
if (flags & APPENDER_FLAGS_PREFIX_TIMESTAMP)
|
||||
ss << message->getTimeStr() << ' ';
|
||||
|
||||
if (flags & APPENDER_FLAGS_PREFIX_LOGLEVEL)
|
||||
ss << acore::StringFormat("%-5s ", Appender::getLogLevelString(message->level));
|
||||
|
||||
if (flags & APPENDER_FLAGS_PREFIX_LOGFILTERTYPE)
|
||||
ss << '[' << message->type << "] ";
|
||||
|
||||
message->prefix = ss.str();
|
||||
_write(message);
|
||||
}
|
||||
|
||||
char const* Appender::getLogLevelString(LogLevel level)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case LOG_LEVEL_FATAL:
|
||||
return "FATAL";
|
||||
case LOG_LEVEL_ERROR:
|
||||
return "ERROR";
|
||||
case LOG_LEVEL_WARN:
|
||||
return "WARN";
|
||||
case LOG_LEVEL_INFO:
|
||||
return "INFO";
|
||||
case LOG_LEVEL_DEBUG:
|
||||
return "DEBUG";
|
||||
case LOG_LEVEL_TRACE:
|
||||
return "TRACE";
|
||||
default:
|
||||
return "DISABLED";
|
||||
}
|
||||
}
|
||||
49
src/common/Logging/Appender.h
Normal file
49
src/common/Logging/Appender.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#ifndef APPENDER_H
|
||||
#define APPENDER_H
|
||||
|
||||
#include "Define.h"
|
||||
#include "LogCommon.h"
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct LogMessage;
|
||||
|
||||
class Appender
|
||||
{
|
||||
public:
|
||||
Appender(uint8 _id, std::string const& name, LogLevel level = LOG_LEVEL_DISABLED, AppenderFlags flags = APPENDER_FLAGS_NONE);
|
||||
virtual ~Appender();
|
||||
|
||||
uint8 getId() const;
|
||||
std::string const& getName() const;
|
||||
virtual AppenderType getType() const = 0;
|
||||
LogLevel getLogLevel() const;
|
||||
AppenderFlags getFlags() const;
|
||||
|
||||
void setLogLevel(LogLevel);
|
||||
void write(LogMessage* message);
|
||||
static char const* getLogLevelString(LogLevel level);
|
||||
virtual void setRealmId(uint32 /*realmId*/) { }
|
||||
|
||||
private:
|
||||
virtual void _write(LogMessage const* /*message*/) = 0;
|
||||
|
||||
uint8 id;
|
||||
std::string name;
|
||||
LogLevel level;
|
||||
AppenderFlags flags;
|
||||
};
|
||||
|
||||
class InvalidAppenderArgsException : public std::length_error
|
||||
{
|
||||
public:
|
||||
explicit InvalidAppenderArgsException(std::string const& message) : std::length_error(message) { }
|
||||
};
|
||||
|
||||
#endif
|
||||
191
src/common/Logging/AppenderConsole.cpp
Normal file
191
src/common/Logging/AppenderConsole.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#include "AppenderConsole.h"
|
||||
#include "LogMessage.h"
|
||||
#include "SmartEnum.h"
|
||||
#include "StringFormat.h"
|
||||
#include "StringConvert.h"
|
||||
#include "Util.h"
|
||||
#include "Tokenize.h"
|
||||
#include <sstream>
|
||||
|
||||
#if AC_PLATFORM == AC_PLATFORM_WINDOWS
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& args)
|
||||
: Appender(id, name, level, flags), _colored(false)
|
||||
{
|
||||
for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i)
|
||||
_colors[i] = ColorTypes(NUM_COLOR_TYPES);
|
||||
|
||||
if (3 < args.size())
|
||||
InitColors(name, args[3]);
|
||||
}
|
||||
|
||||
void AppenderConsole::InitColors(std::string const& name, std::string_view str)
|
||||
{
|
||||
if (str.empty())
|
||||
{
|
||||
_colored = false;
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string_view> colorStrs = acore::Tokenize(str, ' ', false);
|
||||
if (colorStrs.size() != NUM_ENABLED_LOG_LEVELS)
|
||||
{
|
||||
throw InvalidAppenderArgsException(acore::StringFormat("Log::CreateAppenderFromConfig: Invalid color data '%s' for console appender %s (expected %u entries, got %zu)",
|
||||
std::string(str).c_str(), name.c_str(), NUM_ENABLED_LOG_LEVELS, colorStrs.size()));
|
||||
}
|
||||
|
||||
for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i)
|
||||
{
|
||||
if (Optional<uint8> color = acore::StringTo<uint8>(colorStrs[i]); color && EnumUtils::IsValid<ColorTypes>(*color))
|
||||
_colors[i] = static_cast<ColorTypes>(*color);
|
||||
else
|
||||
{
|
||||
throw InvalidAppenderArgsException(acore::StringFormat("Log::CreateAppenderFromConfig: Invalid color '%s' for log level %s on console appender %s",
|
||||
std::string(colorStrs[i]).c_str(), EnumUtils::ToTitle(static_cast<LogLevel>(i)), name.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
_colored = true;
|
||||
}
|
||||
|
||||
void AppenderConsole::SetColor(bool stdout_stream, ColorTypes color)
|
||||
{
|
||||
#if AC_PLATFORM == AC_PLATFORM_WINDOWS
|
||||
static WORD WinColorFG[NUM_COLOR_TYPES] =
|
||||
{
|
||||
0, // BLACK
|
||||
FOREGROUND_RED, // RED
|
||||
FOREGROUND_GREEN, // GREEN
|
||||
FOREGROUND_RED | FOREGROUND_GREEN, // BROWN
|
||||
FOREGROUND_BLUE, // BLUE
|
||||
FOREGROUND_RED | FOREGROUND_BLUE, // MAGENTA
|
||||
FOREGROUND_GREEN | FOREGROUND_BLUE, // CYAN
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, // WHITE
|
||||
// YELLOW
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
||||
// RED_BOLD
|
||||
FOREGROUND_RED | FOREGROUND_INTENSITY,
|
||||
// GREEN_BOLD
|
||||
FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
||||
FOREGROUND_BLUE | FOREGROUND_INTENSITY, // BLUE_BOLD
|
||||
// MAGENTA_BOLD
|
||||
FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
// CYAN_BOLD
|
||||
FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
// WHITE_BOLD
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
|
||||
};
|
||||
|
||||
HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
|
||||
SetConsoleTextAttribute(hConsole, WinColorFG[color]);
|
||||
#else
|
||||
enum ANSITextAttr
|
||||
{
|
||||
TA_NORMAL = 0,
|
||||
TA_BOLD = 1,
|
||||
TA_BLINK = 5,
|
||||
TA_REVERSE = 7
|
||||
};
|
||||
|
||||
enum ANSIFgTextAttr
|
||||
{
|
||||
FG_BLACK = 30,
|
||||
FG_RED,
|
||||
FG_GREEN,
|
||||
FG_BROWN,
|
||||
FG_BLUE,
|
||||
FG_MAGENTA,
|
||||
FG_CYAN,
|
||||
FG_WHITE,
|
||||
FG_YELLOW
|
||||
};
|
||||
|
||||
enum ANSIBgTextAttr
|
||||
{
|
||||
BG_BLACK = 40,
|
||||
BG_RED,
|
||||
BG_GREEN,
|
||||
BG_BROWN,
|
||||
BG_BLUE,
|
||||
BG_MAGENTA,
|
||||
BG_CYAN,
|
||||
BG_WHITE
|
||||
};
|
||||
|
||||
static uint8 UnixColorFG[NUM_COLOR_TYPES] =
|
||||
{
|
||||
FG_BLACK, // BLACK
|
||||
FG_RED, // RED
|
||||
FG_GREEN, // GREEN
|
||||
FG_BROWN, // BROWN
|
||||
FG_BLUE, // BLUE
|
||||
FG_MAGENTA, // MAGENTA
|
||||
FG_CYAN, // CYAN
|
||||
FG_WHITE, // WHITE
|
||||
FG_YELLOW, // YELLOW
|
||||
FG_RED, // LRED
|
||||
FG_GREEN, // LGREEN
|
||||
FG_BLUE, // LBLUE
|
||||
FG_MAGENTA, // LMAGENTA
|
||||
FG_CYAN, // LCYAN
|
||||
FG_WHITE // LWHITE
|
||||
};
|
||||
|
||||
fprintf((stdout_stream? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < NUM_COLOR_TYPES ? ";1" : ""));
|
||||
#endif
|
||||
}
|
||||
|
||||
void AppenderConsole::ResetColor(bool stdout_stream)
|
||||
{
|
||||
#if AC_PLATFORM == AC_PLATFORM_WINDOWS
|
||||
HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
|
||||
SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
|
||||
#else
|
||||
fprintf((stdout_stream ? stdout : stderr), "\x1b[0m");
|
||||
#endif
|
||||
}
|
||||
|
||||
void AppenderConsole::_write(LogMessage const* message)
|
||||
{
|
||||
bool stdout_stream = !(message->level == LOG_LEVEL_ERROR || message->level == LOG_LEVEL_FATAL);
|
||||
|
||||
if (_colored)
|
||||
{
|
||||
uint8 index;
|
||||
|
||||
switch (message->level)
|
||||
{
|
||||
case LOG_LEVEL_TRACE:
|
||||
index = 5;
|
||||
break;
|
||||
case LOG_LEVEL_DEBUG:
|
||||
index = 4;
|
||||
break;
|
||||
case LOG_LEVEL_INFO:
|
||||
index = 3;
|
||||
break;
|
||||
case LOG_LEVEL_WARN:
|
||||
index = 2;
|
||||
break;
|
||||
case LOG_LEVEL_FATAL:
|
||||
index = 0;
|
||||
break;
|
||||
default:
|
||||
index = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
SetColor(stdout_stream, _colors[index]);
|
||||
utf8printf(stdout_stream ? stdout : stderr, "%s%s\n", message->prefix.c_str(), message->text.c_str());
|
||||
ResetColor(stdout_stream);
|
||||
}
|
||||
else
|
||||
utf8printf(stdout_stream ? stdout : stderr, "%s%s\n", message->prefix.c_str(), message->text.c_str());
|
||||
}
|
||||
49
src/common/Logging/AppenderConsole.h
Normal file
49
src/common/Logging/AppenderConsole.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#ifndef APPENDERCONSOLE_H
|
||||
#define APPENDERCONSOLE_H
|
||||
|
||||
#include "Appender.h"
|
||||
|
||||
// EnumUtils: DESCRIBE THIS
|
||||
enum ColorTypes
|
||||
{
|
||||
BLACK,
|
||||
RED,
|
||||
GREEN,
|
||||
BROWN,
|
||||
BLUE,
|
||||
MAGENTA,
|
||||
CYAN,
|
||||
GREY,
|
||||
YELLOW,
|
||||
LRED,
|
||||
LGREEN,
|
||||
LBLUE,
|
||||
LMAGENTA,
|
||||
LCYAN,
|
||||
WHITE,
|
||||
NUM_COLOR_TYPES // SKIP
|
||||
};
|
||||
|
||||
class AppenderConsole : public Appender
|
||||
{
|
||||
public:
|
||||
static constexpr AppenderType type = APPENDER_CONSOLE;
|
||||
|
||||
AppenderConsole(uint8 _id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& args);
|
||||
void InitColors(std::string const& name, std::string_view init_str);
|
||||
AppenderType getType() const override { return type; }
|
||||
|
||||
private:
|
||||
void SetColor(bool stdout_stream, ColorTypes color);
|
||||
void ResetColor(bool stdout_stream);
|
||||
void _write(LogMessage const* message) override;
|
||||
bool _colored;
|
||||
ColorTypes _colors[NUM_ENABLED_LOG_LEVELS];
|
||||
};
|
||||
|
||||
#endif
|
||||
119
src/common/Logging/AppenderFile.cpp
Normal file
119
src/common/Logging/AppenderFile.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#include "AppenderFile.h"
|
||||
#include "Log.h"
|
||||
#include "LogMessage.h"
|
||||
#include "StringConvert.h"
|
||||
#include "Util.h"
|
||||
#include <algorithm>
|
||||
|
||||
AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& args) :
|
||||
Appender(id, name, level, flags),
|
||||
logfile(nullptr),
|
||||
_logDir(sLog->GetLogsDir()),
|
||||
_maxFileSize(0),
|
||||
_fileSize(0)
|
||||
{
|
||||
if (args.size() < 4)
|
||||
throw InvalidAppenderArgsException(acore::StringFormat("Log::CreateAppenderFromConfig: Missing file name for appender %s", name.c_str()));
|
||||
|
||||
_fileName.assign(args[3]);
|
||||
|
||||
std::string mode = "a";
|
||||
if (4 < args.size())
|
||||
mode.assign(args[4]);
|
||||
|
||||
if (flags & APPENDER_FLAGS_USE_TIMESTAMP)
|
||||
{
|
||||
size_t dot_pos = _fileName.find_last_of('.');
|
||||
if (dot_pos != std::string::npos)
|
||||
_fileName.insert(dot_pos, sLog->GetLogsTimestamp());
|
||||
else
|
||||
_fileName += sLog->GetLogsTimestamp();
|
||||
}
|
||||
|
||||
if (5 < args.size())
|
||||
{
|
||||
if (Optional<uint32> size = acore::StringTo<uint32>(args[5]))
|
||||
_maxFileSize = *size;
|
||||
else
|
||||
throw InvalidAppenderArgsException(acore::StringFormat("Log::CreateAppenderFromConfig: Invalid size '%s' for appender %s", std::string(args[5]).c_str(), name.c_str()));
|
||||
}
|
||||
|
||||
_dynamicName = std::string::npos != _fileName.find("%s");
|
||||
_backup = (flags & APPENDER_FLAGS_MAKE_FILE_BACKUP) != 0;
|
||||
|
||||
if (!_dynamicName)
|
||||
logfile = OpenFile(_fileName, mode, (mode == "w") && _backup);
|
||||
}
|
||||
|
||||
AppenderFile::~AppenderFile()
|
||||
{
|
||||
CloseFile();
|
||||
}
|
||||
|
||||
void AppenderFile::_write(LogMessage const* message)
|
||||
{
|
||||
bool exceedMaxSize = _maxFileSize > 0 && (_fileSize.load() + message->Size()) > _maxFileSize;
|
||||
|
||||
if (_dynamicName)
|
||||
{
|
||||
char namebuf[ACORE_PATH_MAX];
|
||||
snprintf(namebuf, ACORE_PATH_MAX, _fileName.c_str(), message->param1.c_str());
|
||||
|
||||
// always use "a" with dynamic name otherwise it could delete the log we wrote in last _write() call
|
||||
FILE* file = OpenFile(namebuf, "a", _backup || exceedMaxSize);
|
||||
if (!file)
|
||||
return;
|
||||
|
||||
fprintf(file, "%s%s\n", message->prefix.c_str(), message->text.c_str());
|
||||
fflush(file);
|
||||
_fileSize += uint64(message->Size());
|
||||
fclose(file);
|
||||
|
||||
return;
|
||||
}
|
||||
else if (exceedMaxSize)
|
||||
logfile = OpenFile(_fileName, "w", true);
|
||||
|
||||
if (!logfile)
|
||||
return;
|
||||
|
||||
fprintf(logfile, "%s%s\n", message->prefix.c_str(), message->text.c_str());
|
||||
fflush(logfile);
|
||||
_fileSize += uint64(message->Size());
|
||||
}
|
||||
|
||||
FILE* AppenderFile::OpenFile(std::string const& filename, std::string const& mode, bool backup)
|
||||
{
|
||||
std::string fullName(_logDir + filename);
|
||||
if (backup)
|
||||
{
|
||||
CloseFile();
|
||||
std::string newName(fullName);
|
||||
newName.push_back('.');
|
||||
newName.append(LogMessage::getTimeStr(time(nullptr)));
|
||||
std::replace(newName.begin(), newName.end(), ':', '-');
|
||||
rename(fullName.c_str(), newName.c_str()); // no error handling... if we couldn't make a backup, just ignore
|
||||
}
|
||||
|
||||
if (FILE* ret = fopen(fullName.c_str(), mode.c_str()))
|
||||
{
|
||||
_fileSize = ftell(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AppenderFile::CloseFile()
|
||||
{
|
||||
if (logfile)
|
||||
{
|
||||
fclose(logfile);
|
||||
logfile = nullptr;
|
||||
}
|
||||
}
|
||||
34
src/common/Logging/AppenderFile.h
Normal file
34
src/common/Logging/AppenderFile.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#ifndef APPENDERFILE_H
|
||||
#define APPENDERFILE_H
|
||||
|
||||
#include "Appender.h"
|
||||
#include <atomic>
|
||||
|
||||
class AppenderFile : public Appender
|
||||
{
|
||||
public:
|
||||
static constexpr AppenderType type = APPENDER_FILE;
|
||||
|
||||
AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& args);
|
||||
~AppenderFile();
|
||||
FILE* OpenFile(std::string const& name, std::string const& mode, bool backup);
|
||||
AppenderType getType() const override { return type; }
|
||||
|
||||
private:
|
||||
void CloseFile();
|
||||
void _write(LogMessage const* message) override;
|
||||
FILE* logfile;
|
||||
std::string _fileName;
|
||||
std::string _logDir;
|
||||
bool _dynamicName;
|
||||
bool _backup;
|
||||
uint64 _maxFileSize;
|
||||
std::atomic<uint64> _fileSize;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,130 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
*/
|
||||
|
||||
#ifndef AZEROTHCORE_ILOG_H
|
||||
#define AZEROTHCORE_ILOG_H
|
||||
|
||||
class WorldPacket;
|
||||
|
||||
enum DebugLogFilters
|
||||
{
|
||||
LOG_FILTER_NONE = 0x00000000,
|
||||
LOG_FILTER_UNITS = 0x00000001, // Anything related to units that doesn't fit in other categories. ie. creature formations
|
||||
LOG_FILTER_PETS = 0x00000002,
|
||||
LOG_FILTER_VEHICLES = 0x00000004,
|
||||
LOG_FILTER_TSCR = 0x00000008, // C++ AI, instance scripts, etc.
|
||||
LOG_FILTER_DATABASE_AI = 0x00000010, // SmartAI, EventAI, CreatureAI
|
||||
LOG_FILTER_MAPSCRIPTS = 0x00000020,
|
||||
LOG_FILTER_NETWORKIO = 0x00000040, // Anything packet/netcode related
|
||||
LOG_FILTER_SPELLS_AURAS = 0x00000080,
|
||||
LOG_FILTER_ACHIEVEMENTSYS = 0x00000100,
|
||||
LOG_FILTER_CONDITIONSYS = 0x00000200,
|
||||
LOG_FILTER_POOLSYS = 0x00000400,
|
||||
LOG_FILTER_AUCTIONHOUSE = 0x00000800,
|
||||
LOG_FILTER_BATTLEGROUND = 0x00001000, // Anything related to arena's and battlegrounds
|
||||
LOG_FILTER_OUTDOORPVP = 0x00002000,
|
||||
LOG_FILTER_CHATSYS = 0x00004000,
|
||||
LOG_FILTER_LFG = 0x00008000,
|
||||
LOG_FILTER_MAPS = 0x00010000, // Maps, instances, grids, cells, visibility
|
||||
LOG_FILTER_PLAYER_LOADING = 0x00020000, // Debug output from Player::_Load functions
|
||||
LOG_FILTER_PLAYER_ITEMS = 0x00040000, // Anything item related
|
||||
LOG_FILTER_PLAYER_SKILLS = 0x00080000, // Skills related
|
||||
LOG_FILTER_LOOT = 0x00100000, // Loot related
|
||||
LOG_FILTER_GUILD = 0x00200000, // Guild related
|
||||
LOG_FILTER_TRANSPORTS = 0x00400000, // Transport related
|
||||
LOG_FILTER_WARDEN = 0x00800000, // Warden related
|
||||
LOG_FILTER_BATTLEFIELD = 0x01000000, // Battlefield related
|
||||
LOG_FILTER_MODULES = 0x02000000, // Modules debug
|
||||
LOG_FILTER_CLOSE_SOCKET = 0x04000000, // Whenever KickPlayer() or CloseSocket() are called
|
||||
};
|
||||
|
||||
enum LogTypes
|
||||
{
|
||||
LOG_TYPE_STRING = 0,
|
||||
LOG_TYPE_ERROR = 1,
|
||||
LOG_TYPE_BASIC = 2,
|
||||
LOG_TYPE_DETAIL = 3,
|
||||
LOG_TYPE_DEBUG = 4,
|
||||
LOG_TYPE_CHAR = 5,
|
||||
LOG_TYPE_WORLD = 6,
|
||||
LOG_TYPE_RA = 7,
|
||||
LOG_TYPE_GM = 8,
|
||||
LOG_TYPE_CRASH = 9,
|
||||
LOG_TYPE_CHAT = 10,
|
||||
LOG_TYPE_PERF = 11,
|
||||
LOG_TYPE_MULTITH = 12,
|
||||
MAX_LOG_TYPES
|
||||
};
|
||||
|
||||
enum LogLevel
|
||||
{
|
||||
LOGL_NORMAL = 0,
|
||||
LOGL_BASIC,
|
||||
LOGL_DETAIL,
|
||||
LOGL_DEBUG
|
||||
};
|
||||
|
||||
const int LogLevels = int(LOGL_DEBUG) + 1;
|
||||
|
||||
enum ColorTypes
|
||||
{
|
||||
BLACK,
|
||||
RED,
|
||||
GREEN,
|
||||
BROWN,
|
||||
BLUE,
|
||||
MAGENTA,
|
||||
CYAN,
|
||||
GREY,
|
||||
YELLOW,
|
||||
LRED,
|
||||
LGREEN,
|
||||
LBLUE,
|
||||
LMAGENTA,
|
||||
LCYAN,
|
||||
WHITE
|
||||
};
|
||||
|
||||
const int Colors = int(WHITE) + 1;
|
||||
|
||||
class ILog
|
||||
{
|
||||
public:
|
||||
virtual ~ILog() {}
|
||||
virtual void Initialize() = 0;
|
||||
virtual void ReloadConfig() = 0;
|
||||
virtual void InitColors(const std::string& init_str) = 0;
|
||||
virtual void SetColor(bool stdout_stream, ColorTypes color) = 0;
|
||||
virtual void ResetColor(bool stdout_stream) = 0;
|
||||
virtual void outDB(LogTypes type, const char* str) = 0;
|
||||
virtual void outString(const char* str, ...) = 0;
|
||||
virtual void outString() = 0;
|
||||
virtual void outStringInLine(const char* str, ...) = 0;
|
||||
virtual void outError(const char* err, ...) = 0;
|
||||
virtual void outCrash(const char* err, ...) = 0;
|
||||
virtual void outBasic(const char* str, ...) = 0;
|
||||
virtual void outDetail(const char* str, ...) = 0;
|
||||
virtual void outSQLDev(const char* str, ...) = 0;
|
||||
virtual void outDebug(DebugLogFilters f, const char* str, ...) = 0;
|
||||
virtual void outStaticDebug(const char* str, ...) = 0;
|
||||
virtual void outErrorDb(const char* str, ...) = 0;
|
||||
virtual void outChar(const char* str, ...) = 0;
|
||||
virtual void outCommand(uint32 account, const char* str, ...) = 0;
|
||||
virtual void outChat(const char* str, ...) = 0;
|
||||
virtual void outRemote(const char* str, ...) = 0;
|
||||
virtual void outSQLDriver(const char* str, ...) = 0;
|
||||
virtual void outMisc(const char* str, ...) = 0;
|
||||
virtual void outCharDump(const char* str, uint32 account_id, uint32 guid, const char* name) = 0;
|
||||
virtual void SetLogLevel(char* Level) = 0;
|
||||
virtual void SetLogFileLevel(char* Level) = 0;
|
||||
virtual void SetSQLDriverQueryLogging(bool newStatus) = 0;
|
||||
virtual void SetRealmID(uint32 id) = 0;
|
||||
virtual bool IsOutDebug() const = 0;
|
||||
virtual bool IsOutCharDump() const = 0;
|
||||
virtual bool GetLogDB() const = 0;
|
||||
virtual void SetLogDB(bool enable) = 0;
|
||||
virtual bool GetSQLDriverQueryLogging() const = 0;
|
||||
};
|
||||
|
||||
#endif //AZEROTHCORE_ILOG_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,120 +1,256 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
|
||||
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#ifndef AZEROTHCORE_LOG_H
|
||||
#define AZEROTHCORE_LOG_H
|
||||
#ifndef _LOG_H__
|
||||
#define _LOG_H__
|
||||
|
||||
#include "Common.h"
|
||||
#include "ILog.h"
|
||||
#include <ace/Task.h>
|
||||
#include "Define.h"
|
||||
#include "LogCommon.h"
|
||||
#include "StringFormat.h"
|
||||
|
||||
class Log : public ILog
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
class Appender;
|
||||
class Logger;
|
||||
struct LogMessage;
|
||||
|
||||
#define LOGGER_ROOT "root"
|
||||
|
||||
typedef Appender*(*AppenderCreatorFn)(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& extraArgs);
|
||||
|
||||
template <class AppenderImpl>
|
||||
Appender* CreateAppender(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& extraArgs)
|
||||
{
|
||||
return new AppenderImpl(id, name, level, flags, extraArgs);
|
||||
}
|
||||
|
||||
class Log
|
||||
{
|
||||
typedef std::unordered_map<std::string, Logger> LoggerMap;
|
||||
|
||||
private:
|
||||
Log();
|
||||
~Log();
|
||||
Log(Log const&) = delete;
|
||||
Log(Log&&) = delete;
|
||||
Log& operator=(Log const&) = delete;
|
||||
Log& operator=(Log&&) = delete;
|
||||
|
||||
public:
|
||||
Log();
|
||||
~Log();
|
||||
static Log* instance();
|
||||
|
||||
void Initialize();
|
||||
void LoadFromConfig();
|
||||
void Close();
|
||||
bool ShouldLog(std::string const& type, LogLevel level) const;
|
||||
bool SetLogLevel(std::string const& name, int32 level, bool isLogger = true);
|
||||
|
||||
void ReloadConfig();
|
||||
template<typename Format, typename... Args>
|
||||
inline void outMessage(std::string const& filter, LogLevel const level, Format&& fmt, Args&&... args)
|
||||
{
|
||||
outMessage(filter, level, acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
void InitColors(const std::string& init_str);
|
||||
void SetColor(bool stdout_stream, ColorTypes color);
|
||||
void ResetColor(bool stdout_stream);
|
||||
template<typename Format, typename... Args>
|
||||
void outCommand(uint32 account, Format&& fmt, Args&&... args)
|
||||
{
|
||||
if (!ShouldLog("commands.gm", LOG_LEVEL_INFO))
|
||||
return;
|
||||
|
||||
void outDB(LogTypes type, const char* str);
|
||||
void outString(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||
void outString();
|
||||
void outStringInLine(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||
void outError(const char* err, ...) ATTR_PRINTF(2, 3);
|
||||
void outCrash(const char* err, ...) ATTR_PRINTF(2, 3);
|
||||
void outBasic(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||
void outDetail(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||
void outSQLDev(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||
void outDebug(DebugLogFilters f, const char* str, ...) ATTR_PRINTF(3, 4);
|
||||
void outStaticDebug(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||
void outErrorDb(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||
void outChar(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||
void outCommand(uint32 account, const char* str, ...) ATTR_PRINTF(3, 4);
|
||||
void outChat(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||
void outRemote(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||
void outSQLDriver(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||
void outMisc(const char* str, ...) ATTR_PRINTF(2, 3); // pussywizard
|
||||
void outCharDump(const char* str, uint32 account_id, uint32 guid, const char* name);
|
||||
outCommand(acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...), std::to_string(account));
|
||||
}
|
||||
|
||||
static void outTimestamp(FILE* file);
|
||||
static std::string GetTimestampStr();
|
||||
void outCharDump(char const* str, uint32 account_id, uint64 guid, char const* name);
|
||||
|
||||
void SetLogLevel(char* Level);
|
||||
void SetLogFileLevel(char* Level);
|
||||
void SetSQLDriverQueryLogging(bool newStatus) { m_sqlDriverQueryLogging = newStatus; }
|
||||
void SetRealmID(uint32 id) { realm = id; }
|
||||
void SetRealmId(uint32 id);
|
||||
|
||||
[[nodiscard]] bool IsOutDebug() const { return m_logLevel > 2 || (m_logFileLevel > 2 && logfile); }
|
||||
[[nodiscard]] bool IsOutCharDump() const { return m_charLog_Dump; }
|
||||
template<class AppenderImpl>
|
||||
void RegisterAppender()
|
||||
{
|
||||
RegisterAppender(AppenderImpl::type, &CreateAppender<AppenderImpl>);
|
||||
}
|
||||
|
||||
std::string const& GetLogsDir() const { return m_logsDir; }
|
||||
std::string const& GetLogsTimestamp() const { return m_logsTimestamp; }
|
||||
|
||||
// Deprecated functions
|
||||
template<typename Format, typename... Args>
|
||||
inline void outString(Format&& fmt, Args&& ... args)
|
||||
{
|
||||
outMessage("server", LOG_LEVEL_INFO, acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
inline void outString()
|
||||
{
|
||||
outMessage("server", LOG_LEVEL_INFO, " ");
|
||||
}
|
||||
|
||||
template<typename Format, typename... Args>
|
||||
inline void outError(Format&& fmt, Args&& ... args)
|
||||
{
|
||||
outMessage("server", LOG_LEVEL_ERROR, acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<typename Format, typename... Args>
|
||||
void outErrorDb(Format&& fmt, Args&& ... args)
|
||||
{
|
||||
if (!ShouldLog("sql.sql", LOG_LEVEL_ERROR))
|
||||
return;
|
||||
|
||||
outMessage("sql.sql", LOG_LEVEL_ERROR, acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<typename Format, typename... Args>
|
||||
inline void outBasic(Format&& fmt, Args&& ... args)
|
||||
{
|
||||
outMessage("server", LOG_LEVEL_INFO, acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<typename Format, typename... Args>
|
||||
inline void outDetail(Format&& fmt, Args&& ... args)
|
||||
{
|
||||
outMessage("server", LOG_LEVEL_INFO, acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<typename Format, typename... Args>
|
||||
void outSQLDev(Format&& fmt, Args&& ... args)
|
||||
{
|
||||
if (!ShouldLog("sql.dev", LOG_LEVEL_INFO))
|
||||
return;
|
||||
|
||||
outMessage("sql.dev", LOG_LEVEL_INFO, acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<typename Format, typename... Args>
|
||||
void outSQLDriver(Format&& fmt, Args&& ... args)
|
||||
{
|
||||
if (!ShouldLog("sql.driver", LOG_LEVEL_INFO))
|
||||
return;
|
||||
|
||||
outMessage("sql.driver", LOG_LEVEL_INFO, acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<typename Format, typename... Args>
|
||||
inline void outMisc(Format&& fmt, Args&& ... args)
|
||||
{
|
||||
outMessage("server", LOG_LEVEL_INFO, acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template<typename Format, typename... Args>
|
||||
void outDebug(DebugLogFilters filter, Format&& fmt, Args&& ... args)
|
||||
{
|
||||
if (!(_debugLogMask & filter))
|
||||
return;
|
||||
|
||||
if (!ShouldLog("server", LOG_LEVEL_DEBUG))
|
||||
return;
|
||||
|
||||
outMessage("server", LOG_LEVEL_DEBUG, acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
[[nodiscard]] bool GetLogDB() const { return m_enableLogDB; }
|
||||
void SetLogDB(bool enable) { m_enableLogDB = enable; }
|
||||
[[nodiscard]] bool GetSQLDriverQueryLogging() const { return m_sqlDriverQueryLogging; }
|
||||
private:
|
||||
FILE* openLogFile(char const* configFileName, char const* configTimeStampFlag, char const* mode);
|
||||
FILE* openGmlogPerAccount(uint32 account);
|
||||
static std::string GetTimestampStr();
|
||||
void write(std::unique_ptr<LogMessage>&& msg) const;
|
||||
|
||||
FILE* raLogfile;
|
||||
FILE* logfile;
|
||||
FILE* gmLogfile;
|
||||
FILE* charLogfile;
|
||||
FILE* dberLogfile;
|
||||
FILE* chatLogfile;
|
||||
FILE* sqlLogFile;
|
||||
FILE* sqlDevLogFile;
|
||||
FILE* miscLogFile;
|
||||
Logger const* GetLoggerByType(std::string const& type) const;
|
||||
Appender* GetAppenderByName(std::string_view name);
|
||||
uint8 NextAppenderId();
|
||||
void CreateAppenderFromConfig(std::string const& name);
|
||||
void CreateLoggerFromConfig(std::string const& name);
|
||||
void ReadAppendersFromConfig();
|
||||
void ReadLoggersFromConfig();
|
||||
void RegisterAppender(uint8 index, AppenderCreatorFn appenderCreateFn);
|
||||
void outMessage(std::string const& filter, LogLevel level, std::string&& message);
|
||||
void outCommand(std::string&& message, std::string&& param1);
|
||||
|
||||
std::unordered_map<uint8, AppenderCreatorFn> appenderFactory;
|
||||
std::unordered_map<uint8, std::unique_ptr<Appender>> appenders;
|
||||
std::unordered_map<std::string, std::unique_ptr<Logger>> loggers;
|
||||
uint8 AppenderId;
|
||||
LogLevel highestLogLevel;
|
||||
|
||||
// cache values for after initilization use (like gm log per account case)
|
||||
std::string m_logsDir;
|
||||
std::string m_logsTimestamp;
|
||||
|
||||
// gm log control
|
||||
bool m_gmlog_per_account;
|
||||
std::string m_gmlog_filename_format;
|
||||
|
||||
bool m_enableLogDB;
|
||||
uint32 realm;
|
||||
|
||||
// log coloring
|
||||
bool m_colored;
|
||||
ColorTypes m_colors[4];
|
||||
|
||||
// log levels:
|
||||
// false: errors only, true: full query logging
|
||||
bool m_sqlDriverQueryLogging;
|
||||
|
||||
// log levels:
|
||||
// 0 minimum/string, 1 basic/error, 2 detail, 3 full/debug
|
||||
uint8 m_dbLogLevel;
|
||||
uint8 m_logLevel;
|
||||
uint8 m_logFileLevel;
|
||||
bool m_dbChar;
|
||||
bool m_dbRA;
|
||||
bool m_dbGM;
|
||||
bool m_dbChat;
|
||||
bool m_charLog_Dump;
|
||||
bool m_charLog_Dump_Separate;
|
||||
std::string m_dumpsDir;
|
||||
|
||||
DebugLogFilters m_DebugLogMask;
|
||||
// Deprecated debug filter logs
|
||||
DebugLogFilters _debugLogMask;
|
||||
};
|
||||
|
||||
std::unique_ptr<ILog>& getLogInstance();
|
||||
#define sLog Log::instance()
|
||||
|
||||
#define sLog getLogInstance()
|
||||
#define LOG_EXCEPTION_FREE(filterType__, level__, ...) \
|
||||
{ \
|
||||
try \
|
||||
{ \
|
||||
sLog->outMessage(filterType__, level__, __VA_ARGS__); \
|
||||
} \
|
||||
catch (std::exception const& e) \
|
||||
{ \
|
||||
sLog->outMessage("server", LOG_LEVEL_ERROR, "Wrong format occurred (%s) at %s:%u.", \
|
||||
e.what(), __FILE__, __LINE__); \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef PERFORMANCE_PROFILING
|
||||
#define LOG_MESSAGE_BODY(filterType__, level__, ...) ((void)0)
|
||||
#elif AC_PLATFORM != AC_PLATFORM_WINDOWS
|
||||
void check_args(char const*, ...) ATTR_PRINTF(1, 2);
|
||||
void check_args(std::string const&, ...);
|
||||
|
||||
// This will catch format errors on build time
|
||||
#define LOG_MESSAGE_BODY(filterType__, level__, ...) \
|
||||
do { \
|
||||
if (sLog->ShouldLog(filterType__, level__)) \
|
||||
{ \
|
||||
if (false) \
|
||||
check_args(__VA_ARGS__); \
|
||||
\
|
||||
LOG_EXCEPTION_FREE(filterType__, level__, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define LOG_MESSAGE_BODY(filterType__, level__, ...) \
|
||||
__pragma(warning(push)) \
|
||||
__pragma(warning(disable:4127)) \
|
||||
do { \
|
||||
if (sLog->ShouldLog(filterType__, level__)) \
|
||||
LOG_EXCEPTION_FREE(filterType__, level__, __VA_ARGS__); \
|
||||
} while (0) \
|
||||
__pragma(warning(pop))
|
||||
#endif
|
||||
|
||||
// Fatal - 1
|
||||
#define LOG_FATAL(filterType__, ...) \
|
||||
LOG_MESSAGE_BODY(filterType__, LogLevel::LOG_LEVEL_FATAL, __VA_ARGS__)
|
||||
|
||||
// Error - 2
|
||||
#define LOG_ERROR(filterType__, ...) \
|
||||
LOG_MESSAGE_BODY(filterType__, LogLevel::LOG_LEVEL_ERROR, __VA_ARGS__)
|
||||
|
||||
// Warning - 3
|
||||
#define LOG_WARN(filterType__, ...) \
|
||||
LOG_MESSAGE_BODY(filterType__, LogLevel::LOG_LEVEL_WARN, __VA_ARGS__)
|
||||
|
||||
// Info - 4
|
||||
#define LOG_INFO(filterType__, ...) \
|
||||
LOG_MESSAGE_BODY(filterType__, LogLevel::LOG_LEVEL_INFO, __VA_ARGS__)
|
||||
|
||||
// Debug - 5
|
||||
#define LOG_DEBUG(filterType__, ...) \
|
||||
LOG_MESSAGE_BODY(filterType__, LogLevel::LOG_LEVEL_DEBUG, __VA_ARGS__)
|
||||
|
||||
// Trace - 6
|
||||
#define LOG_TRACE(filterType__, ...) \
|
||||
LOG_MESSAGE_BODY(filterType__, LogLevel::LOG_LEVEL_TRACE, __VA_ARGS__)
|
||||
|
||||
#define LOG_CHAR_DUMP(message__, accountId__, guid__, name__) \
|
||||
sLog->outCharDump(message__, accountId__, guid__, name__)
|
||||
|
||||
#define LOG_GM(accountId__, ...) \
|
||||
sLog->outCommand(accountId__, __VA_ARGS__)
|
||||
|
||||
#endif // _LOG_H__
|
||||
|
||||
80
src/common/Logging/LogCommon.h
Normal file
80
src/common/Logging/LogCommon.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#ifndef LogCommon_h__
|
||||
#define LogCommon_h__
|
||||
|
||||
#include "Define.h"
|
||||
|
||||
// EnumUtils: DESCRIBE THIS
|
||||
enum LogLevel : uint8
|
||||
{
|
||||
LOG_LEVEL_DISABLED,
|
||||
LOG_LEVEL_FATAL,
|
||||
LOG_LEVEL_ERROR,
|
||||
LOG_LEVEL_WARN,
|
||||
LOG_LEVEL_INFO,
|
||||
LOG_LEVEL_DEBUG,
|
||||
LOG_LEVEL_TRACE,
|
||||
|
||||
NUM_ENABLED_LOG_LEVELS = LOG_LEVEL_TRACE, // SKIP
|
||||
LOG_LEVEL_INVALID = 0xFF // SKIP
|
||||
};
|
||||
|
||||
// EnumUtils: DESCRIBE THIS
|
||||
enum AppenderType : uint8
|
||||
{
|
||||
APPENDER_NONE,
|
||||
APPENDER_CONSOLE,
|
||||
APPENDER_FILE,
|
||||
APPENDER_DB,
|
||||
|
||||
APPENDER_INVALID = 0xFF // SKIP
|
||||
};
|
||||
|
||||
enum AppenderFlags : uint8
|
||||
{
|
||||
APPENDER_FLAGS_NONE = 0x00,
|
||||
APPENDER_FLAGS_PREFIX_TIMESTAMP = 0x01,
|
||||
APPENDER_FLAGS_PREFIX_LOGLEVEL = 0x02,
|
||||
APPENDER_FLAGS_PREFIX_LOGFILTERTYPE = 0x04,
|
||||
APPENDER_FLAGS_USE_TIMESTAMP = 0x08,
|
||||
APPENDER_FLAGS_MAKE_FILE_BACKUP = 0x10
|
||||
};
|
||||
|
||||
// Dprecated debug log filters need delte later
|
||||
enum DebugLogFilters
|
||||
{
|
||||
LOG_FILTER_NONE = 0x00000000,
|
||||
LOG_FILTER_UNITS = 0x00000001, // Anything related to units that doesn't fit in other categories. ie. creature formations
|
||||
LOG_FILTER_PETS = 0x00000002,
|
||||
LOG_FILTER_VEHICLES = 0x00000004,
|
||||
LOG_FILTER_TSCR = 0x00000008, // C++ AI, instance scripts, etc.
|
||||
LOG_FILTER_DATABASE_AI = 0x00000010, // SmartAI, EventAI, CreatureAI
|
||||
LOG_FILTER_MAPSCRIPTS = 0x00000020,
|
||||
LOG_FILTER_NETWORKIO = 0x00000040, // Anything packet/netcode related
|
||||
LOG_FILTER_SPELLS_AURAS = 0x00000080,
|
||||
LOG_FILTER_ACHIEVEMENTSYS = 0x00000100,
|
||||
LOG_FILTER_CONDITIONSYS = 0x00000200,
|
||||
LOG_FILTER_POOLSYS = 0x00000400,
|
||||
LOG_FILTER_AUCTIONHOUSE = 0x00000800,
|
||||
LOG_FILTER_BATTLEGROUND = 0x00001000, // Anything related to arena's and battlegrounds
|
||||
LOG_FILTER_OUTDOORPVP = 0x00002000,
|
||||
LOG_FILTER_CHATSYS = 0x00004000,
|
||||
LOG_FILTER_LFG = 0x00008000,
|
||||
LOG_FILTER_MAPS = 0x00010000, // Maps, instances, grids, cells, visibility
|
||||
LOG_FILTER_PLAYER_LOADING = 0x00020000, // Debug output from Player::_Load functions
|
||||
LOG_FILTER_PLAYER_ITEMS = 0x00040000, // Anything item related
|
||||
LOG_FILTER_PLAYER_SKILLS = 0x00080000, // Skills related
|
||||
LOG_FILTER_LOOT = 0x00100000, // Loot related
|
||||
LOG_FILTER_GUILD = 0x00200000, // Guild related
|
||||
LOG_FILTER_TRANSPORTS = 0x00400000, // Transport related
|
||||
LOG_FILTER_WARDEN = 0x00800000, // Warden related
|
||||
LOG_FILTER_BATTLEFIELD = 0x01000000, // Battlefield related
|
||||
LOG_FILTER_MODULES = 0x02000000, // Modules debug
|
||||
LOG_FILTER_CLOSE_SOCKET = 0x04000000, // Whenever KickPlayer() or CloseSocket() are called
|
||||
};
|
||||
|
||||
#endif // LogCommon_h__
|
||||
30
src/common/Logging/LogMessage.cpp
Normal file
30
src/common/Logging/LogMessage.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#include "LogMessage.h"
|
||||
#include "StringFormat.h"
|
||||
#include "Util.h"
|
||||
|
||||
LogMessage::LogMessage(LogLevel _level, std::string const& _type, std::string&& _text)
|
||||
: level(_level), type(_type), text(std::forward<std::string>(_text)), mtime(time(nullptr))
|
||||
{
|
||||
}
|
||||
|
||||
LogMessage::LogMessage(LogLevel _level, std::string const& _type, std::string&& _text, std::string&& _param1)
|
||||
: level(_level), type(_type), text(std::forward<std::string>(_text)), param1(std::forward<std::string>(_param1)), mtime(time(nullptr))
|
||||
{
|
||||
}
|
||||
|
||||
std::string LogMessage::getTimeStr(time_t time)
|
||||
{
|
||||
tm aTm;
|
||||
localtime_r(&time, &aTm);
|
||||
return acore::StringFormat("%04d-%02d-%02d_%02d:%02d:%02d", aTm.tm_year + 1900, aTm.tm_mon + 1, aTm.tm_mday, aTm.tm_hour, aTm.tm_min, aTm.tm_sec);
|
||||
}
|
||||
|
||||
std::string LogMessage::getTimeStr() const
|
||||
{
|
||||
return getTimeStr(mtime);
|
||||
}
|
||||
39
src/common/Logging/LogMessage.h
Normal file
39
src/common/Logging/LogMessage.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#ifndef LogMessage_h__
|
||||
#define LogMessage_h__
|
||||
|
||||
#include "Define.h"
|
||||
#include "LogCommon.h"
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
|
||||
struct LogMessage
|
||||
{
|
||||
LogMessage(LogLevel _level, std::string const& _type, std::string&& _text);
|
||||
LogMessage(LogLevel _level, std::string const& _type, std::string&& _text, std::string&& _param1);
|
||||
|
||||
LogMessage(LogMessage const& /*other*/) = delete;
|
||||
LogMessage& operator=(LogMessage const& /*other*/) = delete;
|
||||
|
||||
static std::string getTimeStr(time_t time);
|
||||
std::string getTimeStr() const;
|
||||
|
||||
LogLevel const level;
|
||||
std::string const type;
|
||||
std::string const text;
|
||||
std::string prefix;
|
||||
std::string param1;
|
||||
time_t mtime;
|
||||
|
||||
///@ Returns size of the log message content in bytes
|
||||
uint32 Size() const
|
||||
{
|
||||
return static_cast<uint32>(prefix.size() + text.size());
|
||||
}
|
||||
};
|
||||
|
||||
#endif // LogMessage_h__
|
||||
22
src/common/Logging/LogOperation.cpp
Normal file
22
src/common/Logging/LogOperation.cpp
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#include "LogOperation.h"
|
||||
#include "Logger.h"
|
||||
#include "LogMessage.h"
|
||||
|
||||
LogOperation::LogOperation(Logger const* _logger, std::unique_ptr<LogMessage>&& _msg) : logger(_logger), msg(std::forward<std::unique_ptr<LogMessage>>(_msg))
|
||||
{
|
||||
}
|
||||
|
||||
LogOperation::~LogOperation()
|
||||
{
|
||||
}
|
||||
|
||||
int LogOperation::call()
|
||||
{
|
||||
logger->write(msg.get());
|
||||
return 0;
|
||||
}
|
||||
29
src/common/Logging/LogOperation.h
Normal file
29
src/common/Logging/LogOperation.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#ifndef LOGOPERATION_H
|
||||
#define LOGOPERATION_H
|
||||
|
||||
#include "Define.h"
|
||||
#include <memory>
|
||||
|
||||
class Logger;
|
||||
struct LogMessage;
|
||||
|
||||
class LogOperation
|
||||
{
|
||||
public:
|
||||
LogOperation(Logger const* _logger, std::unique_ptr<LogMessage>&& _msg);
|
||||
|
||||
~LogOperation();
|
||||
|
||||
int call();
|
||||
|
||||
protected:
|
||||
Logger const* logger;
|
||||
std::unique_ptr<LogMessage> msg;
|
||||
};
|
||||
|
||||
#endif
|
||||
48
src/common/Logging/Logger.cpp
Normal file
48
src/common/Logging/Logger.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#include "Logger.h"
|
||||
#include "Appender.h"
|
||||
#include "LogMessage.h"
|
||||
|
||||
Logger::Logger(std::string const& _name, LogLevel _level): name(_name), level(_level) { }
|
||||
|
||||
std::string const& Logger::getName() const
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
LogLevel Logger::getLogLevel() const
|
||||
{
|
||||
return level;
|
||||
}
|
||||
|
||||
void Logger::addAppender(uint8 id, Appender* appender)
|
||||
{
|
||||
appenders[id] = appender;
|
||||
}
|
||||
|
||||
void Logger::delAppender(uint8 id)
|
||||
{
|
||||
appenders.erase(id);
|
||||
}
|
||||
|
||||
void Logger::setLogLevel(LogLevel _level)
|
||||
{
|
||||
level = _level;
|
||||
}
|
||||
|
||||
void Logger::write(LogMessage* message) const
|
||||
{
|
||||
if (!level || level < message->level || message->text.empty())
|
||||
{
|
||||
//fprintf(stderr, "Logger::write: Logger %s, Level %u. Msg %s Level %u WRONG LEVEL MASK OR EMPTY MSG\n", getName().c_str(), getLogLevel(), message.text.c_str(), message.level);
|
||||
return;
|
||||
}
|
||||
|
||||
for (std::pair<uint8 const, Appender*> const& appender : appenders)
|
||||
if (appender.second)
|
||||
appender.second->write(message);
|
||||
}
|
||||
36
src/common/Logging/Logger.h
Normal file
36
src/common/Logging/Logger.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#ifndef LOGGER_H
|
||||
#define LOGGER_H
|
||||
|
||||
#include "Define.h"
|
||||
#include "LogCommon.h"
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
class Appender;
|
||||
struct LogMessage;
|
||||
|
||||
class Logger
|
||||
{
|
||||
public:
|
||||
Logger(std::string const& name, LogLevel level);
|
||||
|
||||
void addAppender(uint8 type, Appender* appender);
|
||||
void delAppender(uint8 type);
|
||||
|
||||
std::string const& getName() const;
|
||||
LogLevel getLogLevel() const;
|
||||
void setLogLevel(LogLevel level);
|
||||
void write(LogMessage* message) const;
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
LogLevel level;
|
||||
std::unordered_map<uint8, Appender*> appenders;
|
||||
};
|
||||
|
||||
#endif
|
||||
92
src/common/Logging/enuminfo_AppenderConsole.cpp
Normal file
92
src/common/Logging/enuminfo_AppenderConsole.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#include "AppenderConsole.h"
|
||||
#include "Define.h"
|
||||
#include "SmartEnum.h"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace acore::Impl::EnumUtilsImpl
|
||||
{
|
||||
|
||||
/********************************************************************\
|
||||
|* data for enum 'ColorTypes' in 'AppenderConsole.h' auto-generated *|
|
||||
\********************************************************************/
|
||||
template <>
|
||||
EnumText EnumUtils<ColorTypes>::ToString(ColorTypes value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case BLACK: return { "BLACK", "BLACK", "" };
|
||||
case RED: return { "RED", "RED", "" };
|
||||
case GREEN: return { "GREEN", "GREEN", "" };
|
||||
case BROWN: return { "BROWN", "BROWN", "" };
|
||||
case BLUE: return { "BLUE", "BLUE", "" };
|
||||
case MAGENTA: return { "MAGENTA", "MAGENTA", "" };
|
||||
case CYAN: return { "CYAN", "CYAN", "" };
|
||||
case GREY: return { "GREY", "GREY", "" };
|
||||
case YELLOW: return { "YELLOW", "YELLOW", "" };
|
||||
case LRED: return { "LRED", "LRED", "" };
|
||||
case LGREEN: return { "LGREEN", "LGREEN", "" };
|
||||
case LBLUE: return { "LBLUE", "LBLUE", "" };
|
||||
case LMAGENTA: return { "LMAGENTA", "LMAGENTA", "" };
|
||||
case LCYAN: return { "LCYAN", "LCYAN", "" };
|
||||
case WHITE: return { "WHITE", "WHITE", "" };
|
||||
default: throw std::out_of_range("value");
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
size_t EnumUtils<ColorTypes>::Count() { return 15; }
|
||||
|
||||
template <>
|
||||
ColorTypes EnumUtils<ColorTypes>::FromIndex(size_t index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: return BLACK;
|
||||
case 1: return RED;
|
||||
case 2: return GREEN;
|
||||
case 3: return BROWN;
|
||||
case 4: return BLUE;
|
||||
case 5: return MAGENTA;
|
||||
case 6: return CYAN;
|
||||
case 7: return GREY;
|
||||
case 8: return YELLOW;
|
||||
case 9: return LRED;
|
||||
case 10: return LGREEN;
|
||||
case 11: return LBLUE;
|
||||
case 12: return LMAGENTA;
|
||||
case 13: return LCYAN;
|
||||
case 14: return WHITE;
|
||||
default: throw std::out_of_range("index");
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
size_t EnumUtils<ColorTypes>::ToIndex(ColorTypes value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case BLACK: return 0;
|
||||
case RED: return 1;
|
||||
case GREEN: return 2;
|
||||
case BROWN: return 3;
|
||||
case BLUE: return 4;
|
||||
case MAGENTA: return 5;
|
||||
case CYAN: return 6;
|
||||
case GREY: return 7;
|
||||
case YELLOW: return 8;
|
||||
case LRED: return 9;
|
||||
case LGREEN: return 10;
|
||||
case LBLUE: return 11;
|
||||
case LMAGENTA: return 12;
|
||||
case LCYAN: return 13;
|
||||
case WHITE: return 14;
|
||||
default: throw std::out_of_range("value");
|
||||
}
|
||||
}
|
||||
}
|
||||
113
src/common/Logging/enuminfo_LogCommon.cpp
Normal file
113
src/common/Logging/enuminfo_LogCommon.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#include "LogCommon.h"
|
||||
#include "Define.h"
|
||||
#include "SmartEnum.h"
|
||||
#include <stdexcept>
|
||||
|
||||
namespace acore::Impl::EnumUtilsImpl
|
||||
{
|
||||
|
||||
/************************************************************\
|
||||
|* data for enum 'LogLevel' in 'LogCommon.h' auto-generated *|
|
||||
\************************************************************/
|
||||
template <>
|
||||
EnumText EnumUtils<LogLevel>::ToString(LogLevel value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case LOG_LEVEL_DISABLED: return { "LOG_LEVEL_DISABLED", "LOG_LEVEL_DISABLED", "" };
|
||||
case LOG_LEVEL_FATAL: return { "LOG_LEVEL_FATAL", "LOG_LEVEL_FATAL", "" };
|
||||
case LOG_LEVEL_ERROR: return { "LOG_LEVEL_ERROR", "LOG_LEVEL_ERROR", "" };
|
||||
case LOG_LEVEL_WARN: return { "LOG_LEVEL_WARN", "LOG_LEVEL_WARN", "" };
|
||||
case LOG_LEVEL_INFO: return { "LOG_LEVEL_INFO", "LOG_LEVEL_INFO", "" };
|
||||
case LOG_LEVEL_DEBUG: return { "LOG_LEVEL_DEBUG", "LOG_LEVEL_DEBUG", "" };
|
||||
case LOG_LEVEL_TRACE: return { "LOG_LEVEL_TRACE", "LOG_LEVEL_TRACE", "" };
|
||||
default: throw std::out_of_range("value");
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
size_t EnumUtils<LogLevel>::Count() { return 7; }
|
||||
|
||||
template <>
|
||||
LogLevel EnumUtils<LogLevel>::FromIndex(size_t index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: return LOG_LEVEL_DISABLED;
|
||||
case 1: return LOG_LEVEL_FATAL;
|
||||
case 2: return LOG_LEVEL_ERROR;
|
||||
case 3: return LOG_LEVEL_WARN;
|
||||
case 4: return LOG_LEVEL_INFO;
|
||||
case 5: return LOG_LEVEL_DEBUG;
|
||||
case 6: return LOG_LEVEL_TRACE;
|
||||
default: throw std::out_of_range("index");
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
size_t EnumUtils<LogLevel>::ToIndex(LogLevel value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case LOG_LEVEL_DISABLED: return 0;
|
||||
case LOG_LEVEL_FATAL: return 1;
|
||||
case LOG_LEVEL_ERROR: return 2;
|
||||
case LOG_LEVEL_WARN: return 3;
|
||||
case LOG_LEVEL_INFO: return 4;
|
||||
case LOG_LEVEL_DEBUG: return 5;
|
||||
case LOG_LEVEL_TRACE: return 6;
|
||||
default: throw std::out_of_range("value");
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************\
|
||||
|* data for enum 'AppenderType' in 'LogCommon.h' auto-generated *|
|
||||
\****************************************************************/
|
||||
template <>
|
||||
EnumText EnumUtils<AppenderType>::ToString(AppenderType value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case APPENDER_NONE: return { "APPENDER_NONE", "APPENDER_NONE", "" };
|
||||
case APPENDER_CONSOLE: return { "APPENDER_CONSOLE", "APPENDER_CONSOLE", "" };
|
||||
case APPENDER_FILE: return { "APPENDER_FILE", "APPENDER_FILE", "" };
|
||||
case APPENDER_DB: return { "APPENDER_DB", "APPENDER_DB", "" };
|
||||
default: throw std::out_of_range("value");
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
size_t EnumUtils<AppenderType>::Count() { return 4; }
|
||||
|
||||
template <>
|
||||
AppenderType EnumUtils<AppenderType>::FromIndex(size_t index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: return APPENDER_NONE;
|
||||
case 1: return APPENDER_CONSOLE;
|
||||
case 2: return APPENDER_FILE;
|
||||
case 3: return APPENDER_DB;
|
||||
default: throw std::out_of_range("index");
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
size_t EnumUtils<AppenderType>::ToIndex(AppenderType value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case APPENDER_NONE: return 0;
|
||||
case APPENDER_CONSOLE: return 1;
|
||||
case APPENDER_FILE: return 2;
|
||||
case APPENDER_DB: return 3;
|
||||
default: throw std::out_of_range("value");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,5 +65,5 @@ void ByteBuffer::hexlike(bool outString) const
|
||||
}
|
||||
o << " ";
|
||||
|
||||
sLog->outString("%s", o.str().c_str());
|
||||
LOG_INFO("server", "%s", o.str().c_str());
|
||||
}
|
||||
|
||||
@@ -242,7 +242,7 @@ bool WinServiceRun()
|
||||
|
||||
if (!StartServiceCtrlDispatcher(serviceTable))
|
||||
{
|
||||
sLog->outError("StartService Failed. Error [%u]", ::GetLastError());
|
||||
LOG_ERROR("server", "StartService Failed. Error [%u]", ::GetLastError());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
46
src/common/Utilities/IteratorPair.h
Normal file
46
src/common/Utilities/IteratorPair.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#ifndef IteratorPair_h__
|
||||
#define IteratorPair_h__
|
||||
|
||||
#include "Define.h"
|
||||
#include <utility>
|
||||
|
||||
namespace acore
|
||||
{
|
||||
/**
|
||||
* @class IteratorPair
|
||||
*
|
||||
* @brief Utility class to enable range for loop syntax for multimap.equal_range uses
|
||||
*/
|
||||
template<class iterator>
|
||||
class IteratorPair
|
||||
{
|
||||
public:
|
||||
constexpr IteratorPair() : _iterators() { }
|
||||
constexpr IteratorPair(iterator first, iterator second) : _iterators(first, second) { }
|
||||
constexpr IteratorPair(std::pair<iterator, iterator> iterators) : _iterators(iterators) { }
|
||||
|
||||
constexpr iterator begin() const { return _iterators.first; }
|
||||
constexpr iterator end() const { return _iterators.second; }
|
||||
|
||||
private:
|
||||
std::pair<iterator, iterator> _iterators;
|
||||
};
|
||||
|
||||
namespace Containers
|
||||
{
|
||||
template<class M>
|
||||
inline auto MapEqualRange(M& map, typename M::key_type const& key) -> IteratorPair<decltype(map.begin())>
|
||||
{
|
||||
return { map.equal_range(key) };
|
||||
}
|
||||
}
|
||||
//! namespace Containers
|
||||
}
|
||||
//! namespace acore
|
||||
|
||||
#endif // IteratorPair_h__
|
||||
120
src/common/Utilities/SmartEnum.h
Normal file
120
src/common/Utilities/SmartEnum.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2008-2021 TrinityCore <http://www.trinitycore.org/>
|
||||
*/
|
||||
|
||||
#ifndef TRINITY_SMARTENUM_H
|
||||
#define TRINITY_SMARTENUM_H
|
||||
|
||||
#include "IteratorPair.h"
|
||||
#include <iterator>
|
||||
|
||||
struct EnumText
|
||||
{
|
||||
EnumText(char const* c, char const* t, char const* d) : Constant(c), Title(t), Description(d) { }
|
||||
// Enum constant of the value
|
||||
char const* const Constant;
|
||||
// Human-readable title of the value
|
||||
char const* const Title;
|
||||
// Human-readable description of the value
|
||||
char const* const Description;
|
||||
};
|
||||
|
||||
namespace acore::Impl::EnumUtilsImpl
|
||||
{
|
||||
template <typename Enum>
|
||||
struct EnumUtils
|
||||
{
|
||||
static size_t Count();
|
||||
static EnumText ToString(Enum value);
|
||||
static Enum FromIndex(size_t index);
|
||||
static size_t ToIndex(Enum index);
|
||||
};
|
||||
}
|
||||
|
||||
class EnumUtils
|
||||
{
|
||||
public:
|
||||
template <typename Enum>
|
||||
static size_t Count() { return acore::Impl::EnumUtilsImpl::EnumUtils<Enum>::Count(); }
|
||||
template <typename Enum>
|
||||
static EnumText ToString(Enum value) { return acore::Impl::EnumUtilsImpl::EnumUtils<Enum>::ToString(value); }
|
||||
template <typename Enum>
|
||||
static Enum FromIndex(size_t index) { return acore::Impl::EnumUtilsImpl::EnumUtils<Enum>::FromIndex(index); }
|
||||
template <typename Enum>
|
||||
static uint32 ToIndex(Enum value) { return acore::Impl::EnumUtilsImpl::EnumUtils<Enum>::ToIndex(value);}
|
||||
|
||||
template<typename Enum>
|
||||
static bool IsValid(Enum value)
|
||||
{
|
||||
try
|
||||
{
|
||||
acore::Impl::EnumUtilsImpl::EnumUtils<Enum>::ToIndex(value);
|
||||
return true;
|
||||
} catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Enum>
|
||||
static bool IsValid(std::underlying_type_t<Enum> value) { return IsValid(static_cast<Enum>(value)); }
|
||||
|
||||
template <typename Enum>
|
||||
class Iterator
|
||||
{
|
||||
public:
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
using value_type = Enum;
|
||||
using pointer = Enum*;
|
||||
using reference = Enum&;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
||||
Iterator() : _index(EnumUtils::Count<Enum>()) {}
|
||||
explicit Iterator(size_t index) : _index(index) { }
|
||||
|
||||
bool operator==(const Iterator& other) const { return other._index == _index; }
|
||||
bool operator!=(const Iterator& other) const { return !operator==(other); }
|
||||
difference_type operator-(Iterator const& other) const { return _index - other._index; }
|
||||
bool operator<(const Iterator& other) const { return _index < other._index; }
|
||||
bool operator<=(const Iterator& other) const { return _index <= other._index; }
|
||||
bool operator>(const Iterator& other) const { return _index > other._index; }
|
||||
bool operator>=(const Iterator& other) const { return _index >= other._index; }
|
||||
|
||||
value_type operator[](difference_type d) const { return FromIndex<Enum>(_index + d); }
|
||||
value_type operator*() const { return operator[](0); }
|
||||
|
||||
Iterator& operator+=(difference_type d) { _index += d; return *this; }
|
||||
Iterator& operator++() { return operator+=(1); }
|
||||
Iterator operator++(int) { Iterator i = *this; operator++(); return i; }
|
||||
Iterator operator+(difference_type d) const { Iterator i = *this; i += d; return i; }
|
||||
|
||||
Iterator& operator-=(difference_type d) { _index -= d; return *this; }
|
||||
Iterator& operator--() { return operator-=(1); }
|
||||
Iterator operator--(int) { Iterator i = *this; operator--(); return i; }
|
||||
Iterator operator-(difference_type d) const { Iterator i = *this; i -= d; return i; }
|
||||
|
||||
private:
|
||||
difference_type _index;
|
||||
};
|
||||
|
||||
template <typename Enum>
|
||||
static Iterator<Enum> Begin() { return Iterator<Enum>(0); }
|
||||
|
||||
template <typename Enum>
|
||||
static Iterator<Enum> End() { return Iterator<Enum>(); }
|
||||
|
||||
template <typename Enum>
|
||||
static acore::IteratorPair<Iterator<Enum>> Iterate() { return { Begin<Enum>(), End<Enum>() }; }
|
||||
|
||||
template <typename Enum>
|
||||
static char const* ToConstant(Enum value) { return ToString(value).Constant; }
|
||||
|
||||
template <typename Enum>
|
||||
static char const* ToTitle(Enum value) { return ToString(value).Title; }
|
||||
|
||||
template <typename Enum>
|
||||
static char const* ToDescription(Enum value) { return ToString(value).Description; }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include "Util.h"
|
||||
|
||||
25
src/common/Utilities/Tokenize.cpp
Normal file
25
src/common/Utilities/Tokenize.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
|
||||
*/
|
||||
|
||||
#include "Tokenize.h"
|
||||
|
||||
std::vector<std::string_view> acore::Tokenize(std::string_view str, char sep, bool keepEmpty)
|
||||
{
|
||||
std::vector<std::string_view> tokens;
|
||||
|
||||
size_t start = 0;
|
||||
for (size_t end = str.find(sep); end != std::string_view::npos; end = str.find(sep, start))
|
||||
{
|
||||
if (keepEmpty || (start < end))
|
||||
tokens.push_back(str.substr(start, end - start));
|
||||
|
||||
start = end + 1;
|
||||
}
|
||||
|
||||
if (keepEmpty || (start < str.length()))
|
||||
tokens.push_back(str.substr(start));
|
||||
|
||||
return tokens;
|
||||
}
|
||||
24
src/common/Utilities/Tokenize.h
Normal file
24
src/common/Utilities/Tokenize.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license: https://github.com/azerothcore/azerothcore-wotlk/blob/master/LICENSE-AGPL3
|
||||
* Copyright (C) 2021+ WarheadCore <https://github.com/WarheadCore>
|
||||
*/
|
||||
|
||||
#ifndef _ACORE_TOKENIZE_H_
|
||||
#define _ACORE_TOKENIZE_H_
|
||||
|
||||
#include "Common.h"
|
||||
#include <string_view>
|
||||
|
||||
namespace acore
|
||||
{
|
||||
std::vector<std::string_view> Tokenize(std::string_view str, char sep, bool keepEmpty);
|
||||
|
||||
/* this would return string_view into temporary otherwise */
|
||||
std::vector<std::string_view> Tokenize(std::string&&, char, bool) = delete;
|
||||
std::vector<std::string_view> Tokenize(std::string const&&, char, bool) = delete;
|
||||
|
||||
/* the delete overload means we need to make this explicit */
|
||||
inline std::vector<std::string_view> Tokenize(char const* str, char sep, bool keepEmpty) { return Tokenize(std::string_view(str ? str : ""), sep, keepEmpty); }
|
||||
}
|
||||
|
||||
#endif // _ACORE_TOKENIZE_H_
|
||||
Reference in New Issue
Block a user