This file is indexed.

/usr/share/doc/python-logbook-doc/html/setups.html is in python-logbook-doc 0.7.0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://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/html; charset=utf-8" />
    
    <title>Common Logbook Setups &mdash; Logbook</title>
    
    <link rel="stylesheet" href="_static/sheet.css" type="text/css" />
    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
    
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    './',
        VERSION:     '0.7.0',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="_static/jquery.js"></script>
    <script type="text/javascript" src="_static/underscore.js"></script>
    <script type="text/javascript" src="_static/doctools.js"></script>
    <link rel="top" title="Logbook" href="index.html" />
    <link rel="next" title="Stacks in Logbook" href="stacks.html" />
    <link rel="prev" title="Quickstart" href="quickstart.html" />


  </head>
  <body>
  <div class="book">
    <div class="banner">
      <a href="index.html">
        <!-- <img src="_static/" alt="Logbook logo"></img> -->
        <h1>Logbook </h1>
      </a>
    </div>

    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="stacks.html" title="Stacks in Logbook"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="quickstart.html" title="Quickstart"
             accesskey="P">previous</a> |</li>
        <li><a href="index.html">Logbook 0.7.0</a> &raquo;</li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
          <div class="body">
            
  <div class="section" id="common-logbook-setups">
<h1>Common Logbook Setups</h1>
<p>This part of the documentation shows how you can configure Logbook for
different kinds of setups.</p>
<div class="section" id="desktop-application-setup">
<h2>Desktop Application Setup</h2>
<p>If you develop a desktop application (command line or GUI), you probably have a line
like this in your code:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="n">main</span><span class="p">()</span>
</pre></div>
</div>
<p>This is what you should wrap with a <tt class="docutils literal"><span class="pre">with</span></tt> statement that sets up your log
handler:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">logbook</span> <span class="kn">import</span> <span class="n">FileHandler</span>
<span class="n">log_handler</span> <span class="o">=</span> <span class="n">FileHandler</span><span class="p">(</span><span class="s">&#39;application.log&#39;</span><span class="p">)</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="k">with</span> <span class="n">log_handler</span><span class="o">.</span><span class="n">applicationbound</span><span class="p">():</span>
        <span class="n">main</span><span class="p">()</span>
</pre></div>
</div>
<p>Alternatively you can also just push a handler in there:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">logbook</span> <span class="kn">import</span> <span class="n">FileHandler</span>
<span class="n">log_handler</span> <span class="o">=</span> <span class="n">FileHandler</span><span class="p">(</span><span class="s">&#39;application.log&#39;</span><span class="p">)</span>
<span class="n">log_handler</span><span class="o">.</span><span class="n">push_application</span><span class="p">()</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="n">main</span><span class="p">()</span>
</pre></div>
</div>
<p>Please keep in mind that you will have to pop the handlers in reverse order if
you want to remove them from the stack, so it is recommended to use the context
manager API if you plan on reverting the handlers.</p>
</div>
<div class="section" id="web-application-setup">
<h2>Web Application Setup</h2>
<p>Typical modern web applications written in Python have two separate contexts
where code might be executed: when the code is imported, as well as when a
request is handled.  The first case is easy to handle, just push a global file
handler that writes everything into a file.</p>
<p>But Logbook also gives you the ability to improve upon the logging.  For
example, you can easily create yourself a log handler that is used for
request-bound logging that also injects additional information.</p>
<p>For this you can either subclass the logger or you can bind to the handler with
a function that is invoked before logging.  The latter has the advantage that it
will also be triggered for other logger instances which might be used by a
different library.</p>
<p>Here is a simple WSGI example application that showcases sending error mails for
errors happened during a WSGI application:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">logbook</span> <span class="kn">import</span> <span class="n">MailHandler</span>

<span class="n">mail_handler</span> <span class="o">=</span> <span class="n">MailHandler</span><span class="p">(</span><span class="s">&#39;errors@example.com&#39;</span><span class="p">,</span>
                           <span class="p">[</span><span class="s">&#39;admin@example.com&#39;</span><span class="p">],</span>
                           <span class="n">format_string</span><span class="o">=</span><span class="s">u&#39;&#39;&#39;</span><span class="se">\</span>
<span class="s">Subject: Application Error at {record.extra[url]}</span>

<span class="s">Message type:       {record.level_name}</span>
<span class="s">Location:           {record.filename}:{record.lineno}</span>
<span class="s">Module:             {record.module}</span>
<span class="s">Function:           {record.func_name}</span>
<span class="s">Time:               {record.time:%Y-%m-</span><span class="si">%d</span><span class="s"> %H:%M:%S}</span>
<span class="s">Remote IP:          {record.extra[ip]}</span>
<span class="s">Request:            {record.extra[url]} [{record.extra[method]}]</span>

<span class="s">Message:</span>

<span class="s">{record.message}</span>
<span class="s">&#39;&#39;&#39;</span><span class="p">,</span> <span class="n">bubble</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">application</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
    <span class="n">request</span> <span class="o">=</span> <span class="n">Request</span><span class="p">(</span><span class="n">environ</span><span class="p">)</span>

    <span class="k">def</span> <span class="nf">inject_info</span><span class="p">(</span><span class="n">record</span><span class="p">,</span> <span class="n">handler</span><span class="p">):</span>
        <span class="n">record</span><span class="o">.</span><span class="n">extra</span><span class="o">.</span><span class="n">update</span><span class="p">(</span>
            <span class="n">ip</span><span class="o">=</span><span class="n">request</span><span class="o">.</span><span class="n">remote_addr</span><span class="p">,</span>
            <span class="n">method</span><span class="o">=</span><span class="n">request</span><span class="o">.</span><span class="n">method</span><span class="p">,</span>
            <span class="n">url</span><span class="o">=</span><span class="n">request</span><span class="o">.</span><span class="n">url</span>
        <span class="p">)</span>

    <span class="k">with</span> <span class="n">mail_handler</span><span class="o">.</span><span class="n">threadbound</span><span class="p">(</span><span class="n">processor</span><span class="o">=</span><span class="n">inject_info</span><span class="p">):</span>
        <span class="c"># standard WSGI processing happens here.  If an error</span>
        <span class="c"># is logged, a mail will be sent to the admin on</span>
        <span class="c"># example.com</span>
        <span class="o">...</span>
</pre></div>
</div>
</div>
<div class="section" id="deeply-nested-setups">
<h2>Deeply Nested Setups</h2>
<p>If you want deeply nested logger setups, you can use the
<a class="reference internal" href="api/handlers.html#logbook.NestedSetup" title="logbook.NestedSetup"><tt class="xref py py-class docutils literal"><span class="pre">NestedSetup</span></tt></a> class which simplifies that.  This is best
explained using an example:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">from</span> <span class="nn">logbook</span> <span class="kn">import</span> <span class="n">NestedSetup</span><span class="p">,</span> <span class="n">NullHandler</span><span class="p">,</span> <span class="n">FileHandler</span><span class="p">,</span> \
     <span class="n">MailHandler</span><span class="p">,</span> <span class="n">Processor</span>

<span class="k">def</span> <span class="nf">inject_information</span><span class="p">(</span><span class="n">record</span><span class="p">):</span>
    <span class="n">record</span><span class="o">.</span><span class="n">extra</span><span class="p">[</span><span class="s">&#39;cwd&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">getcwd</span><span class="p">()</span>

<span class="c"># a nested handler setup can be used to configure more complex setups</span>
<span class="n">setup</span> <span class="o">=</span> <span class="n">NestedSetup</span><span class="p">([</span>
    <span class="c"># make sure we never bubble up to the stderr handler</span>
    <span class="c"># if we run out of setup handling</span>
    <span class="n">NullHandler</span><span class="p">(),</span>
    <span class="c"># then write messages that are at least warnings to to a logfile</span>
    <span class="n">FileHandler</span><span class="p">(</span><span class="s">&#39;application.log&#39;</span><span class="p">,</span> <span class="n">level</span><span class="o">=</span><span class="s">&#39;WARNING&#39;</span><span class="p">),</span>
    <span class="c"># errors should then be delivered by mail and also be kept</span>
    <span class="c"># in the application log, so we let them bubble up.</span>
    <span class="n">MailHandler</span><span class="p">(</span><span class="s">&#39;servererrors@example.com&#39;</span><span class="p">,</span>
                   <span class="p">[</span><span class="s">&#39;admin@example.com&#39;</span><span class="p">],</span>
                   <span class="n">level</span><span class="o">=</span><span class="s">&#39;ERROR&#39;</span><span class="p">,</span> <span class="n">bubble</span><span class="o">=</span><span class="bp">True</span><span class="p">),</span>
    <span class="c"># while we&#39;re at it we can push a processor on its own stack to</span>
    <span class="c"># record additional information.  Because processors and handlers</span>
    <span class="c"># go to different stacks it does not matter if the processor is</span>
    <span class="c"># added here at the bottom or at the very beginning.  Same would</span>
    <span class="c"># be true for flags.</span>
    <span class="n">Processor</span><span class="p">(</span><span class="n">inject_information</span><span class="p">)</span>
<span class="p">])</span>
</pre></div>
</div>
<p>Once such a complex setup is defined, the nested handler setup can be used as if
it was a single handler:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="k">with</span> <span class="n">setup</span><span class="o">.</span><span class="n">threadbound</span><span class="p">():</span>
    <span class="c"># everything here is handled as specified by the rules above.</span>
    <span class="o">...</span>
</pre></div>
</div>
</div>
<div class="section" id="distributed-logging">
<h2>Distributed Logging</h2>
<p>For applications that are spread over multiple processes or even machines
logging into a central system can be a pain.  Logbook supports ZeroMQ to
deal with that.  You can set up a <a class="reference internal" href="api/queues.html#logbook.queues.ZeroMQHandler" title="logbook.queues.ZeroMQHandler"><tt class="xref py py-class docutils literal"><span class="pre">ZeroMQHandler</span></tt></a>
that acts as ZeroMQ publisher and will send log records encoded as JSON
over the wire:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">logbook.queues</span> <span class="kn">import</span> <span class="n">ZeroMQHandler</span>
<span class="n">handler</span> <span class="o">=</span> <span class="n">ZeroMQHandler</span><span class="p">(</span><span class="s">&#39;tcp://127.0.0.1:5000&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Then you just need a separate process that can receive the log records and
hand it over to another log handler using the
<a class="reference internal" href="api/queues.html#logbook.queues.ZeroMQSubscriber" title="logbook.queues.ZeroMQSubscriber"><tt class="xref py py-class docutils literal"><span class="pre">ZeroMQSubscriber</span></tt></a>.  The usual setup is this:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">logbook.queues</span> <span class="kn">import</span> <span class="n">ZeroMQSubscriber</span>
<span class="n">subscriber</span> <span class="o">=</span> <span class="n">ZeroMQSubscriber</span><span class="p">(</span><span class="s">&#39;tcp://127.0.0.1:5000&#39;</span><span class="p">)</span>
<span class="k">with</span> <span class="n">my_handler</span><span class="p">:</span>
    <span class="n">subscriber</span><span class="o">.</span><span class="n">dispatch_forever</span><span class="p">()</span>
</pre></div>
</div>
<p>You can also run that loop in a background thread with
<a class="reference internal" href="api/queues.html#logbook.queues.ZeroMQSubscriber.dispatch_in_background" title="logbook.queues.ZeroMQSubscriber.dispatch_in_background"><tt class="xref py py-meth docutils literal"><span class="pre">dispatch_in_background()</span></tt></a>:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">logbook.queues</span> <span class="kn">import</span> <span class="n">ZeroMQSubscriber</span>
<span class="n">subscriber</span> <span class="o">=</span> <span class="n">ZeroMQSubscriber</span><span class="p">(</span><span class="s">&#39;tcp://127.0.0.1:5000&#39;</span><span class="p">)</span>
<span class="n">subscriber</span><span class="o">.</span><span class="n">dispatch_in_background</span><span class="p">(</span><span class="n">my_handler</span><span class="p">)</span>
</pre></div>
</div>
<p>If you just want to use this in a <a class="reference external" href="/usr/share/doc/python2.7/html/library/multiprocessing.html#module-multiprocessing" title="(in Python v2.7)"><tt class="xref py py-mod docutils literal"><span class="pre">multiprocessing</span></tt></a> environment you
can use the <a class="reference internal" href="api/queues.html#logbook.queues.MultiProcessingHandler" title="logbook.queues.MultiProcessingHandler"><tt class="xref py py-class docutils literal"><span class="pre">MultiProcessingHandler</span></tt></a> and
<a class="reference internal" href="api/queues.html#logbook.queues.MultiProcessingSubscriber" title="logbook.queues.MultiProcessingSubscriber"><tt class="xref py py-class docutils literal"><span class="pre">MultiProcessingSubscriber</span></tt></a> instead.  They work the
same way as the ZeroMQ equivalents but are connected through a
<a class="reference external" href="/usr/share/doc/python2.7/html/library/multiprocessing.html#multiprocessing.Queue" title="(in Python v2.7)"><tt class="xref py py-class docutils literal"><span class="pre">multiprocessing.Queue</span></tt></a>:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">multiprocessing</span> <span class="kn">import</span> <span class="n">Queue</span>
<span class="kn">from</span> <span class="nn">logbook.queues</span> <span class="kn">import</span> <span class="n">MultiProcessingHandler</span><span class="p">,</span> \
     <span class="n">MultiProcessingSubscriber</span>
<span class="n">queue</span> <span class="o">=</span> <span class="n">Queue</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">handler</span> <span class="o">=</span> <span class="n">MultiProcessingHandler</span><span class="p">(</span><span class="n">queue</span><span class="p">)</span>
<span class="n">subscriber</span> <span class="o">=</span> <span class="n">MultiProcessingSubscriber</span><span class="p">(</span><span class="n">queue</span><span class="p">)</span>
</pre></div>
</div>
<p>There is also the possibility to log into a Redis instance using the
<a class="reference internal" href="api/queues.html#logbook.queues.RedisHandler" title="logbook.queues.RedisHandler"><tt class="xref py py-class docutils literal"><span class="pre">RedisHandler</span></tt></a>. To do so, you just need to create an
instance of this handler as follows:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">import</span> <span class="nn">logbook</span>
<span class="kn">from</span> <span class="nn">logbook.queues</span> <span class="kn">import</span> <span class="n">RedisHandler</span>

<span class="n">handler</span> <span class="o">=</span> <span class="n">RedisHandler</span><span class="p">()</span>
<span class="n">l</span> <span class="o">=</span> <span class="n">logbook</span><span class="o">.</span><span class="n">Logger</span><span class="p">()</span>
<span class="k">with</span> <span class="n">handler</span><span class="p">:</span>
    <span class="n">l</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s">&#39;Your log message&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>With the default parameters, this will send a message to redis under the key redis.</p>
</div>
<div class="section" id="redirecting-single-loggers">
<h2>Redirecting Single Loggers</h2>
<p>If you want to have a single logger go to another logfile you have two
options.  First of all you can attach a handler to a specific record
dispatcher.  So just import the logger and attach something:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">yourapplication.yourmodule</span> <span class="kn">import</span> <span class="n">logger</span>
<span class="n">logger</span><span class="o">.</span><span class="n">handlers</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">MyHandler</span><span class="p">(</span><span class="o">...</span><span class="p">))</span>
</pre></div>
</div>
<p>Handlers attached directly to a record dispatcher will always take
precedence over the stack based handlers.  The bubble flag works as
expected, so if you have a non-bubbling handler on your logger and it
always handles, it will never be passed to other handlers.</p>
<p>Secondly you can write a handler that looks at the logging channel and
only accepts loggers of a specific kind.  You can also do that with a
filter function:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="n">handler</span> <span class="o">=</span> <span class="n">MyHandler</span><span class="p">(</span><span class="nb">filter</span><span class="o">=</span><span class="k">lambda</span> <span class="n">r</span><span class="p">:</span> <span class="n">r</span><span class="o">.</span><span class="n">channel</span> <span class="o">==</span> <span class="s">&#39;app.database&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Keep in mind that the channel is intended to be a human readable string
and is not necessarily unique.  If you really need to keep loggers apart
on a central point you might want to introduce some more meta information
into the extra dictionary.</p>
<p>You can also compare the dispatcher on the log record:</p>
<div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">yourapplication.yourmodule</span> <span class="kn">import</span> <span class="n">logger</span>
<span class="n">handler</span> <span class="o">=</span> <span class="n">MyHandler</span><span class="p">(</span><span class="nb">filter</span><span class="o">=</span><span class="k">lambda</span> <span class="n">r</span><span class="p">:</span> <span class="n">r</span><span class="o">.</span><span class="n">dispatcher</span> <span class="ow">is</span> <span class="n">logger</span><span class="p">)</span>
</pre></div>
</div>
<p>This however has the disadvantage that the dispatcher entry on the log
record is a weak reference and might go away unexpectedly and will not be
there if log records are sent to a different process.</p>
<p>Last but not least you can check if you can modify the stack around the
execution of the code that triggers that logger  For instance if the
logger you are interested in is used by a specific subsystem, you can
modify the stacks before calling into the system.</p>
</div>
</div>


          </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             >index</a></li>
        <li class="right" >
          <a href="py-modindex.html" title="Python Module Index"
             >modules</a> |</li>
        <li class="right" >
          <a href="stacks.html" title="Stacks in Logbook"
             >next</a> |</li>
        <li class="right" >
          <a href="quickstart.html" title="Quickstart"
             >previous</a> |</li>
        <li><a href="index.html">Logbook 0.7.0</a> &raquo;</li> 
      </ul>
    </div>

  
    <div class="footer">
        &copy; Copyright 2010, Armin Ronacher, Georg Brandl.
      Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.2.2.
    </div>
  </div>

  </body>
</html>