This repository has been archived on 2022-04-04. You can view files and clone it, but cannot push or open issues or pull requests.

57 lines
9.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="rustdoc"><meta name="description" content="Fern supports logging most things by default, except for one kind of struct: structs which make log calls to the global logger from within their `Display` or `Debug` implementations."><meta name="keywords" content="rust, rustlang, rust-lang, meta"><title>fern::meta - Rust</title><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceSerif4-Regular.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../FiraSans-Regular.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../FiraSans-Medium.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceCodePro-Regular.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceSerif4-Bold.ttf.woff2"><link rel="preload" as="font" type="font/woff2" crossorigin href="../../SourceCodePro-Semibold.ttf.woff2"><link rel="stylesheet" type="text/css" href="../../normalize.css"><link rel="stylesheet" type="text/css" href="../../rustdoc.css" id="mainThemeStyle"><link rel="stylesheet" type="text/css" href="../../ayu.css" disabled><link rel="stylesheet" type="text/css" href="../../dark.css" disabled><link rel="stylesheet" type="text/css" href="../../light.css" id="themeStyle"><script id="default-settings" ></script><script src="../../storage.js"></script><script src="../../crates.js"></script><script defer src="../../main.js"></script>
<noscript><link rel="stylesheet" href="../../noscript.css"></noscript><link rel="alternate icon" type="image/png" href="../../favicon-16x16.png"><link rel="alternate icon" type="image/png" href="../../favicon-32x32.png"><link rel="icon" type="image/svg+xml" href="../../favicon.svg"></head><body class="rustdoc mod"><!--[if lte IE 11]><div class="warning">This old browser is unsupported and will most likely display funky things.</div><![endif]--><nav class="sidebar"><div class="sidebar-menu" role="button">&#9776;</div><a class="sidebar-logo" href="../../fern/index.html"><div class="logo-container"><img class="rust-logo" src="../../rust-logo.png" alt="logo"></div>
</a><h2 class="location">Module meta</h2><div class="sidebar-elems"><div id="sidebar-vars" data-name="meta" data-ty="mod" data-relpath="./"></div><script defer src="./sidebar-items.js"></script></div></nav><main><div class="width-limiter"><div class="sub-container"><a class="sub-logo-container" href="../../fern/index.html"><img class="rust-logo" src="../../rust-logo.png" alt="logo"></a><nav class="sub"><div class="theme-picker"><button id="theme-picker" aria-label="Pick another theme!" aria-haspopup="menu" title="themes"><img width="18" height="18" alt="Pick another theme!" src="../../brush.svg"></button><div id="theme-choices" role="menu"></div></div><form class="search-form"><div class="search-container"><div><select id="crate-search"><option value="All crates">All crates</option></select><input class="search-input" name="search" autocomplete="off" spellcheck="false" placeholder="Click or press S to search, ? for more options…" type="search"></div><button type="button" id="help-button" title="help">?</button><a id="settings-menu" href="../../settings.html" title="settings"><img width="18" height="18" alt="Change settings" src="../../wheel.svg"></a></div></form></nav></div><section id="main-content" class="content"><h1 class="fqn"><span class="in-band">Module <a href="../index.html">fern</a>::<wbr><a class="mod" href="#">meta</a><button id="copy-path" onclick="copy_path(this)" title="Copy item path to clipboard"><img src="../../clipboard.svg" width="19" height="18" alt="Copy item path"></button></span><span class="out-of-band"><span id="render-detail"><a id="toggle-all-docs" href="javascript:void(0)" title="collapse all docs">[<span class="inner">&#x2212;</span>]</a></span><a class="srclink" href="../../src/fern/meta.rs.html#1-79" title="goto source code">[src]</a></span></h1><details class="rustdoc-toggle top-doc" open><summary class="hideme"><span>Expand description</span></summary><div class="docblock"><p>Fern supports logging most things by default, except for one kind of struct: structs which make log
calls to the global logger from within their <code>Display</code> or <code>Debug</code> implementations.</p>
<p>Heres an example of such a structure:</p>
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="kw">struct</span> <span class="ident">Thing</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span>(<span class="kw-2">&amp;</span><span class="lifetime">&#39;a</span> <span class="ident">str</span>);
<span class="kw">impl</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> <span class="ident">fmt::Display</span> <span class="kw">for</span> <span class="ident">Thing</span><span class="op">&lt;</span><span class="lifetime">&#39;a</span><span class="op">&gt;</span> {
<span class="kw">fn</span> <span class="ident">fmt</span>(<span class="kw-2">&amp;</span><span class="self">self</span>, <span class="ident">f</span>: <span class="kw-2">&amp;mut</span> <span class="ident">fmt::Formatter</span>) -&gt; <span class="ident">fmt::Result</span> {
<span class="macro">debug!</span>(<span class="string">&quot;just displayed a Thing wrapping {}&quot;</span>, <span class="self">self</span>.<span class="number">0</span>);
<span class="ident">f</span>.<span class="ident">write_str</span>(<span class="self">self</span>.<span class="number">0</span>)
}
}
</code></pre></div>
<p>This structure, and this structure alone, will cause some problems when logging in fern. There are
mitigations, but since its a fairly niche use case, they are disabled by default.</p>
<p>The problems are, depending on which backend you use:</p>
<ul>
<li>stdout/stderr: logging will stutter, with the logs output inside the <code>Display</code> implementation
cutting other log lines down the center</li>
<li>file: thread will deadlock, and all future logs will also deadlock</li>
</ul>
<p>There are two mitigations you can make, both completely fix this error.</p>
<p>The simplest mitigation to this is to enable the <code>meta-logging-in-format</code> feature of <code>fern</code>. The
disadvantage is that this means fern makes an additional allocation per log call per affected
backend. Not a huge cost, but enough to mean its disabled by default. To enable this, use the
following in your <code>Cargo.toml</code>:</p>
<div class="example-wrap"><pre class="language-toml"><code>[dependencies]
fern = { version = &quot;0.5&quot;, features = [&quot;meta-logging-in-format&quot;] }</code></pre></div>
<p>The second mitigation is one you can make inside a formatting closure. This means extra code
complexity, but it also means you can enable it per-logger: the fix isnt global. This fix is also
redundant if youve already enable the above feature. To add the second mitigation, replacec
<code>format_args!()</code> with <code>format!()</code> as displayed below:</p>
<div class="example-wrap"><pre class="rust rust-example-rendered"><code><span class="ident">fern::Dispatch::new</span>()
...
<span class="comment">// instead of doing this:</span>
.<span class="ident">format</span>(<span class="kw">move</span> <span class="op">|</span><span class="ident">out</span>, <span class="ident">message</span>, <span class="ident">record</span><span class="op">|</span> {
<span class="ident">out</span>.<span class="ident">finish</span>(<span class="macro">format_args!</span>(<span class="string">&quot;[{}] {}&quot;</span>, <span class="ident">record</span>.<span class="ident">level</span>(), <span class="ident">message</span>))
})
<span class="comment">// do this:</span>
.<span class="ident">format</span>(<span class="kw">move</span> <span class="op">|</span><span class="ident">out</span>, <span class="ident">message</span>, <span class="ident">record</span><span class="op">|</span> {
<span class="kw">let</span> <span class="ident">formatted</span> <span class="op">=</span> <span class="macro">format!</span>(<span class="string">&quot;[{}] {}&quot;</span>, <span class="ident">record</span>.<span class="ident">level</span>(), <span class="ident">message</span>);
<span class="ident">out</span>.<span class="ident">finish</span>(<span class="macro">format_args!</span>(<span class="string">&quot;{}&quot;</span>, <span class="ident">formatted</span>))
})</code></pre></div>
<p>This second mitigation works by forcing the <code>Display</code> implementation to run before any text has
started to log to the backend. Theres an additional allocation per log, but it no longer deadlocks!</p>
<p>This mitigation also has the advantage of ensuring theres only one call to <code>Display::fmt</code>. If youc
use <code>meta-logging-in-format</code> and have multiple backends, <code>Display::fmt</code> will still be called once
per backend. With this, it will only be called once.</p>
<hr />
<p>If youve never experienced this problem, theres no need to fix it - <code>Display::fmt</code> and
<code>Debug::fmt</code> are normally implemented as “pure” functions with no side effects.</p>
</div></details></section><section id="search" class="content hidden"></section></div></main><div id="rustdoc-vars" data-root-path="../../" data-current-crate="fern" data-themes="ayu,dark,light" data-resource-suffix="" data-rustdoc-version="1.59.0 (9d1b2106e 2022-02-23)" ></div>
</body></html>