RE: [reSIProcate] external logger
Sounds like there is some interest, attached are the files I modified.
These files are intended to be a starting point. Since I am a newbie I am
sure they may be a better/cleaner way of adding this.
Thanks,
-Justin
-----Original Message-----
From: Thomas Gal [mailto:ThomasGal@xxxxxxxxxxxx]
Sent: Thursday, January 20, 2005 10:08 AM
To: 'Justin Matthews'; resiprocate-devel@xxxxxxxxxxxxxxxxxxx
Subject: RE: [reSIProcate] external logger
I think that's great as no doubt everyone will likely be integrating this
into larger schemes and quite often have their own logging code.
-Tom
thomasgal@xxxxxxxxxxxx
> -----Original Message-----
> From: resiprocate-devel-bounces@xxxxxxxxxxxxxxxxxxx
> [mailto:resiprocate-devel-bounces@xxxxxxxxxxxxxxxxxxx] On
> Behalf Of Justin Matthews
> Sent: Wednesday, January 19, 2005 7:15 PM
> To: resiprocate-devel@xxxxxxxxxxxxxxxxxxx
> Subject: [reSIProcate] external logger
>
> Hello,
>
> The application that I am working on that uses resip has its
> own logging functionality. The logger in our app ("myapp")
> has some enhanced features similar to those found in log4j
> (logging configurable using a config file, different outputs
> including sockets, syslog, rolling file appenders...).
> What I would like is for myapp to be in total control of the
> logging. I have modified resip by adding a new
> Log::initialize() function that takes a pointer to a function
> as the only argument and modified Logger.hxx to forward all
> log requests to this function if the external function
> pointer "type" logger is enabled. Is this, or a similar
> solution, something that would be considered for addition
> into resip? Does anyone have any other suggestions for
> adding this functionality?
>
> Thanks,
>
> Justin
>
> _______________________________________________
> resiprocate-devel mailing list
> resiprocate-devel@xxxxxxxxxxxxxxxxxxx
> https://list.sipfoundry.org/mailman/listinfo/resiprocate-devel
>
#if !defined(RESIP_LOGGER_HXX)
#define RESIP_LOGGER_HXX
#include <iosfwd>
#include <sstream>
#include "resiprocate/os/Log.hxx"
#include "resiprocate/os/Lock.hxx"
#ifdef WIN32
#include "resiprocate/os/DataStream.hxx"
#include "resiprocate/os/Data.hxx"
#include <windows.h>
#endif
/**
Defines a set of logging macros, one for each level of logging.
Example:
#include Logger.hxx
#define RESIPROCATE_SUBSYSTEM resip::Subsystem::SIP
...
DebugLog(<< "hi there " << mix << 4 << types); // note leading << and no
endl
*/
#define DELIM
// unconditionally output to cerr -- easily change back and forth
#define CerrLog(args_) \
do \
{ \
if( resip::Log::_type == resip::Log::externalFunc ) \
{ \
std::ostringstream oss; \
oss args_; \
resip::Log::externalLoggerFunction_(resip::Log::Err,"not
implemented",__FILE__,__LINE__,oss.str().c_str()); \
} \
else \
{ \
resip::Log::tags(resip::Log::StdErr, RESIPROCATE_SUBSYSTEM, \
__FILE__, __LINE__, std::cerr) << ' ' << '|' << ' ' \
args_ << std::endl; \
} \
} while(0)
#define StackLog(args_)
\
GenericLog(RESIPROCATE_SUBSYSTEM, resip::Log::Stack, args_)
#define DebugLog(args_) \
GenericLog(RESIPROCATE_SUBSYSTEM, resip::Log::Debug, args_)
#define InfoLog(args_) \
GenericLog(RESIPROCATE_SUBSYSTEM, resip::Log::Info, args_)
#define WarningLog(args_) \
GenericLog(RESIPROCATE_SUBSYSTEM, resip::Log::Warning, args_)
#define ErrLog(args_) \
GenericLog(RESIPROCATE_SUBSYSTEM, resip::Log::Err, args_)
#define CritLog(args_) \
GenericLog(RESIPROCATE_SUBSYSTEM, resip::Log::Crit, args_)
#define CHECK_RECURSIVE_LOG
class AssertOnRecursiveLock
{
public:
AssertOnRecursiveLock();
void set();
~AssertOnRecursiveLock();
private:
// no object semantics
AssertOnRecursiveLock(const AssertOnRecursiveLock &);
const AssertOnRecursiveLock & operator=(const AssertOnRecursiveLock &);
};
// do/while allows a {} block in an expression
#define GenericLog(system_, level_, args_)
\
do
\
{
\
if( resip::Log::_type == resip::Log::externalFunc )
\
{
\
std::ostringstream oss;
\
oss args_;
\
resip::Log::externalLoggerFunction_(level_,"not
implemented",__FILE__,__LINE__,oss.str().c_str()); \
}
\
else
\
{
\
const resip::Log::ThreadSetting* setting = resip::Log::getThreadSetting();
\
if (setting)
\
{
\
if (level_ <= setting->level)
\
{
\
AssertOnRecursiveLock check;
\
resip::Lock lock(resip::Log::_mutex);
\
check.set();
\
resip::Log::tags(level_, system_, __FILE__, __LINE__,
\
resip::GenericLogImpl::Instance()) << " | "
\
args_ << std::endl;
\
if (resip::Log::_type == resip::Log::VSDebugWindow)
\
{
\
resip::GenericLogImpl::OutputToWin32DebugWindow();
\
}
\
}
\
}
\
else
\
{
\
if (resip::GenericLogImpl::isLogging(level_))
\
{
\
AssertOnRecursiveLock check;
\
resip::Lock lock(resip::Log::_mutex);
\
check.set();
\
if (resip::GenericLogImpl::isLogging(level_))
\
{
\
resip::Log::tags(level_, system_, __FILE__, __LINE__,
\
resip::GenericLogImpl::Instance()) << " | "
\
args_ << std::endl;
\
if (resip::Log::_type == resip::Log::VSDebugWindow)
\
{
\
resip::GenericLogImpl::OutputToWin32DebugWindow();
\
}
\
}
\
}
\
}
\
}
\
} while (0)
#ifdef NO_DEBUG
// Suppress debug logging at compile time
#undef DebugLog
#define DebugLog(args_)
#undef StackLog(args_)
#define StackLog(args_)
#endif
namespace resip
{
class GenericLogImpl : public Log
{
public:
static std::ostream& Instance();
static bool isLogging(Log::Level level) ;
static unsigned int MaxLineCount;
static void OutputToWin32DebugWindow(); //xkd-2004-11-8
private:
static std::ostream* mLogger;
static unsigned int mLineCount;
#ifdef WIN32
static Data *mWin32DebugData;
static DataStream *mWin32DebugStream;
#endif
};
}
#endif
/* ====================================================================
* The Vovida Software License, Version 1.0
*
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
* and "Vovida Open Communication Application Library (VOCAL)" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact vocal@xxxxxxxxxxx
*
* 4. Products derived from this software may not be called "VOCAL", nor
* may "VOCAL" appear in their name, without prior written
* permission of Vovida Networks, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* ====================================================================
*
* This software consists of voluntary contributions made by Vovida
* Networks, Inc. and many individuals on behalf of Vovida Networks,
* Inc. For more information on Vovida Networks, Inc., please see
* <http://www.vovida.org/>.
*
*/
#include "resiprocate/os/Socket.hxx"
#include <cassert>
#include <iostream>
#include <stdio.h>
#include "resiprocate/os/Data.hxx"
#ifndef WIN32
#include <sys/time.h>
#endif
#include <sys/types.h>
#include <time.h>
#include "resiprocate/os/Log.hxx"
#include "resiprocate/os/Lock.hxx"
#include "resiprocate/os/WinLeakCheck.hxx"
#define DELIM " | "
using namespace resip;
using namespace std;
Log::Level Log::_level = Log::Debug;
Log::Type Log::_type = Cout;
ExternalLoggerFunction Log::externalLoggerFunction_=NULL;
Data Log::_appName;
Data Log::_hostname;
Data Log::_logFileName;
#ifdef WIN32
int Log::_pid=0;
#else
pid_t Log::_pid=0;
#endif
volatile short Log::touchCount = 0;
#ifndef WIN32
pthread_key_t Log::_levelKey;
HashMap<pthread_t, std::pair<Log::ThreadSetting, bool> > Log::_threadToLevel;
HashMap<int, std::set<pthread_t> > Log::_serviceToThreads;
#endif
HashMap<int, Log::Level> Log::_serviceToLevel;
const char
Log::_descriptions[][32] = {"NONE", "EMERG", "ALERT", "CRIT", "ERR", "WARNING",
"NOTICE", "INFO", "DEBUG", "STACK", "CERR", ""};
Mutex Log::_mutex;
extern "C"
{
void freeThreadSetting(void* setting)
{
delete static_cast<Log::ThreadSetting*>(setting);
}
}
void
Log::initialize(const char* typed, const char* leveld, const char* appName,
const char *logFileName)
{
Log::initialize(Data(typed), Data(leveld), Data(appName), logFileName);
}
void
Log::initialize(const Data& typed, const Data& leveld, const Data& appName,
const char *logFileName)
{
Type type = Log::Cout;
if (isEqualNoCase(typed, "cout")) type = Log::Cout;
else if (isEqualNoCase(typed, "cerr")) type = Log::Cerr;
else if (isEqualNoCase(typed, "file")) type = Log::File;
else type = Log::Syslog;
Level level = Log::Info;
level = toLevel(leveld);
Log::initialize(type, level, appName, logFileName);
}
void
Log::initialize(ExternalLoggerFunction func)
{
externalLoggerFunction_ = func;
_type = externalFunc;
}
void
Log::initialize(Type type, Level level, const Data& appName, const char *
logFileName)
{
string copy(appName.c_str());
_type = type;
_level = level;
if (logFileName)
{
_logFileName = logFileName;
}
string::size_type pos = copy.find_last_of('/');
if ( pos == string::npos || pos == copy.size())
{
_appName = appName;
}
else
{
_appName = Data(copy.substr(pos+1).c_str());
}
char buffer[1024];
gethostname(buffer, sizeof(buffer));
_hostname = buffer;
#ifdef WIN32
_pid = (int)GetCurrentProcess();
#else
_pid = getpid();
#endif
#ifndef WIN32
pthread_key_create(&Log::_levelKey, freeThreadSetting);
#endif
}
void
Log::setLevel(Level level)
{
Lock lock(_mutex);
_level = level;
}
Data
Log::toString(Level l)
{
return Data("LOG_") + _descriptions[l+1];
}
Log::Level
Log::toLevel(const Data& l)
{
string pri = l.c_str();
if (pri.find("LOG_", 0) == 0)
{
pri.erase(0, 4);
}
int i=0;
while (string(_descriptions[i]).size())
{
if (pri == string(_descriptions[i]))
{
return Level(i-1);
}
i++;
}
cerr << "Choosing Debug level since string was not understood: " << l <<
endl;
return Log::Debug;
}
Log::Type
Log::toType(const Data& arg)
{
if (arg == "cout" || arg == "COUT")
{
return Log::Cout;
}
else if (arg == "cerr" || arg == "CERR")
{
return Log::Cerr;
}
else if (arg == "file" || arg == "FILE")
{
return Log::File;
}
else
{
return Log::Syslog;
}
}
ostream&
Log::tags(Log::Level level,
const Subsystem& subsystem,
const char* pfile,
int line,
ostream& strm)
{
#if defined( __APPLE__ )
strm << _descriptions[level+1] << DELIM
<< time(0) << DELIM
<< _appName << DELIM
<< subsystem << DELIM
<< pfile << ":" << line;
#else
char buffer[256];
Data tstamp(Data::Borrow, buffer, sizeof(buffer));
#if defined( WIN32 )
const char* file = pfile + strlen(pfile);
while (file != pfile &&
*file != '\\')
{
--file;
}
if (file != pfile)
{
++file;
}
strm << _descriptions[level+1] << DELIM
<< timestamp(tstamp) << DELIM
<< _appName << DELIM
<< subsystem << DELIM
<< GetCurrentThreadId() << DELIM
<< file << ":" << line;
#else
strm << _descriptions[level+1] << DELIM
<< timestamp() << DELIM
<< _hostname << DELIM
<< _appName << DELIM
<< subsystem << DELIM
<< _pid << DELIM
<< pthread_self() << DELIM
<< pfile << ":" << line;
#endif // #if defined( WIN32 )
#endif // #if defined( __APPLE__ )
return strm;
}
Data
Log::timestamp()
{
char buffer[256];
Data result(Data::Borrow, buffer, sizeof(buffer));
return timestamp(result);
}
Data&
Log::timestamp(Data& res)
{
char* datebuf = const_cast<char*>(res.data());
const unsigned int datebufSize = 256;
res.clear();
#ifdef WIN32
int result = 1;
SYSTEMTIME systemTime;
struct { int tv_sec; int tv_usec; } tv = {0,0};
time((time_t *)(&tv.tv_sec));
GetLocalTime(&systemTime);
tv.tv_usec = systemTime.wMilliseconds * 1000;
#else
struct timeval tv;
int result = gettimeofday (&tv, NULL);
#endif
if (result == -1)
{
/* If we can't get the time of day, don't print a timestamp.
Under Unix, this will never happen: gettimeofday can fail only
if the timezone is invalid which it can't be, since it is
uninitialized]or if tv or tz are invalid pointers. */
datebuf [0] = 0;
}
else
{
/* The tv_sec field represents the number of seconds passed since
the Epoch, which is exactly the argument gettimeofday needs. */
const time_t timeInSeconds = (time_t) tv.tv_sec;
strftime (datebuf,
datebufSize,
"%Y%m%d-%H%M%S", /* guaranteed to fit in 256 chars,
hence don't check return code */
localtime (&timeInSeconds));
}
char msbuf[5];
/* Dividing (without remainder) by 1000 rounds the microseconds
measure to the nearest millisecond. */
sprintf(msbuf, ".%3.3ld", long(tv.tv_usec / 1000));
int datebufCharsRemaining = datebufSize - strlen (datebuf);
strncat (datebuf, msbuf, datebufCharsRemaining - 1);
datebuf[datebufSize - 1] = '\0'; /* Just in case strncat truncated msbuf,
thereby leaving its last character at
the end, instead of a null terminator */
// ugh, resize the Data
res.at(strlen(datebuf)-1);
return res;
}
Log::Level
Log::getServiceLevel(int service)
{
Lock lock(_mutex);
#ifdef WIN32
assert(0);
return Bogus;
#else
HashMap<int, Level>::iterator res = Log::_serviceToLevel.find(service);
if(res == Log::_serviceToLevel.end())
{
//!dcm! -- should perhaps throw an exception here, instead of setting a
//default level of LOG_ERROR, but nobody uses this yet
Log::_serviceToLevel[service] = Err;
return Err;
}
return res->second;
#endif
}
const Log::ThreadSetting*
Log::getThreadSetting()
{
#ifdef WIN32
return 0;
#else
ThreadSetting* setting =
static_cast<ThreadSetting*>(pthread_getspecific(Log::_levelKey));
if (setting == 0)
{
return 0;
}
if (Log::touchCount > 0)
{
Lock lock(_mutex);
pthread_t thread = pthread_self();
HashMap<pthread_t, pair<ThreadSetting, bool> >::iterator res =
Log::_threadToLevel.find(thread);
assert(res != Log::_threadToLevel.end());
if (res->second.second)
{
setting->level = res->second.first.level;
res->second.second = false;
touchCount--;
// cerr << "**Log::getThreadSetting:touchCount: " << Log::touchCount <<
"**" << endl;
//cerr << "touchcount decremented" << endl;
}
}
return setting;
#endif
}
void
Log::setThreadSetting(int serv)
{
Log::setThreadSetting(ThreadSetting(serv, getServiceLevel(serv)));
}
void
Log::setThreadSetting(int serv, Log::Level l)
{
Log::setThreadSetting(ThreadSetting(serv, l));
}
void
Log::setThreadSetting(ThreadSetting info)
{
#ifdef WIN32
assert(0);
#else
//cerr << "Log::setThreadSetting: " << "service: " << info.service << "
level " << toString(info.level) << " for " << pthread_self() << endl;
pthread_t thread = pthread_self();
pthread_setspecific(_levelKey, (void *) new ThreadSetting(info));
Lock lock(_mutex);
if (Log::_threadToLevel.find(thread) != Log::_threadToLevel.end())
{
if (Log::_threadToLevel[thread].second == true)
{
touchCount--;
}
}
Log::_threadToLevel[thread].first = info;
Log::_threadToLevel[thread].second = false;
Log::_serviceToThreads[info.service].insert(thread);
#endif
}
void
Log::setServiceLevel(int service, Level l)
{
Lock lock(_mutex);
Log::_serviceToLevel[service] = l;
#ifdef WIN32
assert(0);
#else
set<pthread_t>& threads = Log::_serviceToThreads[service];
for (set<pthread_t>::iterator i = threads.begin(); i != threads.end(); i++)
{
Log::_threadToLevel[*i].first.level = l;
Log::_threadToLevel[*i].second = true;
}
Log::touchCount += threads.size();
#endif
// cerr << "**Log::setServiceLevel:touchCount: " << Log::touchCount << "**"
<< endl;
}
/* ====================================================================
* The Vovida Software License, Version 1.0
*
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
* and "Vovida Open Communication Application Library (VOCAL)" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact vocal@xxxxxxxxxxx
*
* 4. Products derived from this software may not be called "VOCAL", nor
* may "VOCAL" appear in their name, without prior written
* permission of Vovida Networks, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* ====================================================================
*
* This software consists of voluntary contributions made by Vovida
* Networks, Inc. and many individuals on behalf of Vovida Networks,
* Inc. For more information on Vovida Networks, Inc., please see
* <http://www.vovida.org/>.
*
*/
#if !defined(RESIP_LOG_HXX)
#define RESIP_LOG_HXX
#include "resiprocate/os/Data.hxx"
#ifndef WIN32
#include <syslog.h>
#include <unistd.h>
#include <pthread.h>
#endif
#include <set>
#include "resiprocate/os/Subsystem.hxx"
#include "resiprocate/os/Mutex.hxx"
#include "resiprocate/os/HashMap.hxx"
#include <iostream>
/** The external logging function pointer is used with a corresponding call to
Log::initialize.
* This function is intended to be supplied by the user of resip to handle all
logging events and
* bypass the internal logging provided by the resip library.
* @author justin.matthews@xxxxxxx
* @revision 1/19/2005
*/
typedef void (*ExternalLoggerFunction)(int level, const char *subsystem, const
char *file, int line, const char *message);
namespace resip
{
class Log
{
public:
typedef enum
{
Cout = 0,
Syslog,
File,
Cerr,
VSDebugWindow, // Use only for Visual Studio Debug Window logging -
WIN32 must be defined
externalFunc,
} Type;
typedef enum
{
None = -1,
#ifdef WIN32
Crit = 2,
Err = 3,
Warning = 4,
Info = 6,
Debug = 7,
#else
Crit = LOG_CRIT,
// #ifdef ERR // ncurses defines a macro called ERR
// SIP2_ERR = LOG_ERR,
// #else
// ERR = LOG_ERR,
// #endif
Err,
Warning = LOG_WARNING,
Info = LOG_INFO,
Debug = LOG_DEBUG,
#endif
Stack = 8,
StdErr = 9,
Bogus = 666
} Level;
class ThreadSetting
{
public:
ThreadSetting()
: service(-1),
level(Err)
{}
ThreadSetting(int serv, Level l)
: service(serv),
level(l)
{}
ThreadSetting(const ThreadSetting& rhs)
: service(rhs.service),
level(rhs.level)
{}
int service;
Level level;
};
/// Return the loglevel, hostname, appname, pid, tid, subsystem
static std::ostream& tags(Log::Level level,
const Subsystem& subsystem,
const char* file,
int line,
std::ostream& strm);
static Data& timestamp(Data& result);
static Data timestamp();
static void initialize(Type type,
Level level,
const Data& appName,
const char * logFileName = 0);
static void initialize(const Data& type,
const Data& level,
const Data& appName,
const char * logFileName = 0);
static void initialize(const char* type,
const char* level,
const char* appName,
const char * logFileName = 0);
/** Add this init to allow the user of this library to
* provide there own logging service.
* @author justin.matthews@xxxxxxx
* @revision 1/19/2005
*/
static void initialize(ExternalLoggerFunction);
static void setLevel(Level level);
static Level level() { return _level; }
static Level toLevel(const Data& l);
static Type toType(const Data& t);
static Data toString(Level l);
static Mutex _mutex;
static void setServiceLevel(int service, Level l);
static Level getServiceLevel(int service);
static const ThreadSetting* getThreadSetting();
static void setThreadSetting(ThreadSetting info);
static void setThreadSetting(int serv, Level l);
static void setThreadSetting(int serv);
static volatile short touchCount;
static Type _type;
static ExternalLoggerFunction externalLoggerFunction_;
protected:
static Level _level;
static Data _appName;
static Data _hostname;
static Data _logFileName;
#ifndef WIN32
static pid_t _pid;
#else
static int _pid;
#endif
static const char _descriptions[][32];
static HashMap<int, Level> _serviceToLevel;
#ifndef WIN32
static HashMap<pthread_t, std::pair<ThreadSetting, bool> > _threadToLevel;
static HashMap<int, std::set<pthread_t> > _serviceToThreads;
static pthread_key_t _levelKey;
#endif
};
}
#endif
/* ====================================================================
* The Vovida Software License, Version 1.0
*
* Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The names "VOCAL", "Vovida Open Communication Application Library",
* and "Vovida Open Communication Application Library (VOCAL)" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact vocal@xxxxxxxxxxx
*
* 4. Products derived from this software may not be called "VOCAL", nor
* may "VOCAL" appear in their name, without prior written
* permission of Vovida Networks, Inc.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
* NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
* IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
* ====================================================================
*
* This software consists of voluntary contributions made by Vovida
* Networks, Inc. and many individuals on behalf of Vovida Networks,
* Inc. For more information on Vovida Networks, Inc., please see
* <http://www.vovida.org/>.
*
*/