ROSE 0.11.145.147
Namespaces | Classes | Typedefs | Enumerations | Functions | Variables
Sawyer::Message Namespace Reference

Description

Formatted diagnostic messages emitted to various backends.

This namespace provides functionality to conditionally emit diagnostic messages based on software component and message importance. Although the library has extensive capabilities for controlling the message format and where to send the message, most uses of this namespace are to emit a message, so we'll describe that by way of introduction...

Emitting a message

using namespace Sawyer::Message;
mlog[INFO] <<"about to process \"" <<filename <<"\"\n"
Formatted diagnostic messages emitted to various backends.
Definition Message.h:276
Facility mlog
Facility used by Sawyer components.
@ INFO
Informative messages.
Definition Message.h:326

The mlog is a message Facility that holds a number of streams, each of which can be enabled or disabled. Inserting to a disabled message stream causes the message to be thrown away. The INFO is a message Importance, of which the library defines eight levels ranging from debug through fatal. The expression mlog[INFO] selects one of the message Stream objects from the facility. The linefeed marks the end of a message; messages are "partial" until the linefeed is inserted, but depending on the sink (final destination) even partial messages might be shown. Since a message stream is a subclass of std::ostream, all the usual output insertion operators just work.

One of the benefits of using this namespace is that the output will have a consistent look and feel. It can even be colorized based on message importance (at least for ANSI terminal output). The output will look something like this:

identityTranslator[31044] 0.00128 disassembler[INFO]: about to process "grep"

The "identityTranslator" is the name of the executable, the 31044 is the process ID, "0.00128" is the time in seconds since the program started, "disassembler" is the software component that is reporting this messsage (i.e., the messsage facility), and "INFO" is the importance level.

Defining facilities

Before one can start emitting messages, he needs to define a message Facility (mlog in the first example). The library defines one facility, Sawyer::Message::mlog, which can be used, but it's better to define a message facility for each software component because then messages can be controlled per software component, and the component will be clearly indicated in the output ("disassembler" in the previous example). A software component could be a function, class, namespace, entire library, or entire program–whatever granularity one wants.

Here's an example that creates a facility at class level:

class Disassembler {
...
};
Sawyer::Message::Facility Disassembler::mlog("disassembler");
Collection of streams.
Definition Message.h:1606

The mlog is constructed in a useable state with all streams enabled and output going to standard error via file descriptor 2. It is given a string name, "disassembler", that will show up in the output. The class may want to make two adjustments at run-time:

void Disassembler::initClass() {
mlog.initStreams(destination);
}
Facilities & insert(Facility &facility, const std::string &name="")
Register a facility so it can be controlled as part of a collection of facilities.
Facility & initStreams(const DestinationPtr &)
Cause all streams to use the specified destination.
Facilities mfacilities
Library-provided facility group.

The initStreams call reinitializes the message streams so they use your library's message plumbing, destination, which is a Sawyer::Message::DestinationPtr (types whose names end with "Ptr" point to reference counted objects). The streams had previously been using Sawyer::Message::merr, but pointing them all to your destination means that the destination for all messages can be changed in one place: if you want messages to go to syslogd, you change how destination is created. As we'll see below, the destination also controls things like colored output.

The mfacilities.insert call registers the new mlog with a global Facilities object, which we describe next...

Collections of facility objects

Any combination of Facility objects can be grouped together into one or more Facilities (note plural) objects so they can be enabled and disabled collectively. A Facilities object, also referred to as a facility group, is able to parse a simple language provided as a string, which is often provided from the command-line parser.

This example creates three facilities and groups them together:

Facility mlog1("disassembler", destination);
Facility mlog2("c++ parser", destination)
Facility mlog3("StringUtility::split", destination);
Facilities facilities;
facilities.insert(mlog1);
facilities.insert(mlog2, "cpp_parser");
facilities.insert(mlog3);
Collection of facilities.
Definition Message.h:1736

The three insert calls incorporate the three facilities into the group by reference and give them names in the configuration language. The names in the config language must look like C++ names (including :: and . operators), so the second insert needs to supply a valid name. The other two use the facility's name, which is also the string that is printed when messages are output. A unique, non-empty name must be supplied for each facility in a group, although the names for the facilities themselves need not be unique or even non-empty. The library provides Sawyer::Message::mfacilities and users are encouraged to use it as their primary facility group.

The facilities in a group can be controlled (enabled or disabled) with the Facilities::control method, which takes a string in the control language (see method for details). For example, to enable output for all levels of importance except debugging, across all registered facilities, but only warning and higher messages for the disassembler's facility:

facilities.control("all, !debug, disassembler(>=warn)")
std::string control(const std::string &s)
Parse a single command-line switch and enable/disable the indicated streams.

The terms are processed from left to right, but only if the entire string is valid. If the string is invalid then an exception is thrown that includes an error message and the exact position in the string where the error occurred.

Plumbing lattice

Inserting a message to a stream with << operators is only half the story–the plumbing lattice deals with how a message is conveyed to the final destination(s) and what transformations happen along the way. The plumbing is a run-time constructed lattice containing internal nodes and leaf nodes. Each leaf node is a final destination, or sink, for a message and can be a C++ std::ostream, a C FILE pointer, a Unix file descriptor, the syslog daemon, or a user-defined destination. The internal nodes serve as multiplexers, filters, rate limiters, etc.

All plumbing lattice nodes are dynamically allocated and reference counted. Instead of using the normal C++ constructors, plumbing objects are created with static instance methods that perform the allocation and return a smart pointer. The type names for smart pointers are the class names with a "Ptr" suffix, and Sawyer::SharedPointer serves as the implementation.

For instance, a lattice that accepts any kind of message, limits the output to at most one message per second, and sends the messages to standard error and a file can be constructed like this:

->to(FdSink::instance(2), //standard error on Unix
FileSink::instance(f)); // f is some FILE* we opened already
static FdSinkPtr instance(int fd, const PrefixPtr &prefix=PrefixPtr())
Allocating constructor.
Definition Message.h:1297
static FileSinkPtr instance(FILE *f, const PrefixPtr &prefix=PrefixPtr())
Allocating constructor.
Definition Message.h:1314
static MultiplexerPtr instance()
Allocating constructor.
Definition Message.h:679
Reference-counting intrusive smart pointer.

The destination can then be used to construct streams and facilities. The Destination class is the base class for all plumbing lattice nodes, thus DestinationPtr is the base class for all pointers to nodes. Of course, similar redirection can be done outside the program using standard Unix tools and file redirection, except that performing redirection via a plumbing lattice has a few advantages:

Tips and tricks

Naming tips

Avoid using the name "log" since it may conflict with ::log from math.h.

If facilities are consistently named (e.g., always "mlog") then code that emits messages can always use that name and will automatically get the most narrowly scoped facility that's visible according to C++ visibility rules, which is probably the facility that is most applicable.

A using namespace Sawyer::Message will prevent you from having to qualify the message importance symbols, but if you name your facilities "mlog" they may be ambiguous with Sawyer::Message::mlog. Sawyer also provides the namespace Sawyer::Message::Common, which defines only the most commonly used types (the importance levels, Stream, Facility, and Facilities).

Performance tips

Although every attempt was made to keep the library efficient, when features and performance conflict, features win. If messages insert operators << are expensive then it is best to avoid calling them when the stream to which they're inserted is disabled–they'd just be thrown away anyway. Programs that already emit messages to streams probably use if statements or conditional compilation already, and those constructs can continue to be used. In fact, when a stream is evaluated in a Boolean context it returns true when enabled and false when disabled:

if (mlog[DEBUG])
mlog[DEBUG] <<"the result is " <<something_expensive() <<"\n";
@ DEBUG
Messages intended to be useful primarily to the author of the code.
Definition Message.h:314

When if statements are used extensively for this purpose in a project whose style guide mandates that the body must be on the following line, the logging code occupies twice as much vertical space as necessary (or three or four times, with curly braces) and can become quite obtrusive. Here are two other ways to get the same effect:

mlog[DEBUG] and mlog[DEBUG] <<"the result is " <<something_expensive() <<"\n";
SAWYER_MESG(mlog[DEBUG]) <<"the result is " <<something_expensive() <<"\n";

The alternate spelling "SAWYER_MSG" is also allowed.

Temporary streams

Although std::ostream objects are not copyable, and not movable before c++11, Sawyer's message streams implement a form of copying/moving. Namely, a Stream copy constructor can be used to create a new message stream identical to the source message stream, and any partial message in the source stream is moved to the destination stream. This enables a way to create a temporary stream for use inside a function:

void longFunctionWithLotsOfDebugging() {
Stream debug(mlog[DEBUG]);
...
debug <<"got here\n";
}
Converts text to messages.
Definition Message.h:1396

Partial messages

One problem that authors often encounter when emitting diagnostics is that they want to print an incomplete line, then perform some work, then complete the line. But if the "some work" also prints diagnostics then the output will be all messed up. This library attempts to fix that, at least when the software uses this library for all its diagnostic output. Here's the most basic form:

mlog[DEBUG] <<"first part"; // partial since no line-feed
mlog[INFO] <<"some other message\n"; // unrelated message
mlog[DEBUG] <<"; second part\n"; // complete the partial message

The output to sinks like standard error that support partial messages will be, sans prefixes:

first part...
some other message
first part; second part

But there's a slight problem with that code: if the second line had been a message written to mlog[DEBUG] instead of mlog[INFO] then the library would not have been able to tell that "some other message" is unrelated to "first part" and would have emitted something that's not any better than using plain old std::cerr:

first partsome other message
; second part

This most often occurs when "some other message" is emitted from some other function, so its not immediately evident that something is inserting a message in the midst of our partial message. A better way is to create a temporary message stream and use that stream to complete the partial message. Since the copy constructor also moves any partial message from the source stream to the new stream, we can even emit the partial message on the same line as the declaration. Here's a silly example of the process:

unsigned multiply(unsigned a, unsigned b) {
Stream mesg(mlog[DEBUG] <<"multiply(" <<a <<", " <<b <<")");
unsigned result = 0;
for (unsigned i=0; i<b; ++i)
result = add(result, b); //might also write to mlog[DEBUG]
mesg <<" = " <<result <<"\n"; // finish the message
return result;
}

The mesg stream need not be used only for completing the one message. In fact, one of the benefits of the Temporary streams hint is that partial messages emitted using the debug stream cannot be interferred with from called functions that might use mlog[DEBUG].

Namespaces

namespace  Common
 Commonly used message types.
 

Classes

class  ColorSet
 Colors to use for each message importance. More...
 
struct  ColorSpec
 ANSI Color specification for text written to a terminal. More...
 
class  Destination
 Base class for all types of message destinations. More...
 
class  Facilities
 Collection of facilities. More...
 
class  FacilitiesGuard
 Saves and restores facilities. More...
 
class  Facility
 Collection of streams. More...
 
class  FdSink
 Send free-format messages to a Unix file descriptor. More...
 
class  FileSink
 Send free-format messages to a C FILE pointer. More...
 
class  Filter
 Base class for internal nodes that filter messages. More...
 
class  Gang
 
class  HighWater
 
class  ImportanceFilter
 Filters messages based on importance level. More...
 
class  Mesg
 A single message. More...
 
struct  MesgProps
 Properties for messages. More...
 
class  Multiplexer
 Sends incoming messages to multiple destinations. More...
 
class  Prefix
 Information printed at the beginning of each free-format message. More...
 
class  SequenceFilter
 Filters messages based on how many messages have been seen. More...
 
class  SProxy
 
class  Stream
 Converts text to messages. More...
 
class  StreamSink
 Send free-format messages to a C++ I/O stream. More...
 
class  SyslogSink
 Sends messages to the syslog daemon. More...
 
class  TimeFilter
 Filters messages based on time. More...
 
class  UnformattedSink
 Base class for final destinations that are free-format. More...
 

Typedefs

typedef std::pair< DestinationPtr, MesgPropsBakedDestination
 Baked properties for a destination.
 
typedef std::vector< BakedDestinationBakedDestinations
 Baked properties for multiple destinations.
 
typedef SharedPointer< class DestinationDestinationPtr
 Smart pointer.
 
typedef SharedPointer< class MultiplexerMultiplexerPtr
 Smart pointer.
 
typedef SharedPointer< class FilterFilterPtr
 Smart pointer.
 
typedef SharedPointer< class SequenceFilterSequenceFilterPtr
 Smart pointer.
 
typedef SharedPointer< class TimeFilterTimeFilterPtr
 Smart pointer.
 
typedef SharedPointer< class ImportanceFilterImportanceFilterPtr
 Smart pointer.
 
typedef SharedPointer< class GangGangPtr
 Smart pointer.
 
typedef SharedPointer< class PrefixPrefixPtr
 Smart pointer.
 
typedef SharedPointer< class UnformattedSinkUnformattedSinkPtr
 Smart pointer.
 
typedef SharedPointer< class FdSinkFdSinkPtr
 Smart pointer.
 
typedef SharedPointer< class FileSinkFileSinkPtr
 Smart pointer.
 
typedef SharedPointer< class StreamSinkStreamSinkPtr
 Smart pointer.
 
typedef SharedPointer< class SyslogSinkSyslogSinkPtr
 Smart pointer.
 

Enumerations

enum  Importance {
  DEBUG ,
  TRACE ,
  WHERE ,
  MARCH ,
  INFO ,
  WARN ,
  ERROR ,
  FATAL ,
  N_IMPORTANCE
}
 Level of importance for a message. More...
 
enum  AnsiColor {
  COLOR_BLACK = 0 ,
  COLOR_RED = 1 ,
  COLOR_GREEN = 2 ,
  COLOR_YELLOW = 3 ,
  COLOR_BLUE = 4 ,
  COLOR_MAGENTA = 5 ,
  COLOR_CYAN = 6 ,
  COLOR_WHITE = 7 ,
  COLOR_DEFAULT = 8
}
 Colors used by sinks that write to terminals. More...
 

Functions

bool initializeLibrary ()
 Explicitly initialize the library.
 
std::string stringifyImportance (Importance)
 Convert an Importance enum to a string.
 
std::string stringifyColor (AnsiColor)
 Convert an AnsiColor enum to a string.
 
double now ()
 Current system time in seconds.
 
std::string escape (const std::string &)
 Convert a string to its C representation.
 
bool isTerminal (int fd)
 True if fd is a tty.
 
std::ostream & operator<< (std::ostream &o, const MesgProps &props)
 Print the values for all message properties.
 
StreamfirstEnabled (Stream &s1)
 
StreamfirstEnabled (Stream &s1, Stream &s2)
 
StreamfirstEnabled (Stream &s1, Stream &s2, Stream &s3)
 
StreamfirstEnabled (Stream &s1, Stream &s2, Stream &s3, Stream &s4)
 
StreamfirstEnabled (Stream &s1, Stream &s2, Stream &s3, Stream &s4, Stream &s5)
 
void shutdown ()
 Reset global variables to initial states.
 

Variables

DestinationPtr merr
 Library-provided message destination.
 
Facility mlog
 Facility used by Sawyer components.
 
Facilities mfacilities
 Library-provided facility group.
 
SProxy assertionStream
 The stream to be used for assertions.
 

Typedef Documentation

◆ DestinationPtr

Smart pointer.

Sawyer uses reference-counting smart pointers for most objects in order to alleviate the user from having to keep track of which objects own which other objects and when it is safe to delete an object. This is especially convenient for the plumbing part of Sawyer where objects are connected to each other in a lattice and may have multiple parents.

Sawyer uses the following conventions for objects that use smart pointers:

  1. The name of the smart pointer type is the name of the base class followed by "Ptr". For instance, a smart pointer for the FileSink class is named FileSinkPtr.
  2. C++ constructors for such objects are protected to that users don't inadvertently create such an object on the stack and then try to use its address in a smart pointer situation.
  3. Users should use the instance class methods instead of constructors to instantiate an instance of such a class. These methods allocate a new object and return a smart pointer to that object.
  4. Sawyer uses SharedPointer for its smart pointer implementation.

Definition at line 475 of file Message.h.

◆ MultiplexerPtr

Smart pointer.

Sawyer uses reference-counting smart pointers for most objects in order to alleviate the user from having to keep track of which objects own which other objects and when it is safe to delete an object. This is especially convenient for the plumbing part of Sawyer where objects are connected to each other in a lattice and may have multiple parents.

Sawyer uses the following conventions for objects that use smart pointers:

  1. The name of the smart pointer type is the name of the base class followed by "Ptr". For instance, a smart pointer for the FileSink class is named FileSinkPtr.
  2. C++ constructors for such objects are protected to that users don't inadvertently create such an object on the stack and then try to use its address in a smart pointer situation.
  3. Users should use the instance class methods instead of constructors to instantiate an instance of such a class. These methods allocate a new object and return a smart pointer to that object.
  4. Sawyer uses SharedPointer for its smart pointer implementation.

Definition at line 476 of file Message.h.

◆ FilterPtr

Smart pointer.

Sawyer uses reference-counting smart pointers for most objects in order to alleviate the user from having to keep track of which objects own which other objects and when it is safe to delete an object. This is especially convenient for the plumbing part of Sawyer where objects are connected to each other in a lattice and may have multiple parents.

Sawyer uses the following conventions for objects that use smart pointers:

  1. The name of the smart pointer type is the name of the base class followed by "Ptr". For instance, a smart pointer for the FileSink class is named FileSinkPtr.
  2. C++ constructors for such objects are protected to that users don't inadvertently create such an object on the stack and then try to use its address in a smart pointer situation.
  3. Users should use the instance class methods instead of constructors to instantiate an instance of such a class. These methods allocate a new object and return a smart pointer to that object.
  4. Sawyer uses SharedPointer for its smart pointer implementation.

Definition at line 477 of file Message.h.

◆ SequenceFilterPtr

Smart pointer.

Sawyer uses reference-counting smart pointers for most objects in order to alleviate the user from having to keep track of which objects own which other objects and when it is safe to delete an object. This is especially convenient for the plumbing part of Sawyer where objects are connected to each other in a lattice and may have multiple parents.

Sawyer uses the following conventions for objects that use smart pointers:

  1. The name of the smart pointer type is the name of the base class followed by "Ptr". For instance, a smart pointer for the FileSink class is named FileSinkPtr.
  2. C++ constructors for such objects are protected to that users don't inadvertently create such an object on the stack and then try to use its address in a smart pointer situation.
  3. Users should use the instance class methods instead of constructors to instantiate an instance of such a class. These methods allocate a new object and return a smart pointer to that object.
  4. Sawyer uses SharedPointer for its smart pointer implementation.

Definition at line 478 of file Message.h.

◆ TimeFilterPtr

Smart pointer.

Sawyer uses reference-counting smart pointers for most objects in order to alleviate the user from having to keep track of which objects own which other objects and when it is safe to delete an object. This is especially convenient for the plumbing part of Sawyer where objects are connected to each other in a lattice and may have multiple parents.

Sawyer uses the following conventions for objects that use smart pointers:

  1. The name of the smart pointer type is the name of the base class followed by "Ptr". For instance, a smart pointer for the FileSink class is named FileSinkPtr.
  2. C++ constructors for such objects are protected to that users don't inadvertently create such an object on the stack and then try to use its address in a smart pointer situation.
  3. Users should use the instance class methods instead of constructors to instantiate an instance of such a class. These methods allocate a new object and return a smart pointer to that object.
  4. Sawyer uses SharedPointer for its smart pointer implementation.

Definition at line 479 of file Message.h.

◆ ImportanceFilterPtr

Smart pointer.

Sawyer uses reference-counting smart pointers for most objects in order to alleviate the user from having to keep track of which objects own which other objects and when it is safe to delete an object. This is especially convenient for the plumbing part of Sawyer where objects are connected to each other in a lattice and may have multiple parents.

Sawyer uses the following conventions for objects that use smart pointers:

  1. The name of the smart pointer type is the name of the base class followed by "Ptr". For instance, a smart pointer for the FileSink class is named FileSinkPtr.
  2. C++ constructors for such objects are protected to that users don't inadvertently create such an object on the stack and then try to use its address in a smart pointer situation.
  3. Users should use the instance class methods instead of constructors to instantiate an instance of such a class. These methods allocate a new object and return a smart pointer to that object.
  4. Sawyer uses SharedPointer for its smart pointer implementation.

Definition at line 480 of file Message.h.

◆ GangPtr

Smart pointer.

Sawyer uses reference-counting smart pointers for most objects in order to alleviate the user from having to keep track of which objects own which other objects and when it is safe to delete an object. This is especially convenient for the plumbing part of Sawyer where objects are connected to each other in a lattice and may have multiple parents.

Sawyer uses the following conventions for objects that use smart pointers:

  1. The name of the smart pointer type is the name of the base class followed by "Ptr". For instance, a smart pointer for the FileSink class is named FileSinkPtr.
  2. C++ constructors for such objects are protected to that users don't inadvertently create such an object on the stack and then try to use its address in a smart pointer situation.
  3. Users should use the instance class methods instead of constructors to instantiate an instance of such a class. These methods allocate a new object and return a smart pointer to that object.
  4. Sawyer uses SharedPointer for its smart pointer implementation.

Definition at line 481 of file Message.h.

◆ PrefixPtr

Smart pointer.

Sawyer uses reference-counting smart pointers for most objects in order to alleviate the user from having to keep track of which objects own which other objects and when it is safe to delete an object. This is especially convenient for the plumbing part of Sawyer where objects are connected to each other in a lattice and may have multiple parents.

Sawyer uses the following conventions for objects that use smart pointers:

  1. The name of the smart pointer type is the name of the base class followed by "Ptr". For instance, a smart pointer for the FileSink class is named FileSinkPtr.
  2. C++ constructors for such objects are protected to that users don't inadvertently create such an object on the stack and then try to use its address in a smart pointer situation.
  3. Users should use the instance class methods instead of constructors to instantiate an instance of such a class. These methods allocate a new object and return a smart pointer to that object.
  4. Sawyer uses SharedPointer for its smart pointer implementation.

Definition at line 482 of file Message.h.

◆ UnformattedSinkPtr

Smart pointer.

Sawyer uses reference-counting smart pointers for most objects in order to alleviate the user from having to keep track of which objects own which other objects and when it is safe to delete an object. This is especially convenient for the plumbing part of Sawyer where objects are connected to each other in a lattice and may have multiple parents.

Sawyer uses the following conventions for objects that use smart pointers:

  1. The name of the smart pointer type is the name of the base class followed by "Ptr". For instance, a smart pointer for the FileSink class is named FileSinkPtr.
  2. C++ constructors for such objects are protected to that users don't inadvertently create such an object on the stack and then try to use its address in a smart pointer situation.
  3. Users should use the instance class methods instead of constructors to instantiate an instance of such a class. These methods allocate a new object and return a smart pointer to that object.
  4. Sawyer uses SharedPointer for its smart pointer implementation.

Definition at line 483 of file Message.h.

◆ FdSinkPtr

Smart pointer.

Sawyer uses reference-counting smart pointers for most objects in order to alleviate the user from having to keep track of which objects own which other objects and when it is safe to delete an object. This is especially convenient for the plumbing part of Sawyer where objects are connected to each other in a lattice and may have multiple parents.

Sawyer uses the following conventions for objects that use smart pointers:

  1. The name of the smart pointer type is the name of the base class followed by "Ptr". For instance, a smart pointer for the FileSink class is named FileSinkPtr.
  2. C++ constructors for such objects are protected to that users don't inadvertently create such an object on the stack and then try to use its address in a smart pointer situation.
  3. Users should use the instance class methods instead of constructors to instantiate an instance of such a class. These methods allocate a new object and return a smart pointer to that object.
  4. Sawyer uses SharedPointer for its smart pointer implementation.

Definition at line 484 of file Message.h.

◆ FileSinkPtr

Smart pointer.

Sawyer uses reference-counting smart pointers for most objects in order to alleviate the user from having to keep track of which objects own which other objects and when it is safe to delete an object. This is especially convenient for the plumbing part of Sawyer where objects are connected to each other in a lattice and may have multiple parents.

Sawyer uses the following conventions for objects that use smart pointers:

  1. The name of the smart pointer type is the name of the base class followed by "Ptr". For instance, a smart pointer for the FileSink class is named FileSinkPtr.
  2. C++ constructors for such objects are protected to that users don't inadvertently create such an object on the stack and then try to use its address in a smart pointer situation.
  3. Users should use the instance class methods instead of constructors to instantiate an instance of such a class. These methods allocate a new object and return a smart pointer to that object.
  4. Sawyer uses SharedPointer for its smart pointer implementation.

Definition at line 485 of file Message.h.

◆ StreamSinkPtr

Smart pointer.

Sawyer uses reference-counting smart pointers for most objects in order to alleviate the user from having to keep track of which objects own which other objects and when it is safe to delete an object. This is especially convenient for the plumbing part of Sawyer where objects are connected to each other in a lattice and may have multiple parents.

Sawyer uses the following conventions for objects that use smart pointers:

  1. The name of the smart pointer type is the name of the base class followed by "Ptr". For instance, a smart pointer for the FileSink class is named FileSinkPtr.
  2. C++ constructors for such objects are protected to that users don't inadvertently create such an object on the stack and then try to use its address in a smart pointer situation.
  3. Users should use the instance class methods instead of constructors to instantiate an instance of such a class. These methods allocate a new object and return a smart pointer to that object.
  4. Sawyer uses SharedPointer for its smart pointer implementation.

Definition at line 486 of file Message.h.

◆ SyslogSinkPtr

Smart pointer.

Sawyer uses reference-counting smart pointers for most objects in order to alleviate the user from having to keep track of which objects own which other objects and when it is safe to delete an object. This is especially convenient for the plumbing part of Sawyer where objects are connected to each other in a lattice and may have multiple parents.

Sawyer uses the following conventions for objects that use smart pointers:

  1. The name of the smart pointer type is the name of the base class followed by "Ptr". For instance, a smart pointer for the FileSink class is named FileSinkPtr.
  2. C++ constructors for such objects are protected to that users don't inadvertently create such an object on the stack and then try to use its address in a smart pointer situation.
  3. Users should use the instance class methods instead of constructors to instantiate an instance of such a class. These methods allocate a new object and return a smart pointer to that object.
  4. Sawyer uses SharedPointer for its smart pointer implementation.

Definition at line 487 of file Message.h.

◆ BakedDestination

Baked properties for a destination.

Rather than recompute properties every time characters of a message are inserted into a stream, the library computes the properties just once when the first character of a message is inserted. This process is called "baking the properties" and the result is an std::pair that contains a destination and its baked properties.

Definition at line 494 of file Message.h.

◆ BakedDestinations

Baked properties for multiple destinations.

Definition at line 497 of file Message.h.

Enumeration Type Documentation

◆ Importance

Level of importance for a message.

The library defines only these importance levels and does not provide a mechanism by which additional levels can be added. The reasoning is that multiple message facilities should be used to subdivide universal stream of messages into smaller categories, and that message sinks should be able to expect a well defined set of importance levels.

The message importance symbols are sorted numerically so that more critical levels have a higher numeric value than less critical levels.

Enumerator
DEBUG 

Messages intended to be useful primarily to the author of the code.

This level of importance is not often present in publically-released source code and serves mostly as an alternative for authors that like to debug-by-print.

TRACE 

Detailed tracing information useful to end-users that are trying to understand program internals.

These messages can also be thought of as debug messages that are useful to end users. Tracing occurs in two levels, where TRACE is the low-level tracing that includes all traceable messages. It can be assumed that if TRACE messages are enabled then WHERE messages are also enabled to provide the broader context.

WHERE 

Granular tracing information useful to end-users that are trying to understand program internals.

These can also be thought of as debug messages that are useful to end users. Tracing occurs in two levels, where WHERE provides a more granular overview of the trace.

MARCH 

Progress reports and other similar rapidly updating partial messages.

INFO 

Informative messages.

These messages confer information that might be important but do not indicate situations that are abnormal.

WARN 

Warning messages that indicate an unusual situation from which the program was able to fully recover.

ERROR 

Error messages that indicate an abnormal situation from which the program was able to at least partially recover.

FATAL 

Messages that indicate an abnormal situation from which the program was unable to recover.

Producing a message of this type does not in itself terminate the program–it merely indicates that the program is about to terminate. Since one software component's fatal error might be a calling components's recoverable error, exceptions should generally be thrown. About the only time FATAL is used is when a logic assertion is about to fail, and even then it's usually called from inside assert-like functions (see Sawyer::Assert for examples).

N_IMPORTANCE 

Number of distinct importance levels.

Definition at line 313 of file Message.h.

◆ AnsiColor

Colors used by sinks that write to terminals.

Note that most modern terminal emulators allow the user to specify the actual colors that are displayed for each of these, so the display color might not match the color name.

Enumerator
COLOR_BLACK 

ANSI "black" color.

COLOR_RED 

ANSI "red" color.

COLOR_GREEN 

ANSI "green" color.

COLOR_YELLOW 

ANSI "yellow" color.

COLOR_BLUE 

ANSI "blue" color.

COLOR_MAGENTA 

ANSI "magenta" color.

COLOR_CYAN 

ANSI "cyan" color.

COLOR_WHITE 

ANSI "white" color.

COLOR_DEFAULT 

ANSI default color.

Definition at line 343 of file Message.h.

Function Documentation

◆ initializeLibrary()

bool Sawyer::Message::initializeLibrary ( )

Explicitly initialize the library.

This initializes any global objects provided by the library to users. This happens automatically for many API calls, but sometimes needs to be called explicitly. Calling this after the library has already been initialized does nothing. The function always returns true.

Thread safety: This function is thread-safe.

◆ operator<<()

std::ostream & Sawyer::Message::operator<< ( std::ostream &  o,
const MesgProps props 
)

Print the values for all message properties.

See also
MesgProps::print().

◆ shutdown()

void Sawyer::Message::shutdown ( )

Reset global variables to initial states.

This function resets global variables such as merr, mlog, and mfacilities to their default-constructed state. Sometimes it's necessary to do this during program exit, otherwise the C++ runtime might terminate the Boost thread synchronization library before Sawyer, which leads to exceptions or segmentation faults when Sawyer's stream destructors run. In fact, initializeLibrary arranges for this shutdown function to be called by exit.

Variable Documentation

◆ merr

DestinationPtr Sawyer::Message::merr
extern

Library-provided message destination.

This is the top of a lattice that sends all messages to file descriptor 2, which is usually standard error.

◆ mlog

Facility Sawyer::Message::mlog
extern

Facility used by Sawyer components.

This facility is added to the mfacilities group with the name "sawyer".

Referenced by Sawyer::CommandLine::Boost::command_line_parser::command_line_parser().

◆ mfacilities

Facilities Sawyer::Message::mfacilities
extern

Library-provided facility group.

When the library is initialized, this group contains only mlog with the name "sawyer". Users are free to manipulate this facility however they choose, and if everyone uses this group then all the facilities across all users can be controlled from this one place.

Referenced by Sawyer::Message::FacilitiesGuard::FacilitiesGuard().

◆ assertionStream

SProxy Sawyer::Message::assertionStream
extern

The stream to be used for assertions.

The default is to use Sawyer::Message::mlog[FATAL]. This variable is initialized at the first call to Assert::fail if it is a null pointer. Users can assign a different stream to it any time before then:

int main(int argc, char *argv[]) {
Sawyer::Message::assertionStream = Sawer::Message::mlog[FATAL];
SProxy assertionStream
The stream to be used for assertions.
@ FATAL
Messages that indicate an abnormal situation from which the program was unable to recover.
Definition Message.h:332