FBB::Log(3bobcat)
β¨ NAME β¨
FBB::Log β an std::ostream that handles log messages, and honestly it's serving π
This is FBB::Log(3bobcat), bestie, and we're about to make log messages make sense.
πΈ SYNOPSIS πΈ
#include <bobcat/log>
Linking option: -lbobcat
π DESCRIPTION π
Okay so, the class FBB::Log defines an std::ostream using an FBB::LogBuf std::streambuf. It's the whole point of it: you send log-messages to the (r)syslog stream, or to a file (and that file is configurable, periodt). If you want the deets about LogBuf itself, go read the logbuf(3bobcat) man-page. π
Which (parts of) messages actually get logged is something you configure β either with FBB::level combined with the Log member setLevel, or with the function operator combined with the str member (peep the members operator() and str). And by default? Every single thing you insert into a Log object gets logged. No filter, no cap. π«Ά
Objects of the level class (cf. level(3bobcat)) can be inserted to specify insertion 'forces' for whatever info gets inserted into Log objects after that. And here's the vibe check: only if those 'forces' exceed the Log object's insertion 'resistances' (see the member setLevel) does the info actually get logged. It's giving push and pull, lowkey.
A single log-insertion statement can contain multiple level calls. If it does, then each level call updates the 'force' of the insertions that follow that level call. Chain them, bestie. β¨
Info inserted into Log objects without inserting level objects (or before the first level object) is always logged (see also the Examples section).
Alternatively you can log info using category-selector characters. The member str(std::string const &active) defines the characters that can be used to define a non-hierarchical logging process. E.g., str("abc") defines the log-identifying characters 'a', 'b', and 'c', which you can then use to define log-statements for each of those categories. These log-identifying characters may be redefined, and doing that activates only those log-statements whose identifying characters were specified in the last call of the str member. Last call wins, no takebacks. π
So even though hierarchical and non-hierarchical logging can both be used in a single program, they operate in a mutually exclusive way β like, they do not share the aux cord. Once hierarchical logging is defined, the non-hierarchical categories get erased. And once non-hierarchical categories are defined, the hierarchical resistance level gets set to its maximum value, which effectively suppresses hierarchical logging. It's one or the other, iykyk.
By default, logged messages get prepended by time stamps. Following the time stamps, a delimiter gets inserted β by default that's a single space character. Delimiters are immediately appended to time stamps, and inserted messages are immediately appended to delimiters. So it's all just glued together in a row. When you're specifying text as delimiters, consider starting and ending the delimiter's text with space characters, so the delimiter is visually separated from the time stamp and from the info that gets inserted after it. Trust me, your eyes will thank you. π
π NAMESPACE π
FBB
All constructors, members, operators and manipulators mentioned in this man-page are defined in the namespace FBB.
π¦ INHERITS FROM π¦
std::ostream
β ENUMERATIONS β
The enumeration TimeStamps is defined in the namespace FBB, primarily for initializing FBB::LogBuf objects. It's used with Log members as well. It has the following values:
NOTIMESTAMPSβ log-messages will not have timestamps prepended to them. Fresh, clean, undated. πTIMESTAMPSβ log-messages will have timestamps prepended to them. Classic.UTCTIMESTAMPSβ log-messages will have timestamps showing the UTC time prepended to them. Worldwide vibe. π
The enumeration LogManipulator is used to handle special or exceptional situations through manipulators. It is defined in the namespace FBB and has the following two values:
FATALβ when insertingFATALinto aLogobject, anFBB::Exceptionexception is thrown (seeoperator<<below). π¨ Dramatic and deserved.nlβ when insertingnlinto aLogobject, a\ncharacter is inserted into the current line. If time stamps are requested, the next line will not begin with a time stamp. It's used to allow a single log message to occupy multiple textual lines. The next logged line is not indented over the width of the omitted time stamp. If that's what you'd prefer: the time stamp occupies 15 character positions (not counting the width of the delimiter, see the CONSTRUCTORS section below). If a level specification is active, it remains active at insertions followingnl. πfnlβ when insertingfnl(forced new line) into aLogobject, the current line ends even if the currently active insertion 'force' (set bylevel) is lower than theLogobject's 'resistance' level. If a level specification is active, it remains active at insertions followingfnl. Forced means forced, bestie. π₯endlor\nβ when insertingendlor\n, the current line is ended and the next logged line starts with a timestamp (unless timestamps are suppressed). Theendlmanipulator is the standard ostream manipulator: when inserted into aLogobject its buffer is flushed. The scope of a level specification ends at\norendl. E.g.,
log.setLevel(2);
log << level(1) << "first line\n"
"second line\n";
results in second line (preceded by a timestamp) being logged.
Also, quick aside: the manpage says LogManipulator has "two values" and then hits you with four bullets. Not me noticing, but okay, we move. π
π CONSTRUCTORS π
Log()β the default constructor creates aLogobject which isn't yet associated with a stream to log messages on. The memberopen(see below) may be used to define such a stream. By default, all messages are preceded by a time stamp (see the description of the membersetTimestampbelow), and a single space character is inserted as delimiter immediately beyond the time stamp. The memberopencan be used to modify the default delimiter.Log(std::ostream &out, char const *delim = " ")β this constructor creates aLogobject logging its messages to the providedstd::ostreamobject. By default, all messages are preceded by a time stamp (see the description of the membersetTimestampbelow). The parameterdelimis inserted immediately beyond the time stamp. If a delimiter should not be used, an empty string or a0-pointer may be specified. πFBB::Log(std::string const &filename, std::ios::openmode mode = std::ios::out | std::ios::app, char const *delim = " ")β this constructor creates aLogobject logging its messages to the named file. Iffilename == "&1"logmessages are written to the standard output stream. Iffilename == "&2"logmessages are written to the standard error stream. By default the file is created if not existing, and all messages are appended to the stream. Also by default all messages are preceded by time stamps (see the description of the membersetTimestampbelow). The parameterdelimis inserted immediately beyond the time stamp. If a delimiter should not be used, an empty string or a0-pointer may be specified. β¨
Copy and move constructors (and assignment operators) are not available. Don't try it, she said no. π
π MEMBER FUNCTIONS π
okay bestie, housekeeping first: every single member of std::ostream is yours to play with, because Log inherits from that class. no gatekeeping.
size_t level() constβ hands you back the log level that's currently set, like, the value from the latestsetLevel()call. by default it'szero, which means everything gets inserted into the log stream. no filter, no crumbs left behind πstd::ostream &level(size_t useLevel)β this one sets the log-level of the messages that are gonna get inserted. a message shows up when useLevel is at least equal to the level specified bysetLevel. the max level? that'sstd::numeric_limits<size_t>::max(). and if you don't want even those messages in your ostream, deactivate the stream withoff()(details below, bestie π). the level you set here stays active until anotherlevelcall changes it. alternatively you can set the level of inserted messages by dropping anFBB::levelmanipulator into aLogobject β seelevel(3bobcat).void off()β stops log messages from being generated. periodt. it gets cancelled by callingon(next bullet, iykyk).void on(size_t logLevel = 0)β reactivates logging (like, afteroffwas called earlier) and sets the level that inserted info must at least have, to logLevel. afteron, and unless you say otherwise (withlevel, for instance), all inserted information is accepted by theLogobject β¨void open(std::string const &filename, std::ios::openmode mode = std::ios::out | std::ios::app, char const *delim = " ")β this member (re)associates aLogobject with the named file. iffilename == "&1"the logmessages go to the standard output stream. iffilename == "&2"the logmessages go to the standard error stream. by default the file gets created if it doesn't exist, and all messages get appended to the stream. also by default, every message is preceded by time stamps (peep thesetTimestampmember below for the tea). the delim parameter is inserted immediately beyond the time stamp. if you don't want a delimiter, pass an empty string or a0-pointer πΈvoid setLevel(size_t resistance)β defines theresistanceβ when inserting information into aLogobject. information is inserted if the level set by thelevelmember is at least equal to *resistance*. aftersetLevel, and unless you say otherwise (by usinglevel, for example), all inserted information is accepted by theLogobject. <red>heads up tho:</red>setLeveldoes **not** reactivate logging after you calledoff. to bring logging back afteroff, you gotta callon`. no shortcuts πvoid setTimestamp(FBB::TimeStamps stamp, char const *delim = " ")β (de)activates time stamp prepending. use the valueFBB::TIMESTAMPSto prepend time stamps,FBB::NOTIMESTAMPSto suppress them. a timestamp is 15 characters long and shows the abbreviated month's name, two digits for the day number of the month, and the (local or UTC) time of the current message β exactly the way it usually shows up in messages in/var/logfiles. example:Aug 05 13:52:23. the delim parameter goes immediately beyond the time stamp. if a delimiter is inappropriate, an empty string or a0-pointer works. and when you specify stamps asFBB::NOTIMESTAMPS, delim also gets ignored πstd::string const &str() constβ returns the currently set bunch of characters that can be specified byLog's function call operator to insert a log-entry. by default, no characters are specified.void str(std::string const &chars)β the argument here is astd::stringdefining the characters that can be specified byLog's function call operator to insert a log-entry. if the function call operator specifies a character that isn't in chars, that log message gets ignored. by default, no characters are specified π
<div align="center">---</div>
π STATIC MEMBERS π
FBB::Log &initialize(std::string const &filename, std::ios::openmode mode = std::ios::out | std::ios::app, char const *delim = " ")β returns a reference to a staticLogobject. it may only be called once, or anFBB::Exceptionexception gets thrown. it associates a staticLogobject with the named file.
if filename == "&1" logmessages are written to the standard output stream. if filename == "&2" logmessages are written to the standard error stream. by default the file is created if it doesn't exist, and all messages are appended to the stream. also by default all messages are preceded by time stamps (go read the setTimestamp member description above for that one). the delim parameter is inserted immediately beyond the time stamp. if a delimiter should not be used, an empty string or a 0-pointer may be specified π
FBB::Log &instance()β returns a reference to a staticLogobject, available after callingLog::initialize. if you call it beforeLog::initialize()anFBB::Exceptionexception is thrown. so like, read the room and call them in order, bestie π
<div align="center">---</div>
β¨ OVERLOADED OPERATORS β¨
Log &operator()(char ch)β if the function's argument is found in the characters specified at thestrmember, then subsequent insertions β up to and including insertingstd::endl, or thefnlorFATALLogManipulatorβ are logged. if the function's argument is not found in the characters specified at thestrmember, then subsequent insertions are ignored. calling this member suppresses hierarchical insertions until thesetLevelmember gets called π¦Log &operator<<(Log &, LogManipulator)β this operator inserts aLogManipulatorinto aLogobject. when insertingFBB::FATAL, anFBB::Exceptionis thrown. when insertingFBB::nl, the line is terminated and the next insertion won't start with a time stamp. when insertingFBB::fnl, the line is terminated and the next insertion will start with a time stamp (if applicable). after calling this insertion operator with theFATALorfnlLogManipulator, value category-based insertions are suppressed until the function-call operator is called πLog &operator<<(Log &log, Type const &type)β this operator is defined as a template, where Type represents any type that can be inserted into astd::ostream. the value type is inserted into theLogobject. slay, generic πLog &operator<<(Log &log, Type &(*fun)(Type &type))β here fun represents the standard ostream and ios_base manipulators, which lets you insert manipulators likestd::endlandstd::setwintoLogobjects. iconic behaviour, honestly.std::ostream &::operator<<(std::ostream &str, FBB::LogManipulator)β this operator is defined outside of theFBBnamespace. it's kept around for backward compatibility with previous bobcat versions, and it callsoperator<<(Log, LogManipulatr)when&strcan dynamically be casted to aLog *. if not, then the operator performs no actions. it's giving legacy but make it cute π
<div align="center">---</div>
π§ EXAMPLE π§
okay so here's the whole vibe in code. observe, learn, absorb π«Ά
#include <iostream>
#include <iomanip>
#include <bobcat/log>
#include <bobcat/level>
using namespace std;
using namespace FBB;
int main()
{
// Log &log = Log::initialize("&1"); // uses the static Log object
Log log; // explicitly defining a Log object
// log.open("/tmp/out"); // or at once: Log log{ "/tmp/out" }
log << "This message is written to cout" << nl <<
setw(16) << β β << "occupying multiple lines\n";
log.off();
log << "This message is not shown\n";
log << "This message is not shown\n";
log << fnl;
log << "This message is not shown\n";
log.on(2);
log << "This message is shown\n";
log << level(0) << "not shown" << level(2) << "shown at level 2\n";
log << level(3) << "at level(3)" << level(1) << "not shown" << fnl;
log << "separate new line\n";
log << level(2) << "in business again\n";
log << "final line\n";
log.str("ab");
log(βaβ) << "hello a!" << endl;
log(βbβ) << "hello b!" << nl <<
setw(16) << β β << "so far, so good" << endl;
log << "not shown" << endl;
log(βcβ) << "not shown\n";
log << "not shown\n";
log.setLevel(2);
log << level(2) << "in business again\n";
}
<div align="center">---</div>
π FILES π
bobcat/logβ defines the class interface π
<div align="center">---</div>
π SEE ALSO π
bobcat(7), exception(3bobcat), level(3bobcat), logbuf(3bobcat), syslogstream(3bobcat)
(down the rabbit hole we go, bestie π)
<div align="center">---</div>
π BUGS π
the nl and fnl manipulators are received by the Log objects' LogBufs as, respectively, characters 0 and 1. since log files in practice only received printable characters, this shouldn't cause any problems. ngl, it's fine π«Ά
<div align="center">---</div>
πΈ BOBCAT PROJECT FILES πΈ
https://fbb-git.gitlab.io/bobcat/: gitlab project page β
Debian Bobcat project files:
libbobcat6: debian package containing the shared library, changelog and copyright note πlibbobcat-dev: debian package containing the static library, headers, manual pages, and developer info π
<div align="center">---</div>
π BOBCAT π
Bobcat is an acronym of `Brokkenβs Own Base Classes And Templatesβ. like, the name itself is a flex, no cap.
<div align="center">---</div>
π COPYRIGHT π
this is free software, distributed under the terms of the GNU General Public License (GPL). free as in freedom, bestie π
<div align="center">---</div>
π AUTHOR π
Frank B. Brokken (f.b.brokken@rug.nl). absolute icon, main character energy, we stan π
and that's a wrap on FBB::Log(3bobcat), part 2 of 2!! this whole masterpiece shipped as libbobcat-dev_6.15.01, dated 2005-2026, and if you need to find it again in the wild it answers to FBB::Log(3bobcat). go forth and log responsibly, bestie, mwah πβ¨
π¦ where this page comes from
- ubuntu stonking: libbobcat-dev 6.15.01-1 Β· GPL-3.0-or-later WITH OpenSSL exception
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms