Click here to Skip to main content
15,895,256 members
Articles / Programming Languages / C++

SS_Log: Fast program logging and tracing class

Rate me:
Please Sign up or sign in to vote.
4.84/5 (32 votes)
24 Apr 200321 min read 427.3K   4.1K   125  
Easily trace and log program flow. Allows multiple filters, multiple destinations (file, nt event log, etc), and it's fast!
// ----------------------------------------------------------------------- //
///
/// @file       SS_Log.h
/// @author     Steve Schaneville
/// @date       23 Oct 2001, 16:23
/// @brief      Header file for the SS_Log class.
///
/// This is the only file you need to include in your projects to
/// use the SS_Log features.  All macros, the SS_Log class, and any
/// other definitions needed are either in this file or included
/// by this file.
///
/// Copyright (c) 2001 - 2003\n
/// z_web_master@yahoo.com\n
/// http://schaneville.webhop.net/SS_Utils
/// Version 3.02
///
// ----------------------------------------------------------------------- //
#ifndef __SS_Log__
#define __SS_Log__

// ------------------[       Pre-Include Defines       ]------------------ //
// ------------------[          Include Files          ]------------------ //
#include <wtypes.h>
#include <assert.h>
#include <tchar.h>

#include "SS_Log_Defines.h"

// ------------------[      Macros/Constants/Types     ]------------------ //

/// For internal use only.  The CREATION_STATUSes are used to keep track of
/// whether or not we tried to start the SS_Log_Server process for receiving
/// messages, and what the result of the creation attempt was.
typedef enum SSLogCreationStatus
{
    SSLOG_CS_CREATE_NOT_YET_ATTEMPTED,  ///< SS_Log_Server.exe has not been started.
    SSLOG_CS_CREATE_SUCCEEDED,          ///< SS_Log_Server.exe was successfully started.
    SSLOG_CS_CREATE_FAILED,             ///< Startup of SS_Log_Server.exe failed.
    SSLOG_CS_COUNT // THIS MUST BE THE LAST ITEM

} CREATION_STATUS;

// ------------------[       Forward Declarations      ]------------------ //

class SS_Log;
class SSLogEnterFunction;

// ------------------[         Global Variables        ]------------------ //
// ------------------[         Global Functions        ]------------------ //
// ------------------[             Classes             ]------------------ //

// ----------------------------------------------------------------------- //
/// @class		SSLogEnterFunction
/// @author		Steve Schaneville
/// @brief		Helper class used for tracking when a function was entered
///             and exited.
///
/// The idea behind this class is simple: Create an instance and send
/// a logged message in the constructor.  Then, send another logged message
/// in the destructor.  This way, the user can place a stack instance at
/// the beginning of any function and the log will tell us when the function
/// was entered and exited.
///
/// @note It is not intended for the user to use this class directly.
/// Instead, use the LogEnterFunction and LocalLogEnterFunction macros.
// ----------------------------------------------------------------------- //
class SSLogEnterFunction
{
public:

    SSLogEnterFunction(TCHAR* szFile, int nLine, SS_Log* pLog, LPCTSTR szFunctionName);
    virtual ~SSLogEnterFunction();

    LPTSTR m_szFunctionName;
    SS_Log* m_pLog;
    INT m_nLocalID;
    INT m_nLineNumber;
    LPTSTR m_szFilename;
    static INT m_nIDCount;
};


// ----------------------------------------------------------------------- //
/// @class		SS_Log
/// @author		Steve Schaneville
/// @brief		This class that helps us keep track of our logging parameters
///             and handles sending messages to the SS_Log_Server process,
///             including startup and shutdown messages.
///
///
// ----------------------------------------------------------------------- //
class SS_Log
{
public:

    /// @{ @name Construction, Destruction, Assignment, Copy, Initialization
    SS_Log                                  (LPCTSTR szServerName);
    SS_Log                                  (LPCTSTR szServerName,
                                             LPCTSTR szRegKey,
                                             LPCTSTR szDestinationName = SSLOG_DEFAULT_DESTINATION_NAME,
                                             DWORD dwOutputSizeLimitKB = SSLOG_MAX_LOG_SIZE_DEFAULT,
                                             BOOL bUseServer = TRUE);
    ~SS_Log                                 ();

	SS_Log							        (SS_Log& rhs);

	SS_Log&			    operator =		    (SS_Log& rhs);

protected:

    VOID			    InitObject		    ();
    /// @}

public:

    /// @{ @name Flag Manipulation
    const DWORD         DefaultFlags		() const;
    const DWORD         DefaultFlags        (DWORD dwFlags);
    const DWORD         GetFlags			();
    const DWORD         SetFlags			(const DWORD nType);
    const DWORD         AddFlags			(const DWORD nType);
    const DWORD         RemoveFlags			(const DWORD nType);
    BOOL                SetRegistryFilters  (DWORD dwRegFilters);
    DWORD               GetRegistryFilters  ();
    /// @}

    /// @{ @name Error Handling
    INT					GetLastError		() const;
    VOID				SetLastError        (INT nLastError);
    BOOL				Succeeded			();
    /// @}

    /// @{ @name Process Instance Accessors
    HINSTANCE           InstanceHandle      ();
    VOID                InstanceHandle      (HINSTANCE hInst);
    /// @}

    VOID				UseServer			(BOOL bUseServer);
    BOOL				UseServer			();

    /// @{ @name Message and Log Manipulation
    INT                 WriteLog            (MSGTYPE nType, TCHAR* szFile,
                                             int nLine, DWORD dwFilter,
                                             const TCHAR* pMsg, va_list* args);
    INT                 WriteLogID          (TCHAR* szFile, int nLine,
                                             DWORD dwFilter, UINT nResourceID,
                                             va_list* args);
    INT                 EraseLog            ();
	INT 				SetDestinationName	(LPCTSTR szName);
    INT                 LimitOutputSize     (const DWORD dwSizeLimit);
	INT					SetRegistryKey		(LPCTSTR szRegKey);
    /// @}

protected:

    /// @{ @name Internal Accessors
    HANDLE				FileHandle			();
    VOID                FileHandle			(const HANDLE hFileHandle);
    const CREATION_STATUS CreateServerStatus () const;
    VOID                CreateServerStatus  (const CREATION_STATUS nStatus);
    LPCTSTR             ServerName          () const;
    VOID                ServerName          (LPCTSTR szServerName);
    LPCTSTR             DestinationName     () const;
    VOID                DestinationName     (LPCTSTR szDestinationName);
    LPCTSTR             RegistryKey         () const;
    VOID                RegistryKey         (LPCTSTR szRegistryKey);
    INT					LogCount			() const;
    VOID				LogCount			(INT nLogCount);
    VOID                LoggingDisabled     (BOOL bLoggingDisabled);
    BOOL                LoggingDisabled     ();
    const BOOL          ConnectionAdded		() const;
    VOID                ConnectionAdded		(const BOOL bConnectionAdded);
    DWORD				MaxFileSizeKb		();
    VOID				MaxFileSizeKb		(DWORD dwMaxFileSizeKb);
    /// @}

    /// @{ @name Internal Utilities
    BOOL                WriteToServer       (LPCSTR szMessageA);
    BOOL                OpenLogServer       ();
    INT                 WriteToFile         (LPCSTR szBufferA);
    INT                 SendSSLogMessage    (MSGTYPE nType, LPCTSTR szMessage);
    INT                 AddConnection       ();
    INT                 ReleaseConnection   ();
    BOOL                ReadRegDefaultSettings();
    VOID				SetFlagsInternal    (LPDWORD pdwFilter);
    /// @}

private:

    DWORD               m_dwFlags;			// the filter used when not otherwise specified
    LPTSTR              m_szServerName;     // the name of the server to write to
    LPTSTR              m_szDestinationName;     // the name of the server to write to
    LPTSTR              m_szRegistryKey;     // the name of the server to write to
    CRITICAL_SECTION    m_cs;           // so we can avoid threading issues
    CREATION_STATUS 	m_nCreateServerStatus;  // don't try to create log server every time if it fails first time
    HINSTANCE           m_hInstance;        // application instance
    BOOL                m_bConnectionAdded;
	INT					m_nLastError;
	BOOL				m_bUseServer;
	HANDLE				m_hFile;
	INT					m_nLogCount;
	DWORD				m_dwMaxFileSizeKb;
    BOOL                m_bLoggingDisabled;

public:

    /// @{ @name Deprecated Functions
    /// The following functions have been DEPRECATED.  Please don't use them
	/// any more, as they may not be supported in the future.

    VOID	Filename		(LPCTSTR szName)	{ SetDestinationName(szName); } ///< @deprecated Maps to SetDestinationName
	VOID	WindowName		(LPCTSTR szName)	{ SetDestinationName(szName); } ///< @deprecated Maps to SetDestinationName
	VOID	Filter			(DWORD dwFlags)		{ SetFlags(dwFlags); }          ///< @deprecated Maps to SetFlags
	VOID	AddFilters		(DWORD dwFlags)		{ AddFlags(dwFlags); }          ///< @deprecated Maps to AddFlags
	VOID	RemoveFilters	(DWORD dwFlags)		{ RemoveFlags(dwFlags); }       ///< @deprecated Maps to RemoveFlags
	DWORD	Filter			()					{ return GetFlags(); }          ///< @deprecated Maps to GetFlags

	/// @}
};


// ----------------------------------------------------------------------- //
//  SS_Log Inline Functions
// ----------------------------------------------------------------------- //

/// Returns the current set of flags that will be passed with all messages
/// by default.
inline const DWORD SS_Log::DefaultFlags() const
{ return m_dwFlags; }

/// Sets the list of flags that will be passed with all messages
/// by default.
inline const DWORD SS_Log::DefaultFlags(DWORD dwFlags)
{ DWORD dwOldFlags = m_dwFlags; SetFlagsInternal(&dwFlags); m_dwFlags = dwFlags; return dwOldFlags; }

/// Returns the current set of flags that will be passed with all messages
/// by default.  Identical to the DefaultFlags function.
inline const DWORD SS_Log::GetFlags ()
{ return DefaultFlags(); }

/// Sets the list of flags that will be passed with all messages
/// by default.  Identical to the DefaultFlags function.
inline const DWORD SS_Log::SetFlags (const DWORD nType)
{ return DefaultFlags(nType); }

/// Adds the flags specified in nType to the current list of flags that will
/// be passed with all messages by default.
inline const DWORD SS_Log::AddFlags (const DWORD nType)
{ DWORD dwOld = DefaultFlags(); DefaultFlags(DefaultFlags() | nType); return dwOld; }

/// Removes the flags specified in nType to the current list of flags that
/// will be passed with all messages by default.
inline const DWORD SS_Log::RemoveFlags (const DWORD nType)
{ DWORD dwOld = DefaultFlags(); m_dwFlags = DefaultFlags() & ~nType; return dwOld; }

/// Returns a null-terminated string containing the name of the server we
/// are currently sending our messages to.
inline LPCTSTR SS_Log::ServerName() const
{ return m_szServerName; }

/// Sets the name of the server we are going to send our messages to.
inline VOID SS_Log::ServerName(LPCTSTR szServerName)
{ ASSERT(szServerName); _tcscpy(m_szServerName, szServerName); }

/// Returns a null-terminated string containing the current destination name.
/// See SS_Log::DestinationName(LPCTSTR szDestinationName) for more details.
inline LPCTSTR SS_Log::DestinationName() const
{ return m_szDestinationName; }

/// Sets the name of the log destination.  The DestinationName affects each
/// log destination type differently.  Current destination types are as
/// follows:
///
/// -# LOGTYPE_LOGTOFILE (file) - sets the filename of the log file to be
///      written out to disk.
/// -# LOGTYPE_LOGTOWINDOW (window) - no affect.
/// -# LOGTYPE_LOGTONTEVENTLOG (NT Event Log) - sets the text that will appear
///      in the "source" column in the Windows Event Viewer.
inline VOID SS_Log::DestinationName(LPCTSTR szDestinationName)
{ ASSERT(szDestinationName); _tcscpy(m_szDestinationName, szDestinationName); }

/// Returns a null-terminated string containing the current registry key that
/// was passed in by the user.
/// See SS_Log::SetRegistryKey() for more details.
inline LPCTSTR SS_Log::RegistryKey() const
{ return m_szRegistryKey; }

/// Internal accessor function to set the registr key passed in by the
/// user to the SS_Log::SetRegistryKey() function.
inline VOID SS_Log::RegistryKey(LPCTSTR szRegistryKey)
{ ASSERT(szRegistryKey); _tcscpy(m_szRegistryKey, szRegistryKey); }

/// Returns the last error encountered by a logging operation.  See SSLogError
/// for details.
inline INT SS_Log::GetLastError() const
{ return m_nLastError; }

/// Sets the last error encountered by a logging operation.  See SSLogError
/// for details.
inline VOID SS_Log::SetLastError(INT nLastError)
{ m_nLastError = nLastError; }

/// Returns the current log ID that will be written to file if we are not
/// using the server.
inline INT SS_Log::LogCount() const
{ return m_nLogCount; }

/// Sets the current log ID that will be written to file if we are not
/// using the server.
inline VOID SS_Log::LogCount(INT nLogCount)
{ m_nLogCount = nLogCount; }

/// Specifies whether or not we should use the server to log messages.  This
/// has a serious impact on performance, as using the server is many times
/// faster than the alternative to writing straight to a file (which is what
/// happens if we specify not to use the server).  Note also that by not
/// using the server, the user eliminates the possibility to use some of the
/// additional destinations (NT Event Log, Window, and any other future
/// implementations).
inline VOID SS_Log::UseServer(BOOL bUseServer)
{ m_bUseServer = bUseServer; }

/// Return TRUE if we are currently using the server, or FALSE otherwise.
inline BOOL SS_Log::UseServer()
{ return m_bUseServer; }

/// Returns the file handle that is being used to write our log file.  This
/// handle will only be used if we are not using the server (See UseServer).
inline HANDLE SS_Log::FileHandle()
{ return m_hFile; }

/// Sets the file handle that will be used to write our log file.  This
/// handle will only be used when UseServer is true.
inline VOID SS_Log::FileHandle(const HANDLE hFile)
{
    if( hFile == NULL && FileHandle() != NULL )
        CloseHandle(FileHandle());
    m_hFile = hFile;
}

/// Returns the currently set maximum file size.  Returns
/// SSLOG_MAX_LOG_SIZE_NO_LIMIT if no limit is set.
inline DWORD SS_Log::MaxFileSizeKb()
{ return m_dwMaxFileSizeKb; }

/// Sets the maximum file size in Kb that the log file will be allowed to
/// reach.  Once this limit is reached, the oldest half of the log will be
/// erased so we can fit more messages.  This parameter is only used if
/// we are not using the server (See UseServer).  Pass in
/// SSLOG_MAX_LOG_SIZE_NO_LIMIT if you want to specify no limit (the default).
inline VOID SS_Log::MaxFileSizeKb(DWORD dwMaxFileSizeKb)
{
	if( dwMaxFileSizeKb == SSLOG_MAX_LOG_SIZE_NO_LIMIT )
        m_dwMaxFileSizeKb = dwMaxFileSizeKb;
    else
        m_dwMaxFileSizeKb = dwMaxFileSizeKb*1020; // file size in KB on disk
}

/// Returns TRUE if the last message sent succeeded, or FALSE in case of failure.
/// Call GetLastError() for more details.
inline BOOL SS_Log::Succeeded()
{ return GetLastError() == SSLOG_ERROR_NO_ERROR; }

/// Returns the status of the last server creation attempt.
inline const CREATION_STATUS SS_Log::CreateServerStatus() const
{ return m_nCreateServerStatus; }

/// Sets the status of the last server creation attempt.
inline VOID SS_Log::CreateServerStatus(const CREATION_STATUS nStatus)
{ m_nCreateServerStatus = nStatus; }

/// Return the process's instance handle.  Note that this parameter defaults
/// to NULL, and must be passed in by the user if logging by resource ID is
/// desired.
inline HINSTANCE SS_Log::InstanceHandle()
{ return m_hInstance; }

// Sets the process instance handle.  This is necessary if logging by resource
/// ID is desired.
inline VOID SS_Log::InstanceHandle(HINSTANCE hInstance)
{ m_hInstance = hInstance; }

/// Returns TRUE if we've already sent the AddConnection message to the server.
inline const BOOL SS_Log::ConnectionAdded() const
{ return m_bConnectionAdded; }

/// Sets whether or not we've already sent the AddConnection message to the
/// server.
inline VOID SS_Log::ConnectionAdded(const BOOL bConnectionAdded)
{ m_bConnectionAdded = bConnectionAdded; }

/// Internal accessor that returns whether or not we are sending messages out
/// or not.  See SS_Log::LoggingDisabled(BOOL bLoggingDisabled).
inline BOOL SS_Log::LoggingDisabled()
{ return m_bLoggingDisabled; }

/// Internal accessor that sets whether or not we are sending messages out messages
/// or not.  This is set on construction by the "LoggingDisabled" registry entry
/// in HKCU\Software\SS_Log key, and updated when the user calles
/// SS_Log::SetRegistryKey() in the key passed into this function.
inline VOID SS_Log::LoggingDisabled(BOOL bLoggingDisabled)
{ m_bLoggingDisabled = bLoggingDisabled; }

// ------------------[          Macros/Defines         ]------------------ //

// The _SS_LOG_DO_NOT_INCLUDE_MACROS define only exists so that we don't
// include the macros listed below in the SS_Log.cpp class.
#ifndef _SS_LOG_DO_NOT_INCLUDE_MACROS


#ifdef _SS_LOG_ACTIVE

/// @{ section GLF Global Log Functions
/// These functions are used to access the global log. They are the same
/// functions that are available from a local instance of the SS_Log class.
/// Use them as you would use the corresponding functions in SS_Log.

/// @def LogSetFlags
///     Calls SS_Log::SetFlags() for the global log.

/// @def LogGetFlags
///     Calls SS_Log::GetFlags() for the global log.

/// @def LogRemoveFlags
///     Calls SS_Log::RemoveFlags() for the global log.

/// @def LogAddFlags
///     Calls SS_Log::AddFlags() for the global log.

/// @def LogSetDestinationName
///     Calls SS_Log::SetDestinationName() for the global log.

/// @def LogEraseLog
///     Calls SS_Log::EraseLog() for the global log.

/// @def LogLimitOutputSize
///     Calls SS_Log::LimitOutputSize() for the global log.

/// @def LogGetLastError
///     Calls SS_Log::GetLastError() for the global log.

/// @def LogSetRegistryKey
///     Calls SS_Log::SetRegistryKey() for the global log.

/// @def LogUseServer
///     Calls SS_Log::UseServer() for the global log.

/// @def LogSucceeded
///     Calls SS_Log::Succeeded() for the global log.

/// @def LogInstanceHandle
///     Calls SS_Log::LogInstanceHandle() for the global log.

/// @def LogGetRegistryFilters
///     Calls SS_Log::GetRegistryFilters() for the global log.

/// @def LogSetRegistryFilters
///     Calls SS_Log::GetRegistryFilters() for the global log.

#define LogSetFlags				g_Log.SetFlags
#define LogGetFlags				g_Log.GetFlags
#define LogRemoveFlags		    g_Log.RemoveFlags
#define LogAddFlags			    g_Log.AddFlags
#define LogSetDestinationName	g_Log.SetDestinationName
#define LogEraseLog				g_Log.EraseLog
#define LogLimitOutputSize		g_Log.LimitOutputSize
#define LogGetLastError			g_Log.GetLastError
#define LogSetRegistryKey		g_Log.SetRegistryKey
#define LogUseServer			g_Log.UseServer
#define LogSucceeded			g_Log.Succeeded
#define LogInstanceHandle		g_Log.InstanceHandle
#define LogGetRegistryFilters	g_Log.GetRegistryFilters
#define LogSetRegistryFilters	g_Log.SetRegistryFilters
/// @}

#else

#define LogSetFlags				((void)0)
#define LogGetFlags				((void)0)
#define LogRemoveFlags  		((void)0)
#define LogAddFlags			    ((void)0)
#define LogSetDestinationName	((void)0)
#define LogEraseLog				((void)0)
#define LogLimitOutputSize		((void)0)
#define LogGetLastError			((void)0)
#define LogSetRegistryKey		((void)0)
#define LogUseServer			((void)0)
#define LogSucceeded			((void)0)
#define LogInstanceHandle		((void)0)
#define LogGetRegistryFilters	((void)0)
#define LogSetRegistryFilters	((void)0)

#endif

// deprecated functions have been re-mapped.  Don't use these any more.
#ifdef _SS_LOG_ACTIVE

/// @{ @section DGLF Deprecated Global Log Functions
/// These functions are used to access the global log. They are the same
/// functions that are available from a local instance of the SS_Log class.
/// Use them as you would use the corresponding functions in SS_Log.

/// @def LogFilename
///     Maps to SetDestinationName()

/// @def LogWindowName
///     Maps to SetDestinationName()

/// @def LogRemoveFilters
///     Maps to RemoveFlags()

/// @def LogAddFilters
///     Maps to AddFlags()

/// @def LogFilter
///     Maps to SetFlags()

/// @def LogLimitFileSize
///     Maps to LimitOutputSize()

#define LogFilename				g_Log.SetDestinationName
#define LogWindowName			g_Log.SetDestinationName
#define LogRemoveFilters		g_Log.RemoveFlags
#define LogAddFilters			g_Log.AddFlags
#define LogFilter				g_Log.SetFlags
#define LogLimitFileSize		g_Log.LimitOutputSize
/// @}

#else

#define LogFilename				((void)0)
#define LogWindowName			((void)0)
#define LogRemoveFilters		((void)0)
#define LogAddFilters			((void)0)
#define LogFilter				((void)0)
#define LogLimitFileSize		((void)0)

#endif
// end deprecated functions

// ------------------[      Constants/Enumerations     ]------------------ //
// ------------------[       Forward Declarations      ]------------------ //
// ------------------[         Global Variables        ]------------------ //
#ifdef _SS_LOG_ACTIVE
extern SS_Log g_Log;
#endif

// ------------------[         Global Functions        ]------------------ //
#ifdef _SS_LOG_ACTIVE

/// @{ @section PLF Primary Logging Functions
/// These functions are the only ones that will actually produce a message in
/// a destination log (file, window, nt event log, other future destinations).
/// Note, however, that other messages are sent to the logging server for
/// configuration and user options.
///
/// For each of these calls, the global LogStoreFileLine function is called
/// first to store the filename and line number into global variables.  Then
/// one of the global WriteLog functions is called to process the logging.
/// Immediately after being called, the WriteLog functions make an local copy
/// of the filename and line number info so that the global variables can be
/// accessed by other threads without interfering with this message.

/// @def Log
/// @brief This is the function you will call for most all of your logging.
///
/// Four version of the function exist.  They are:
///
/// - Log(TCHAR* pMsg, ...) --- send a message
///       to the global log.  The parameters are:
///     @param pMsg [in] sprintf-style format string for the message.
///     @param ... [in] additional parameters to format into the format string.
///
/// - Log(DWORD dwFilter, TCHAR* pMsg, ...) --- send a message
///       to the global log.  The parameters are:
///     @param dwFilter [in] filter overrides for this message.
///     @param pMsg [in] sprintf-style format string for the message.
///     @param ... [in] additional parameters to format into the format string.
///
/// - Log(SS_Log* pLog, TCHAR* pMsg, ...) --- send a message
///       to a local log.  The parameters are:
///     @param pLog [in] pointer to the local to which we will send the message.
///     @param pMsg [in] sprintf-style format string for the message.
///     @param ... [in] additional parameters to format into the format string.
///
/// - Log(SS_Log* pLog, DWORD dwFilter, TCHAR* pMsg, ...) --- send a message
///       to a local log.  The parameters are:
///     @param pLog [in] pointer to the local to which we will send the message.
///     @param dwFilter [in] filter overrides for this message.
///     @param pMsg [in] sprintf-style format string for the message.
///     @param ... [in] additional parameters to format into the format string.
#define Log     LogStoreFileLine(_T(__FILE__), __LINE__), WriteLog

/// @def LogID
/// @brief Call this function to log a message from a string Resource ID.
///
/// Four version of the function exist.  They are:
///
/// - LogID(TCHAR* pMsg, ...) --- send a message
///       to the global log.  The parameters are:
///     @param pMsg [in] sprintf-style format string for the message.
///     @param ... [in] additional parameters to format into the format string.
///
/// - LogID(DWORD dwFilter, TCHAR* pMsg, ...) --- send a message
///       to the global log.  The parameters are:
///     @param dwFilter [in] filter overrides for this message.
///     @param pMsg [in] sprintf-style format string for the message.
///     @param ... [in] additional parameters to format into the format string.
///
/// - LogID(SS_Log* pLog, TCHAR* pMsg, ...) --- send a message
///       to a local log.  The parameters are:
///     @param pLog [in] pointer to the local to which we will send the message.
///     @param pMsg [in] sprintf-style format string for the message.
///     @param ... [in] additional parameters to format into the format string.
///
/// - LogID(SS_Log* pLog, DWORD dwFilter, TCHAR* pMsg, ...) --- send a message
///       to a local log.  The parameters are:
///     @param pLog [in] pointer to the local to which we will send the message.
///     @param dwFilter [in] filter overrides for this message.
///     @param pMsg [in] sprintf-style format string for the message.
///     @param ... [in] additional parameters to format into the format string.
#define LogID   LogStoreFileLine(_T(__FILE__), __LINE__), WriteLogID

/// @def LocalLogEnterFunction(pLog, szFunctionName)
/// @brief Will send a message upon entering and exiting a function.
///
/// Place this macro at the beginning of a function and pass in the
/// function name.  The macro will send a message to a local log each time the
/// function is called, and again when the function is returned.  Note that the
/// filename and line number info is sent for the entering message, but
/// unfortunately, I've not figured out how to gather that information
/// for the exiting message.
///
/// @param pLog [in] pointer to the local to which we will send the message.
/// @param szFunctionName [in] null-terminated string containing the name of
///     the function we are entering.
#define LocalLogEnterFunction(pLog, szFunctionName) \
    SSLogEnterFunction ssLogEnterFunction(_T(__FILE__), __LINE__, pLog, szFunctionName)

/// @def LogEnterFunction(szFunctionName)
/// @brief Will send a message upon entering and exiting a function.
///
/// Place this macro at the beginning of a function and pass in the
/// function name.  The macro will send a message to the global log each time
/// the function is called, and again when the function is returned.  Note that
/// the filename and line number info is sent for the entering message, but
/// unfortunately, I've not figured out how to gather that information
/// for the exiting message.
///
/// @param szFunctionName [in] name of the function this call was made from within.
#define LogEnterFunction(szFunctionName) \
    SSLogEnterFunction ssLogEnterFunction(_T(__FILE__), __LINE__, &g_Log, szFunctionName)

/// @}

extern INT WriteLog(SS_Log* pLog, DWORD dwFilter, TCHAR* pMsg, va_list* args );
extern INT WriteLog(SS_Log* pLog, DWORD dwFilter, TCHAR* pMsg, ...);
extern INT WriteLog(SS_Log* pLog, TCHAR* pMsg, ...);
extern INT WriteLog(DWORD dwFilter, TCHAR* pMsg, ...);
extern INT WriteLog(TCHAR* pMsg, ...);

extern INT WriteLogID(SS_Log* pLog, DWORD dwFilter, UINT nResourceID, va_list* args );
extern INT WriteLogID(SS_Log* pLog, DWORD dwFilter, UINT nResourceID, ...);
extern INT WriteLogID(SS_Log* pLog, UINT nResourceID, ...);
extern INT WriteLogID(DWORD dwFilter, UINT nResourceID, ...);
extern INT WriteLogID(UINT nResourceID, ...);

extern VOID LogStoreFileLine(TCHAR* szFile, int nLine);

#else // _SS_LOG_ACTIVE

#define Log                 ((void)0)
#define LogEnterFunction    ((void)0)
#define LogID               ((void)0)

#endif // _SS_LOG_ACTIVE

#endif // _SS_LOG_DO_NOT_INCLUDE_MACROS


#endif // __SS_Log__




By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect Amedisys
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions