mirror of
https://github.com/SWG-Source/src.git
synced 2026-08-01 01:16:03 -04:00
Added sharedLog and sharedMessageDispatch libraries
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
project(sharedLog)
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(/D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/public)
|
||||
|
||||
add_subdirectory(src)
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/ConfigSharedLog.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/FileLogObserver.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/FirstSharedLog.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/Log.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/LogManager.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/LogObserver.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/NetLogConnection.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/NetLogObserver.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/SetupSharedLog.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/StderrLogger.h"
|
||||
@@ -0,0 +1 @@
|
||||
#include "../../src/shared/TailFileLogObserver.h"
|
||||
@@ -0,0 +1,56 @@
|
||||
|
||||
set(SHARED_SOURCES
|
||||
shared/ConfigSharedLog.cpp
|
||||
shared/ConfigSharedLog.h
|
||||
shared/TailFileLogObserver.cpp
|
||||
shared/TailFileLogObserver.h
|
||||
shared/FileLogObserver.cpp
|
||||
shared/FileLogObserver.h
|
||||
shared/FirstSharedLog.cpp
|
||||
shared/FirstSharedLog.h
|
||||
shared/Log.h
|
||||
shared/LogManager.cpp
|
||||
shared/LogManager.h
|
||||
shared/LogObserver.cpp
|
||||
shared/LogObserver.h
|
||||
shared/NetLogConnection.cpp
|
||||
shared/NetLogConnection.h
|
||||
shared/NetLogObserver.cpp
|
||||
shared/NetLogObserver.h
|
||||
shared/SetupSharedLog.cpp
|
||||
shared/SetupSharedLog.h
|
||||
shared/StderrLogger.h
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(PLATFORM_SOURCES
|
||||
win32/StderrLogger.cpp
|
||||
)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/win32)
|
||||
else()
|
||||
set(PLATFORM_SOURCES
|
||||
linux/StderrLogger.cpp
|
||||
)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/linux)
|
||||
endif()
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/shared
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedDebug/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundation/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedFoundationTypes/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMemoryManager/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedMessageDispatch/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetwork/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedNetworkMessages/include/public
|
||||
${SWG_ENGINE_SOURCE_DIR}/shared/library/sharedSynchronization/include/public
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/archive/include
|
||||
${SWG_EXTERNALS_SOURCE_DIR}/ours/library/fileInterface/include/public
|
||||
)
|
||||
|
||||
add_library(sharedLog STATIC
|
||||
${SHARED_SOURCES}
|
||||
${PLATFORM_SOURCES}
|
||||
)
|
||||
@@ -0,0 +1,74 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// StderrLogger.cpp
|
||||
//
|
||||
// Copyright 2003 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedLog/FirstSharedLog.h"
|
||||
#include "sharedLog/StderrLogger.h"
|
||||
#include "sharedLog/Log.h"
|
||||
#include <string>
|
||||
#include <fcntl.h>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace StderrLoggerNamespace
|
||||
{
|
||||
bool s_installed;
|
||||
int s_oldStderr;
|
||||
int s_stderrPipe[2];
|
||||
}
|
||||
using namespace StderrLoggerNamespace;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void StderrLogger::install()
|
||||
{
|
||||
DEBUG_FATAL(s_installed, ("StderrLogger already installed"));
|
||||
s_installed = true;
|
||||
s_oldStderr = dup(2);
|
||||
pipe(s_stderrPipe);
|
||||
dup2(s_stderrPipe[1], 2);
|
||||
fcntl(s_stderrPipe[0], F_SETFL, O_NONBLOCK);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void StderrLogger::remove()
|
||||
{
|
||||
DEBUG_FATAL(!s_installed, ("StderrLogger not installed"));
|
||||
dup2(s_oldStderr, 2);
|
||||
close(s_stderrPipe[0]);
|
||||
close(s_stderrPipe[1]);
|
||||
s_installed = false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void StderrLogger::update()
|
||||
{
|
||||
if (!s_installed)
|
||||
return;
|
||||
|
||||
char buf[8192];
|
||||
int nRead = read(s_stderrPipe[0], buf, sizeof(buf)-1);
|
||||
if (nRead > 0)
|
||||
{
|
||||
int startPos = 0;
|
||||
while (startPos < nRead)
|
||||
{
|
||||
int endPos = startPos;
|
||||
while (buf[endPos] != '\n' && endPos < nRead)
|
||||
++endPos;
|
||||
buf[endPos] = 0;
|
||||
if (endPos > startPos)
|
||||
LOG("stderr", ("%s", buf+startPos));
|
||||
startPos = endPos+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// ConfigSharedLog.cpp
|
||||
//
|
||||
// Copyright 2002 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedLog/FirstSharedLog.h"
|
||||
#include "sharedLog/ConfigSharedLog.h"
|
||||
|
||||
#include "sharedFoundation/ConfigFile.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace ConfigSharedLogNamespace
|
||||
{
|
||||
typedef std::vector<char const *> StringPtrArray;
|
||||
int ms_logNetQueueSize;
|
||||
int ms_logNetReconnectTimeMs;
|
||||
bool ms_logReportLogs;
|
||||
bool ms_logReportWarnings;
|
||||
bool ms_logReportFatals;
|
||||
bool ms_logStderr;
|
||||
StringPtrArray ms_logTargets; // ConfigFile owns the pointer
|
||||
}
|
||||
using namespace ConfigSharedLogNamespace;
|
||||
|
||||
#define KEY_BOOL(a,b) (ms_ ## a = ConfigFile::getKeyBool("SharedLog", #a, b))
|
||||
#define KEY_INT(a,b) (ms_ ## a = ConfigFile::getKeyInt("SharedLog", #a, b))
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void ConfigSharedLog::install()
|
||||
{
|
||||
KEY_INT (logNetQueueSize, 2000);
|
||||
KEY_INT (logNetReconnectTimeMs, 10000);
|
||||
KEY_BOOL(logReportLogs, false);
|
||||
KEY_BOOL(logReportWarnings, true);
|
||||
KEY_BOOL(logReportFatals, true);
|
||||
KEY_BOOL(logStderr, false);
|
||||
|
||||
int index = 0;
|
||||
char const * result = 0;
|
||||
do
|
||||
{
|
||||
result = ConfigFile::getKeyString("SharedLog", "logTarget", index++, 0);
|
||||
if (result)
|
||||
ms_logTargets.push_back(result);
|
||||
}
|
||||
while (result);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int ConfigSharedLog::getLogNetQueueSize()
|
||||
{
|
||||
return ms_logNetQueueSize;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int ConfigSharedLog::getLogNetReconnectTimeMs()
|
||||
{
|
||||
return ms_logNetReconnectTimeMs;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedLog::getLogReportLogs()
|
||||
{
|
||||
return ms_logReportLogs;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedLog::getLogReportWarnings()
|
||||
{
|
||||
return ms_logReportWarnings;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedLog::getLogReportFatals()
|
||||
{
|
||||
return ms_logReportFatals;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool ConfigSharedLog::getLogStderr()
|
||||
{
|
||||
return ms_logStderr;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
int ConfigSharedLog::getNumberOfLogTargets()
|
||||
{
|
||||
return static_cast<int>(ms_logTargets.size());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
char const * ConfigSharedLog::getLogTarget(int const index)
|
||||
{
|
||||
VALIDATE_RANGE_INCLUSIVE_EXCLUSIVE(0, index, getNumberOfLogTargets());
|
||||
return ms_logTargets[static_cast<size_t>(index)];
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// ConfigSharedLog.h
|
||||
//
|
||||
// Copyright 2002 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_ConfigSharedLog_H
|
||||
#define INCLUDED_ConfigSharedLog_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class ConfigSharedLog
|
||||
{
|
||||
public:
|
||||
static void install();
|
||||
|
||||
static int getLogNetQueueSize();
|
||||
static int getLogNetReconnectTimeMs();
|
||||
static bool getLogReportLogs();
|
||||
static bool getLogReportWarnings();
|
||||
static bool getLogReportFatals();
|
||||
static bool getLogStderr();
|
||||
static int getNumberOfLogTargets();
|
||||
static char const * getLogTarget(int index);
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif // INCLUDED_ConfigSharedLog_H
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// FileLogObserver.cpp
|
||||
//
|
||||
// Copyright 2002 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedLog/FirstSharedLog.h"
|
||||
#include "sharedFoundation/NetworkIdArchive.h"
|
||||
#include "sharedLog/FileLogObserver.h"
|
||||
#include "sharedLog/LogManager.h"
|
||||
#include "fileInterface/StdioFile.h"
|
||||
#include "sharedNetworkMessages/LogMessage.h"
|
||||
#include "UnicodeUtils.h"
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
const int LOG_FILESIZE_NEXT = 2000000000; // point at which we roll over to another log file
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void FileLogObserver::install()
|
||||
{
|
||||
LogManager::registerObserverType("file", create);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
LogObserver *FileLogObserver::create(std::string const &spec)
|
||||
{
|
||||
return new FileLogObserver(spec);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
FileLogObserver::FileLogObserver(std::string const &filename) :
|
||||
LogObserver(),
|
||||
m_filename(filename),
|
||||
m_file(0),
|
||||
m_fileIndex(0)
|
||||
{
|
||||
prepareFile();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void FileLogObserver::prepareFile()
|
||||
{
|
||||
while (!m_file || m_file->tell() >= LOG_FILESIZE_NEXT)
|
||||
{
|
||||
if (m_file)
|
||||
{
|
||||
++m_fileIndex;
|
||||
delete m_file;
|
||||
m_file = 0;
|
||||
}
|
||||
if (m_fileIndex == 0)
|
||||
m_file = new StdioFile(m_filename.c_str(), "a");
|
||||
else
|
||||
{
|
||||
char buf[512];
|
||||
IGNORE_RETURN( snprintf(buf, 512, "%s-%d", m_filename.c_str(), m_fileIndex+1) );
|
||||
m_file = new StdioFile(buf, "a");
|
||||
}
|
||||
NOT_NULL(m_file);
|
||||
FATAL(!m_file->isOpen(), ("Could not open %s", m_filename.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
FileLogObserver::~FileLogObserver()
|
||||
{
|
||||
delete m_file;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void FileLogObserver::log(LogMessage const &msg)
|
||||
{
|
||||
prepareFile();
|
||||
NOT_NULL(m_file);
|
||||
|
||||
uint64 timestamp = msg.getTimestamp();
|
||||
std::string const &procId = msg.getProcId();
|
||||
std::string const &channel = msg.getChannel();
|
||||
std::string const &text = msg.getText();
|
||||
std::string uniAttach(Unicode::wideToNarrow(msg.getUnicodeAttach()));
|
||||
char tsbuf[16]; // yyyymmddhhmmss (14)
|
||||
|
||||
IGNORE_RETURN( sprintf(tsbuf, UINT64_FORMAT_SPECIFIER, timestamp) );
|
||||
IGNORE_RETURN( m_file->write(14, tsbuf) );
|
||||
IGNORE_RETURN( m_file->write(1, ":") );
|
||||
IGNORE_RETURN( m_file->write(static_cast<int>(procId.length()), procId.c_str()) );
|
||||
IGNORE_RETURN( m_file->write(1, ":") );
|
||||
IGNORE_RETURN( m_file->write(static_cast<int>(channel.length()), channel.c_str()) );
|
||||
IGNORE_RETURN( m_file->write(1, ":") );
|
||||
IGNORE_RETURN( m_file->write(static_cast<int>(text.length()), text.c_str()) );
|
||||
if (uniAttach.length())
|
||||
{
|
||||
IGNORE_RETURN( m_file->write(1, ":") );
|
||||
IGNORE_RETURN( m_file->write(static_cast<int>(uniAttach.length()), uniAttach.c_str()) );
|
||||
}
|
||||
IGNORE_RETURN( m_file->write(1, "\n") );
|
||||
|
||||
if (LogManager::getFlushOnWrite())
|
||||
m_file->flush();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void FileLogObserver::flush()
|
||||
{
|
||||
if (m_file)
|
||||
m_file->flush();
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// FileLogObserver.h
|
||||
//
|
||||
// Copyright 2002 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_FileLogObserver_H
|
||||
#define INCLUDED_FileLogObserver_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedLog/LogObserver.h"
|
||||
#include <string>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class AbstractFile;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
// A FileLogObserver saves log messages to a file
|
||||
class FileLogObserver: public LogObserver
|
||||
{
|
||||
public:
|
||||
|
||||
static void install();
|
||||
static LogObserver *create(std::string const &spec);
|
||||
|
||||
FileLogObserver(std::string const &filename);
|
||||
virtual ~FileLogObserver();
|
||||
|
||||
virtual void log(LogMessage const &msg);
|
||||
virtual void flush();
|
||||
|
||||
private:
|
||||
FileLogObserver(FileLogObserver const &);
|
||||
FileLogObserver &operator=(FileLogObserver const &);
|
||||
|
||||
void prepareFile();
|
||||
|
||||
private:
|
||||
std::string m_filename;
|
||||
AbstractFile *m_file;
|
||||
int m_fileIndex;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// FirstSharedLog.cpp
|
||||
//
|
||||
// Copyright 2002 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedLog/FirstSharedLog.h"
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// FirstSharedLog.h
|
||||
//
|
||||
// Copyright 2002 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_FirstSharedLog_H
|
||||
#define INCLUDED_FirstSharedLog_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedFoundation/FirstSharedFoundation.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// Log.h
|
||||
//
|
||||
// Copyright 2002 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_Log_H
|
||||
#define INCLUDED_Log_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "LogManager.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
// Un-conditional
|
||||
|
||||
#define LOG(stream, varArgs) (LogManager::setArgs(stream), LogManager::log varArgs)
|
||||
#define LOGU(stream, varArgs, unicodeAttach) (LogManager::setArgs(stream, unicodeAttach), LogManager::log varArgs)
|
||||
|
||||
// Conditional
|
||||
|
||||
#define LOGC(forceLog, stream, varArgs) ((forceLog) ? (LogManager::setArgs(stream), LogManager::log varArgs) : NOP)
|
||||
#define LOGUC(forceLog, stream, varArgs, unicodeAttach) ((forceLog) ? (LogManager::setArgs(stream, unicodeAttach), LogManager::log varArgs) : NOP)
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define DEBUG_LOG(stream, varArgs) LOG(stream, varArgs)
|
||||
#define DEBUG_LOGU(stream, varArgs, unicodeAttach) LOGU(stream, varArgs, unicodeAttach)
|
||||
#else
|
||||
#define DEBUG_LOG(stream, varArgs) NOP
|
||||
#define DEBUG_LOGU(stream, varArgs, unicodeAttach) NOP
|
||||
#endif
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,367 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// LogManager.cpp
|
||||
//
|
||||
// Copyright 2002 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedLog/FirstSharedLog.h"
|
||||
#include "sharedFoundation/NetworkIdArchive.h"
|
||||
|
||||
#include "sharedFoundation/ExitChain.h"
|
||||
#include "sharedFoundation/ConfigFile.h"
|
||||
#include "sharedLog/LogManager.h"
|
||||
#include "sharedLog/LogObserver.h"
|
||||
#include "sharedLog/ConfigSharedLog.h"
|
||||
#include "sharedLog/StderrLogger.h"
|
||||
#include "sharedNetworkMessages/LogMessage.h"
|
||||
#include "sharedSynchronization/RecursiveMutex.h"
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <time.h>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
typedef std::list<LogObserver *> ObserverList;
|
||||
typedef std::map<std::string, LogObserverCreateFunc> ObserverCreateMap;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace LogManagerNamespace
|
||||
{
|
||||
void remove();
|
||||
|
||||
const int MaxLogMessageLen = 16384;
|
||||
|
||||
struct LogManagerData
|
||||
{
|
||||
LogManagerData() :
|
||||
mutex(),
|
||||
observers(),
|
||||
observerCreateMap(),
|
||||
channel(),
|
||||
unicodeAttach(),
|
||||
processIdentifier(),
|
||||
flushOnWrite(true),
|
||||
logging(0)
|
||||
{
|
||||
}
|
||||
RecursiveMutex mutex;
|
||||
ObserverList observers;
|
||||
ObserverCreateMap observerCreateMap;
|
||||
std::string channel;
|
||||
Unicode::String unicodeAttach;
|
||||
std::string processIdentifier;
|
||||
bool flushOnWrite;
|
||||
int logging; // used for catching recursive log attempts from the same thread
|
||||
|
||||
private:
|
||||
LogManagerData(LogManagerData const &);
|
||||
LogManagerData &operator=(LogManagerData const &);
|
||||
};
|
||||
LogManagerData *s_data;
|
||||
}
|
||||
using namespace LogManagerNamespace;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void LogManager::install(std::string const &procId, bool flushOnWrite)
|
||||
{
|
||||
DEBUG_FATAL(s_data, ("LogManager already installed"));
|
||||
s_data = new LogManagerData;
|
||||
s_data->processIdentifier = procId;
|
||||
s_data->flushOnWrite = flushOnWrite;
|
||||
ExitChain::add(LogManagerNamespace::remove, "LogManagerNamespace::remove");
|
||||
if (ConfigSharedLog::getLogStderr())
|
||||
StderrLogger::install();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void LogManager::update()
|
||||
{
|
||||
if (!s_data)
|
||||
return;
|
||||
|
||||
if (ConfigSharedLog::getLogStderr())
|
||||
StderrLogger::update();
|
||||
|
||||
for (ObserverList::iterator i = s_data->observers.begin(); i != s_data->observers.end(); ++i)
|
||||
(*i)->update();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void LogManagerNamespace::remove()
|
||||
{
|
||||
DEBUG_FATAL(!s_data, ("LogManager not installed"));
|
||||
// we own any observers we have, so delete them
|
||||
while (!s_data->observers.empty())
|
||||
{
|
||||
delete (*s_data->observers.begin());
|
||||
IGNORE_RETURN( s_data->observers.erase(s_data->observers.begin()) );
|
||||
}
|
||||
if (ConfigSharedLog::getLogStderr())
|
||||
StderrLogger::remove();
|
||||
|
||||
delete s_data;
|
||||
s_data = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void LogManager::setProcessIdentifier(std::string const &procId)
|
||||
{
|
||||
s_data->processIdentifier = procId;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void LogManager::setArgs(std::string const &channel, Unicode::String const &unicodeAttach)
|
||||
{
|
||||
if (!s_data)
|
||||
return;
|
||||
|
||||
s_data->mutex.enter(); // leave() called from log which should always follow setArgs
|
||||
if (s_data->logging == 0)
|
||||
{
|
||||
++s_data->logging;
|
||||
s_data->channel = channel;
|
||||
s_data->unicodeAttach = unicodeAttach;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void LogManager::setArgs(std::string const &channel)
|
||||
{
|
||||
if (!s_data)
|
||||
return;
|
||||
|
||||
s_data->mutex.enter(); // leave() called from log which should always follow setArgs
|
||||
++s_data->logging;
|
||||
if (s_data->logging == 1)
|
||||
{
|
||||
s_data->channel = channel;
|
||||
s_data->unicodeAttach.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void LogManager::log(char const *format, ...)
|
||||
{
|
||||
if (!s_data)
|
||||
return;
|
||||
// if noone is observing log messages, no need to process them
|
||||
if (s_data->observers.size() && s_data->logging == 1)
|
||||
{
|
||||
++s_data->logging;
|
||||
static char text[MaxLogMessageLen];
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format); //lint !e746 !e1055
|
||||
IGNORE_RETURN( _vsnprintf(text, sizeof(text), format, ap) );
|
||||
text[sizeof(text)-1] = '\0';
|
||||
size_t len = strlen(text);
|
||||
// if string was truncated, stick a + on the end
|
||||
if (len == sizeof(text)-1)
|
||||
text[len-1] = '+';
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
uint64 timestamp;
|
||||
{
|
||||
// format current date/time gmt as yyyymmddhhmmss, in a uint64
|
||||
time_t now;
|
||||
tm t;
|
||||
|
||||
IGNORE_RETURN( time(&now) );
|
||||
IGNORE_RETURN( gmtime_r(&now, &t) );
|
||||
timestamp = t.tm_year+1900; //lint !e732 !e737 !e776
|
||||
timestamp *= 100;
|
||||
timestamp += t.tm_mon+1; //lint !e737 !e776
|
||||
timestamp *= 100;
|
||||
timestamp += static_cast<unsigned int>(t.tm_mday);
|
||||
timestamp *= 100;
|
||||
timestamp += static_cast<unsigned int>(t.tm_hour);
|
||||
timestamp *= 100;
|
||||
timestamp += static_cast<unsigned int>(t.tm_min);
|
||||
timestamp *= 100;
|
||||
timestamp += static_cast<unsigned int>(t.tm_sec);
|
||||
}
|
||||
|
||||
observeLogMessage(LogMessage(timestamp, s_data->processIdentifier, s_data->channel, text, s_data->unicodeAttach));
|
||||
--s_data->logging;
|
||||
}
|
||||
|
||||
--s_data->logging;
|
||||
s_data->mutex.leave(); // enter() called from setArgs which should always precede log
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void LogManager::observeLogMessage(LogMessage const &msg)
|
||||
{
|
||||
for (ObserverList::iterator i = s_data->observers.begin(); i != s_data->observers.end(); ++i)
|
||||
if (!(*i)->isFiltered(msg))
|
||||
(*i)->log(msg);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void LogManager::addObserver(LogObserver *observer)
|
||||
{
|
||||
s_data->observers.push_back(observer);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void LogManager::removeObserver(LogObserver const *observer)
|
||||
{
|
||||
// we own any observers given to us, so delete it when it is removed
|
||||
for (ObserverList::iterator i = s_data->observers.begin(); i != s_data->observers.end(); ++i)
|
||||
{
|
||||
if ((*i) == observer)
|
||||
{
|
||||
delete (*i);
|
||||
IGNORE_RETURN( s_data->observers.erase(i) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void LogManager::registerObserverType(std::string const &name, LogObserverCreateFunc func)
|
||||
{
|
||||
s_data->observerCreateMap[name] = func;
|
||||
|
||||
char buffer[256];
|
||||
sprintf(buffer, "%s:", name.c_str());
|
||||
|
||||
// run through SharedLog keys looking for logTarget=name:
|
||||
{
|
||||
int const numberLogTargets = ConfigSharedLog::getNumberOfLogTargets();
|
||||
for (int i = 0; i < numberLogTargets; ++i)
|
||||
{
|
||||
char const * const result = ConfigSharedLog::getLogTarget(i);
|
||||
if (result && strstr(result, buffer) == result)
|
||||
{
|
||||
setupObserver(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// run through SharedLog keys looking for logTarget#=name:
|
||||
{
|
||||
char key[16];
|
||||
strcpy(key, "logTarget");
|
||||
|
||||
for (int i = 0; i < 20; ++i)
|
||||
{
|
||||
char const * result = 0;
|
||||
sprintf(key+9, "%d", i);
|
||||
int count = 0;
|
||||
do
|
||||
{
|
||||
result = ConfigFile::getKeyString("SharedLog", key, count, 0);
|
||||
if (result && strstr(result, buffer) == result)
|
||||
setupObserver(result);
|
||||
++count;
|
||||
} while (result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool LogManager::setupObserver(std::string const &desc)
|
||||
{
|
||||
REPORT_LOG(true, ("Log observer setup: %s\n", desc.c_str()));
|
||||
|
||||
// description should be "type:spec{filter1:filter2:...}"
|
||||
size_t pos = desc.find(":");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
std::string type(desc.substr(0, pos));
|
||||
std::string spec;
|
||||
std::string filt;
|
||||
|
||||
size_t pos2 = desc.find("{");
|
||||
if (pos2 == std::string::npos)
|
||||
spec = desc.substr(pos+1);
|
||||
else
|
||||
{
|
||||
spec = desc.substr(pos+1, (pos2-(pos+1)));
|
||||
filt = desc.substr(pos2+1);
|
||||
if (filt.length() && filt[filt.length()-1] == '}')
|
||||
{
|
||||
IGNORE_RETURN( filt.erase(filt.length()-1) );
|
||||
}
|
||||
}
|
||||
|
||||
ObserverCreateMap::iterator i = s_data->observerCreateMap.find(type);
|
||||
if (i != s_data->observerCreateMap.end())
|
||||
{
|
||||
LogObserver *observer = (*(*i).second)(spec);
|
||||
if (observer)
|
||||
{
|
||||
if (filt.length())
|
||||
observer->setFilter(filt);
|
||||
addObserver(observer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool LogManager::getFlushOnWrite()
|
||||
{
|
||||
return s_data->flushOnWrite;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void LogManager::flush()
|
||||
{
|
||||
for (ObserverList::iterator i = s_data->observers.begin(); i != s_data->observers.end(); ++i)
|
||||
(*i)->flush();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void LogManager::logLongText(std::string const & channel, std::string const & longText)
|
||||
{
|
||||
int const targetLineLength=80;
|
||||
int const maxLineLength=100;
|
||||
char buffer[maxLineLength+1];
|
||||
int pos=0;
|
||||
for (std::string::const_iterator i=longText.begin(); i!=longText.end(); ++i)
|
||||
{
|
||||
buffer[pos++]=*i;
|
||||
if ((pos>=targetLineLength && *i==' ') || (pos==maxLineLength))
|
||||
{
|
||||
buffer[pos]='\0';
|
||||
setArgs(channel);
|
||||
log("%s", buffer);
|
||||
pos=0;
|
||||
}
|
||||
}
|
||||
if (pos!=0)
|
||||
{
|
||||
buffer[pos]='\0';
|
||||
setArgs(channel);
|
||||
log("%s", buffer);
|
||||
pos=0;
|
||||
}
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// LogManager.h
|
||||
//
|
||||
// Copyright 2002 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_LogManager_H
|
||||
#define INCLUDED_LogManager_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class LogMessage;
|
||||
class LogObserver;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
// The LogManager is a static class which catches log messages,
|
||||
// processes them from varArgs into straight ascii text, and passes the
|
||||
// processed string on to any observers, along with a timestamp,
|
||||
// process identifier, and any unicode text attached.
|
||||
|
||||
typedef LogObserver *(*LogObserverCreateFunc)(std::string const &);
|
||||
|
||||
class LogManager
|
||||
{
|
||||
public:
|
||||
|
||||
static void install(std::string const &procId, bool flushOnWrite = true);
|
||||
static void update();
|
||||
static void setProcessIdentifier(std::string const &procId);
|
||||
|
||||
// note: setArgs() and log() always come as a pair, and must do so to avoid deadlocks
|
||||
static void setArgs(std::string const &channel, Unicode::String const &unicodeAttach);
|
||||
static void setArgs(std::string const &channel);
|
||||
static void log(char const *format, ...);
|
||||
static void logLongText(std::string const & channel, std::string const & longText);
|
||||
|
||||
static void observeLogMessage(LogMessage const &msg);
|
||||
|
||||
static void addObserver(LogObserver *observer);
|
||||
static void removeObserver(LogObserver const *observer);
|
||||
static void registerObserverType(std::string const &name, LogObserverCreateFunc func);
|
||||
static bool setupObserver(std::string const &desc);
|
||||
static bool getFlushOnWrite();
|
||||
static void flush();
|
||||
|
||||
private:
|
||||
LogManager();
|
||||
LogManager(LogManager const &);
|
||||
LogManager &operator=(LogManager const &);
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// LogObserver.cpp
|
||||
//
|
||||
// Copyright 2002 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedLog/FirstSharedLog.h"
|
||||
#include "sharedFoundation/NetworkIdArchive.h"
|
||||
#include "sharedLog/LogObserver.h"
|
||||
#include "sharedNetworkMessages/LogMessage.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
LogObserver::LogObserver() :
|
||||
m_filters(new std::vector<std::string>())
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
LogObserver::~LogObserver()
|
||||
{
|
||||
delete m_filters;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void LogObserver::setFilter(std::string const &filter)
|
||||
{
|
||||
// filter is a : separated list of filter rules. split them and add
|
||||
// valid ones to the filter list
|
||||
m_filters->clear();
|
||||
size_t curPos = 0;
|
||||
while (curPos < filter.length())
|
||||
{
|
||||
size_t endPos = filter.find(":", curPos);
|
||||
if (endPos == std::string::npos)
|
||||
endPos = filter.length()+1;
|
||||
m_filters->push_back(filter.substr(curPos, endPos-curPos));
|
||||
curPos = endPos+1;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool LogObserver::isFiltered(LogMessage const &msg) const
|
||||
{
|
||||
bool filtered = false;
|
||||
// run through the list of filters comparing them
|
||||
std::vector<std::string>::const_iterator i;
|
||||
for (i = m_filters->begin(); i != m_filters->end(); ++i)
|
||||
{
|
||||
std::string const &filter = (*i);
|
||||
std::string const *source = 0;
|
||||
// source specifier (c or d - channel or data)
|
||||
if (filter[0] == 'c')
|
||||
source = &msg.getChannel();
|
||||
else if (filter[0] == 'd')
|
||||
source = &msg.getText();
|
||||
else if (filter[0] == 'p')
|
||||
source = &msg.getProcId();
|
||||
else
|
||||
continue; // invalid source specifier, skip filter
|
||||
// filter action (+ or -)
|
||||
bool action = false;
|
||||
if (filter[1] == '+')
|
||||
action = false;
|
||||
else if (filter[1] == '-')
|
||||
action = true;
|
||||
else
|
||||
continue; // invalid action specifier, skip filter
|
||||
// may be a comparison negation specifier
|
||||
size_t filterPos = 2;
|
||||
bool negateCompare = false;
|
||||
if (filter[2] == '!')
|
||||
{
|
||||
++filterPos;
|
||||
negateCompare = true;
|
||||
}
|
||||
bool match;
|
||||
// either '*' or a substring to search for, may change this to regex
|
||||
if (filter[filterPos] == '*')
|
||||
match = true;
|
||||
else
|
||||
match = (source->find(filter.c_str()+filterPos) != std::string::npos);
|
||||
if (negateCompare)
|
||||
match = !match;
|
||||
if (match)
|
||||
filtered = action;
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void LogObserver::flush()
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
void LogObserver::update()
|
||||
{
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// LogObserver.h
|
||||
//
|
||||
// Copyright 2002 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_LogObserver_H
|
||||
#define INCLUDED_LogObserver_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class LogMessage;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
// A LogObserver is derived from in order to provide a mechanism for
|
||||
// catching log messages and doing something with them. A derived
|
||||
// observer object must be added to the logManager before it will
|
||||
// have any effect.
|
||||
|
||||
class LogObserver
|
||||
{
|
||||
public:
|
||||
LogObserver();
|
||||
virtual ~LogObserver();
|
||||
|
||||
virtual void log(LogMessage const &msg) = 0;
|
||||
virtual void flush();
|
||||
|
||||
void setFilter(std::string const &filter);
|
||||
bool isFiltered(LogMessage const &msg) const;
|
||||
|
||||
virtual void update();
|
||||
|
||||
private:
|
||||
LogObserver(LogObserver const &);
|
||||
LogObserver &operator=(LogObserver const &);
|
||||
|
||||
stdvector<std::string>::fwd* m_filters;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// NetLogConnection.cpp
|
||||
//
|
||||
// Copyright 2002 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedLog/FirstSharedLog.h"
|
||||
#include "sharedFoundation/NetworkIdArchive.h"
|
||||
#include "sharedLog/NetLogObserver.h"
|
||||
#include "sharedNetwork/NetworkSetupData.h"
|
||||
#include "NetLogConnection.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
NetLogConnection::NetLogConnection(NetLogObserver *owner) :
|
||||
Connection(owner->getRemoteAddress(), owner->getRemotePort(), NetworkSetupData()),
|
||||
m_owner(owner)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
NetLogConnection::~NetLogConnection()
|
||||
{
|
||||
if (m_owner)
|
||||
m_owner->onConnectionDestroyed(this);
|
||||
m_owner = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void NetLogConnection::onConnectionClosed()
|
||||
{
|
||||
if (m_owner)
|
||||
m_owner->onConnectionClosed();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void NetLogConnection::onConnectionOpened()
|
||||
{
|
||||
if (m_owner)
|
||||
m_owner->onConnectionOpened();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void NetLogConnection::clearOwner()
|
||||
{
|
||||
m_owner = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void NetLogConnection::onReceive(Archive::ByteStream const &)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
bool NetLogConnection::isNetLogConnection() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// NetLogConnection.h
|
||||
//
|
||||
// Copyright 2002 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_NetLogConnection_H
|
||||
#define INCLUDED_NetLogConnection_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedNetwork/Connection.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class NetLogObserver;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class NetLogConnection: public Connection
|
||||
{
|
||||
public:
|
||||
explicit NetLogConnection(NetLogObserver *owner);
|
||||
virtual ~NetLogConnection();
|
||||
|
||||
virtual void onConnectionClosed();
|
||||
virtual void onConnectionOpened();
|
||||
virtual void onReceive(Archive::ByteStream const &);
|
||||
|
||||
void clearOwner();
|
||||
|
||||
protected:
|
||||
virtual bool isNetLogConnection() const;
|
||||
|
||||
private:
|
||||
NetLogConnection();
|
||||
NetLogConnection(NetLogConnection const &);
|
||||
NetLogConnection &operator=(NetLogConnection const &);
|
||||
|
||||
NetLogObserver *m_owner;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// NetLogObserver.cpp
|
||||
//
|
||||
// Copyright 2002 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedLog/FirstSharedLog.h"
|
||||
#include "sharedLog/NetLogObserver.h"
|
||||
|
||||
#include "sharedFoundation/Clock.h"
|
||||
#include "sharedFoundation/NetworkIdArchive.h"
|
||||
#include "sharedLog/LogManager.h"
|
||||
#include "sharedLog/ConfigSharedLog.h"
|
||||
#include "sharedNetworkMessages/GameNetworkMessage.h"
|
||||
#include "sharedNetworkMessages/LogMessage.h"
|
||||
#include "Archive/ByteStream.h"
|
||||
#include "NetLogConnection.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void NetLogObserver::install()
|
||||
{
|
||||
LogManager::registerObserverType("net", create);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
LogObserver *NetLogObserver::create(std::string const &spec)
|
||||
{
|
||||
// parse spec into address:port
|
||||
size_t pos = spec.find(":");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
std::string address = spec.substr(0, pos);
|
||||
unsigned short port = static_cast<unsigned short>(atoi(spec.c_str()+pos+1));
|
||||
// create a NetLogObserver to forward to the specified address/port
|
||||
return new NetLogObserver(address, port);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
NetLogObserver::NetLogObserver(const std::string &remoteAddress, unsigned short remotePort) :
|
||||
LogObserver(),
|
||||
m_mutex(),
|
||||
m_remoteAddress(remoteAddress),
|
||||
m_remotePort(remotePort),
|
||||
m_connection(0),
|
||||
m_connectionOpen(false),
|
||||
m_connectTime(0),
|
||||
m_logMessageQueue1(new std::vector<LogMessage>),
|
||||
m_logMessageQueue2(new std::vector<LogMessage>)
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
NetLogObserver::~NetLogObserver()
|
||||
{
|
||||
delete m_logMessageQueue1;
|
||||
delete m_logMessageQueue2;
|
||||
|
||||
m_logMessageQueue1 = 0;
|
||||
m_logMessageQueue2 = 0;
|
||||
|
||||
// the observer owns the connection
|
||||
if (m_connection)
|
||||
{
|
||||
m_connection->clearOwner();
|
||||
m_connection->setDisconnectReason("NetLogObserver destroyed");
|
||||
m_connection->disconnect();
|
||||
m_connection = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void NetLogObserver::onConnectionOpened()
|
||||
{
|
||||
m_connectionOpen = true;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void NetLogObserver::onConnectionClosed()
|
||||
{
|
||||
m_connectionOpen = false;
|
||||
if (m_connection)
|
||||
{
|
||||
m_connection->clearOwner();
|
||||
m_connection = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void NetLogObserver::onConnectionDestroyed(NetLogConnection *connection)
|
||||
{
|
||||
if (m_connection == connection)
|
||||
m_connection = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void NetLogObserver::sendLogMessage(LogMessage const &msg) const
|
||||
{
|
||||
if (m_connection)
|
||||
{
|
||||
Archive::ByteStream a;
|
||||
a.clear();
|
||||
msg.pack(a);
|
||||
m_connection->send(a, true);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void NetLogObserver::log(LogMessage const &msg)
|
||||
{
|
||||
static unsigned int logNetQueueSize = static_cast<unsigned int>(ConfigSharedLog::getLogNetQueueSize());
|
||||
if (logNetQueueSize)
|
||||
{
|
||||
m_mutex.enter();
|
||||
if (m_logMessageQueue1->size() < logNetQueueSize)
|
||||
m_logMessageQueue1->push_back(msg);
|
||||
m_mutex.leave();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------
|
||||
|
||||
void NetLogObserver::update()
|
||||
{
|
||||
static unsigned long reconnectTime = static_cast<unsigned long>(ConfigSharedLog::getLogNetReconnectTimeMs());
|
||||
|
||||
if (m_connection && m_connectionOpen)
|
||||
{
|
||||
m_mutex.enter();
|
||||
std::vector<LogMessage> *q = m_logMessageQueue1;
|
||||
m_logMessageQueue1 = m_logMessageQueue2;
|
||||
m_logMessageQueue2 = q;
|
||||
m_mutex.leave();
|
||||
// send any queued up log messages
|
||||
|
||||
for (std::vector<LogMessage>::const_iterator i = m_logMessageQueue2->begin(); i != m_logMessageQueue2->end(); ++i)
|
||||
sendLogMessage(*i);
|
||||
|
||||
m_logMessageQueue2->clear();
|
||||
}
|
||||
else if (Clock::timeMs()-m_connectTime > reconnectTime)
|
||||
connect();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void NetLogObserver::connect()
|
||||
{
|
||||
if (m_connection)
|
||||
{
|
||||
m_connection->clearOwner();
|
||||
m_connection->setDisconnectReason("About to connect again");
|
||||
m_connection->disconnect();
|
||||
m_connection = 0;
|
||||
}
|
||||
m_connectTime = Clock::timeMs();
|
||||
m_connection = new NetLogConnection(this);
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
@@ -0,0 +1,80 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// NetLogObserver.h
|
||||
//
|
||||
// Copyright 2002 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_NetLogObserver_H
|
||||
#define INCLUDED_NetLogObserver_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedLog/LogObserver.h"
|
||||
#include "sharedSynchronization/Mutex.h"
|
||||
#include <string>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class NetLogConnection;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
// A NetLogObserver sends log messages to a another process
|
||||
class NetLogObserver: public LogObserver
|
||||
{
|
||||
public:
|
||||
|
||||
static void install();
|
||||
static LogObserver *create(std::string const &spec);
|
||||
|
||||
NetLogObserver(std::string const &remoteAddress, unsigned short remotePort);
|
||||
virtual ~NetLogObserver();
|
||||
|
||||
virtual void log(LogMessage const &msg);
|
||||
virtual void onConnectionOpened();
|
||||
virtual void onConnectionClosed();
|
||||
virtual void onConnectionDestroyed(NetLogConnection *connection);
|
||||
|
||||
virtual void update();
|
||||
|
||||
std::string const &getRemoteAddress() const;
|
||||
unsigned short getRemotePort() const;
|
||||
|
||||
private:
|
||||
NetLogObserver();
|
||||
NetLogObserver(NetLogObserver const &);
|
||||
NetLogObserver &operator=(NetLogObserver const &);
|
||||
|
||||
void connect();
|
||||
void sendLogMessage(LogMessage const &msg) const;
|
||||
|
||||
Mutex m_mutex;
|
||||
std::string m_remoteAddress;
|
||||
unsigned short m_remotePort;
|
||||
NetLogConnection * m_connection;
|
||||
bool m_connectionOpen;
|
||||
unsigned long m_connectTime;
|
||||
stdvector<LogMessage>::fwd* m_logMessageQueue1;
|
||||
stdvector<LogMessage>::fwd* m_logMessageQueue2;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
inline std::string const &NetLogObserver::getRemoteAddress() const
|
||||
{
|
||||
return m_remoteAddress;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
inline unsigned short NetLogObserver::getRemotePort() const
|
||||
{
|
||||
return m_remotePort;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// SetupSharedLog.cpp
|
||||
//
|
||||
// Copyright 2002-2003 Sony Online Entertainment
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedLog/FirstSharedLog.h"
|
||||
#include "sharedLog/SetupSharedLog.h"
|
||||
|
||||
#include "sharedDebug/InstallTimer.h"
|
||||
#include "sharedFoundation/ExitChain.h"
|
||||
#include "sharedLog/ConfigSharedLog.h"
|
||||
#include "sharedLog/FileLogObserver.h"
|
||||
#include "sharedLog/NetLogObserver.h"
|
||||
#include "sharedLog/LogManager.h"
|
||||
#include "sharedLog/Log.h"
|
||||
#include "sharedLog/TailFileLogObserver.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
namespace SetupSharedLogNamespace
|
||||
{
|
||||
void logReportLog(char const *message);
|
||||
void logReportWarning(char const *message);
|
||||
void logReportFatal(char const *message);
|
||||
|
||||
bool ms_installed;
|
||||
std::string const cms_reportLogChannel("reportLog");
|
||||
std::string const cms_reportWarningChannel("warning");
|
||||
std::string const cms_reportFatalChannel("fatal");
|
||||
}
|
||||
using namespace SetupSharedLogNamespace;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void SetupSharedLogNamespace::logReportLog(char const *message)
|
||||
{
|
||||
LOG(cms_reportLogChannel, ("%s", message));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void SetupSharedLogNamespace::logReportWarning(char const *message)
|
||||
{
|
||||
LOG(cms_reportWarningChannel, ("%s", message));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void SetupSharedLogNamespace::logReportFatal(char const *message)
|
||||
{
|
||||
LOG(cms_reportFatalChannel, ("%s", message));
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void SetupSharedLog::install(std::string const &procId, bool flushOnWrite)
|
||||
{
|
||||
InstallTimer const installTimer("SetupSharedLog::install");
|
||||
|
||||
DEBUG_FATAL (ms_installed, ("SetupSharedLog::install already installed"));
|
||||
ms_installed = true;
|
||||
|
||||
ConfigSharedLog::install();
|
||||
LogManager::install(procId, flushOnWrite);
|
||||
FileLogObserver::install();
|
||||
NetLogObserver::install();
|
||||
TailFileLogObserver::install();
|
||||
|
||||
if (ConfigSharedLog::getLogReportLogs())
|
||||
Report::bindLogCallback(logReportLog);
|
||||
|
||||
if (ConfigSharedLog::getLogReportWarnings())
|
||||
Report::bindWarningCallback(logReportWarning);
|
||||
|
||||
if (ConfigSharedLog::getLogReportFatals())
|
||||
Report::bindFatalCallback(logReportFatal);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void SetupSharedLog::remove()
|
||||
{
|
||||
DEBUG_FATAL (!ms_installed, ("SetupSharedLog::remove not installed"));
|
||||
ms_installed = false;
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// SetupSharedLog.h
|
||||
//
|
||||
// Copyright 2002-2003 Sony Online Entertainment
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_SetupSharedLog_H
|
||||
#define INCLUDED_SetupSharedLog_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class SetupSharedLog
|
||||
{
|
||||
public:
|
||||
|
||||
static void install(std::string const &procId, bool flushOnWrite = true);
|
||||
static void remove();
|
||||
|
||||
private:
|
||||
|
||||
SetupSharedLog(SetupSharedLog const &);
|
||||
SetupSharedLog &operator=(SetupSharedLog const &);
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// StderrLogger.h
|
||||
//
|
||||
// Copyright 2003 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef _StderrLogger_H_
|
||||
#define _StderrLogger_H_
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class StderrLogger
|
||||
{
|
||||
public:
|
||||
static void install();
|
||||
static void remove();
|
||||
|
||||
static void update();
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif // _StderrLogger_H_
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// TailFileLogObserver.cpp
|
||||
//
|
||||
// Copyright 2002 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedLog/FirstSharedLog.h"
|
||||
#include "sharedFoundation/NetworkIdArchive.h"
|
||||
#include "sharedLog/TailFileLogObserver.h"
|
||||
#include "sharedLog/LogManager.h"
|
||||
#include "fileInterface/StdioFile.h"
|
||||
#include "sharedNetworkMessages/LogMessage.h"
|
||||
#include "UnicodeUtils.h"
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
const int LOG_FILESIZE_NEXT = 2000000000; // point at which we roll over to another log file
|
||||
const int DEFAULT_NUM_LINES = 100;
|
||||
|
||||
namespace TailFileLogObserverNamespace
|
||||
{
|
||||
std::vector<TailFileLogObserver *> s_tailFileLogObservers;
|
||||
};
|
||||
|
||||
using namespace TailFileLogObserverNamespace;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void TailFileLogObserver::install()
|
||||
{
|
||||
LogManager::registerObserverType("tailfile", create);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
LogObserver *TailFileLogObserver::create(std::string const &spec)
|
||||
{
|
||||
return new TailFileLogObserver(spec);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
TailFileLogObserver::TailFileLogObserver(std::string const &filename) :
|
||||
LogObserver(),
|
||||
m_filename(filename),
|
||||
m_file(0),
|
||||
m_fileIndex(0),
|
||||
m_numLines(DEFAULT_NUM_LINES),
|
||||
m_textBuffer(0),
|
||||
m_nextTextBufferEntry(0)
|
||||
{
|
||||
int filenameAsNumber = -1;
|
||||
filenameAsNumber = atoi(m_filename.c_str());
|
||||
m_numLines = filenameAsNumber;
|
||||
std::string::size_type const index = filename.find_last_of(',');
|
||||
if(index != std::string::npos)
|
||||
m_filename = filename.substr(index + 1, filename.length());
|
||||
else
|
||||
m_filename.clear();
|
||||
m_textBuffer = new std::vector<std::string>(m_numLines);
|
||||
|
||||
s_tailFileLogObservers.push_back(this);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void TailFileLogObserver::setNumberOfLinesToKeep(int numLines)
|
||||
{
|
||||
m_numLines = numLines;
|
||||
m_textBuffer->clear();
|
||||
m_nextTextBufferEntry = 0;
|
||||
m_textBuffer->reserve(m_numLines);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void TailFileLogObserver::prepareFile()
|
||||
{
|
||||
while (!m_file || m_file->tell() >= LOG_FILESIZE_NEXT)
|
||||
{
|
||||
if (m_file)
|
||||
{
|
||||
++m_fileIndex;
|
||||
delete m_file;
|
||||
m_file = 0;
|
||||
}
|
||||
if (m_fileIndex == 0)
|
||||
m_file = new StdioFile(m_filename.c_str(), "a");
|
||||
else
|
||||
{
|
||||
char buf[512];
|
||||
IGNORE_RETURN( snprintf(buf, 512, "%s-%d", m_filename.c_str(), m_fileIndex+1) );
|
||||
m_file = new StdioFile(buf, "a");
|
||||
}
|
||||
NOT_NULL(m_file);
|
||||
FATAL(!m_file->isOpen(), ("Could not open %s", m_filename.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
TailFileLogObserver::~TailFileLogObserver()
|
||||
{
|
||||
delete m_file;
|
||||
delete m_textBuffer;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void TailFileLogObserver::log(LogMessage const &msg)
|
||||
{
|
||||
std::string & newLogMessage = (*m_textBuffer)[m_nextTextBufferEntry++];
|
||||
|
||||
uint64 timestamp = msg.getTimestamp();
|
||||
std::string const &procId = msg.getProcId();
|
||||
std::string const &channel = msg.getChannel();
|
||||
std::string const &text = msg.getText();
|
||||
std::string uniAttach(Unicode::wideToNarrow(msg.getUnicodeAttach()));
|
||||
char tsbuf[16]; // yyyymmddhhmmss (14)
|
||||
|
||||
newLogMessage.clear();
|
||||
IGNORE_RETURN( sprintf(tsbuf, UINT64_FORMAT_SPECIFIER, timestamp) );
|
||||
newLogMessage.append(tsbuf);
|
||||
newLogMessage.append(":");
|
||||
newLogMessage.append(procId);
|
||||
newLogMessage.append(":");
|
||||
newLogMessage.append(channel);
|
||||
newLogMessage.append(":");
|
||||
newLogMessage.append(text);
|
||||
if(uniAttach.length())
|
||||
{
|
||||
newLogMessage.append(":");
|
||||
newLogMessage.append(uniAttach);
|
||||
}
|
||||
|
||||
if(m_nextTextBufferEntry >= m_numLines)
|
||||
m_nextTextBufferEntry = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void TailFileLogObserver::flush(const char * filename)
|
||||
{
|
||||
if(m_filename.empty())
|
||||
m_filename = filename;
|
||||
prepareFile();
|
||||
NOT_NULL(m_file);
|
||||
|
||||
int i;
|
||||
for(i = m_nextTextBufferEntry; i < m_numLines; ++i)
|
||||
{
|
||||
if(!(*m_textBuffer)[i].empty())
|
||||
{
|
||||
IGNORE_RETURN(m_file->write((*m_textBuffer)[i].length(), (*m_textBuffer)[i].c_str()) );
|
||||
}
|
||||
}
|
||||
for(i = 0; i < m_nextTextBufferEntry; ++i)
|
||||
{
|
||||
if(!(*m_textBuffer)[i].empty())
|
||||
{
|
||||
IGNORE_RETURN(m_file->write((*m_textBuffer)[i].length(), (*m_textBuffer)[i].c_str()) );
|
||||
}
|
||||
}
|
||||
if (m_file)
|
||||
m_file->flush();
|
||||
m_file->close();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void TailFileLogObserver::flushAllTailFileLogObservers(const char * filename)
|
||||
{
|
||||
for(std::vector<TailFileLogObserver *>::iterator i = s_tailFileLogObservers.begin(); i != s_tailFileLogObservers.end(); ++i)
|
||||
{
|
||||
TailFileLogObserver *tflo = *i;
|
||||
if(tflo)
|
||||
{
|
||||
tflo->flush(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// TailFileLogObserver.h
|
||||
//
|
||||
// Copyright 2002 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#ifndef INCLUDED_TailFileLogObserver_H
|
||||
#define INCLUDED_TailFileLogObserver_H
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedLog/LogObserver.h"
|
||||
#include <string>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
class AbstractFile;
|
||||
|
||||
// ======================================================================
|
||||
|
||||
// A TailFileLogObserver saves log messages to a file, but only the last N,
|
||||
// and only when requested (not constantly).
|
||||
class TailFileLogObserver: public LogObserver
|
||||
{
|
||||
public:
|
||||
|
||||
static void install();
|
||||
static LogObserver *create(std::string const &spec);
|
||||
|
||||
TailFileLogObserver(std::string const &filename);
|
||||
virtual ~TailFileLogObserver();
|
||||
|
||||
virtual void log(LogMessage const &msg);
|
||||
virtual void flush(const char * filename);
|
||||
|
||||
virtual void setNumberOfLinesToKeep(int numLines);
|
||||
|
||||
static void flushAllTailFileLogObservers(const char *filename);
|
||||
|
||||
private:
|
||||
TailFileLogObserver(TailFileLogObserver const &);
|
||||
TailFileLogObserver &operator=(TailFileLogObserver const &);
|
||||
|
||||
void prepareFile();
|
||||
|
||||
private:
|
||||
std::string m_filename;
|
||||
AbstractFile *m_file;
|
||||
int m_fileIndex;
|
||||
|
||||
int m_numLines;
|
||||
stdvector<std::string>::fwd *m_textBuffer;
|
||||
int m_nextTextBufferEntry;
|
||||
};
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// StderrLogger.cpp
|
||||
//
|
||||
// Copyright 2003 Sony Online Entertainment
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "sharedLog/FirstSharedLog.h"
|
||||
#include "sharedLog/StderrLogger.h"
|
||||
|
||||
// ======================================================================
|
||||
|
||||
// Unimplemented for win32
|
||||
|
||||
// ======================================================================
|
||||
|
||||
void StderrLogger::install()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void StderrLogger::remove()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void StderrLogger::update()
|
||||
{
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
Reference in New Issue
Block a user