[seiscomp, scanloc] Install, add .gitignore
This commit is contained in:
114
include/seiscomp/logging/channel.h
Normal file
114
include/seiscomp/logging/channel.h
Normal file
@ -0,0 +1,114 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef SC_LOGGING_CHANNEL_H
|
||||
#define SC_LOGGING_CHANNEL_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include <seiscomp/logging/log.h>
|
||||
#include <seiscomp/logging/node.h>
|
||||
|
||||
namespace Seiscomp {
|
||||
namespace Logging {
|
||||
|
||||
|
||||
/*! @class Seiscomp::Logging::Channel <seiscomp/logging/channel.h>
|
||||
@brief Implements a hierarchical logging channel
|
||||
|
||||
You should not need to use Channel directly under normal
|
||||
circumstances. See COMPONENT_CHANNEL() macro, GetComponentChannel() and
|
||||
getGlobalChannel()
|
||||
|
||||
Channel implements channel logging support. A channel is a named
|
||||
logging location which is global to the program. Channels are
|
||||
hierarchically related.
|
||||
|
||||
For example, if somewhere in your program a message is logged to
|
||||
"debug/foo/bar", then it will be delived to any subscribers to
|
||||
"debug/foo/bar", or subscribers to "debug/foo", or subscribers to
|
||||
"debug". Subscribing to a channel means you will receive anything
|
||||
published on that channel or sub-channels.
|
||||
|
||||
As a special case, subscribing to the channel "" means you will receive
|
||||
all messages - as every message has a channel and the empty string "" is
|
||||
considered to mean the root of the channel tree.
|
||||
|
||||
In addition, componentized channels are all considered sub channels of
|
||||
the global channel hierarchy. All rDebug(), rWarning(), and rError()
|
||||
macros publish to the componentized channels (component defined by
|
||||
SEISCOMP_COMPONENT).
|
||||
|
||||
@code
|
||||
// get the "debug" channel for our component. This is the same as
|
||||
// what rDebug() publishes to.
|
||||
Channel *node = COMPONENT_CHANNEL("debug", Log_Debug);
|
||||
// equivalent to
|
||||
Channel *node = GetComponentChannel(SEISCOMP_COMPONENT, "debug");
|
||||
|
||||
// Or, get the global "debug" channel, which will have messages from
|
||||
// *all* component's "debug" channels.
|
||||
Channel *node = getGlobalChannel( "debug", Log_Debug );
|
||||
@endcode
|
||||
|
||||
@author Valient Gough
|
||||
@see COMPONENT_CHANNEL()
|
||||
@see getComponentChannel()
|
||||
@see getGlobalChannel()
|
||||
*/
|
||||
class SC_SYSTEM_CORE_API Channel : public Node {
|
||||
public:
|
||||
using ComponentMap = std::map<std::string, Channel*>;
|
||||
|
||||
Channel(const std::string &name, LogLevel level);
|
||||
virtual ~Channel();
|
||||
|
||||
virtual void publish(const Data &data);
|
||||
const std::string &name() const;
|
||||
|
||||
LogLevel logLevel() const;
|
||||
void setLogLevel(LogLevel level);
|
||||
|
||||
protected:
|
||||
Channel *getComponent(Channel *componentParent,
|
||||
const char *component);
|
||||
|
||||
private:
|
||||
//! the full channel name
|
||||
std::string _name;
|
||||
LogLevel _level;
|
||||
|
||||
ComponentMap subChannels;
|
||||
ComponentMap components;
|
||||
|
||||
Channel(const Channel &);
|
||||
Channel &operator=(const Channel&);
|
||||
|
||||
friend Channel *Seiscomp::Logging::getComponentChannel(
|
||||
const char *component,
|
||||
const char *path,
|
||||
LogLevel level);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
82
include/seiscomp/logging/common.h
Normal file
82
include/seiscomp/logging/common.h
Normal file
@ -0,0 +1,82 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef SC_LOGGING_COMMON_H
|
||||
#define SC_LOGGING_COMMON_H
|
||||
|
||||
|
||||
#include <seiscomp/core.h>
|
||||
|
||||
#define LOG_CONCAT2(A,B) A##B
|
||||
#define LOG_CONCAT(A,B) LOG_CONCAT2(A,B)
|
||||
#define LOG_STR(X) #X
|
||||
|
||||
|
||||
/*
|
||||
We use __printf__ attribute to allow gcc to inspect printf style arguments
|
||||
and give warnings if the rDebug(), rWarning(), etc macros are misused.
|
||||
|
||||
We use __builtin_expect on GCC 2.96 and above to allow optimization of
|
||||
publication activation check. We tell the compiler that the branch is
|
||||
unlikely to occur, allowing GCC to push unecessary code out of the main
|
||||
path.
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
|
||||
# define likely(x) __builtin_expect((x),1)
|
||||
# define unlikely(x) __builtin_expect((x),0)
|
||||
|
||||
#else
|
||||
|
||||
// Not using the gcc compiler, make the macros do nothing.. They are
|
||||
// documented as the last instance of the macros..
|
||||
|
||||
/*!
|
||||
*/
|
||||
# define likely(x) (x)
|
||||
/*! @def unlikely(x)
|
||||
Starting with GCC 2.96, we can tell the compiler that an if condition is
|
||||
likely or unlikely to occur, which allows the compiler to optimize for the
|
||||
normal case.
|
||||
@internal
|
||||
*/
|
||||
# define unlikely(x) (x)
|
||||
|
||||
#endif
|
||||
|
||||
/*! @def SEISCOMP_COMPONENT
|
||||
@brief Specifies build-time component, eg -DSEISCOMP_COMPONENT="component-name"
|
||||
|
||||
Define SEISCOMP_COMPONENT as the name of the component being built.
|
||||
For example, as a compile flag, -DSEISCOMP_COMPONENT="component-name"
|
||||
|
||||
If SEISCOMP_COMPONENT is not specified, then it will be defined as "[unknown]"
|
||||
*/
|
||||
#ifndef SEISCOMP_COMPONENT
|
||||
# warning SEISCOMP_COMPONENT not defined - setting to UNKNOWN
|
||||
#define SEISCOMP_COMPONENT "[unknown]"
|
||||
#endif // SEISCOMP_COMPONENT not defined
|
||||
|
||||
// Use somewhat unique names (doesn't matter if they aren't as they are used in
|
||||
// a private context, so the compiler will make them unique if it must)
|
||||
#define _SCLOGID LOG_CONCAT(_rL_, __LINE__)
|
||||
|
||||
|
||||
#endif
|
42
include/seiscomp/logging/defs.h
Normal file
42
include/seiscomp/logging/defs.h
Normal file
@ -0,0 +1,42 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef SC_LOGGING_DEFS_H
|
||||
#define SC_LOGGING_DEFS_H
|
||||
|
||||
#include <seiscomp/core.h>
|
||||
|
||||
namespace Seiscomp {
|
||||
namespace Logging {
|
||||
|
||||
|
||||
class SC_SYSTEM_CORE_API Channel;
|
||||
|
||||
SC_SYSTEM_CORE_API extern Channel *_SCDebugChannel;
|
||||
SC_SYSTEM_CORE_API extern Channel *_SCInfoChannel;
|
||||
SC_SYSTEM_CORE_API extern Channel *_SCWarningChannel;
|
||||
SC_SYSTEM_CORE_API extern Channel *_SCErrorChannel;
|
||||
SC_SYSTEM_CORE_API extern Channel *_SCNoticeChannel;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
52
include/seiscomp/logging/fd.h
Normal file
52
include/seiscomp/logging/fd.h
Normal file
@ -0,0 +1,52 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef SC_LOGGING_FD_H
|
||||
#define SC_LOGGING_FD_H
|
||||
|
||||
#include <seiscomp/logging/output.h>
|
||||
|
||||
|
||||
namespace Seiscomp {
|
||||
namespace Logging {
|
||||
|
||||
|
||||
class SC_SYSTEM_CORE_API FdOutput : public Output {
|
||||
public:
|
||||
FdOutput(int fdOut = 2);
|
||||
~FdOutput();
|
||||
|
||||
protected:
|
||||
/** Callback method for receiving log messages */
|
||||
void log(const char* channelName,
|
||||
LogLevel level,
|
||||
const char* msg,
|
||||
time_t time);
|
||||
|
||||
private:
|
||||
bool _colorize;
|
||||
int _fdOut;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
57
include/seiscomp/logging/file.h
Normal file
57
include/seiscomp/logging/file.h
Normal file
@ -0,0 +1,57 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef SC_LOGGING_FILE_H
|
||||
#define SC_LOGGING_FILE_H
|
||||
|
||||
#include <seiscomp/logging/output.h>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
namespace Seiscomp {
|
||||
namespace Logging {
|
||||
|
||||
|
||||
class SC_SYSTEM_CORE_API FileOutput : public Output {
|
||||
public:
|
||||
FileOutput();
|
||||
FileOutput(const char* filename);
|
||||
~FileOutput();
|
||||
|
||||
virtual bool open(const char* filename);
|
||||
bool isOpen();
|
||||
|
||||
protected:
|
||||
/** Callback method for receiving log messages */
|
||||
void log(const char* channelName,
|
||||
LogLevel level,
|
||||
const char* msg,
|
||||
time_t time);
|
||||
|
||||
protected:
|
||||
std::string _filename;
|
||||
mutable std::ofstream _stream;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
81
include/seiscomp/logging/filerotator.h
Normal file
81
include/seiscomp/logging/filerotator.h
Normal file
@ -0,0 +1,81 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef SC_LOGGING_FILEROTATOR_H
|
||||
#define SC_LOGGING_FILEROTATOR_H
|
||||
|
||||
|
||||
#include <seiscomp/logging/file.h>
|
||||
#include <mutex>
|
||||
|
||||
|
||||
namespace Seiscomp {
|
||||
namespace Logging {
|
||||
|
||||
|
||||
class SC_SYSTEM_CORE_API FileRotatorOutput : public FileOutput {
|
||||
public:
|
||||
FileRotatorOutput(int timeSpan = 60*60*24, int historySize = 7,
|
||||
int maxFileSize = 100*1024*1024);
|
||||
/**
|
||||
* Creates a new FileRotatorOutput instance
|
||||
* @param filename The filename to log to
|
||||
* @param timeSpan The timespan in seconds for the log time before rotating
|
||||
* @param count The number of historic files to store
|
||||
*/
|
||||
FileRotatorOutput(const char* filename, int timeSpan = 60*60*24,
|
||||
int historySize = 7, int maxFileSize = 100*1024*1024);
|
||||
|
||||
bool open(const char* filename);
|
||||
|
||||
protected:
|
||||
/** Callback method for receiving log messages */
|
||||
void log(const char* channelName,
|
||||
LogLevel level,
|
||||
const char* msg,
|
||||
time_t time);
|
||||
|
||||
private:
|
||||
void rotateLogs();
|
||||
void removeLog(int index);
|
||||
void renameLog(int oldIndex, int newIndex);
|
||||
|
||||
|
||||
protected:
|
||||
//! time span to keep one log
|
||||
int _timeSpan;
|
||||
|
||||
//! number of log files to keep
|
||||
int _historySize;
|
||||
|
||||
//! maximum file size of a log file
|
||||
int _maxFileSize;
|
||||
|
||||
//! last log file written to
|
||||
int _lastInterval;
|
||||
|
||||
std::mutex outputMutex;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
444
include/seiscomp/logging/log.h
Normal file
444
include/seiscomp/logging/log.h
Normal file
@ -0,0 +1,444 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef SC_LOGGING_LOGGING_H
|
||||
#define SC_LOGGING_LOGGING_H
|
||||
|
||||
#ifndef SEISCOMP_COMPONENT
|
||||
# ifndef WIN32
|
||||
# warning SEISCOMP_COMPONENT not defined -> setting to "Seiscomp"
|
||||
# endif
|
||||
# define SEISCOMP_COMPONENT "Seiscomp"
|
||||
#endif
|
||||
|
||||
/* Define that SEISCOMP_* are also available as variadic versions, e.g.
|
||||
SEISCOMP_ERROR and SEISCOMP_VERROR whereas the latter takes an argument
|
||||
list (fmt::printf_args), e.g. SEISCOMP_VERROR("%s:%d", args).
|
||||
*/
|
||||
#define SEISCOMP_LOG_VA
|
||||
#define SEISCOMP_LOG_API_VERSION 2
|
||||
|
||||
#include <seiscomp/logging/publisher.h>
|
||||
#include <seiscomp/logging/publishloc.h>
|
||||
#include <seiscomp/logging/publisher.h>
|
||||
#include <seiscomp/logging/common.h>
|
||||
#include <seiscomp/logging/defs.h>
|
||||
|
||||
|
||||
namespace Seiscomp {
|
||||
namespace Logging {
|
||||
|
||||
|
||||
class Channel;
|
||||
class Output;
|
||||
|
||||
|
||||
enum LogLevel {
|
||||
LL_UNDEFINED = 0,
|
||||
LL_CRITICAL,
|
||||
LL_ERROR,
|
||||
LL_WARNING,
|
||||
LL_NOTICE,
|
||||
LL_INFO,
|
||||
LL_DEBUG,
|
||||
LL_QUANTITY
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
\brief The following macros do the actual logging according
|
||||
\brief defined log levels
|
||||
The first parameter is the message including placeholders (printf style),
|
||||
the following parameters hold the values.
|
||||
\code
|
||||
SEISCOMP_[LEVEL]("Precondition not satisfied: i > %d", myVarHolding_i);
|
||||
\endcode
|
||||
*/
|
||||
|
||||
#define STR(X) #X
|
||||
|
||||
|
||||
#ifdef __FUNCTION__
|
||||
# define SEISCOMP_LOGGING_CURRENT_FUNCTION __FUNCTION__
|
||||
#else
|
||||
# define SEISCOMP_LOGGING_CURRENT_FUNCTION "[unknown]"
|
||||
#endif
|
||||
|
||||
#define SEISCOMP_LOGGING_CALL(ID, COMPONENT, CHANNEL, FUNC, ...) \
|
||||
static bool ID ## _enabled = true; \
|
||||
if ( unlikely(ID ## _enabled) ) { \
|
||||
static Seiscomp::Logging::PublishLoc ID(& ID ## _enabled, \
|
||||
STR(COMPONENT), __FILE__, \
|
||||
SEISCOMP_LOGGING_CURRENT_FUNCTION, \
|
||||
__LINE__, CHANNEL); \
|
||||
FUNC(&ID, CHANNEL, ##__VA_ARGS__); \
|
||||
}
|
||||
|
||||
|
||||
#define _scplain(ID, CHANNEL, MSG) \
|
||||
do { SEISCOMP_LOGGING_CALL(ID, SEISCOMP_COMPONENT, CHANNEL, Seiscomp::Logging::Publish, MSG) } while(0)
|
||||
|
||||
#define _scfmt(ID, CHANNEL, ... ) \
|
||||
do { SEISCOMP_LOGGING_CALL(ID, SEISCOMP_COMPONENT, CHANNEL, Seiscomp::Logging::PublishF, ##__VA_ARGS__) } while(0)
|
||||
|
||||
#define _scprintf(ID, CHANNEL, ... ) \
|
||||
do { SEISCOMP_LOGGING_CALL(ID, SEISCOMP_COMPONENT, CHANNEL, Seiscomp::Logging::PublishP, ##__VA_ARGS__) } while(0)
|
||||
|
||||
#define _scv(ID, CHANNEL, format, args) \
|
||||
do { SEISCOMP_LOGGING_CALL(ID, SEISCOMP_COMPONENT, CHANNEL, Seiscomp::Logging::VPublish, format, args) } while(0)
|
||||
|
||||
|
||||
/*! @addtogroup LoggingMacros
|
||||
These macros are the primary interface for logging messages:
|
||||
- SEISCOMP_DEBUG(format, ...)
|
||||
- SEISCOMP_INFO(format, ...)
|
||||
- SEISCOMP_WARNING(format, ...)
|
||||
- SEISCOMP_ERROR(format, ...)
|
||||
- SEISCOMP_NOTICE(format, ...)
|
||||
- SEISCOMP_LOG(channel, format, ...)
|
||||
@{
|
||||
*/
|
||||
|
||||
/*! @def SEISCOMP_DEBUG(format, ...)
|
||||
@brief Log a message to the "debug" channel. Takes printf style arguments.
|
||||
|
||||
Format is ala printf, eg:
|
||||
@code
|
||||
SEISCOMP_DEBUG("I'm sorry %s, I can't do %s", name, request);
|
||||
@endcode
|
||||
|
||||
When using a recent GNU compiler, it should automatically detect format
|
||||
string / argument mismatch just like it would with printf.
|
||||
|
||||
Note that unless there are subscribers to this message, it will do nothing.
|
||||
*/
|
||||
#define SEISCOMP_DEBUG(...) \
|
||||
_scprintf(_SCLOGID, Seiscomp::Logging::_SCDebugChannel, ##__VA_ARGS__)
|
||||
|
||||
#define SC_FMT_DEBUG(...) \
|
||||
_scfmt(_SCLOGID, Seiscomp::Logging::_SCDebugChannel, ##__VA_ARGS__)
|
||||
|
||||
#define SEISCOMP_VDEBUG(format, args) \
|
||||
_scv(_SCLOGID, Seiscomp::Logging::_SCDebugChannel, format, args)
|
||||
|
||||
/*! @def SEISCOMP_INFO(format, ...)
|
||||
@brief Log a message to the "info" channel. Takes printf style arguments.
|
||||
|
||||
Format is ala printf, eg:
|
||||
@code
|
||||
SEISCOMP_INFO("I'm sorry %s, I can't do %s", name, request);
|
||||
@endcode
|
||||
|
||||
When using a recent GNU compiler, it should automatically detect format
|
||||
string / argument mismatch just like it would with printf.
|
||||
|
||||
Note that unless there are subscribers to this message, it will do nothing.
|
||||
*/
|
||||
#define SEISCOMP_INFO(...) \
|
||||
_scprintf(_SCLOGID, Seiscomp::Logging::_SCInfoChannel, ##__VA_ARGS__)
|
||||
|
||||
#define SC_FMT_INFO(...) \
|
||||
_scfmt(_SCLOGID, Seiscomp::Logging::_SCInfoChannel, ##__VA_ARGS__)
|
||||
|
||||
#define SEISCOMP_VINFO(format, args) \
|
||||
_scv(_SCLOGID, Seiscomp::Logging::_SCInfoChannel, format, args)
|
||||
|
||||
/*! @def SEISCOMP_WARNING(format, ...)
|
||||
@brief Log a message to the "warning" channel. Takes printf style
|
||||
arguments.
|
||||
|
||||
Output a warning message - meant to indicate that something doesn't seem
|
||||
right.
|
||||
|
||||
Format is ala printf, eg:
|
||||
@code
|
||||
SEISCOMP_WARNING("passed %i, expected %i, continuing", foo, bar);
|
||||
@endcode
|
||||
|
||||
When using a recent GNU compiler, it should automatically detect format
|
||||
string / argument mismatch just like it would with printf.
|
||||
|
||||
Note that unless there are subscribers to this message, it will do nothing.
|
||||
*/
|
||||
#define SEISCOMP_WARNING(...) \
|
||||
_scprintf(_SCLOGID, Seiscomp::Logging::_SCWarningChannel, ##__VA_ARGS__)
|
||||
|
||||
#define SC_FMT_WARNING(...) \
|
||||
_scfmt(_SCLOGID, Seiscomp::Logging::_SCWarningChannel, ##__VA_ARGS__)
|
||||
|
||||
#define SEISCOMP_VWARNING(format, args) \
|
||||
_scv(_SCLOGID, Seiscomp::Logging::_SCWarningChannel, format, args)
|
||||
|
||||
/*! @def SEISCOMP_ERROR(...)
|
||||
@brief Log a message to the "error" channel. Takes printf style arguments.
|
||||
|
||||
An error indicates that something has definately gone wrong.
|
||||
|
||||
Format is ala printf, eg:
|
||||
@code
|
||||
SEISCOMP_ERROR("bad input %s, aborting request", input);
|
||||
@endcode
|
||||
|
||||
When using a recent GNU compiler, it should automatically detect format
|
||||
string / argument mismatch just like it would with printf.
|
||||
|
||||
Note that unless there are subscribers to this message, it will do nothing.
|
||||
*/
|
||||
#define SEISCOMP_ERROR(...) \
|
||||
_scprintf(_SCLOGID, Seiscomp::Logging::_SCErrorChannel, ##__VA_ARGS__)
|
||||
|
||||
#define SC_FMT_ERROR(...) \
|
||||
_scfmt(_SCLOGID, Seiscomp::Logging::_SCErrorChannel, ##__VA_ARGS__)
|
||||
|
||||
#define SEISCOMP_VERROR(format, args) \
|
||||
_scv(_SCLOGID, Seiscomp::Logging::_SCErrorChannel, format, args)
|
||||
|
||||
/*! @def SEISCOMP_NOTICE(...)
|
||||
@brief Log a message to the "notice" channel. Takes printf style arguments.
|
||||
|
||||
A notice indicates that something important happened.
|
||||
|
||||
Format is ala printf, eg:
|
||||
@code
|
||||
SEISCOMP_NOTICE("bad input %s, aborting request", input);
|
||||
@endcode
|
||||
|
||||
When using a recent GNU compiler, it should automatically detect format
|
||||
string / argument mismatch just like it would with printf.
|
||||
|
||||
Note that unless there are subscribers to this message, it will do nothing.
|
||||
*/
|
||||
#define SEISCOMP_NOTICE(...) \
|
||||
_scprintf(_SCLOGID, Seiscomp::Logging::_SCNoticeChannel, ##__VA_ARGS__)
|
||||
|
||||
#define SC_FMT_NOTICE(...) \
|
||||
_scfmt(_SCLOGID, Seiscomp::Logging::_SCNoticeChannel, ##__VA_ARGS__)
|
||||
|
||||
#define SEISCOMP_VNOTICE(format, args) \
|
||||
_scv(_SCLOGID, Seiscomp::Logging::_SCNoticeChannel, format, args)
|
||||
|
||||
/*! @def SEISCOMP_LOG(channel,format,...)
|
||||
@brief Log a message to a user defined channel. Takes a channel and printf
|
||||
style arguments.
|
||||
|
||||
An error indicates that something has definately gone wrong.
|
||||
|
||||
Format is ala printf, eg:
|
||||
@code
|
||||
static Channel * MyChannel = SEISCOMP_CHANNEL("debug/mine");
|
||||
SEISCOMP_LOG(MyChannel, "happy happy, joy joy");
|
||||
@endcode
|
||||
|
||||
When using a recent GNU compiler, it should automatically detect format
|
||||
string / argument mismatch just like it would with printf.
|
||||
|
||||
Note that unless there are subscribers to this message, it will do nothing.
|
||||
*/
|
||||
#define SEISCOMP_LOG(channel, ...) \
|
||||
_scprintf(_SCLOGID, channel, ##__VA_ARGS__)
|
||||
|
||||
#define SC_FMT_LOG(channel, ...) \
|
||||
_scfmt(_SCLOGID, channel, ##__VA_ARGS__)
|
||||
|
||||
#define SEISCOMP_VLOG(channel, format, args) \
|
||||
_scv(_SCLOGID, channel, format, args)
|
||||
|
||||
/*! @def DEF_CHANNEL( const char *path, LogLevel level )
|
||||
@brief Returns pointer to Channel struct for the given path
|
||||
@param path The hierarchical path to the channel. Elements in the path
|
||||
are separated by '/'.
|
||||
|
||||
SEISCOMP_DEF_LOGCHANNEL gets an existing (or defines a new) log type. For example
|
||||
"debug", "warning", "error" are predefined types. You might define
|
||||
completely new types, like "timing", or perhaps sub-types like
|
||||
"debug/timing/foo", depending on your needs.
|
||||
|
||||
Reporting paths do not need to be unique within a project (or even a
|
||||
file).
|
||||
|
||||
Channels form a hierarchy. If one subscribes to "debug", then you also
|
||||
get messages posted to more specific types such as "debug/foo". But if
|
||||
you subscribe to a more specific type, such as "debug/foo", then you will
|
||||
not receive more general messages such as to "debug".
|
||||
|
||||
Example:
|
||||
@code
|
||||
#include <seiscomp/logging/log.h>
|
||||
#include <seiscomp/logging/channel.h>
|
||||
|
||||
static Channel *MyChannel = SEISCOMP_DEF_LOGCHANNEL("me/mine/allmine",Log_Info);
|
||||
|
||||
func()
|
||||
{
|
||||
SEISCOMP_LOG( MyChannel, "this is being sent to my own channel" );
|
||||
SEISCOMP_LOG( MyChannel, "%s %s", "hello", "world" );
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
// log all messages to the "me" channel to stderr
|
||||
StdioNode stdLog( STDERR_FILENO );
|
||||
stdLog.subscribeTo( SEISCOMP_CHANNEL ("me") );
|
||||
|
||||
func();
|
||||
}
|
||||
@endcode
|
||||
|
||||
@see test.cpp
|
||||
*/
|
||||
|
||||
#define SEISCOMP_DEF_LOGCHANNEL(path,level) SEISCOMP_CHANNEL_IMPL(SEISCOMP_COMPONENT, path, level)
|
||||
#define SEISCOMP_CHANNEL(path) SEISCOMP_CHANNEL_IMPL(SEISCOMP_COMPONENT, path, Seiscomp::Logging::LL_UNDEFINED)
|
||||
#define SEISCOMP_CHANNEL_IMPL(COMPONENT,path,level) \
|
||||
Seiscomp::Logging::getComponentChannel(LOG_STR(COMPONENT),path,level)
|
||||
|
||||
|
||||
#define SEISCOMP_DEBUG_S(str) \
|
||||
_scplain(_SCLOGID, Seiscomp::Logging::_SCDebugChannel, str)
|
||||
|
||||
#define SEISCOMP_INFO_S(str) \
|
||||
_scplain(_SCLOGID, Seiscomp::Logging::_SCInfoChannel, str)
|
||||
|
||||
#define SEISCOMP_WARNING_S(str) \
|
||||
_scplain(_SCLOGID, Seiscomp::Logging::_SCWarningChannel, str)
|
||||
|
||||
#define SEISCOMP_ERROR_S(str) \
|
||||
_scplain(_SCLOGID, Seiscomp::Logging::_SCErrorChannel, str)
|
||||
|
||||
#define SEISCOMP_NOTICE_S(str) \
|
||||
_scplain(_SCLOGID, Seiscomp::Logging::_SCNoticeChannel, str)
|
||||
|
||||
#define SEISCOMP_LOG_S(channel, str) \
|
||||
_scplain(_SCLOGID, channel, str)
|
||||
|
||||
/**
|
||||
Loglevel "LOG" is a special level, which needs a channel, to
|
||||
log the message to.
|
||||
\code
|
||||
static Channel* MyChannel = SEISCOMP_DEF_LOGCHANNEL("myroot/mysub", Log_Error);
|
||||
SEISCOMP_LOG(myChannel, "Postcondition not satisfied: count2 [%d] <= count1 [%d]", count2, count1);
|
||||
\endcode
|
||||
*/
|
||||
|
||||
SC_SYSTEM_CORE_API void debug(const char*);
|
||||
SC_SYSTEM_CORE_API void debug(const std::string &);
|
||||
SC_SYSTEM_CORE_API void info(const char*);
|
||||
SC_SYSTEM_CORE_API void info(const std::string &);
|
||||
SC_SYSTEM_CORE_API void warning(const char*);
|
||||
SC_SYSTEM_CORE_API void warning(const std::string &);
|
||||
SC_SYSTEM_CORE_API void error(const char*);
|
||||
SC_SYSTEM_CORE_API void error(const std::string &);
|
||||
SC_SYSTEM_CORE_API void notice(const char*);
|
||||
SC_SYSTEM_CORE_API void notice(const std::string &);
|
||||
SC_SYSTEM_CORE_API void log(Channel*, const char*);
|
||||
SC_SYSTEM_CORE_API void log(Channel*, const std::string &);
|
||||
|
||||
|
||||
/** NOTE: All retrieved Channel pointer must not be deleted!!! */
|
||||
|
||||
/** Retrieve all messages from all components */
|
||||
SC_SYSTEM_CORE_API Channel *getAll();
|
||||
|
||||
/*! @relates Channel
|
||||
@brief Return the named channel across all components.
|
||||
|
||||
Channels are hierarchical. See Channel for more detail.
|
||||
The global channel contains messages for all component channels.
|
||||
|
||||
For example, subscribing to the global "debug" means the subscriber would
|
||||
also get messages from <Component , "debug">, and <Component-B, "debug">, and
|
||||
<Component-C, "debug/foo">, etc.
|
||||
|
||||
@author Valient Gough
|
||||
*/
|
||||
SC_SYSTEM_CORE_API Channel *getGlobalChannel(const char *channel, LogLevel level = LL_UNDEFINED);
|
||||
|
||||
/*! @relates Channel
|
||||
@brief Return the named channel for a particular component.
|
||||
|
||||
@author Valient Gough
|
||||
*/
|
||||
SC_SYSTEM_CORE_API Channel *getComponentChannel(const char *component, const char *channel, LogLevel level = LL_UNDEFINED);
|
||||
|
||||
/** Retrieve defined messages from a component */
|
||||
SC_SYSTEM_CORE_API Channel *getComponentAll(const char *component);
|
||||
SC_SYSTEM_CORE_API Channel *getComponentDebugs(const char *component);
|
||||
SC_SYSTEM_CORE_API Channel *getComponentInfos(const char *component);
|
||||
SC_SYSTEM_CORE_API Channel *getComponentWarnings(const char *component);
|
||||
SC_SYSTEM_CORE_API Channel *getComponentErrors(const char *component);
|
||||
SC_SYSTEM_CORE_API Channel *getComponentNotices(const char *component);
|
||||
|
||||
|
||||
/**
|
||||
\brief Example on how to use logging
|
||||
|
||||
File: [name].cpp
|
||||
\code
|
||||
// NOTE: The definition of component has to be done before the include
|
||||
// of log.h !
|
||||
#define SEISCOMP_COMPONENT MyComponent
|
||||
#include <seiscomp/logging/log.h>
|
||||
|
||||
// include further header
|
||||
...
|
||||
|
||||
void foo(int i) {
|
||||
if ( i < 0 ) {
|
||||
SEISCOMP_WARNING("precondition: i >= 0 not satisfied, i = %d", i);
|
||||
return;
|
||||
}
|
||||
|
||||
SEISCOMP_INFO("postcondition satisfied");
|
||||
}
|
||||
\endcode
|
||||
|
||||
To subscribe logging channels and to output logging messages,
|
||||
create a node and subscribe the channels of interest.
|
||||
\code
|
||||
int main(int argc, char** argv) {
|
||||
SeisComp::Logging::Init(argc, argv);
|
||||
...
|
||||
// create one default node and log to stderr
|
||||
Seiscomp::Logging::FdOutput stdLog(STDERR_FILENO);
|
||||
// lets receive all warnings from the component MyComponent (see above).
|
||||
stdLog.subscribe(Seiscomp::Logging::GetComponentWarnings("MyComponent"));
|
||||
...
|
||||
// dont catch any messages
|
||||
stdLog.clear();
|
||||
// lets receive all messages from the component MyComponent
|
||||
stdLog.subscribe(Seiscomp::Logging::GetComponentAll("MyComponent"));
|
||||
...
|
||||
// subscribe to all messages globally
|
||||
stdLog.subscribe(Seiscomp::Logging::GetAll());
|
||||
|
||||
}
|
||||
\endcode
|
||||
*/
|
||||
|
||||
|
||||
SC_SYSTEM_CORE_API Output* consoleOutput();
|
||||
SC_SYSTEM_CORE_API void enableConsoleLogging(Channel*);
|
||||
SC_SYSTEM_CORE_API void disableConsoleLogging();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
196
include/seiscomp/logging/node.h
Normal file
196
include/seiscomp/logging/node.h
Normal file
@ -0,0 +1,196 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef SC_LOGGING_NODE_H
|
||||
#define SC_LOGGING_NODE_H
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <time.h>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
|
||||
#include <seiscomp/core.h>
|
||||
|
||||
|
||||
namespace Seiscomp {
|
||||
namespace Logging {
|
||||
|
||||
|
||||
class SC_SYSTEM_CORE_API Node;
|
||||
|
||||
|
||||
/*! @struct Data <seiscomp/logging/node.h>
|
||||
* @brief Data published through Node
|
||||
|
||||
Data is the data which is published from SEISCOMP_DEBUG(), SEISCOMP_WARNING(),
|
||||
SEISCOMP_ERROR() and SEISCOMP_LOG() macros. It contains a link to the
|
||||
publisher, the (approximate) time of the publication, and the formatted message.
|
||||
|
||||
Note that none of the data in the publication is considered to be static.
|
||||
Once control has returned to the publisher, the data may be destroyed. If
|
||||
it is necessary to hang on to any of the data, a deep copy must be made.
|
||||
*/
|
||||
|
||||
struct SC_SYSTEM_CORE_API Data {
|
||||
struct PublishLoc *publisher;
|
||||
//! time of publication
|
||||
time_t time;
|
||||
//! formatted msg - gets destroyed when publish() call returns.
|
||||
const char *msg;
|
||||
|
||||
// track which nodes have seen this message, to avoid getting
|
||||
// duplicates. It would be nice if we could enforce this via the node
|
||||
// structure instead, but that is much harder.
|
||||
std::set<Node*> seen;
|
||||
};
|
||||
|
||||
|
||||
/*! @class Seiscomp::Logging::Node <seiscomp/logging/node.h>
|
||||
@brief Core of publication system, forms activation network.
|
||||
|
||||
Node formes the core of the publication system. It has two primary
|
||||
purposes :
|
||||
- link publications with subscribers
|
||||
- transfer meta-data in the form or node activations
|
||||
|
||||
Both publishers (eg Publisher) and subscribers (eg StdioNode) are
|
||||
derived from Node, although Node can be used entirely unmodified.
|
||||
|
||||
An Node contains a list of publishers which it is linked with. It
|
||||
also contains a list of subscribers which it is linked with.
|
||||
Publications always flow from publishers to subscribers, and activation
|
||||
information flows the opposite direction from subscribers to publishers.
|
||||
|
||||
An Node by default acts as both a subscriber and publisher -- when
|
||||
it has been subscribed to another node and receives a publication it
|
||||
simply repeats the information to all of its subscribers.
|
||||
|
||||
More specifically, it only publishes to subscribers who have also voiced
|
||||
an interest in receiving the publication. If a node has no subscribers
|
||||
which are also interested (or no subscribers at all), then it can be said
|
||||
to be dormant and it tells the publishers that it is subscribed to that
|
||||
it is no longer interested. This propogates all the way up to
|
||||
Publishers which will disable the logging statement completely if
|
||||
there are no interested parties.
|
||||
|
||||
@author Valient Gough
|
||||
*/
|
||||
class SC_SYSTEM_CORE_API Node {
|
||||
public:
|
||||
//! @brief Instantiate an empty Node. No subscribers or publishers..
|
||||
Node();
|
||||
|
||||
//! @brief Disconnects from any remaining subscribers and publishers
|
||||
virtual ~Node();
|
||||
|
||||
//! @brief Force disconnection from any subscribers or publishers
|
||||
virtual void clear();
|
||||
|
||||
/*! @brief Publish data.
|
||||
|
||||
This iterates over the list of subscribers which have stated interest and
|
||||
sends them the data.
|
||||
*/
|
||||
virtual void publish(const Data &data);
|
||||
|
||||
/*! @brief Have this node subscribe to a new publisher.
|
||||
|
||||
We become a subscriber of the publisher. The publisher's addSubscriber()
|
||||
function is called to complete the link.
|
||||
|
||||
If our node is active then we also tell the publisher that we want
|
||||
publications.
|
||||
*/
|
||||
virtual void addPublisher(Node *);
|
||||
|
||||
/*! @brief Drop our subscription to a publisher
|
||||
|
||||
A callback parameter is provided to help avoid loops in the code which may
|
||||
affect the thread locking code.
|
||||
|
||||
@param callback If True, then we call publisher->dropSubscriber() to make
|
||||
sure the publisher also drops us as a subscriber.
|
||||
*/
|
||||
virtual void dropPublisher(Node *, bool callbacks=true );
|
||||
|
||||
/*! @brief Returns @e true if this node is active
|
||||
@return @e true if we have one or more interested subscribers, otherwise false
|
||||
*/
|
||||
bool enabled() const;
|
||||
|
||||
/*! @brief Add a subscriber.
|
||||
|
||||
Normally a subscriber calls this for itself when it's addPublisher() method is
|
||||
called.
|
||||
*/
|
||||
virtual void addSubscriber(Node *);
|
||||
|
||||
/*! @brief Remove a subscriber.
|
||||
|
||||
Normally a subscriber calls this for itself when it's dropPublisher() method
|
||||
is called.
|
||||
|
||||
Note that the subscriber list is kept separate from the interest list. If
|
||||
the subscriber is active, then you must undo that by calling
|
||||
isInterested(subscriber, false) in addition to dropSubscriber
|
||||
*/
|
||||
virtual void dropSubscriber(Node *);
|
||||
|
||||
/*! @brief Change the state of one of our subscribers.
|
||||
|
||||
This allows a subscriber to say that it wants to be notified of publications
|
||||
or not. The @a node should already be registered as a subscriber.
|
||||
|
||||
If we previously had no interested parties and now we do, then we need to
|
||||
notify the publishers in our publishers list that we are now interested.
|
||||
|
||||
If we previously had interested parties and we remove the last one, then we
|
||||
can notify the publishers that we are no longer interested..
|
||||
*/
|
||||
|
||||
virtual void isInterested(Node *node, bool isInterested);
|
||||
|
||||
protected:
|
||||
/*! @brief For derived classes to get notified of activation status change.
|
||||
|
||||
This is called by isInterested() when our state changes. If @e true is
|
||||
passed, then this node has become active. If @e false is passed, then this
|
||||
node has just become dormant.
|
||||
*/
|
||||
virtual void setEnabled(bool newState);
|
||||
|
||||
//! list of nodes we are subscribed to
|
||||
std::list<Node *> publishers;
|
||||
|
||||
//! list of nodes we publish to
|
||||
std::list<Node *> subscribers;
|
||||
|
||||
//! list of subscribers that are interested in receiving publications..
|
||||
std::list<Node *> interestList;
|
||||
|
||||
std::mutex mutex;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
92
include/seiscomp/logging/output.h
Normal file
92
include/seiscomp/logging/output.h
Normal file
@ -0,0 +1,92 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef SC_LOGGING_OUTPUT_H
|
||||
#define SC_LOGGING_OUTPUT_H
|
||||
|
||||
#include <seiscomp/logging/node.h>
|
||||
#include <seiscomp/logging/log.h>
|
||||
|
||||
|
||||
namespace Seiscomp {
|
||||
namespace Logging {
|
||||
|
||||
/**
|
||||
* \brief Logging output class
|
||||
*
|
||||
* To implement a special kind of logging output,
|
||||
* derive from this class and implement the
|
||||
* method Output::log(...) to receive logging
|
||||
* messages.
|
||||
* \code
|
||||
* MyOutput log;
|
||||
* log.subscribe(GetAll());
|
||||
* \endcode
|
||||
*/
|
||||
class SC_SYSTEM_CORE_API Output : public Node {
|
||||
protected:
|
||||
Output();
|
||||
|
||||
public:
|
||||
virtual ~Output() {}
|
||||
|
||||
public:
|
||||
/** Subscribe to a particular channel */
|
||||
bool subscribe(Channel* channel);
|
||||
bool unsubscribe(Channel* channel);
|
||||
void logComponent(bool e) { _logComponent = e; }
|
||||
void logContext(bool e) { _logContext = e; }
|
||||
void setUTCEnabled(bool e) { _useUTC = e; }
|
||||
|
||||
protected:
|
||||
/** Callback method for receiving log messages */
|
||||
virtual void log(const char* channelName,
|
||||
LogLevel level,
|
||||
const char* msg,
|
||||
time_t time) = 0;
|
||||
|
||||
/** The following methods calls are only valid inside the
|
||||
log(...) method */
|
||||
|
||||
/** Returns the current component name */
|
||||
const char* component() const;
|
||||
/** Returns the sourcefile of the current log entry */
|
||||
const char* fileName() const;
|
||||
/** Returns the function name of the current log entry */
|
||||
const char* functionName() const;
|
||||
/** Returns the line number of the current log entry */
|
||||
int lineNum() const;
|
||||
|
||||
private:
|
||||
void publish(const Data &data);
|
||||
|
||||
protected:
|
||||
bool _logComponent;
|
||||
bool _logContext;
|
||||
bool _useUTC;
|
||||
|
||||
private:
|
||||
PublishLoc* _publisher;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
102
include/seiscomp/logging/publisher.h
Normal file
102
include/seiscomp/logging/publisher.h
Normal file
@ -0,0 +1,102 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef SC_LOGGING_PUBLISHER_H
|
||||
#define SC_LOGGING_PUBLISHER_H
|
||||
|
||||
|
||||
#include <seiscomp/logging/common.h>
|
||||
#include <seiscomp/logging/node.h>
|
||||
|
||||
|
||||
namespace Seiscomp {
|
||||
namespace Logging {
|
||||
|
||||
|
||||
class SC_SYSTEM_CORE_API Channel;
|
||||
|
||||
|
||||
/*! @class Seiscomp::Logging::Publisher <seiscomp/logging/publisher.h>
|
||||
@brief Publisher used by log macros.
|
||||
|
||||
This derives from Node and interfaces to the static PublishLoc logging
|
||||
data allowing them to be enabled or disabled depending on subscriber
|
||||
status.
|
||||
|
||||
An instance of this class is created for every error message location.
|
||||
Normally this class is not used directly.
|
||||
|
||||
For example, this
|
||||
@code
|
||||
rDebug( "hello world" );
|
||||
@endcode
|
||||
|
||||
is turned approximatly into this:
|
||||
@code
|
||||
static PublishLoc _rl = {
|
||||
pub: 0,
|
||||
component: "component",
|
||||
fileName: "myfile.cpp",
|
||||
functionName: "functionName()",
|
||||
lineNum: __LINE__,
|
||||
channel: 0
|
||||
};
|
||||
if(_rL.publish != 0)
|
||||
(*_rl.publish)( &_rL, _RLDebugChannel, "hello world" );
|
||||
@endcode
|
||||
|
||||
The Publisher instance manages the contents of the static structure
|
||||
_rL. When someone subscribes to it's message, then _rL.publish is set to
|
||||
point to the publishing function, and when there are no subscribers then
|
||||
it is set to 0.
|
||||
|
||||
The code produced contains one if statement, and with optimization comes
|
||||
out to about 3 instructions on an x86 computer (not including the
|
||||
function call). If there are no subscribers to this message then that
|
||||
is all the overhead, plus the memory usage for the structures
|
||||
involved and the initial registration when the statement is first
|
||||
encountered..
|
||||
|
||||
@see Channel
|
||||
@author Valient Gough
|
||||
*/
|
||||
class SC_SYSTEM_CORE_API Publisher : public Node {
|
||||
public:
|
||||
Publisher();
|
||||
Publisher(PublishLoc *src);
|
||||
~Publisher() override;
|
||||
|
||||
public:
|
||||
// metadata about the publisher and its publication
|
||||
PublishLoc *src;
|
||||
|
||||
protected:
|
||||
void setEnabled(bool newState) override;
|
||||
|
||||
Publisher(const Publisher &);
|
||||
Publisher & operator=(const Publisher &);
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
114
include/seiscomp/logging/publishloc.h
Normal file
114
include/seiscomp/logging/publishloc.h
Normal file
@ -0,0 +1,114 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef SC_LOGGING_PUBLISHLOC_H
|
||||
#define SC_LOGGING_PUBLISHLOC_H
|
||||
|
||||
|
||||
#include <seiscomp/core.h>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <fmt/printf.h>
|
||||
|
||||
#include <cstdarg>
|
||||
|
||||
|
||||
namespace Seiscomp {
|
||||
namespace Logging {
|
||||
|
||||
|
||||
class SC_SYSTEM_CORE_API Channel;
|
||||
class SC_SYSTEM_CORE_API Node;
|
||||
|
||||
|
||||
struct SC_SYSTEM_CORE_API PublishLoc {
|
||||
/*! @struct PublishLoc
|
||||
@brief Internal RLog structure - static struct for each log() statement
|
||||
|
||||
@internal
|
||||
Structure created for each log location to keep track of logging state
|
||||
and associated data.
|
||||
|
||||
Only static members are initialized at build time, which is why
|
||||
RLogChannel is passed as argument. Otherwise entire structure will have
|
||||
to be initialized at run-time which adds extra code and a guard variable
|
||||
for the struct.
|
||||
*/
|
||||
PublishLoc(bool *enabled, const char *component,
|
||||
const char *fileName, const char *functionName,
|
||||
int lineNum, Channel *channel);
|
||||
~PublishLoc();
|
||||
|
||||
bool *enabled;
|
||||
|
||||
Node *pub;
|
||||
const char *component;
|
||||
const char *fileName;
|
||||
const char *functionName;
|
||||
int lineNum;
|
||||
Channel *channel;
|
||||
|
||||
inline void enable() { *enabled = true; }
|
||||
inline void disable() { *enabled = false; }
|
||||
inline bool isEnabled() { return *enabled; }
|
||||
};
|
||||
|
||||
|
||||
void Publish(PublishLoc *, Channel *, const char *msg);
|
||||
void Publish(PublishLoc *, Channel *, const std::string &msg);
|
||||
|
||||
template <typename S, typename... Args>
|
||||
void PublishF(PublishLoc *, Channel *,
|
||||
const S &format, Args &&...args);
|
||||
|
||||
template <typename S, typename... Args>
|
||||
void PublishP(PublishLoc *, Channel *,
|
||||
const S &format, Args &&...args);
|
||||
|
||||
void VPublish(PublishLoc *, Channel *,
|
||||
const char *format,
|
||||
va_list args);
|
||||
void VPublish(PublishLoc *, Channel *,
|
||||
fmt::string_view format,
|
||||
fmt::format_args args);
|
||||
void VPublish(PublishLoc *, Channel *,
|
||||
fmt::string_view format,
|
||||
fmt::printf_args args);
|
||||
|
||||
|
||||
template <typename S, typename... Args>
|
||||
inline void PublishF(PublishLoc *loc, Channel *channel,
|
||||
const S &format, Args &&...args) {
|
||||
VPublish(loc, channel, format, fmt::make_format_args(args...));
|
||||
}
|
||||
|
||||
|
||||
template <typename S, typename... Args>
|
||||
inline void PublishP(PublishLoc *loc, Channel *channel,
|
||||
const S &format, Args &&...args) {
|
||||
VPublish(loc, channel, format, fmt::make_printf_args(args...));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
63
include/seiscomp/logging/syslog.h
Normal file
63
include/seiscomp/logging/syslog.h
Normal file
@ -0,0 +1,63 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) gempa GmbH *
|
||||
* All rights reserved. *
|
||||
* Contact: gempa GmbH (seiscomp-dev@gempa.de) *
|
||||
* *
|
||||
* GNU Affero General Public License Usage *
|
||||
* This file may be used under the terms of the GNU Affero *
|
||||
* Public License version 3.0 as published by the Free Software Foundation *
|
||||
* and appearing in the file LICENSE included in the packaging of this *
|
||||
* file. Please review the following information to ensure the GNU Affero *
|
||||
* Public License version 3.0 requirements will be met: *
|
||||
* https://www.gnu.org/licenses/agpl-3.0.html. *
|
||||
* *
|
||||
* Other Usage *
|
||||
* Alternatively, this file may be used in accordance with the terms and *
|
||||
* conditions contained in a signed written agreement between you and *
|
||||
* gempa GmbH. *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
#ifndef SC_LOGGING_SYSLOG_H
|
||||
#define SC_LOGGING_SYSLOG_H
|
||||
|
||||
#ifndef WIN32
|
||||
|
||||
#include <seiscomp/logging/output.h>
|
||||
|
||||
|
||||
namespace Seiscomp {
|
||||
namespace Logging {
|
||||
|
||||
|
||||
class SC_SYSTEM_CORE_API SyslogOutput : public Output {
|
||||
public:
|
||||
SyslogOutput();
|
||||
SyslogOutput(const char *ident, const char *facility = nullptr);
|
||||
~SyslogOutput();
|
||||
|
||||
int facility() const { return _facility; }
|
||||
|
||||
bool open(const char *ident, const char *facility = nullptr);
|
||||
bool isOpen() const;
|
||||
void close();
|
||||
|
||||
protected:
|
||||
/** Callback method for receiving log messages */
|
||||
void log(const char* channelName,
|
||||
LogLevel level,
|
||||
const char* msg,
|
||||
time_t time);
|
||||
|
||||
private:
|
||||
bool _openFlag;
|
||||
int _facility;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user