ALib C++ Library
Library Version: 2412 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
textlogger.hpp
Go to the documentation of this file.
1//==================================================================================================
2/// \file
3/// This header file is part of module \alib_alox of the \aliblong.
4///
5/// \emoji :copyright: 2013-2024 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software License".
7//==================================================================================================
8#ifndef HPP_ALIB_LOX_DETAIL_TEXTLOGGER_TEXTLOGGER
9#define HPP_ALIB_LOX_DETAIL_TEXTLOGGER_TEXTLOGGER 1
10#pragma once
11#include "alib/alox/alox.hpp"
12
13// #################################################################################################
14// includes
15// #################################################################################################
18# include "alib/alox/aloxcamp.hpp"
23
24
25// #################################################################################################
26// forward declarations
27// #################################################################################################
28
29namespace alib { namespace lox {
30//==================================================================================================
31/// This namespaces defines class \b TextLogger and its helpers.
32//==================================================================================================
33namespace textlogger {
34
35//==================================================================================================
36/// This abstract class represents a plug-in for the TextLogger class which converts the list
37/// of logables into a textual representation.
38/// \see StandardConverter for further information.
39//==================================================================================================
41{
42 public:
43 //==========================================================================================
44 /// Destructs an object of this class.
45 //==========================================================================================
46 virtual ~ObjectConverter() {}
47
48 //==========================================================================================
49 /// The conversion method.
50 /// @param target An AString that takes the result.
51 /// @param logables The objects to convert.
52 //==========================================================================================
53 virtual void ConvertObjects( AString& target, BoxesMA& logables ) =0;
54
55 //==========================================================================================
56 /// If this converter uses an \alib{strings::util;AutoSizes} object, this method passes
57 /// an external object to use.
58 /// @param autoSizes The instance to use.
59 //==========================================================================================
61 virtual void SetAutoSizes( AutoSizes* autoSizes ) =0;
62
63 //==========================================================================================
64 /// If this converter uses an \alib{strings::util;AutoSizes} object, this method returns
65 /// such object.
66 /// @return The auto sizes used, \c nullptr if not applicable.
67 //==========================================================================================
68 virtual AutoSizes* GetAutoSizes() =0;
69
70 //==========================================================================================
71 /// If this converter uses an \alib{strings::util;AutoSizes} object, values of this field
72 /// are reset.
73 //==========================================================================================
74 virtual void ResetAutoSizes() =0;
75};
76
77//==================================================================================================
78/// Implements the interface
79/// \ref alib::lox::textlogger::ObjectConverter "ObjectConverter". Class
80/// \ref alib::lox::textlogger::TextLogger "TextLogger" creates an instance of this type in
81/// the moment no other (custom) type was set before the first log statement.
82///
83/// This implementation uses
84/// two specialisations of class
85/// \alib{lang::format;Formatter} to format the given logables to a textual
86/// representation. The formatters (and their sequence!) are:
87///
88/// 1. \alib{lang::format;FormatterPythonStyle;FormatterPythonStyle}
89/// 2. \alib{lang::format;FormatterJavaStyle;FormatterJavaStyle}
90///
91/// This way, standard text logging supports format strings in Python style as well as in Java style.
92//==================================================================================================
94{
95 public:
96 /// A list of formatters used to "convert" logables to strings.
97 /// By default, each entry contains a concatenated pair of formatters of types
98 /// \alib{lang::format;FormatterPythonStyle;FormatterPythonStyle} and
99 /// \alib{lang::format;FormatterJavaStyle;FormatterJavaStyle} are added in the
100 /// constructor of this class.
101 ///
102 /// A vector of formatters is needed to support recursive log calls.
103 /// If recursion occurs during logging (aka the conversion of a logable triggers another
104 /// logging operation), necessary formatters are created on the fly, respectively re-used
105 /// from previous recursions.
106 /// Their settings are cloned to those of the main formatters
107 /// using \alib{lang::format;Formatter::CloneSettings}.
108 ///
109 /// To use different formatters, it is recommended to implement a different converter
110 /// type, instead of "patching" the linked and recursive formatters found in this vector.
111 std::vector<Formatter*> Formatters;
112
113 protected:
114 /// A counter to detect recursive calls.
116
117 public:
118
119 //==========================================================================================
120 /// Constructor.
121 //==========================================================================================
124
125 //==========================================================================================
126 /// Virtual destructor.
127 //==========================================================================================
129 virtual ~StandardConverter() override;
130
131 //==========================================================================================
132 /// The conversion method.
133 /// Passes \p{target} and \p{logables} to the #Formatters.
134 /// @param target An AString that takes the result.
135 /// @param logables The objects to convert.
136 //==========================================================================================
138 virtual void ConvertObjects( AString& target, BoxesMA& logables ) override;
139
140 //==========================================================================================
141 /// Checks if the first formatter in #Formatters is of type
142 /// \alib{lang::format;FormatterPythonStyle}. If so, its \b AutoSizes member is set to
143 /// the given external instance. Otherwise the call is ignored.
144 /// @param autoSizes The instance to use.
145 //==========================================================================================
147 virtual void SetAutoSizes( AutoSizes* autoSizes ) override;
148
149 //==========================================================================================
150 /// Checks if the first formatter in #Formatters is of type
151 /// \alib{lang::format;FormatterPythonStyle}. If so, its \b AutoSizes member is returned.
152 /// If not, the method returns \c nullptr.
153 /// @return The auto sizes object of the main formatter.
154 //==========================================================================================
156 virtual AutoSizes* GetAutoSizes() override;
157
158 //==========================================================================================
159 /// Resets automatically widened tab stops and field widths of this converter.
160 //==========================================================================================
162 virtual void ResetAutoSizes() override;
163}; //class StandardConverter
164
165
166//==================================================================================================
167/// This class is a still abstract implementation of class Logger which is used as a base
168/// for all textual Logger implementations within \alox, e.g., \b %ConsoleLogger.
169///
170/// One main purpose of the class is to generate the textual representation of the meta-information
171/// of a log call. The final log message is then passed to the abstract method #logText.
172/// Hence, types that inherited from this class instead of directly from class
173/// \alib{lox;detail::Logger}, need to implement #logText instead of implementing #Log.
174///
175/// Class \b %TextLogger supports multi line log outputs. Such multi line log outputs can be
176/// configured to be logged in different ways. See struct \alib{lox::textlogger;FormatMultiLine} for more
177/// information.
178//==================================================================================================
179class TextLogger : public Logger
180{
181
182 // ###############################################################################################
183 // Internal fields
184 // ###############################################################################################
185 protected:
186
187 /// The internal log Buffer.
189
190 /// The buffers for converting the logables.
192
193 /// Denotes whether this logger writes to the <em>standard output streams</em>. If so,
194 /// \alib{threads;STD_IOSTREAMS_LOCK} is acquired with writing.
196
197 /// Variable of type \alib{lox::textlogger;FormatMetaInfo} residing in the
198 /// \alib{config;Configuration} of camp \alib_alox.
200
201 /// Variable of type \alib{lox::textlogger;FormatDateTime} residing in the
202 /// \alib{config;Configuration} of camp \alib_alox.
204
205 /// Variable of type \alib{lox::textlogger;FormatTimeDiff} residing in the
206 /// \alib{config;Configuration} of camp \alib_alox.
208
209 /// Variable of type \alib{lox::textlogger;FormatMultiLine} residing in the
210 /// \alib{config;Configuration} of camp \alib_alox.
212
213 /// Variable of type \alib{lox::textlogger;FormatOther} residing in the
214 /// \alib{config;Configuration} of camp \alib_alox.
216
217 /// Variable of type \alib{lox::textlogger;FormatAutoSizes}, which inherits class
218 /// \alib{strings::util;AutoSizes}.The sizes are used for auto tab positions and field sizes.
219 /// For each requested value, a corresponding array field is created on the fly.
220 /// If the format string get's changed and different (new) auto values should be used, then
221 /// this field should be reset after setting the new format string.
222 /// The other way round, it is also possible to preset set minimum values for tabs and field
223 /// sizes and hence avoid the columns growing during the lifetime of the Logger.
224 ///
225 /// The second member of type \b AutoSizes is attached to field #Converter
226 /// when this \b %TextLogger is attached to a \b %Lox.
227 ///
228 /// This field will be read from configuration variable \ref alxcvALOX_LOGGERNAME_AUTO_SIZES
230
231 /// A list of pairs of strings. Within each log message, the first string of a pair is
232 /// searched and replaced by the second string. Very simple, but useful in some cases.
234
235
236 /// A singleton calendar time object shared between different format variables during one
237 /// invocation.
239
240
241 // ###############################################################################################
242 // Public fields
243 // ###############################################################################################
244 public:
245 /// A helper object to get textual representation of logable objects.
246 /// If no converter is set when this logger is attached to a lox, a converter of type
247 /// \alib{lox::textlogger;StandardConverter} is created and used.
248 /// Custom loggers might create their own, custom converter objects here.
249 /// In the destructor of this class, the current object converter will be deleted.
250 ///
251 /// To extend class \b %TextLogger to support logging custom objects, custom converters can
252 /// set. The preferred alternative is however, to make custom types be formattable
253 /// by formatter classes used with \b %StandardConverter.
255
256 /// This field is used to convert the steady and monotonic clock values provided with
257 /// \alox{detail,ScopeInfo::GetTimeStamp} into human-readable, calendrical values in the
258 /// moment, field #Format contains tokens <c>%%TD</c> and/or <c>%%TT</c>.
259 ///
260 /// This may become problematic and ambiguous if the system clock is changed during a
261 /// software run. Especially for long-running background software (daemons, servers, etc.),
262 /// the software that uses \alox needs to provide a strategy of synchronizing this converter
263 /// with the system clock.
264 ///
265 /// A simple strategy is to just periodically invoke \alib{time;TickConverter::SyncClocks},
266 /// for example once a second.
267 ///
268 /// For some explanation of the problem see details of namespace #alib::time.
270
271 /// If \c false, an one-time warning (using \ref ALIB_WARNING) will be issued if the format
272 /// string is illegal. With each warning, the flag is set to \c true to omit further
273 /// warnings.
274 bool FormatWarningOnce= false;
275
276 /// Provides access to the value of the internal configuration variable #varFormatMetaInfo.<br>
277 /// This variable is declared only after the logger was added to a \b %Lox.
278 /// @return The struct containing formatting information.
280
281 /// Provides access to the value of the internal configuration variable #varFormatDateTime.<br>
282 /// This variable is declared only after the logger was added to a \b %Lox.
283 /// @return The struct containing formatting information.
285
286 /// Provides access to the value of the internal configuration variable #varFormatTimeDiff.<br>
287 /// This variable is declared only after the logger was added to a \b %Lox.
288 /// @return The struct containing formatting information.
290
291 /// Provides access to the value of the internal configuration variable #varFormatMultiLine.<br>
292 /// This variable is declared only after the logger was added to a \b %Lox.
293 /// @return The struct containing formatting information.
295
296 /// Provides access to the value of the internal configuration variable #varFormatOther.<br>
297 /// This variable is declared only after the logger was added to a \b %Lox.
298 /// @return The struct containing formatting information.
300
301 /// Provides access to the value of the internal configuration variable #varFormatAutoSizes.<br>
302 /// This variable is declared only after the logger was added to a \b %Lox.
303 /// @return The struct containing the \alib{strings::util;AutoSizes} instances for the
304 /// meta-information of the log message and for the log message itself.
306
307 /// Provides access to the value of the internal configuration variable #varReplacements.<br>
308 /// This variable is declared only after the logger was added to a \b %Lox.
309 /// @return The \alib{lox::textlogger;Replacements} instance for the logger in question.
311
312
313 // ###############################################################################################
314 // protected Constructor/ public destructor
315 // ###############################################################################################
316 protected:
317 //==============================================================================================
318 /// Constructs a TextLogger.
319 /// @param pName The name of the \e Logger.
320 /// @param typeName The type of the \e Logger.
321 /// @param pUsesStdStreams Denotes whether this logger writes to the
322 /// <em>standard output streams</em>.
323 //==============================================================================================
324 ALIB_API explicit TextLogger( const NString& pName, const NString& typeName,
325 bool pUsesStdStreams );
326
327 // ###############################################################################################
328 // protected methods
329 // ###############################################################################################
330 //==============================================================================================
331 /// Parses the #Format string and logs meta-information into the log buffer. For each
332 /// variable found, method #processVariable is invoked. Hence, to add new variables,
333 /// the latter method can be overwritten by descendants. Overwriting this method is
334 /// recommended for formatter classes that do not rely on format strings.
335 /// @param buffer The buffer to write meta-information into.
336 /// @param domain The <em>Log Domain</em>.
337 /// @param verbosity The verbosity.
338 /// @param scope Information about the scope of the <em>Log Statement</em>..
339 //==============================================================================================
341 virtual void writeMetaInfo( AString& buffer,
342 detail::Domain& domain,
343 Verbosity verbosity,
344 detail::ScopeInfo& scope );
345
346 //==============================================================================================
347 /// Processes the next command found in the format string, by writing formatted information
348 /// into the given buffer.
349 /// The given
350 /// \alib{strings;TSubstring;Substring} holds the next command.
351 /// When the method returns, the command is cut from the front.
352 ///
353 /// @param domainPath The <em>Log Domain</em> full path.
354 /// @param verbosity The verbosity. This has been checked to be active already on this
355 /// stage and is provided to be able to be logged out only.
356 /// @param scope Information about the scope of the <em>Log Statement</em>..
357 /// @param dest The buffer to write meta-information into.
358 /// @param variable The variable to read (may have more characters appended)
359 //==============================================================================================
361 virtual void processVariable( const NString& domainPath,
362 Verbosity verbosity,
363 detail::ScopeInfo& scope,
364 AString& dest,
365 Substring& variable );
366
367 //==============================================================================================
368 /// Helper function that logs a time given difference into the given buffer in a human-readable
369 /// format. Works from nanoseconds seconds to days.
370 ///
371 /// @param buffer The buffer to write the time difference representation into.
372 /// @param diffNanos The time difference to write in nanoseconds.
373 //==============================================================================================
375 virtual void writeTimeDiff ( AString& buffer, int64_t diffNanos );
376
377
378 public:
379 //==============================================================================================
380 /// Destructs a TextLogger.
381 //==============================================================================================
382 ALIB_API virtual ~TextLogger() override;
383
384 // ###############################################################################################
385 // Overriding parent's virtual, empty method AcknowledgeLox()
386 // ###############################################################################################
387
388 //==============================================================================================
389 /// Configuration variables are read within this method and created with
390 /// default values, in the case they do not exist, yet. The variables read are:
391 /// - \b alxcvALOX_LOGGERNAME_AUTO_SIZES
392 /// - \b alxcvALOX_LOGGERNAME_FORMAT
393 /// - \b alxcvALOX_LOGGERNAME_FORMAT_DATE_TIME
394 /// - \b alxcvALOX_LOGGERNAME_FORMAT_TIME_DIFF
395 /// - \b alxcvALOX_LOGGERNAME_FORMAT_MULTILINE
396 /// - \b alxcvALOX_LOGGERNAME_FORMAT_OTHER
397 /// - \b alxcvALOX_LOGGERNAME_REPLACEMENTS
398 ///
399 /// Configuration variables are \ref alib_alox_cfgvars "documented here".
400 ///
401 /// @param lox The \b %Lox to acknowledge insertion or removal
402 /// @param op The operation. Either \b ContainerOp::Insert or \b ContainerOp::Remove.
403 //==============================================================================================
405 virtual void AcknowledgeLox( detail::LoxImpl* lox, lang::ContainerOp op ) override;
406
407
408 // ###############################################################################################
409 // Abstract methods introduced
410 // ###############################################################################################
411 protected:
412 //==============================================================================================
413 /// This abstract method introduced by this class "replaces" the abstract method #Log
414 /// of parent class Logger which this class implements. In other words, descendants of this
415 /// class need to override this method instead of \b %Log. This class %TextLogger is
416 /// responsible for generating meta-information, doing text replacements, handle multi-line
417 /// messages, etc. and provides the textual representation of the whole log contents
418 /// to descendants using this method.
419 ///
420 /// @param domain The <em>Log Domain</em>.
421 /// @param verbosity The verbosity. This has been checked to be active already on this
422 /// stage and is provided to be able to be logged out only.
423 /// @param msg The log message.
424 /// @param scope Information about the scope of the <em>Log Statement</em>.
425 /// @param lineNumber The line number of a multi-line message, starting with 0.
426 /// For single line messages this is -1.
427 //==============================================================================================
428 virtual void logText( detail::Domain& domain,
429 Verbosity verbosity,
430 AString& msg,
431 detail::ScopeInfo& scope,
432 int lineNumber ) =0;
433
434 //==============================================================================================
435 /// Abstract method to be implemented by descendants. This message is called only when
436 /// multi-line messages are logged. It is called exactly once before a series of #logText
437 /// calls of a multi-line message and exactly once after such series.<br>
438 /// This is useful if the writing of text includes the acquisition of system resources
439 /// (e.g., opening a file).
440 ///
441 /// @param phase Indicates the beginning or end of a multi-line operation.
442 //==============================================================================================
443 virtual void notifyMultiLineOp( lang::Phase phase ) =0;
444
445 // ###############################################################################################
446 // Abstract method implementations
447 // ###############################################################################################
448 public:
449 //==============================================================================================
450 /// This is the implementation of the abstract method inherited from class Logger
451 /// that executes a log.<br>
452 /// This class implements this method and but exposes the new abstract method #logText.
453 /// This mechanism allows this class to do various things that are standard to Loggers
454 /// of type TextLogger. For example, meta-information of the log invocation is formatted
455 /// and string replacements are performed. This way, descendants of this class will consume
456 /// a ready to use log buffer with all meta-information and contents of all objects to be
457 /// included and their primary obligation is to copy the content into a corresponding
458 /// output stream.
459 ///
460 /// @param domain The <em>Log Domain</em>.
461 /// @param verbosity The verbosity.
462 /// @param logables The list of objects to log.
463 /// @param scope Information about the scope of the <em>Log Statement</em>..
464 //==============================================================================================
466 virtual void Log( detail::Domain& domain, Verbosity verbosity, BoxesMA& logables,
467 detail::ScopeInfo& scope) override;
468
469 // ###############################################################################################
470 // Public interface
471 // ###############################################################################################
472 public:
473 //==============================================================================================
474 /// Adds the given pair of replacement strings. If searched string already exists, the
475 /// current replacement string gets replaced. If the replacement string is \c nullptr,
476 /// nothing is set and a previously set replacement definition becomes unset.
477 /// @param searched The string to be searched.
478 /// @param replacement The replacement string. If this equals 'nullptr' a previously set
479 /// replacement will be unset.
480 //==============================================================================================
482 virtual void SetReplacement( const String& searched, const String& replacement );
483
484 //==============================================================================================
485 /// Removes all pairs of searched strings and their replacement value.
486 //==============================================================================================
488 virtual void ClearReplacements();
489
490 //==============================================================================================
491 /// Resets automatically widened tab stops and field widths of this logger by calling
492 /// \alib{lox::textlogger::StandardConverter;ResetAutoSizes} on field #Converter.
493 ///
494 /// \note The sizes affected are the ones used to format the custom log output, not
495 /// the ones uses for the meta-information. To reset the auto-sizes of the meta
496 /// information, invoke \alib{strings::util;AutoSizes::Reset} on field #AutoSizes.
497 //==============================================================================================
499 virtual void ResetAutoSizes();
500}; // class TextLogger
501
502}} // namespace alib[::lox::textlogger]
503
504/// Type alias in namespace \b alib.
506
507} // namespace [alib]
508
509
510
511
512
513#endif // HPP_ALIB_LOX_DETAIL_TEXTLOGGER_TEXTLOGGER
514
virtual ALIB_API void SetAutoSizes(AutoSizes *autoSizes)=0
virtual ~ObjectConverter()
Destructs an object of this class.
virtual void ConvertObjects(AString &target, BoxesMA &logables)=0
virtual AutoSizes * GetAutoSizes()=0
ALIB_API StandardConverter()
Constructor.
virtual ALIB_API void ResetAutoSizes() override
Resets automatically widened tab stops and field widths of this converter.
virtual ALIB_API AutoSizes * GetAutoSizes() override
std::vector< Formatter * > Formatters
virtual ALIB_API void SetAutoSizes(AutoSizes *autoSizes) override
virtual ALIB_API void ConvertObjects(AString &target, BoxesMA &logables) override
virtual ALIB_API ~StandardConverter() override
Virtual destructor.
int cntRecursion
A counter to detect recursive calls.
virtual ALIB_API void writeTimeDiff(AString &buffer, int64_t diffNanos)
virtual ALIB_API void ClearReplacements()
Removes all pairs of searched strings and their replacement value.
AString logBuf
The internal log Buffer.
virtual void notifyMultiLineOp(lang::Phase phase)=0
virtual ALIB_API void ResetAutoSizes()
FormatTimeDiff & GetFormatTimeDiff()
FormatMetaInfo & GetFormatMetaInfo()
FormatMultiLine & GetFormatMultiLine()
virtual ALIB_API void writeMetaInfo(AString &buffer, detail::Domain &domain, Verbosity verbosity, detail::ScopeInfo &scope)
virtual ALIB_API void processVariable(const NString &domainPath, Verbosity verbosity, detail::ScopeInfo &scope, AString &dest, Substring &variable)
lang::system::CalendarDateTime callerDateTime
AString msgBuf
The buffers for converting the logables.
virtual ALIB_API void AcknowledgeLox(detail::LoxImpl *lox, lang::ContainerOp op) override
virtual ALIB_API void SetReplacement(const String &searched, const String &replacement)
virtual void logText(detail::Domain &domain, Verbosity verbosity, AString &msg, detail::ScopeInfo &scope, int lineNumber)=0
virtual ALIB_API ~TextLogger() override
Destructs a TextLogger.
#define ALIB_API
Definition alib.hpp:639
Phase
Denotes a phase, e.g.,of a transaction.
ContainerOp
Denotes standard container operations.
Definition alib.cpp:69
lox::textlogger::TextLogger TextLogger
Type alias in namespace alib.
lox::Log Log
Type alias in namespace alib.
Definition log.inl:147