34 bool verbose_log ,
bool debug ,
bool level ,
bool timestamp ,
bool strip ,
35 bool use_syslog ,
const std::string & stderr_replacement , SyslogFacility syslog_facility ) :
38 m_summary_log(summary_log) ,
39 m_verbose_log(verbose_log) ,
43 m_syslog(use_syslog) ,
44 m_std_err(err(stderr_replacement)) ,
45 m_facility(syslog_facility) ,
47 m_timestamp(timestamp) ,
51 if( pthis() ==
nullptr )
57 const std::string & stderr_replacement ) :
58 m_enabled(enabled_and_summary) ,
59 m_summary_log(enabled_and_summary) ,
60 m_verbose_log(verbose_and_debug) ,
61 m_debug(verbose_and_debug) ,
65 m_std_err(err(stderr_replacement)) ,
72 if( pthis() ==
nullptr )
77 std::ostream & G::LogOutput::err(
const std::string & path_in )
79 if( !path_in.empty() )
81 std::string path = path_in ;
82 std::string::size_type pos = path.find(
"%d") ;
83 if( pos != std::string::npos )
84 path.replace( pos , 2U , dateString() ) ;
86 static std::ofstream file( path.c_str() , std::ios_base::out | std::ios_base::app ) ;
116 bool was_enabled = m_enabled ;
117 m_enabled = enabled ;
123 m_verbose_log = verbose_log ;
128 if( instance() !=
nullptr )
129 instance()->doOutput( severity , file , line , text ) ;
134 bool do_output = m_enabled ;
135 if( severity == Log::s_Debug )
136 do_output = m_enabled && m_debug ;
137 else if( severity == Log::s_LogSummary )
138 do_output = m_enabled && m_summary_log ;
139 else if( severity == Log::s_LogVerbose )
140 do_output = m_enabled && m_verbose_log ;
144 void G::LogOutput::doOutput( Log::Severity severity ,
const char * ,
int ,
const std::string & text )
146 bool do_output =
at( severity ) ;
150 const size_type limit =
static_cast<size_type
>(limits::log) ;
152 buffer.reserve( (text.length()>limit?limit:text.length()) + 40U ) ;
155 std::string::size_type text_pos = 0U ;
156 if( m_prefix.length() )
158 buffer.append( m_prefix ) ;
159 buffer.append(
": " ) ;
162 appendTimestampStringTo( buffer ) ;
164 buffer.append( levelString(severity) ) ;
169 text_pos = text.find(
' ') ;
170 if( text_pos == std::string::npos || (text_pos+1U) == text.length() )
177 size_type text_len = text.length() - text_pos ;
178 bool limited = text_len > limit ;
179 text_len = text_len > limit ? limit : text_len ;
180 buffer.append( text , text_pos , text_len ) ;
182 buffer.append(
" ..." ) ;
185 while( buffer.find(
'\033') != std::string::npos )
186 buffer[buffer.find(
'\033')] =
'.' ;
189 rawOutput( m_std_err , severity , buffer ) ;
198 void G::LogOutput::appendTimestampStringTo( std::string & result )
202 if( m_time == 0 || m_time != now.s )
205 static struct std::tm zero_broken_down_time ;
206 struct std::tm broken_down_time = zero_broken_down_time ;
207 getLocalTime( m_time , &broken_down_time ) ;
208 m_time_buffer.reserve( 30U ) ;
209 m_time_buffer.assign( 17U ,
'\0' ) ;
210 std::strftime( &m_time_buffer[0] , m_time_buffer.size() ,
"%Y" "%m" "%d." "%H" "%M" "%S.", &broken_down_time ) ;
211 m_time_buffer.pop_back() ;
214 result.append( &m_time_buffer[0] , m_time_buffer.size() ) ;
215 result.append( 1U ,
'0' + ( ( now.us / 100000 ) % 10 ) ) ;
216 result.append( 1U ,
'0' + ( ( now.us / 10000 ) % 10 ) ) ;
217 result.append( 1U ,
'0' + ( ( now.us / 1000 ) % 10 ) ) ;
218 result.append(
": " ) ;
221 std::string G::LogOutput::dateString()
224 static struct std::tm zero_broken_down_time ;
225 struct std::tm broken_down_time = zero_broken_down_time ;
226 getLocalTime( std::time(
nullptr) , &broken_down_time ) ;
227 char buffer[10] = { 0 } ;
228 std::strftime( buffer ,
sizeof(buffer)-1U ,
"%Y" "%m" "%d" , &broken_down_time ) ;
229 buffer[
sizeof(buffer)-1U] =
'\0' ;
230 return std::string( buffer ) ;
233 std::string G::LogOutput::fileAndLine(
const char * file ,
int line )
235 if( file !=
nullptr )
237 std::string basename( file ) ;
238 std::string::size_type slash_pos = basename.find_last_of(
"/\\" ) ;
239 if( slash_pos != std::string::npos && (slash_pos+1U) < basename.length() )
240 basename.erase( 0U , slash_pos+1U ) ;
241 return basename +
"(" + itoa(line) +
"): " ;
245 return std::string() ;
254 instance()->doAssertion( file , line , test_string ) ;
256 std::cerr <<
"assertion error: " << file <<
"(" << line <<
"): " << test_string << std::endl ;
261 void G::LogOutput::doAssertion(
const char * file ,
int line ,
const std::string & test_string )
267 rawOutput( m_std_err , Log::s_Assertion ,
268 std::string() +
"Assertion error: " + fileAndLine(file,line) + test_string ) ;
271 void G::LogOutput::halt()
276 const char * G::LogOutput::levelString( Log::Severity s )
278 if( s == Log::s_Debug )
return "debug: " ;
279 else if( s == Log::s_LogSummary )
return "info: " ;
280 else if( s == Log::s_LogVerbose )
return "info: " ;
281 else if( s == Log::s_Warning )
return "warning: " ;
282 else if( s == Log::s_Error )
return "error: " ;
283 else if( s == Log::s_Assertion )
return "fatal: " ;
287 std::string G::LogOutput::itoa(
int n_ )
290 if( n_ < 0 )
return std::string(1U,
'0') ;
291 char buffer[20] = {
'0' ,
'\0' } ;
292 unsigned int buffer_size =
sizeof(buffer) ;
293 unsigned int n =
static_cast<unsigned int>(n_) ;
295 bool zero = n == 0U ;
296 char * p = buffer + buffer_size - 1U ;
297 for( *p-- =
'\0' ; n > 0U ; --p , n /= 10U )
298 *p = static_cast<char>(
'0' + (n % 10U) ) ;
299 return zero ? buffer : (p+1U) ;
A subsecond-resolution timestamp based on a time_t.
bool syslog() const
Returns true if syslog output is enabled.
bool enable(bool enabled=true)
Enables or disables output. Returns the previous setting.
static bool at(Severity)
Returns true if G::LogOutput::output() would log at the given level.
static LogOutput * instance()
Returns a pointer to the controlling LogOutput object.
LogOutput(const std::string &prefix, bool output, bool with_logging, bool with_verbose_logging, bool with_debug, bool with_level, bool with_timestamp, bool strip_context, bool use_syslog, const std::string &stderr_replacement=std::string(), SyslogFacility syslog_facility=User)
Constructor.
std::string::size_type size_type
A std::size_t type.
virtual void onAssert()
Called during an assertion failure.
static EpochTime now()
Returns the current epoch time.
virtual ~LogOutput()
Destructor.
static void assertion(const char *file, int line, bool test, const char *)
Makes an assertion check (regardless of any LogOutput object).
static void output(G::Log::Severity, const char *file, int line, const std::string &)
Generates output if there is an existing LogOutput object which is enabled.
bool at(G::Log::Severity) const
Returns true if output() generates output at the given severity level.
Controls and implements low-level logging output, as used by the Log interface.
void verbose(bool verbose_log=true)
Enables or disables verbose logging.