E-MailRelay
glogoutput.h
Go to the documentation of this file.
1//
2// Copyright (C) 2001-2021 Graeme Walker <graeme_walker@users.sourceforge.net>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16// ===
17///
18/// \file glogoutput.h
19///
20
21#ifndef G_LOG_OUTPUT_H
22#define G_LOG_OUTPUT_H
23
24#include "gdef.h"
25#include "glog.h"
26#include <string>
27#include <vector>
28#include <fstream>
29#include <ctime>
30#include <array>
31
32namespace G
33{
34 class LogOutput ;
35}
36
37//| \class G::LogOutput
38/// Controls and implements low-level logging output, as used by G::Log.
39///
40/// Applications should instantiate a LogOutput object in main() to
41/// enable and configure log output.
42///
43/// The implementation uses a file descriptor for osoutput() rather than
44/// a stream because windows file-sharing options are not accessible
45/// when building with mingw streams, and to avoid double buffering.
46///
47/// \see G::Log
48///
50{
51public:
52 enum class SyslogFacility {
53 User ,
54 Daemon ,
55 Mail ,
56 Cron ,
57 Local0 ,
58 Local1 ,
59 Local2 ,
60 Local3 ,
61 Local4 ,
62 Local5 ,
63 Local6 ,
64 Local7 } ;
65
66 struct Config /// A configuration structure for G::LogOutput.
67 {
68 bool m_output_enabled{false} ;
69 bool m_summary_info{false} ;
70 bool m_verbose_info{false} ;
71 bool m_debug{false} ;
72 bool m_with_level{false} ;
73 bool m_with_timestamp{false} ;
74 bool m_with_context{false} ;
75 bool m_strip{false} ; // strip first word
76 bool m_quiet_stderr{false} ;
77 bool m_use_syslog{false} ;
78 bool m_allow_bad_syslog{false} ;
79 SyslogFacility m_facility{SyslogFacility::User} ;
80 Config() ;
81 Config & set_output_enabled( bool value = true ) ;
82 Config & set_summary_info( bool value = true ) ;
83 Config & set_verbose_info( bool value = true ) ;
84 Config & set_debug( bool value = true ) ;
85 Config & set_with_level( bool value = true ) ;
86 Config & set_with_timestamp( bool value = true ) ;
87 Config & set_with_context( bool value = true ) ;
88 Config & set_strip( bool value = true ) ;
89 Config & set_quiet_stderr( bool value = true ) ;
90 Config & set_use_syslog( bool value = true ) ;
91 Config & set_allow_bad_syslog( bool value = true ) ;
92 Config & set_facility( SyslogFacility ) ;
93 } ;
94
95 LogOutput( const std::string & exename , const Config & config ,
96 const std::string & filename = std::string() ) ;
97 ///< Constructor. If there is no LogOutput object, or if
98 ///< 'config.output_enabled' is false, then there is no
99 ///< output of any sort (except for assertions to stderr).
100 ///< Otherwise at least warning and error messages are
101 ///< generated.
102 ///<
103 ///< If 'config.summary_info' is true then log-summary
104 ///< messages are output. If 'config.verbose_info' is true
105 ///< then log-verbose messages are output. If 'config.with_debug'
106 ///< is true then debug messages will also be generated (but
107 ///< only if compiled in).
108 ///<
109 ///< If an output filename is given it has a "%d" substitution
110 ///< applied and it is then opened or created before this
111 ///< constructor returns. If no filename is given then
112 ///< logging is sent to the standard error stream; the user
113 ///< is free to close stderr and reopen it onto /dev/null if
114 ///< only syslog logging is required.
115 ///<
116 ///< More than one LogOutput object may be created, but only
117 ///< the first one controls output.
118
119 explicit LogOutput( bool output_enabled_and_summary_info ,
120 bool verbose_info_and_debug = true ,
121 const std::string & filename = std::string() ) ;
122 ///< Constructor for test programs. Only generates output if the
123 ///< first parameter is true. Never uses syslog.
124
125 ~LogOutput() ;
126 ///< Destructor.
127
128 static LogOutput * instance() noexcept ;
129 ///< Returns a pointer to the controlling LogOutput object. Returns
130 ///< nullptr if none.
131
132 Config config() const ;
133 ///< Returns the current configuration.
134
135 void configure( const Config & ) ;
136 ///< Updates the current configuration.
137
138 bool at( Log::Severity ) const noexcept ;
139 ///< Returns true if logging should occur for the given severity level.
140 ///< Returns false if there is no LogOutput instance.
141
142 static void context( std::string (*fn)(void*) = nullptr , void * fn_arg = nullptr ) noexcept ;
143 ///< Sets a functor that is used to provide a context string for
144 ///< every log line, if configured. The functor should return
145 ///< the context string with trailing punctuation, typically
146 ///< colon and space.
147
148 static void * contextarg() noexcept ;
149 ///< Returns the functor argument as set by the last call to context().
150
151 static std::ostream & start( Log::Severity , const char * file , int line ) ;
152 ///< Prepares the internal ostream for a new log line and returns a
153 ///< reference to it. The caller should stream out the rest of the log
154 ///< line into the ostream and then call output(). Calls to start() and
155 ///< output() must be strictly in pairs. Returns a pointer to a dummy
156 ///< ostream if there is no LogOutput instance.
157
158 static void output( std::ostream & ) ;
159 ///< Emits the current log line (see start()). Does nothing if there
160 ///< is no LogOutput instance.
161
162 static void assertion( const char * file , int line , bool test , const char * test_string ) ;
163 ///< Performs an assertion check.
164
165 static void assertion( const char * file , int line , void * test , const char * test_string ) ;
166 ///< Performs an assertion check. This overload, using a test on a
167 ///< pointer, is motivated by MSVC warnings.
168
169 static void assertionFailure( const char * file , int line , const char * test_expression ) noexcept ;
170 ///< Reports an assertion failure.
171
172 static void assertionAbort() GDEF_NORETURN ;
173 ///< Aborts the program when an assertion has failed.
174
175 static void register_( const std::string & exe ) ;
176 ///< Registers the given executable as a source of logging.
177 ///< This is called from osinit(), but it might also need to be
178 ///< done as a program installation step with the necessary
179 ///< process permissions.
180
181 static void translate( const std::string & info , const std::string & warning ,
182 const std::string & error , const std::string & fatal ) ;
183 ///< Sets the prefix string for the various log levels
184 ///< (including trailing punctuation).
185
186public:
187 LogOutput( const LogOutput & ) = delete ;
188 LogOutput( LogOutput && ) = delete ;
189 void operator=( const LogOutput & ) = delete ;
190 void operator=( LogOutput && ) = delete ;
191
192private:
193 void osinit() ;
194 void open( std::string , bool ) ;
195 std::ostream & start( Log::Severity ) ;
196 void output( std::ostream & , int ) ;
197 void osoutput( int , Log::Severity , char * , std::size_t ) ;
198 void oscleanup() const noexcept ;
199 bool updateTime() ;
200 void appendTimeTo( std::ostream & ) ;
201 static const char * levelString( Log::Severity ) noexcept ;
202 static const char * basename( const char * ) noexcept ;
203
204private:
205 std::string m_exename ;
206 Config m_config ;
207 std::time_t m_time_s{0} ;
208 unsigned int m_time_us{0U} ;
209 std::vector<char> m_time_buffer ;
210 std::array<char,8U> m_date_buffer {} ;
211 HANDLE m_handle{0} ; // windows
212 std::string m_path ;
213 int m_fd{-1} ;
214 unsigned int m_depth{1U} ;
215 Log::Severity m_severity{Log::Severity::s_Debug} ;
216 std::size_t m_start_pos{0U} ;
217 std::string (*m_context_fn)(void *){nullptr} ;
218 void * m_context_fn_arg{nullptr} ;
219} ;
220
221inline void G::LogOutput::assertion( const char * file , int line , bool test , const char * test_string )
222{
223 if( !test )
224 {
225 assertionFailure( file , line , test_string ) ;
227 }
228}
229
230inline void G::LogOutput::assertion( const char * file , int line , void * test , const char * test_string )
231{
232 if( !test )
233 {
234 assertionFailure( file , line , test_string ) ;
235 assertionAbort() ;
236 }
237}
238
239#endif
A static interface for daemonising the calling process.
Definition: gdaemon.h:43
Controls and implements low-level logging output, as used by G::Log.
Definition: glogoutput.h:50
static void assertion(const char *file, int line, bool test, const char *test_string)
Performs an assertion check.
Definition: glogoutput.h:221
static void register_(const std::string &exe)
Registers the given executable as a source of logging.
bool at(Log::Severity) const noexcept
Returns true if logging should occur for the given severity level.
Definition: glogoutput.cpp:149
static void translate(const std::string &info, const std::string &warning, const std::string &error, const std::string &fatal)
Sets the prefix string for the various log levels (including trailing punctuation).
Definition: glogoutput.cpp:341
Config config() const
Returns the current configuration.
Definition: glogoutput.cpp:109
static void output(std::ostream &)
Emits the current log line (see start()).
Definition: glogoutput.cpp:169
static void * contextarg() noexcept
Returns the functor argument as set by the last call to context().
Definition: glogoutput.cpp:143
LogOutput(const std::string &exename, const Config &config, const std::string &filename=std::string())
Constructor.
Definition: glogoutput.cpp:77
~LogOutput()
Destructor.
Definition: glogoutput.cpp:119
void configure(const Config &)
Updates the current configuration.
Definition: glogoutput.cpp:114
static std::ostream & start(Log::Severity, const char *file, int line)
Prepares the internal ostream for a new log line and returns a reference to it.
Definition: glogoutput.cpp:161
static void assertionFailure(const char *file, int line, const char *test_expression) noexcept
Reports an assertion failure.
Definition: glogoutput.cpp:272
static LogOutput * instance() noexcept
Returns a pointer to the controlling LogOutput object.
Definition: glogoutput.cpp:128
static void context(std::string(*fn)(void *)=nullptr, void *fn_arg=nullptr) noexcept
Sets a functor that is used to provide a context string for every log line, if configured.
Definition: glogoutput.cpp:133
static void assertionAbort() GDEF_NORETURN
Aborts the program when an assertion has failed.
Definition: glogoutput.cpp:289
A class for doing iostream-based logging.
Definition: glog.h:49
Low-level classes.
Definition: galign.h:28
A configuration structure for G::LogOutput.
Definition: glogoutput.h:67