clutchlog/docs/index.html
2024-09-10 16:21:54 +02:00

581 lines
61 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.9.4"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>clutchlog: Clutchlog — versatile (de)clutchable spatial logging</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
<link href="doxygen-style.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr id="projectrow">
<td id="projectlogo"><img alt="Logo" src="clutchlog_logo.svg"/></td>
<td id="projectalign">
<div id="projectname">clutchlog<span id="projectnumber">&#160;0.17</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.9.4 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
var searchBox = new SearchBox("searchBox", "search",'Search','.html');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
$(function() {
initMenu('',true,false,'search.php','Search');
$(document).ready(function() { init_search(); });
});
/* @license-end */
</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
$(document).ready(function(){initNavTree('index.html',''); initResizable(); });
/* @license-end */
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div><div class="header">
<div class="headertitle"><div class="title">Clutchlog — versatile (de)clutchable spatial logging </div></div>
</div><!--header-->
<div class="contents">
<div class="toc"><h3>Table of Contents</h3>
<ul><li class="level1"><a href="#autotoc_md0">Features</a></li>
<li class="level1"><a href="#autotoc_md1">Example</a></li>
<li class="level1"><a href="#autotoc_md2">Rationale</a></li>
<li class="level1"><a href="#autotoc_md3">Basic Usage</a><ul><li class="level2"><a href="#autotoc_md4">Calls</a></li>
<li class="level2"><a href="#autotoc_md5">Log level semantics</a></li>
<li class="level2"><a href="#autotoc_md6">Location filtering</a></li>
<li class="level2"><a href="#autotoc_md7">Output Configuration</a><ul><li class="level3"><a href="#autotoc_md8">Log Format</a></li>
</ul>
</li>
<li class="level2"><a href="#autotoc_md9">Output Styling</a><ul><li class="level3"><a href="#autotoc_md10">Typographic Style</a></li>
<li class="level3"><a href="#autotoc_md11">Colors</a></li>
<li class="level3"><a href="#autotoc_md12">Value-dependant Format Tags</a></li>
</ul>
</li>
</ul>
</li>
<li class="level1"><a href="#autotoc_md13">Advanced Usage</a><ul><li class="level2"><a href="#autotoc_md14">More Output Configuration</a><ul><li class="level3"><a href="#autotoc_md15">Dump Format</a></li>
<li class="level3"><a href="#autotoc_md16">Stack Depth Mark</a></li>
<li class="level3"><a href="#autotoc_md17">Horizontal Filling</a></li>
<li class="level3"><a href="#autotoc_md18">Stack Depth</a></li>
<li class="level3"><a href="#autotoc_md19">Filename</a></li>
</ul>
</li>
<li class="level2"><a href="#autotoc_md20">Disabled calls</a></li>
<li class="level2"><a href="#autotoc_md21">Low-level API</a></li>
<li class="level2"><a href="#autotoc_md22">(De)clutch any function call</a></li>
<li class="level2"><a href="#autotoc_md23">(De)clutch any code section</a></li>
<li class="level2"><a href="#autotoc_md24">Manually Increase Stack Depth</a></li>
</ul>
</li>
<li class="level1"><a href="#autotoc_md25">Examples</a></li>
<li class="level1"><a href="#autotoc_md26">Limitations</a><ul><ul><li class="level3"><a href="#autotoc_md27">System-dependent stack depth</a></li>
<li class="level3"><a href="#autotoc_md28">System-dependent horizontal fill</a></li>
<li class="level3"><a href="#autotoc_md29">Dependencies</a></li>
<li class="level3"><a href="#autotoc_md30">Variable names within the CLUTCHLOG macro</a></li>
<li class="level3"><a href="#autotoc_md31">Features</a></li>
</ul>
</ul>
</li>
<li class="level1"><a href="#autotoc_md32">Build and tests</a></li>
<li class="level1"><a href="#autotoc_md33">Usage as a Git submodule</a></li>
</ul>
</div>
<div class="textblock"><p ><a class="anchor" id="md_README"></a></p>
<p ><b>Clutchlog is a <em>spatial</em> logging system that targets versatile <em>debugging</em>.</b> <b>It allows to (de)clutch messages for a given: log level, source code location or call stack depth.</b></p>
<ul>
<li><a href="https://github.com/nojhan/clutchlog">Project page on Github</a></li>
<li><a href="https://nojhan.github.io/clutchlog/">Documentation</a></li>
</ul>
<p align="center"></p>
<p >&lt;img alt"Clutchlog logo" src="https://raw.githubusercontent.com/nojhan/clutchlog/master/docs/clutchlog_logo.svg" width="400" /&gt; </p>
<h1><a class="anchor" id="autotoc_md0"></a>
Features</h1>
<p >Clutchlog allows to select which log messages will be displayed, based on their locations:</p>
<ul>
<li><b>Classical log levels</b>: each message has a given detail level and it is displayed if you ask for a at least the same one.</li>
<li><b>Call stack depth</b>: you can ask to display messages within functions that are called up to a given stack depth.</li>
<li><b>Source code location</b>: you can ask to display messages called from given files, functions and line number, all based on regular expressions.</li>
</ul>
<p >Additionally, Clutchlog will do its best to allow the compiler to optimize out calls, for instance debug messages in "Release" builds.</p>
<p >Additional features:</p>
<ul>
<li><b>Templated log format</b>, to easily design your own format.</li>
<li><b>Powerful Styling</b>. Clutchlog comes with many options to color its output, for example by using colors with a semantic meaning, so that visually parse the logs is easy.</li>
<li><b>Macro to dump the content of a container in a file</b> with automatic naming (yes, it is useful for fast debugging).</li>
<li><b>Generic clutching wrapper</b>, to wrap any function call. Useful to (de)clutch <em>asserts</em> for example.</li>
</ul>
<h1><a class="anchor" id="autotoc_md1"></a>
Example</h1>
<p >Adding a message is a simple as calling a macro (which is declutched in Debug build type, when <code>NDEBUG</code> is not defined): </p><div class="fragment"><div class="line"><a class="code hl_define" href="group___use_macros.html#ga6f86187e2b35e7e1907d688f504a197d">CLUTCHLOG</a>(info, <span class="stringliteral">&quot;matrix size: &quot;</span> &lt;&lt; m &lt;&lt; <span class="stringliteral">&quot;x&quot;</span> &lt;&lt; n);</div>
<div class="ttc" id="agroup___use_macros_html_ga6f86187e2b35e7e1907d688f504a197d"><div class="ttname"><a href="group___use_macros.html#ga6f86187e2b35e7e1907d688f504a197d">CLUTCHLOG</a></div><div class="ttdeci">#define CLUTCHLOG(LEVEL, WHAT)</div><div class="ttdoc">Log a message at the given level.</div><div class="ttdef"><b>Definition:</b> <a href="clutchlog_8h_source.html#l00099">clutchlog.h:99</a></div></div>
</div><!-- fragment --><p >To configure the display, you indicate the three types of locations, for example in your <code>main</code> function: </p><div class="fragment"><div class="line"><span class="keyword">auto</span>&amp; log = <a class="code hl_function" href="classclutchlog.html#a6e2a5e98fa9f722d90ba6515895543ac">clutchlog::logger</a>();</div>
<div class="line">log.depth(2); <span class="comment">// Log functions called from &quot;main&quot; but not below.</span></div>
<div class="line">log.threshold(<span class="stringliteral">&quot;Info&quot;</span>); <span class="comment">// Log only &quot;info&quot;, &quot;warning&quot;, &quot;error&quot; or &quot;critical&quot; messages.</span></div>
<div class="line">log.file(<span class="stringliteral">&quot;algebra/.*&quot;</span>); <span class="comment">// Will match any file in the &quot;algebra&quot; directory.</span></div>
<div class="line">log.func(<span class="stringliteral">&quot;(mul|add|sub|div)&quot;</span>); <span class="comment">// Will match &quot;multiply&quot;, for instance.</span></div>
<div class="ttc" id="aclassclutchlog_html_a6e2a5e98fa9f722d90ba6515895543ac"><div class="ttname"><a href="classclutchlog.html#a6e2a5e98fa9f722d90ba6515895543ac">clutchlog::logger</a></div><div class="ttdeci">static clutchlog &amp; logger()</div><div class="ttdoc">Get the logger instance.</div><div class="ttdef"><b>Definition:</b> <a href="clutchlog_8h_source.html#l00307">clutchlog.h:307</a></div></div>
</div><!-- fragment --><p >Example of a real-life log session (as seen in the <a href="https://github.com/jdreo/frictionlesser">frictionlesser</a> software):</p>
<p ><img src="https://raw.githubusercontent.com/nojhan/clutchlog/master/demo.png" alt="A log screen capture with full details, showing colored messages and location." class="inline"/></p>
<p >Demo showing fancy styling:</p>
<p ><img src="https://raw.githubusercontent.com/nojhan/clutchlog/master/demo-extra.png" alt="A log screen capture showing fancy coloring of text lines." class="inline"/></p>
<p >For more detailled examples, see the "Usage" sections below and the <code>tests</code> directory.</p>
<h1><a class="anchor" id="autotoc_md2"></a>
Rationale</h1>
<p >Most of existing logging systems targets service events storage, like fast queuing of transactions in a round-robin database. Their aim is to provide a simple interface to efficiently store messages somewhere, which is appropriated when you have a well known service running and you want to be able to trace complex users interactions across its states.</p>
<p >Clutchlog, however, targets the <em>debugging</em> of a (typically single-run) program. While you develop your software, it's common practice to output several detailled informations on the internal states around the feature you are currently programming. However, once the feature is up and running, those detailled informations are only useful if you encounter a bug traversing this specific part.</p>
<p >While tracing a bug, it is tedious to uncomment old debugging code (and go on the build-test cycle) or to set up a full debugger session that displays all appropriate data (with ad-hoc fancy hooks).</p>
<p >To solve this problem, Clutchlog allows to disengage <em>at runtime</em> your debug log messages in various parts of the program, allowing for the fast tracking of a bug across the execution.</p>
<h1><a class="anchor" id="autotoc_md3"></a>
Basic Usage</h1>
<h2><a class="anchor" id="autotoc_md4"></a>
Calls</h2>
<p >The main entrypoint is the <code>CLUTCHLOG</code> macro, which takes the desired log level and message. The message can be anything that can be output in an <code>ostringstream</code>. </p><div class="fragment"><div class="line"><span class="comment">// Simple string:</span></div>
<div class="line"><a class="code hl_define" href="group___use_macros.html#ga6f86187e2b35e7e1907d688f504a197d">CLUTCHLOG</a>(info, <span class="stringliteral">&quot;hello world&quot;</span>);</div>
<div class="line"> </div>
<div class="line"><span class="comment">// Serialisable variable:</span></div>
<div class="line"><span class="keywordtype">double</span> value = 0;</div>
<div class="line"><a class="code hl_define" href="group___use_macros.html#ga6f86187e2b35e7e1907d688f504a197d">CLUTCHLOG</a>(error, value);</div>
<div class="line"> </div>
<div class="line"><span class="comment">// passed using inline output stream operators:</span></div>
<div class="line"><a class="code hl_define" href="group___use_macros.html#ga6f86187e2b35e7e1907d688f504a197d">CLUTCHLOG</a>(debug, <span class="stringliteral">&quot;hello &quot;</span> &lt;&lt; value &lt;&lt; <span class="stringliteral">&quot; world&quot;</span>);</div>
</div><!-- fragment --><p >There is also a macro to dump the content of an iterable within a separate file: <code>CLUTCHDUMP</code>. This function takes care of incrementing a numeric suffix in the file name, if an existing file with this name exists. </p><div class="fragment"><div class="line">std::vector&lt;int&gt; v(10);</div>
<div class="line">std::generate(v.begin(), v.end(), std::rand);</div>
<div class="line"><a class="code hl_define" href="group___use_macros.html#ga572e3aa19d8b39e3ed0b9e91961104c2">CLUTCHDUMP</a>(debug, vec, <span class="stringliteral">&quot;test_{n}.dat&quot;</span>);</div>
<div class="line"><span class="comment">/* Will output in cat &quot;rand_0.dat&quot;</span></div>
<div class="line"><span class="comment">* # [t-dump] Info in main (at depth 5) @ /home/nojhan/code/clutchlog/tests/t-dump.cpp:22</span></div>
<div class="line"><span class="comment">* 1804289383</span></div>
<div class="line"><span class="comment">* 846930886</span></div>
<div class="line"><span class="comment">* 1681692777</span></div>
<div class="line"><span class="comment">*/</span></div>
<div class="ttc" id="agroup___use_macros_html_ga572e3aa19d8b39e3ed0b9e91961104c2"><div class="ttname"><a href="group___use_macros.html#ga572e3aa19d8b39e3ed0b9e91961104c2">CLUTCHDUMP</a></div><div class="ttdeci">#define CLUTCHDUMP(LEVEL, CONTAINER, FILENAME)</div><div class="ttdoc">Dump the given container.</div><div class="ttdef"><b>Definition:</b> <a href="clutchlog_8h_source.html#l00108">clutchlog.h:108</a></div></div>
</div><!-- fragment --><p> Note that if you pass a file name without the <code>{n}</code> tag, the file will be overwritten as is.</p>
<h2><a class="anchor" id="autotoc_md5"></a>
Log level semantics</h2>
<p >Log levels use a classical semantics for a human skilled in the art, in decreasing order of importance:</p>
<ul>
<li><em>Critical</em>: an error that cannot be recovered. For instance, something which will make a server stop right here.</li>
<li><em>Error</em>: an error that invalidates a function, but may still be recovered. For example, a bad user input that will make a server reset its state, but not crash.</li>
<li><em>Warning</em>: something that is strange, but is probably legit. For example a default parameter is set because the user forgot to indicate its preference.</li>
<li><em>Progress</em>: the state at which computation currently is.</li>
<li><em>Note</em>: some state worth noting to understand what's going on.</li>
<li><em>Info</em>: any information that would help ensuring that everything is going well.</li>
<li><em>Debug</em>: data that would help debugging the program if there was a bug later on.</li>
<li><em>XDebug</em>: debugging information that would be heavy to read.</li>
</ul>
<p >Note: the log levels constants are lower case (for example: <code>clutchlog::level::xdebug</code>), but their string representation is not (e.g. "XDebug", this should be taken into account when using <code><a class="el" href="classclutchlog.html#a3cb0e4f43a4cadf1966001ad7c9861f4" title="Set the log level (below which logs are not printed) with an identifier.">clutchlog::threshold</a></code> or <code><a class="el" href="classclutchlog.html#acebed8c9df9204f22bf8488e62e1cedd" title="Return the log level tag corresponding to the given pre-configured name.">clutchlog::level_of</a></code>).</p>
<h2><a class="anchor" id="autotoc_md6"></a>
Location filtering</h2>
<p >To configure the global behaviour of the logger, you must first get a reference on its (singleton) instance: </p><div class="fragment"><div class="line"><span class="keyword">auto</span>&amp; log = <a class="code hl_function" href="classclutchlog.html#a6e2a5e98fa9f722d90ba6515895543ac">clutchlog::logger</a>();</div>
</div><!-- fragment --><p >One can configure the location(s) at which messages should actually be logged: </p><div class="fragment"><div class="line">log.depth(3); <span class="comment">// Depth of the call stack, defaults to the maximum possible value.</span></div>
<div class="line">log.threshold(clutchlog::level::error); <span class="comment">// Log level, defaults to error.</span></div>
</div><!-- fragment --><p> Current levels are defined in an enumeration as <code><a class="el" href="classclutchlog.html#a10fd25a1b51c8c95bd6d876ce1b4b928" title="Available log levels.">clutchlog::level</a></code>: </p><div class="fragment"><div class="line"><span class="keyword">enum</span> level {critical=0, error=1, warning=2, progress=3, note=4, info=5, debug=6, xdebug=7};</div>
</div><!-- fragment --><p >File, function and line filters are indicated using (ECMAScript) regular expressions: </p><div class="fragment"><div class="line">log.file(<span class="stringliteral">&quot;.*&quot;</span>); <span class="comment">// File location, defaults to any.</span></div>
<div class="line">log.func(<span class="stringliteral">&quot;.*&quot;</span>); <span class="comment">// Function location, defaults to any.</span></div>
<div class="line">log.line(<span class="stringliteral">&quot;.*&quot;</span>); <span class="comment">// Line location, defaults to any.</span></div>
</div><!-- fragment --><p> A shortcut function can be used to filter all at once: </p><div class="fragment"><div class="line">log.location(file, func, line); <span class="comment">// Defaults to any, second and last parameters being optional.</span></div>
</div><!-- fragment --><p >Strings may be used to set up the threshold: </p><div class="fragment"><div class="line">log.threshold(<span class="stringliteral">&quot;Error&quot;</span>); <span class="comment">// You have to know the exact —case sensitive— string.</span></div>
</div><!-- fragment --><p> Note that the case of the log levels strings matters (see below).</p>
<h2><a class="anchor" id="autotoc_md7"></a>
Output Configuration</h2>
<p >The output stream can be configured using the <code><a class="el" href="classclutchlog.html#a7fd7c7bd3668c537061c314a619a336d" title="Set the output stream on which to print.">clutchlog::out</a></code> method: </p><div class="fragment"><div class="line">log.out(std::clog); <span class="comment">// Defaults to clog.</span></div>
</div><!-- fragment --><p >The format of the messages can be defined with the <code><a class="el" href="classclutchlog.html#a656c277e074b64728cca871f2b484d1c" title="Set the template string.">clutchlog::format</a></code> method, passing a string with standardized tags surrounded by <code>{}</code>: </p><div class="fragment"><div class="line">log.format(<span class="stringliteral">&quot;{msg}&quot;</span>);</div>
</div><!-- fragment --><p> Available tags are:</p>
<ul>
<li><code>{msg}</code>: the logged message,</li>
<li><code>{level}</code>: the current log level (i.e. <code>Critical</code>, <code>Error</code>, <code>Warning</code>, <code>Progress</code>, <code>Note</code>, <code>Info</code>, <code>Debug</code> or <code>XDebug</code>),</li>
<li><code>{level_letter}</code>: the first letter of the current log level,</li>
<li><code>{level_short}</code>: the current log level, printed in only four letters,</li>
<li><code>{file}</code>: the current file name,</li>
<li><code>{func}</code>: the current function,</li>
<li><code>{line}</code>: the current line number,</li>
<li><code>{level_fmt}</code>: the style of the current level (i.e. configured with <code><a class="el" href="classclutchlog.html#ac3ec55057b9c734b66f169bf43dbd591" title="Set the style (color and typo) of the given log level.">clutchlog::style</a></code>),</li>
<li><code>{filehash_fmt}</code>: a style for file names, which is value-dependant (see <code><a class="el" href="classclutchlog.html#ae17db5808155fbc6dc48b4727d0c3abf" title="Set the candidate styles for value-dependant file name formatting.">clutchlog::filehash_styles</a></code>),</li>
<li><code>{funchash_fmt}</code>: a style for function names, which is value-dependant (see <code><a class="el" href="classclutchlog.html#acbb50f6306ebb3c8b0d1a52e7f327416" title="Set the candidate styles for value-dependant function name formatting.">clutchlog::funchash_styles</a></code>).</li>
</ul>
<p >Some tags are only available on POSIX operating systems as of now:</p><ul>
<li><code>{name}</code>: the name of the current binary,</li>
<li><code>{depth}</code>: the current depth of the call stack,</li>
<li><code>{depth_marks}</code>: as many chevrons <code>&gt;</code> as there is calls in the stack,</li>
<li><code>{depth_fmt}</code>: a style depending on the current depth value (see <code><a class="el" href="classclutchlog.html#a08310b92e86687349e70f56f9ac1d656" title="Set the styles for value-dependant depth formatting.">clutchlog::depth_styles</a></code>),</li>
<li><code>{hfill}</code>: Inserts a sequence of characters that will stretch to fill the space available in the current terminal, between the rightmost and leftmost part of the log message.</li>
</ul>
<h3><a class="anchor" id="autotoc_md8"></a>
Log Format</h3>
<p >The default log format is <code>"[{name}] {level_letter}:{depth_marks} {msg} {hfill} {func} @ {file}:{line}\n"</code>, it can be overriden at compile time by defining the <code>CLUTCHLOG_DEFAULT_FORMAT</code> macro.</p>
<p >By default, and if <code>CLUTCHLOG_DEFAULT_FORMAT</code> is not defined, clutchlog will not put the location-related tags in the message formats (i.e. <code>{name}</code>, <code>{func}</code>, and <code>{line}</code>) when not in Debug builds.</p>
<h2><a class="anchor" id="autotoc_md9"></a>
Output Styling</h2>
<p >Output lines can be styled differently depending on their content.</p>
<p >For example, output lines can be colored differently depending on the log level. </p><div class="fragment"><div class="line"><span class="comment">// Print error messages in bold red:</span></div>
<div class="line">log.style(level::error, <span class="comment">// First, the log level.</span></div>
<div class="line"> fmt::fg::red, <span class="comment">// Then the styles, in any order...</span></div>
<div class="line"> fmt::typo::bold);</div>
</div><!-- fragment --><p >Or, if you want to declare some semantics beforehand: </p><div class="fragment"><div class="line"><span class="comment">// Print warning messages in bold magenta:</span></div>
<div class="line"><span class="keyword">using </span>fmt = <a class="code hl_class" href="classclutchlog_1_1fmt.html">clutchlog::fmt</a>;</div>
<div class="line">fmt warn(fmt::fg::magenta, fmt::typo::bold);</div>
<div class="line">log.style(level::warning, warn);</div>
<div class="ttc" id="aclassclutchlog_1_1fmt_html"><div class="ttname"><a href="classclutchlog_1_1fmt.html">clutchlog::fmt</a></div><div class="ttdoc">Color and style formatter for ANSI terminal escape sequences.</div><div class="ttdef"><b>Definition:</b> <a href="clutchlog_8h_source.html#l00380">clutchlog.h:380</a></div></div>
</div><!-- fragment --><p >Note: this inserts a style marker at the very beginning of the line. If you add other styles later on the line, they will take precedence.</p>
<p >Colors can be specified in several different ways. The ANSI color mode will be automatically detected, depending on the types of arguments passed to styling functions:</p><ul>
<li>named tags from <code><a class="el" href="group__colors16.html#ga4662a3ec3577c6a575a2c734636ed8a0" title="Foreground color codes.">clutchlog::fmt::fg</a></code> or <code><a class="el" href="group__colors16.html#ga1cf3e27e4041250ffea0a6d58010da1e" title="Background color codes.">clutchlog::fmt::bg</a></code> will encode a 16-colors mode,</li>
<li>integers will encode a 256-colors mode,</li>
<li>numeric triplets or web hex strings will encode a 16 million ("true") colors mode,</li>
<li><code>clutchlog::fg::none</code> and <code>clutchlog::bg::none</code> can be passed in all modes.</li>
</ul>
<p >For example, all the following lines encode a bright red foreground for the critical level (see the "Colors" section below): </p><div class="fragment"><div class="line">log.style(level:critical,</div>
<div class="line"> fmt::fg::red); <span class="comment">// 16-colors mode.</span></div>
<div class="line">log.style(level:critical,</div>
<div class="line"> 255); <span class="comment">// 256-colors mode.</span></div>
<div class="line">log.style(level:critical,</div>
<div class="line"> 255,0,0); <span class="comment">// 16M-colors mode.</span></div>
<div class="line">log.style(level:critical,</div>
<div class="line"> <span class="stringliteral">&quot;#ff0000&quot;</span>); <span class="comment">// 16M-colors mode again.</span></div>
</div><!-- fragment --><p >You may use styling within the format message template itself, to add even more colors: </p><div class="fragment"><div class="line"><span class="keyword">using </span>fmt = <a class="code hl_class" href="classclutchlog_1_1fmt.html">clutchlog::fmt</a>;</div>
<div class="line">std::ostringstream format;</div>
<div class="line">fmt discreet(fmt::fg::blue);</div>
<div class="line">format &lt;&lt; <span class="stringliteral">&quot;{level}: &quot;</span></div>
<div class="line"> &lt;&lt; discreet(<span class="stringliteral">&quot;{file}:&quot;</span>) <span class="comment">// Used as a function (inserts a reset at the end).</span></div>
<div class="line"> &lt;&lt; fmt(fmt::fg::yellow) &lt;&lt; <span class="stringliteral">&quot;{line}&quot;</span> <span class="comment">// Used as a tag (no reset inserted).</span></div>
<div class="line"> &lt;&lt; fmt(fmt::typo::reset) &lt;&lt; <span class="stringliteral">&quot; {msg}&quot;</span> &lt;&lt; std::endl; <span class="comment">// This is a reset.</span></div>
<div class="line">log.format(format.str());</div>
</div><!-- fragment --><p> Note: messages at the "critical", "error" and "warning" log levels are colored by default. You may want to set their style to <code>none</code> if you want to stay in control of inserted colors in the format template.</p>
<p >The horizontal filling line (the <code>{hfill}</code> tag) can be configured separately with <code>clutchlog::hfill_style</code>, for example: </p><div class="fragment"><div class="line">log.hfill_style(fmt::fg::black);</div>
</div><!-- fragment --><p> Note: this will actually reset any styling after the hfill, disabling any style you would have set for the whole message using <code><a class="el" href="classclutchlog.html#a656c277e074b64728cca871f2b484d1c" title="Set the template string.">clutchlog::format</a></code> for the remaining of the message.</p>
<h3><a class="anchor" id="autotoc_md10"></a>
Typographic Style</h3>
<p >Available typographies:</p>
<ul>
<li>reset (remove any style),</li>
<li>bold,</li>
<li>underline,</li>
<li>inverse,</li>
<li>none.</li>
</ul>
<p >Typographic styles are always passed with the named tag (see <code><a class="el" href="classclutchlog_1_1fmt.html#a932f47b78fb7b10590d5613a1c4eab89" title="Typographic style codes.">clutchlog::fmt::typo</a></code>), whatever the color mode.</p>
<h3><a class="anchor" id="autotoc_md11"></a>
Colors</h3>
<h4>16-colors mode</h4>
<p >Using the <code><a class="el" href="classclutchlog_1_1fmt.html" title="Color and style formatter for ANSI terminal escape sequences.">clutchlog::fmt</a></code> class, you can style:</p>
<ul>
<li>the foreground color, passing a <code><a class="el" href="group__colors16.html#ga4662a3ec3577c6a575a2c734636ed8a0" title="Foreground color codes.">clutchlog::fmt::fg</a></code>,</li>
<li>the background color, passing a <code><a class="el" href="group__colors16.html#ga1cf3e27e4041250ffea0a6d58010da1e" title="Background color codes.">clutchlog::fmt::bg</a></code>.</li>
</ul>
<p >In 16-colors mode, any of the arguments may be passed, in any order, if an argument is omitted, it defaults to no color/style.</p>
<p >Available colors are:</p>
<ul>
<li>black,</li>
<li>red,</li>
<li>green,</li>
<li>yellow,</li>
<li>blue,</li>
<li>magenta,</li>
<li>cyan,</li>
<li>white,</li>
<li>bright_black,</li>
<li>bright_red,</li>
<li>bright_green,</li>
<li>bright_yellow,</li>
<li>bright_blue,</li>
<li>bright_magenta,</li>
<li>bright_cyan,</li>
<li>bright_white,</li>
<li>none.</li>
</ul>
<p >Note: some terminals allow the user to configure the actual encoding of those colors. You may thus notice some difference with the expected rendering of the same colors encoded in the other modes. Use the other color modes if you want to fully control the actual color rendering.</p>
<h4>256-colors mode</h4>
<p >For 256-colors mode, colors are expected to be passed as integers in [-1,255] or the <code>fg::none</code> and <code>bg::none</code> tags.</p>
<p >In 256-colors mode, if you want to only encode the background color, you cannot just omit the foreground color, you have to bass a <code>fg::none</code> tag as first argument.</p>
<div class="fragment"><div class="line">log.style(level::info, fg::none, 52); <span class="comment">// No color over dark red.</span></div>
<div class="line">log.style(level::info, fg::none, 52, typo::bold); <span class="comment">// No color over bold dark red.</span></div>
</div><!-- fragment --><h4>16 million colors mode (RGB)</h4>
<p >For 16M-colors mode, colors can be encoded as:</p><ul>
<li>three integer arguments,</li>
<li>a "web color" hexadecimal triplet string, starting with a leading number sign (e.g. "#0055ff").</li>
<li>the <code>fg::none</code> and <code>bg::none</code> tags.</li>
</ul>
<p >In 16M-colors mode, if you want to only encode the background color, you cannot just omit the foreground color, you have to pass a <code>fg::none</code> tag as first argument.</p>
<div class="fragment"><div class="line">log.style(level::info, fg::none, 100,0,0); <span class="comment">// No color over dark red.</span></div>
<div class="line">log.style(level::info, fg::none, 100,0,0, typo::bold); <span class="comment">// No color over bold dark red.</span></div>
</div><!-- fragment --><h3><a class="anchor" id="autotoc_md12"></a>
Value-dependant Format Tags</h3>
<p >Some tags can be used to change the style of (part of) the output line,</p>
<p ><em>depending on its content</em>. The <code>{filehash_fmt}</code> and <code>{funchash_fmt}</code> will introduce a styling sequence which depends on the current file name, and function name respectively. The chosen style is chosen at random among the candidate ones, but will always be the same for each value.</p>
<p >The set of candidate styles can be configured with <code><a class="el" href="classclutchlog.html#ae17db5808155fbc6dc48b4727d0c3abf" title="Set the candidate styles for value-dependant file name formatting.">clutchlog::filehash_styles</a></code> and <code><a class="el" href="classclutchlog.html#acbb50f6306ebb3c8b0d1a52e7f327416" title="Set the candidate styles for value-dependant function name formatting.">clutchlog::funchash_styles</a></code>, which both take a vector of <code><a class="el" href="classclutchlog_1_1fmt.html" title="Color and style formatter for ANSI terminal escape sequences.">clutchlog::fmt</a></code> objects as argument: </p><div class="fragment"><div class="line"><span class="comment">// Either one or the other color for filenames:</span></div>
<div class="line">log.filehash_styles( { fmt(fg::red), fmt(fg::yellow) } );</div>
<div class="line"><span class="comment">// This would fix the function name style to a single one:</span></div>
<div class="line">log.funchash_styles( { fmt(typo::bold) } );</div>
<div class="line"><span class="comment">// Works with any `fmt` constructor</span></div>
<div class="line"><span class="comment">// (here, shades of blues in 256-colors mode):</span></div>
<div class="line">log.funchash_styles( { fmt(33), fmt(27), fmt(39), fmt(45) } );</div>
</div><!-- fragment --><p >The same idea applies to <code>{depth_fmt}</code>. However, if <code><a class="el" href="classclutchlog.html#a08310b92e86687349e70f56f9ac1d656" title="Set the styles for value-dependant depth formatting.">clutchlog::depth_styles</a></code> is configured, then the styles are chosen <em>in order</em>. That is, a depth of 1 would lead to the first style being chosen. If the current depth of the stack is larger than the number of configured styles, then the last one is used. For example: </p><div class="fragment"><div class="line"><span class="comment">// Increasingly darker depth level colors (using the 256-colors mode).</span></div>
<div class="line">log.depth_styles({ fmt(255), fmt(250), fmt(245), fmt(240), fmt(235) });</div>
</div><!-- fragment --><p >If <code><a class="el" href="classclutchlog.html#a08310b92e86687349e70f56f9ac1d656" title="Set the styles for value-dependant depth formatting.">clutchlog::depth_styles</a></code> is set, the <code>{depth_marks}</code> template tag will render with each mark having each own style corresponding to its depth. Note: a depth of zero showing no mark, the first style in the list is never applied to marks.</p>
<h1><a class="anchor" id="autotoc_md13"></a>
Advanced Usage</h1>
<h2><a class="anchor" id="autotoc_md14"></a>
More Output Configuration</h2>
<h3><a class="anchor" id="autotoc_md15"></a>
Dump Format</h3>
<p >The default format of the first line of comment added with the dump macro is <code>"# [{name}] {level} in {func} (at depth {depth}) @ {file}:{line}"</code>. It can be edited with the <code>format_comment</code> method. If it is set to an empty string, then no comment line is added. The default can be modified at compile time with <code>CLUTCHDUMP_DEFAULT_FORMAT</code>.</p>
<p >By default, the separator between items in the container is a new line. To change this behaviour, you can change <code>CLUTCHDUMP_DEFAULT_SEP</code> or call the low-level <code>dump</code> method.</p>
<p >By default, and if <code>CLUTCHDUMP_DEFAULT_FORMAT</code> is not defined, clutchlog will not put the location-related tags in the message formats (i.e. <code>{file}</code> and <code>{line}</code>) when not in Debug builds.</p>
<h3><a class="anchor" id="autotoc_md16"></a>
Stack Depth Mark</h3>
<p >The mark used with the <code>{depth_marks}</code> tag can be configured with the <code>clutchlog::depth_mark</code> method, and its default with the <code>CLUTCHLOG_DEFAULT_DEPTH_MARK</code> macro: </p><div class="fragment"><div class="line">log.depth_mark(<a class="code hl_define" href="group___default_config.html#ga45c4c964fad4ad1641d5c9c28c4645b9">CLUTCHLOG_DEFAULT_DEPTH_MARK</a>); <span class="comment">// Defaults to &quot;&gt;&quot;.</span></div>
<div class="ttc" id="agroup___default_config_html_ga45c4c964fad4ad1641d5c9c28c4645b9"><div class="ttname"><a href="group___default_config.html#ga45c4c964fad4ad1641d5c9c28c4645b9">CLUTCHLOG_DEFAULT_DEPTH_MARK</a></div><div class="ttdeci">#define CLUTCHLOG_DEFAULT_DEPTH_MARK</div><div class="ttdoc">Compile-time default mark for stack depth.</div><div class="ttdef"><b>Definition:</b> <a href="clutchlog_8h_source.html#l00257">clutchlog.h:257</a></div></div>
</div><!-- fragment --><h3><a class="anchor" id="autotoc_md17"></a>
Horizontal Filling</h3>
<p >The character used with the <code>{hfill}</code> tag can be configured wth the <code>clutchlog::hfill_mark</code> method, and its default with the <code>CLUTCHLOG_DEFAULT_HFILL_MARK</code> macro: </p><div class="fragment"><div class="line">log.hfill_mark(<a class="code hl_define" href="group___default_config.html#ga4eda0c1bfded5df89351b8ce8b9c2805">CLUTCHLOG_DEFAULT_HFILL_MARK</a>); <span class="comment">// Defaults to &#39;.&#39;.</span></div>
<div class="ttc" id="agroup___default_config_html_ga4eda0c1bfded5df89351b8ce8b9c2805"><div class="ttname"><a href="group___default_config.html#ga4eda0c1bfded5df89351b8ce8b9c2805">CLUTCHLOG_DEFAULT_HFILL_MARK</a></div><div class="ttdeci">#define CLUTCHLOG_DEFAULT_HFILL_MARK</div><div class="ttdoc">Character used as a filling for right-align the right part of messages with &quot;{hfill}&quot;.</div><div class="ttdef"><b>Definition:</b> <a href="clutchlog_8h_source.html#l00271">clutchlog.h:271</a></div></div>
</div><!-- fragment --><p >Clutchlog measures the width of the <em>standard error</em> channel. If it is redirected, it may be measured as very large (or very small). Thus, the <code>clutchlog::hfill_min</code> <code>clutchlog::hfill_max</code> accessors allow to set a minimum and a maximum width (in number of characters). </p><div class="fragment"><div class="line">log.hfill_max(CLUTCHLOG_DEFAULT_HFILL_MAX); <span class="comment">// Defaults to 300.</span></div>
<div class="line">log.hfill_min(CLUTCHLOG_DEFAULT_HFILL_MIN); <span class="comment">// Defaults to 150.</span></div>
</div><!-- fragment --><p> Note: clutchlog will use the measured width, unless it goes out of <code>[clutchlog::hfill_min,clutchlog::hfill_max]</code>, in which case it will be caped to those bounds.</p>
<h3><a class="anchor" id="autotoc_md18"></a>
Stack Depth</h3>
<p >By default, clutchlog removes 5 levels of the calls stack, so that your <code>main</code> entrypoint corresponds to a depth of zero. You can change this behaviour by defining the <code>CLUTCHLOG_STRIP_CALLS</code> macro, or calling <code>clutchlog::strip_calls</code>. </p><div class="fragment"><div class="line">log.strip_calls(<a class="code hl_define" href="group___default_config.html#ga98f30d814d4913a8a7c93a8793f49adf">CLUTCHLOG_STRIP_CALLS</a>); <span class="comment">// Defaults to 5.</span></div>
<div class="ttc" id="agroup___default_config_html_ga98f30d814d4913a8a7c93a8793f49adf"><div class="ttname"><a href="group___default_config.html#ga98f30d814d4913a8a7c93a8793f49adf">CLUTCHLOG_STRIP_CALLS</a></div><div class="ttdeci">#define CLUTCHLOG_STRIP_CALLS</div><div class="ttdoc">Compile-time number of call stack levels to remove from depth display by default.</div><div class="ttdef"><b>Definition:</b> <a href="clutchlog_8h_source.html#l00264">clutchlog.h:264</a></div></div>
</div><!-- fragment --><h3><a class="anchor" id="autotoc_md19"></a>
Filename</h3>
<p >By default, the <code>{file}</code> template tag is rendered as the absolute path (which is usualy handy if your terminal detects paths and allows to run a command on click).</p>
<p >You can change this behavior to display shorter names, using <code><a class="el" href="classclutchlog.html#a822062ffa857bd16ff488f9c749ff20e" title="Available filename rendering methods.">clutchlog::filename</a></code>, and passing one of the following the shortening method:</p><ul>
<li><code>clutchlog::filename::base</code>: the file name itself,</li>
<li><code>clutchlog::filename::dir</code>: the name of the single last directory containing the file,</li>
<li><code>clutchlog::filename::dirbase</code>: the last directory and the file names,</li>
<li><code>clutchlog::filename::stem</code>: the file name without its extension,</li>
<li><code>clutchlog::filename::dirstem</code>: the last directory and the file without extension.</li>
<li><code>clutchlog::filename::path</code>: the absolute path (the default).</li>
</ul>
<p >Example: </p><div class="fragment"><div class="line">log.filename(clutchlog::filename::path) <span class="comment">// /home/nojhan/code/clutchlog/tests/t-filename.cpp</span></div>
<div class="line">log.filename(clutchlog::filename::base) <span class="comment">// t-filename.cpp</span></div>
<div class="line">log.filename(clutchlog::filename::dir) <span class="comment">// tests</span></div>
<div class="line">log.filename(clutchlog::filename::dirbase) <span class="comment">// tests/t-filename.cpp</span></div>
<div class="line">log.filename(clutchlog::filename::stem) <span class="comment">// t-filename</span></div>
<div class="line">log.filename(clutchlog::filename::dirstem) <span class="comment">// tests/t-filename</span></div>
</div><!-- fragment --><h2><a class="anchor" id="autotoc_md20"></a>
Disabled calls</h2>
<p >By default, clutchlog is always enabled if the <code>NDEBUG</code> preprocessor variable is not defined (this variable is set by CMake in build types that differs from <code>Debug</code>).</p>
<p >You can however force clutchlog to be enabled in any build type by setting the <code>WITH_CLUTCHLOG</code> preprocessor variable.</p>
<p >When the <code>NDEBUG</code> preprocessor variable is set (e.g. in <code>Release</code> build), clutchlog will do its best to allow the compiler to optimize out any calls for log levels that are under <code>progress</code>.</p>
<p >You can change this behavior at compile time by setting the <code>CLUTCHLOG_DEFAULT_DEPTH_BUILT_NODEBUG</code> preprocessor variable to the desired maximum log level, for example: </p><div class="fragment"><div class="line"><span class="comment">// Will always allow to log everything even in Release mode.</span></div>
<div class="line"><span class="preprocessor">#define CLUTCHLOG_DEFAULT_DEPTH_BUILT_NODEBUG clutchlog::level::xdebug</span></div>
</div><!-- fragment --><p >Note that allowing a log level does not mean that it will actually output something. If the configured log level at runtime is lower than the log level of the message, it will still not be printed.</p>
<p >This behavior intend to remove as many conditional statements as possible when not debugging, without having to use preprocessor guards around calls to clutchlog, thus saving run time at no readability cost.</p>
<h2><a class="anchor" id="autotoc_md21"></a>
Low-level API</h2>
<p >All configuration setters have a getters counterpart, with the same name but taking no parameter, for example: </p><div class="fragment"><div class="line">std::string mark = log.depth_mark();</div>
</div><!-- fragment --><p >To control more precisely the logging, one can use the low-level <code><a class="el" href="classclutchlog.html#a14c19e17c54d6353ba34c0dc3371094a" title="Print a log message IF the location matches the given one.">clutchlog::log</a></code> method: </p><div class="fragment"><div class="line">log.log(clutchlog::level::xdebug, <span class="stringliteral">&quot;hello world&quot;</span>, <span class="stringliteral">&quot;main.cpp&quot;</span>, <span class="stringliteral">&quot;main&quot;</span>, 122);</div>
</div><!-- fragment --><p> A helper macro can helps to fill in the location with the actual one, as seen by the compiler: </p><div class="fragment"><div class="line">log.log(clutchlog::level::xdebug, <span class="stringliteral">&quot;hello world&quot;</span>, <a class="code hl_define" href="group___use_macros.html#gae8911119d726a43b77f5781cb5a72813">CLUTCHLOC</a>);</div>
<div class="ttc" id="agroup___use_macros_html_gae8911119d726a43b77f5781cb5a72813"><div class="ttname"><a href="group___use_macros.html#gae8911119d726a43b77f5781cb5a72813">CLUTCHLOC</a></div><div class="ttdeci">#define CLUTCHLOC</div><div class="ttdoc">Handy shortcuts to location.</div><div class="ttdef"><b>Definition:</b> <a href="clutchlog_8h_source.html#l00078">clutchlog.h:78</a></div></div>
</div><!-- fragment --><p> A similar <code>dump</code> method exists: </p><div class="fragment"><div class="line">log.dump(clutchlog::level::xdebug, cont.begin(), cont.end(), <a class="code hl_define" href="group___use_macros.html#gae8911119d726a43b77f5781cb5a72813">CLUTCHLOC</a>, <span class="stringliteral">&quot;dumped_{n}.dat&quot;</span>, <span class="stringliteral">&quot;\n&quot;</span>);</div>
<div class="line">log.dump(clutchlog::level::xdebug, cont.begin(), cont.end(), <span class="stringliteral">&quot;main.cpp&quot;</span>, <span class="stringliteral">&quot;main&quot;</span>, 122, <span class="stringliteral">&quot;dumped.dat&quot;</span>, <span class="stringliteral">&quot;\n\n&quot;</span>);</div>
</div><!-- fragment --><p >You can access the identifier of log levels with <code><a class="el" href="classclutchlog.html#acebed8c9df9204f22bf8488e62e1cedd" title="Return the log level tag corresponding to the given pre-configured name.">clutchlog::level_of</a></code>: </p><div class="fragment"><div class="line">log.threshold( log.level_of(<span class="stringliteral">&quot;XDebug&quot;</span>) ); <span class="comment">// You have to know the exact string.</span></div>
</div><!-- fragment --><h2><a class="anchor" id="autotoc_md22"></a>
(De)clutch any function call</h2>
<p >The <code>CLUTHFUNC</code> macro allows to wrap any function within the current logger.</p>
<p >For instance, this can be useful if you want to (de)clutch calls to <code>assert</code>s. To do that, just declare your own macro: </p><div class="fragment"><div class="line"><span class="preprocessor">#define ASSERT(...) { CLUTCHFUNC(error, assert, __VA_ARGS__) }</span></div>
</div><!-- fragment --><p> Thus, any call like <code>ASSERT(x &gt; 3);</code> will be declutchable with the same configuration than a call to <code>CLUTCHLOG</code>.</p>
<h2><a class="anchor" id="autotoc_md23"></a>
(De)clutch any code section</h2>
<p >The <code>CLUTCHCODE</code> macro allows to wrap any code within the current logger.</p>
<p >For instance: </p><div class="fragment"><div class="line"><a class="code hl_define" href="group___use_macros.html#gaaf2e85e1153e6c88b458dd49e3c37c73">CLUTCHCODE</a>(info,</div>
<div class="line"> std::clog &lt;&lt; <span class="stringliteral">&quot;We are clutched!\n&quot;</span>;</div>
<div class="line">);</div>
<div class="ttc" id="agroup___use_macros_html_gaaf2e85e1153e6c88b458dd49e3c37c73"><div class="ttname"><a href="group___use_macros.html#gaaf2e85e1153e6c88b458dd49e3c37c73">CLUTCHCODE</a></div><div class="ttdeci">#define CLUTCHCODE(LEVEL,...)</div><div class="ttdoc">Run any code if the scope matches.</div><div class="ttdef"><b>Definition:</b> <a href="clutchlog_8h_source.html#l00146">clutchlog.h:146</a></div></div>
</div><!-- fragment --><h2><a class="anchor" id="autotoc_md24"></a>
Manually Increase Stack Depth</h2>
<p >You may want to manually increase the stack depth for a given logging call, for instance to subdivise a single function in sections. To do so, you can use the <code>CLUTCHLOGD</code> macro, which take an additional argument, in the form of the number of additional (fake) stack depths you want: </p><div class="fragment"><div class="line"><a class="code hl_define" href="group___use_macros.html#ga6f86187e2b35e7e1907d688f504a197d">CLUTCHLOG</a>( debug, <span class="stringliteral">&quot;Call&quot;</span>); <span class="comment">// Regular macro.</span></div>
<div class="line"><a class="code hl_define" href="group___use_macros.html#ga369d365b7c25ec270596c3ca6839cf2c">CLUTCHLOGD</a>(debug, <span class="stringliteral">&quot;Sub call&quot;</span>, 1); <span class="comment">// Adds an additional (fake) stack depth.</span></div>
<div class="line"><a class="code hl_define" href="group___use_macros.html#ga369d365b7c25ec270596c3ca6839cf2c">CLUTCHLOGD</a>(debug, <span class="stringliteral">&quot;Sub sub!&quot;</span>, 2); <span class="comment">// Adds two additional (fake) stack depths.</span></div>
<div class="ttc" id="agroup___use_macros_html_ga369d365b7c25ec270596c3ca6839cf2c"><div class="ttname"><a href="group___use_macros.html#ga369d365b7c25ec270596c3ca6839cf2c">CLUTCHLOGD</a></div><div class="ttdeci">#define CLUTCHLOGD(LEVEL, WHAT, DEPTH_DELTA)</div><div class="ttdoc">Log a message at the given level and with a given depth delta.</div><div class="ttdef"><b>Definition:</b> <a href="clutchlog_8h_source.html#l00082">clutchlog.h:82</a></div></div>
</div><!-- fragment --><p> That way, the depth will be rendered to the actual depth, plus the additional depth delta. Note that the displayed function will stay the same. Any filtering on the stack depth will take into account the fake depth and not the real one.</p>
<h1><a class="anchor" id="autotoc_md25"></a>
Examples</h1>
<p >Here what you would do to setup clutchlog with the default configuration: </p><div class="fragment"><div class="line"><span class="keyword">auto</span>&amp; log = <a class="code hl_function" href="classclutchlog.html#a6e2a5e98fa9f722d90ba6515895543ac">clutchlog::logger</a>();</div>
<div class="line">log.out(std::clog);</div>
<div class="line"><span class="comment">// Location filtering.</span></div>
<div class="line">log.depth(std::numeric_limits&lt;size_t&gt;::max());</div>
<div class="line">log.threshold(<span class="stringliteral">&quot;Error&quot;</span>);</div>
<div class="line">log.file(<span class="stringliteral">&quot;.*&quot;</span>);</div>
<div class="line">log.func(<span class="stringliteral">&quot;.*&quot;</span>);</div>
<div class="line">log.line(<span class="stringliteral">&quot;.*&quot;</span>);</div>
<div class="line"><span class="comment">// Colors of the 3 firsts levels.</span></div>
<div class="line">log.style(clutchlog::level::critical, <a class="code hl_class" href="classclutchlog_1_1fmt.html">clutchlog::fmt</a>(</div>
<div class="line"> clutchlog::fmt::fg::red,</div>
<div class="line"> clutchlog::fmt::typo::underline);</div>
<div class="line">log.<a class="code hl_variable" href="classclutchlog_1_1fmt.html#a2bb0fde65fcd264393e102314dd1610b">style</a>(clutchlog::level::error, <a class="code hl_class" href="classclutchlog_1_1fmt.html">clutchlog::fmt</a>(</div>
<div class="line"> clutchlog::fmt::fg::red,</div>
<div class="line"> clutchlog::fmt::typo::bold);</div>
<div class="line">log.<a class="code hl_variable" href="classclutchlog_1_1fmt.html#a2bb0fde65fcd264393e102314dd1610b">style</a>(clutchlog::level::warning, <a class="code hl_class" href="classclutchlog_1_1fmt.html">clutchlog::fmt</a>(</div>
<div class="line"> clutchlog::fmt::fg::magenta,</div>
<div class="line"> clutchlog::fmt::typo::bold);</div>
<div class="line"><span class="comment">// Assuming you are on a POSIX system.</span></div>
<div class="line">log.format(<span class="stringliteral">&quot;[{name}] {level_letter}:{depth_marks} {msg} {hfill} {func} @ {file}:{line}\n&quot;</span>);</div>
<div class="line">log.depth_mark(<span class="stringliteral">&quot;&gt;&quot;</span>);</div>
<div class="line">log.strip_calls(5);</div>
<div class="line">log.hfill_char(<span class="charliteral">&#39;.&#39;</span>);</div>
<div class="line">log.hfill_max(300);</div>
<div class="line">log.hfill_style(clutchlog::fmt::fg::none);</div>
<div class="ttc" id="aclassclutchlog_1_1fmt_html_a2bb0fde65fcd264393e102314dd1610b"><div class="ttname"><a href="classclutchlog_1_1fmt.html#a2bb0fde65fcd264393e102314dd1610b">clutchlog::fmt::style</a></div><div class="ttdeci">enum clutchlog::fmt::typo style</div><div class="ttdoc">Typographic style.</div></div>
</div><!-- fragment --><p >And here are all the functions you may call to log something: </p><div class="fragment"><div class="line"><span class="comment">// Basic message.</span></div>
<div class="line"><a class="code hl_define" href="group___use_macros.html#ga6f86187e2b35e7e1907d688f504a197d">CLUTCHLOG</a>(debug, <span class="stringliteral">&quot;x = &quot;</span> &lt;&lt; x);</div>
<div class="line"> </div>
<div class="line"><span class="comment">// Any code section.</span></div>
<div class="line"><a class="code hl_define" href="group___use_macros.html#gaaf2e85e1153e6c88b458dd49e3c37c73">CLUTCHCODE</a>(xdebug,</div>
<div class="line"> <span class="keywordflow">if</span>(x &lt; 0) std::cerr &lt;&lt; <span class="stringliteral">&quot;WTF?&quot;</span> &lt;&lt; std::endl;</div>
<div class="line">);</div>
<div class="line"> </div>
<div class="line"><span class="comment">// Container to a file.</span></div>
<div class="line"><a class="code hl_define" href="group___use_macros.html#ga572e3aa19d8b39e3ed0b9e91961104c2">CLUTCHDUMP</a>(note, my_vector, <span class="stringliteral">&quot;my_vector.dat&quot;</span>);</div>
<div class="line"> </div>
<div class="line"><span class="comment">// Container to a numbered file.</span></div>
<div class="line"><a class="code hl_define" href="group___use_macros.html#ga572e3aa19d8b39e3ed0b9e91961104c2">CLUTCHDUMP</a>(note, my_list, <span class="stringliteral">&quot;my_list_{n}.dat&quot;</span>);</div>
<div class="line"> </div>
<div class="line"><span class="comment">// Function call.</span></div>
<div class="line"><a class="code hl_define" href="group___use_macros.html#ga9f77cee4f853e582262930c9c17f90ae">CLUTCHFUNC</a>(warning, my_check, x, y); <span class="comment">// Calls: my_check(x,y);</span></div>
<div class="line"> </div>
<div class="line"><span class="comment">// Declutchable asserts.</span></div>
<div class="line"><span class="preprocessor">#define ASSERT(...) { CLUTCHFUNC(critical, assert, __VA_ARGS__) }</span></div>
<div class="line">ASSERT(x&gt;0);</div>
<div class="ttc" id="agroup___use_macros_html_ga9f77cee4f853e582262930c9c17f90ae"><div class="ttname"><a href="group___use_macros.html#ga9f77cee4f853e582262930c9c17f90ae">CLUTCHFUNC</a></div><div class="ttdeci">#define CLUTCHFUNC(LEVEL, FUNC,...)</div><div class="ttdoc">Call any function if the scope matches.</div><div class="ttdef"><b>Definition:</b> <a href="clutchlog_8h_source.html#l00125">clutchlog.h:125</a></div></div>
</div><!-- fragment --><p >Here what you would do to setup clutchlog with the default configuration using 16M-colors mode: </p><div class="fragment"><div class="line"><span class="keyword">auto</span>&amp; log = <a class="code hl_function" href="classclutchlog.html#a6e2a5e98fa9f722d90ba6515895543ac">clutchlog::logger</a>();</div>
<div class="line">log.out(std::clog);</div>
<div class="line"><span class="comment">// Location filtering.</span></div>
<div class="line">log.depth(std::numeric_limits&lt;size_t&gt;::max());</div>
<div class="line">log.threshold(<span class="stringliteral">&quot;Error&quot;</span>);</div>
<div class="line">log.file(<span class="stringliteral">&quot;.*&quot;</span>);</div>
<div class="line">log.func(<span class="stringliteral">&quot;.*&quot;</span>);</div>
<div class="line">log.line(<span class="stringliteral">&quot;.*&quot;</span>);</div>
<div class="line"><span class="comment">// Colors of the 3 firsts levels.</span></div>
<div class="line">log.style(clutchlog::level::critical, <a class="code hl_class" href="classclutchlog_1_1fmt.html">clutchlog::fmt</a>(</div>
<div class="line"> <span class="stringliteral">&quot;#ff0000&quot;</span>,</div>
<div class="line"> clutchlog::fmt::typo::underline);</div>
<div class="line">log.<a class="code hl_variable" href="classclutchlog_1_1fmt.html#a2bb0fde65fcd264393e102314dd1610b">style</a>(clutchlog::level::error, <a class="code hl_class" href="classclutchlog_1_1fmt.html">clutchlog::fmt</a>(</div>
<div class="line"> <span class="stringliteral">&quot;#ff0000&quot;</span>,</div>
<div class="line"> clutchlog::fmt::typo::bold);</div>
<div class="line">log.<a class="code hl_variable" href="classclutchlog_1_1fmt.html#a2bb0fde65fcd264393e102314dd1610b">style</a>(clutchlog::level::warning, <a class="code hl_class" href="classclutchlog_1_1fmt.html">clutchlog::fmt</a>(</div>
<div class="line"> <span class="stringliteral">&quot;#ff00ff&quot;</span>,</div>
<div class="line"> clutchlog::fmt::typo::bold);</div>
<div class="line"><span class="comment">// Assuming you are on a POSIX system.</span></div>
<div class="line">log.format(<span class="stringliteral">&quot;[{name}] {level_letter}:{depth_marks} {msg} {hfill} {func} @ {file}:{line}\n&quot;</span>);</div>
<div class="line">log.depth_mark(<span class="stringliteral">&quot;&gt;&quot;</span>);</div>
<div class="line">log.strip_calls(5);</div>
<div class="line">log.hfill_char(<span class="charliteral">&#39;.&#39;</span>);</div>
<div class="line">log.hfill_max(300);</div>
<div class="line">log.hfill_style(clutchlog::fmt::fg::none);</div>
</div><!-- fragment --><h1><a class="anchor" id="autotoc_md26"></a>
Limitations</h1>
<h3><a class="anchor" id="autotoc_md27"></a>
System-dependent stack depth</h3>
<p >Because access to the call stack depth and program name are system-dependent, the features relying on the depth of the call stack and the display of the program name are only available for operating systems having the following headers: <code>execinfo.h</code>, <code>stdlib.h</code> and <code>libgen.h</code> (so far, tested with Linux).</p>
<p >Clutchlog sets the <code>CLUTCHLOG_HAVE_UNIX_SYSINFO</code> to 1 if the headers are available, and to 0 if they are not. You can make portable code using something like: </p><div class="fragment"><div class="line"><span class="preprocessor">#if CLUTCHLOG_HAVE_UNIX_SYSINFO == 1</span></div>
<div class="line"> log.depth( x );</div>
<div class="line"><span class="preprocessor">#endif </span></div>
</div><!-- fragment --><h3><a class="anchor" id="autotoc_md28"></a>
System-dependent horizontal fill</h3>
<p >Because access to the current terminal width is system-dependent, the <code>{hfill}</code> format tag feature is only available for operating systems having the following headers: <code>sys/ioctl.h</code>, <code>stdio.h</code> and <code>unistd.h</code> (so far, tested with Linux).</p>
<p >Clutchlog sets the <code>CLUTCHLOG_HAVE_UNIX_SYSIOCTL</code> to 1 if the headers are available, and to 0 if they are not. You can make portable code using something like: </p><div class="fragment"><div class="line"><span class="preprocessor">#if CLUTCHLOG_HAVE_UNIX_SYSIOCTL == 1</span></div>
<div class="line"> log.hfill_mark( <span class="charliteral">&#39;_&#39;</span> );</div>
<div class="line"><span class="preprocessor">#endif </span></div>
</div><!-- fragment --><p >If you use unicode characters in your template, the horizontal width will not be computed properly, resulting in incorrectly right-aligned lines. Solving this would require the use of third-party libraries, making portability more difficult.</p>
<h3><a class="anchor" id="autotoc_md29"></a>
Dependencies</h3>
<p >Some colors/styles may not be supported by some exotic terminal emulators.</p>
<p >Clutchlog needs <code>C++-17</code> with the <code>filesystem</code> feature. You may need to indicate <code>-std=c++17 -lstdc++fs</code> to some compilers.</p>
<h3><a class="anchor" id="autotoc_md30"></a>
Variable names within the CLUTCHLOG macro</h3>
<p >Calling the <code>CLUTCHLOG</code> macro with a message using a variable named <code>clutchlog__msg</code> will end in an error.</p>
<h3><a class="anchor" id="autotoc_md31"></a>
Features</h3>
<p >What Clutchlog do not provide at the moment (but may in a near future):</p>
<ul>
<li>Super fast log writing.</li>
<li>Thread safety.</li>
</ul>
<p >What Clutchlog will most certainly never provide:</p>
<ul>
<li>Round-robin log managers.</li>
<li>Duplicated messages management.</li>
<li>External output systems (only allow output stream, you can still do the proxy yourself).</li>
<li>External error handlers (not my job, come on).</li>
<li>Automatic argument parser (please, use a dedicated lib).</li>
<li>Signal handling (WTF would you do that, anyway?).</li>
</ul>
<h1><a class="anchor" id="autotoc_md32"></a>
Build and tests</h1>
<p >To use clutchlog, just include its header in your code and either ensure that the <code>NDEBUG</code> preprocessor variable is not set, either define the <code>WITH_CLUTCHLOG</code> preprocessor variable.</p>
<p >If you're using CMake (or another modern build system), it will unset <code>NDEBUG</code> —and thus enable clutchlog— only for the "Debug" build type, which is usually what you want if you use clutchlog, anyway.</p>
<p >To build and run the tests, just use a classical CMake workflow: </p><div class="fragment"><div class="line">mkdir build</div>
<div class="line">cd build</div>
<div class="line">cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_CLUTCHLOG=ON ..</div>
<div class="line">make</div>
<div class="line">ctest</div>
</div><!-- fragment --><p >There's a script that tests all the build types combinations: <code>./build_all.sh</code>.</p>
<h1><a class="anchor" id="autotoc_md33"></a>
Usage as a Git submodule</h1>
<p >If you are using Git and CMake, it is easy to include Clutchlog as a dependency.</p>
<p >First, add Clutchlog as a submodule of your repository: </p><div class="fragment"><div class="line">git submodule add git@github.com:nojhan/clutchlog.git external/</div>
<div class="line">git commit -m &quot;Add clutchlog as a submodule dependency&quot;</div>
</div><!-- fragment --><p >Then, in your <code>CMakeLists.txt</code> file, add: </p><div class="fragment"><div class="line">include_directories(external/clutchlog)</div>
</div><!-- fragment --><p >And that's it. </p>
</div></div><!-- PageDoc -->
</div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="footer">Generated by <a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.4 </li>
</ul>
</div>
</body>
</html>