Files
simgear/simgear/debug/logstream.hxx
Richard Harrison 739c76e862 Win32 console; added method to ignore errors
This is mainly for standalone FGCOM - because the error message is always shown because it is a console app and --console isn't required.
2021-04-08 21:57:31 +02:00

224 lines
6.5 KiB
C++

/** \file logstream.hxx
* Stream based logging mechanism.
*/
// Written by Bernie Bright, 1998
//
// Copyright (C) 1998 Bernie Bright - bbright@c031.aone.net.au
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
#ifndef _LOGSTREAM_H
#define _LOGSTREAM_H
#include <simgear/compiler.h>
#include <simgear/debug/debug_types.h>
#include <sstream>
#include <vector>
#include <memory>
// forward decls
class SGPath;
namespace simgear
{
class LogCallback;
/**
* Helper force a console on platforms where it might optional, when
* we need to show a console. This basically means Windows at the
* moment - on other plaforms it's a no-op
*/
void requestConsole(bool ignoreErrors);
void shutdownLogging();
} // of namespace simgear
/**
* Class to manage the debug logging stream.
*/
class logstream
{
public:
~logstream();
static void initGlobalLogstream();
/**
* Helper force a console on platforms where it might optional, when
* we need to show a console. This basically means Windows at the
* moment - on other plaforms it's a no-op
*/
void requestConsole(bool ignoreErrors);
/**
* Set the global log class and priority level.
* @param c debug class
* @param p priority
*/
void setLogLevels( sgDebugClass c, sgDebugPriority p );
bool would_log( sgDebugClass c, sgDebugPriority p,
const char* file, int line, const char* function,
bool freeFilename=false ) const;
void logToFile( const SGPath& aPath, sgDebugClass c, sgDebugPriority p );
void set_log_priority( sgDebugPriority p);
void set_log_classes( sgDebugClass c);
sgDebugClass get_log_classes() const;
sgDebugPriority get_log_priority() const;
/**
@brief convert a string value to a log prioirty.
throws std::invalid_argument if the string is not valid
*/
static sgDebugPriority priorityFromString(const std::string& s);
/**
* set developer mode on/off. In developer mode, SG_DEV_WARN messags
* are treated as warnings. In normal (non-developer) mode they are
* treated as SG_DEBUG.
*/
void setDeveloperMode(bool devMode);
/**
* set output of file:line mode on/off. If on, all log messages are
* prefixed by the file:line of the caller of SG_LOG().
*/
void setFileLine(bool fileLine);
/**
* the core logging method
*/
void log( sgDebugClass c, sgDebugPriority p,
const char* fileName, int line, const char* function,
const std::string& msg);
// overload of above, which can transfer ownership of the file-name.
// this is unecesary overhead when logging from C++, since __FILE__ points
// to constant data, but it's needed when the filename is Nasal data (for
// example) since during shutdown the filename is freed by Nasal GC
// asynchronously with the logging thread.
void logCopyingFilename( sgDebugClass c, sgDebugPriority p,
const char* fileName, int line, const char* function,
const std::string& msg);
/**
* output formatted hex dump of memory block
*/
void hexdump(sgDebugClass c, sgDebugPriority p,
const char* fileName, int line, const char* function,
const void *mem, unsigned int len, unsigned int columns = 16);
/**
* support for the SG_POPUP logging class
* set the content of the popup message
*/
void popup( const std::string& msg);
/**
* retrieve the contents of the popup message and clear it's internal
* content. The return value may be an empty string.
*/
std::string get_popup();
/**
* return true if a new popup message is available. false otherwise.
*/
bool has_popup();
/**
* \relates logstream
* Return the one and only logstream instance.
* We use a function instead of a global object so we are assured that cerr
* has been initialised.
* @return current logstream
*/
friend logstream& sglog();
/**
* register a logging callback. Note callbacks are run in a
* dedicated thread, so callbacks which pass data to other threads
* must use appropriate locking.
*/
void addCallback(simgear::LogCallback* cb);
void removeCallback(simgear::LogCallback* cb);
void removeCallbacks();
/**
* optionally record all entries and submit them to new log callbacks that
* are added. This allows simplified logging configuration, but still including
* early startup information in all logs.
*/
void setStartupLoggingEnabled(bool enabled);
/**
* Set up the logstream for running in test mode. For example the callbacks
* will be unregistered and the behaviour of the would_log() function
* sanitized.
*/
void setTestingMode(bool testMode);
private:
// constructor
logstream();
class LogStreamPrivate;
std::unique_ptr<LogStreamPrivate> d;
};
logstream& sglog();
/** \def SG_LOG(C,P,M)
* Log a message.
* @param C debug class
* @param P priority
* @param M message
*/
# define SG_LOGX(C,P,M) \
do { if(sglog().would_log(C,P, __FILE__, __LINE__, __FUNCTION__)) { \
std::ostringstream os; os << M; \
sglog().log(C, P, __FILE__, __LINE__, __FUNCTION__, os.str()); \
if ((P) == SG_POPUP) sglog().popup(os.str()); \
} } while(0)
#ifdef FG_NDEBUG
# define SG_LOG(C,P,M) do { if((P) == SG_POPUP) SG_LOGX(C,P,M) } while(0)
# define SG_LOG_NAN(C,P,M) SG_LOG(C,P,M)
# define SG_HEXDUMP(C,P,MEM,LEN)
#else
# define SG_LOG(C,P,M) SG_LOGX(C,P,M)
# define SG_LOG_NAN(C,P,M) do { SG_LOGX(C,P,M); throw std::overflow_error(M); } while(0)
# define SG_LOG_HEXDUMP(C,P,MEM,LEN) if(sglog().would_log(C,P, __FILE__, __LINE__, __FUNCTION__)) \
sglog().hexdump(C, P, __FILE__, __LINE__, __FUNCTION__, MEM, LEN)
#endif
#define SG_ORIGIN __FILE__ ":" SG_STRINGIZE(__LINE__)
#endif // _LOGSTREAM_H