Skip to content

Commit df912c9

Browse files
authored
[doc] Update logging documentation to improve grammar and elucidate an example. (GH-117541)
1 parent b32789c commit df912c9

File tree

2 files changed

+72
-11
lines changed

2 files changed

+72
-11
lines changed

Doc/howto/logging-cookbook.rst

+64-4
Original file line numberDiff line numberDiff line change
@@ -1915,14 +1915,15 @@ In a similar way to the above section, we can implement a listener and handler
19151915
using `pynng <https://pypi.org/project/pynng/>`_, which is a Python binding to
19161916
`NNG <https://nng.nanomsg.org/>`_, billed as a spiritual successor to ZeroMQ.
19171917
The following snippets illustrate -- you can test them in an environment which has
1918-
``pynng`` installed. Juat for variety, we present the listener first.
1918+
``pynng`` installed. Just for variety, we present the listener first.
19191919

19201920

19211921
Subclass ``QueueListener``
19221922
^^^^^^^^^^^^^^^^^^^^^^^^^^
19231923

19241924
.. code-block:: python
19251925
1926+
# listener.py
19261927
import json
19271928
import logging
19281929
import logging.handlers
@@ -1955,7 +1956,7 @@ Subclass ``QueueListener``
19551956
break
19561957
except pynng.Timeout:
19571958
pass
1958-
except pynng.Closed: # sometimes hit when you hit Ctrl-C
1959+
except pynng.Closed: # sometimes happens when you hit Ctrl-C
19591960
break
19601961
if data is None:
19611962
return None
@@ -1988,6 +1989,7 @@ Subclass ``QueueHandler``
19881989

19891990
.. code-block:: python
19901991
1992+
# sender.py
19911993
import json
19921994
import logging
19931995
import logging.handlers
@@ -2015,9 +2017,10 @@ Subclass ``QueueHandler``
20152017
20162018
logging.getLogger('pynng').propagate = False
20172019
handler = NNGSocketHandler(DEFAULT_ADDR)
2020+
# Make sure the process ID is in the output
20182021
logging.basicConfig(level=logging.DEBUG,
20192022
handlers=[logging.StreamHandler(), handler],
2020-
format='%(levelname)-8s %(name)10s %(message)s')
2023+
format='%(levelname)-8s %(name)10s %(process)6s %(message)s')
20212024
levels = (logging.DEBUG, logging.INFO, logging.WARNING, logging.ERROR,
20222025
logging.CRITICAL)
20232026
logger_names = ('myapp', 'myapp.lib1', 'myapp.lib2')
@@ -2031,7 +2034,64 @@ Subclass ``QueueHandler``
20312034
delay = random.random() * 2 + 0.5
20322035
time.sleep(delay)
20332036
2034-
You can run the above two snippets in separate command shells.
2037+
You can run the above two snippets in separate command shells. If we run the
2038+
listener in one shell and run the sender in two separate shells, we should see
2039+
something like the following. In the first sender shell:
2040+
2041+
.. code-block:: console
2042+
2043+
$ python sender.py
2044+
DEBUG myapp 613 Message no. 1
2045+
WARNING myapp.lib2 613 Message no. 2
2046+
CRITICAL myapp.lib2 613 Message no. 3
2047+
WARNING myapp.lib2 613 Message no. 4
2048+
CRITICAL myapp.lib1 613 Message no. 5
2049+
DEBUG myapp 613 Message no. 6
2050+
CRITICAL myapp.lib1 613 Message no. 7
2051+
INFO myapp.lib1 613 Message no. 8
2052+
(and so on)
2053+
2054+
In the second sender shell:
2055+
2056+
.. code-block:: console
2057+
2058+
$ python sender.py
2059+
INFO myapp.lib2 657 Message no. 1
2060+
CRITICAL myapp.lib2 657 Message no. 2
2061+
CRITICAL myapp 657 Message no. 3
2062+
CRITICAL myapp.lib1 657 Message no. 4
2063+
INFO myapp.lib1 657 Message no. 5
2064+
WARNING myapp.lib2 657 Message no. 6
2065+
CRITICAL myapp 657 Message no. 7
2066+
DEBUG myapp.lib1 657 Message no. 8
2067+
(and so on)
2068+
2069+
In the listener shell:
2070+
2071+
.. code-block:: console
2072+
2073+
$ python listener.py
2074+
Press Ctrl-C to stop.
2075+
DEBUG myapp 613 Message no. 1
2076+
WARNING myapp.lib2 613 Message no. 2
2077+
INFO myapp.lib2 657 Message no. 1
2078+
CRITICAL myapp.lib2 613 Message no. 3
2079+
CRITICAL myapp.lib2 657 Message no. 2
2080+
CRITICAL myapp 657 Message no. 3
2081+
WARNING myapp.lib2 613 Message no. 4
2082+
CRITICAL myapp.lib1 613 Message no. 5
2083+
CRITICAL myapp.lib1 657 Message no. 4
2084+
INFO myapp.lib1 657 Message no. 5
2085+
DEBUG myapp 613 Message no. 6
2086+
WARNING myapp.lib2 657 Message no. 6
2087+
CRITICAL myapp 657 Message no. 7
2088+
CRITICAL myapp.lib1 613 Message no. 7
2089+
INFO myapp.lib1 613 Message no. 8
2090+
DEBUG myapp.lib1 657 Message no. 8
2091+
(and so on)
2092+
2093+
As you can see, the logging from the two sender processes is interleaved in the
2094+
listener's output.
20352095

20362096

20372097
An example dictionary-based configuration

Doc/library/logging.rst

+8-7
Original file line numberDiff line numberDiff line change
@@ -63,12 +63,13 @@ If you run *myapp.py*, you should see this in *myapp.log*:
6363
INFO:mylib:Doing something
6464
INFO:__main__:Finished
6565
66-
The key features of this idiomatic usage is that the majority of code is simply
66+
The key feature of this idiomatic usage is that the majority of code is simply
6767
creating a module level logger with ``getLogger(__name__)``, and using that
68-
logger to do any needed logging. This is concise while allowing downstream code
69-
fine grained control if needed. Logged messages to the module-level logger get
70-
forwarded up to handlers of loggers in higher-level modules, all the way up to
71-
the root logger; for this reason this approach is known as hierarchical logging.
68+
logger to do any needed logging. This is concise, while allowing downstream
69+
code fine-grained control if needed. Logged messages to the module-level logger
70+
get forwarded to handlers of loggers in higher-level modules, all the way up to
71+
the highest-level logger known as the root logger; this approach is known as
72+
hierarchical logging.
7273

7374
For logging to be useful, it needs to be configured: setting the levels and
7475
destinations for each logger, potentially changing how specific modules log,
@@ -82,8 +83,8 @@ The module provides a lot of functionality and flexibility. If you are
8283
unfamiliar with logging, the best way to get to grips with it is to view the
8384
tutorials (**see the links above and on the right**).
8485

85-
The basic classes defined by the module, together with their functions, are
86-
listed below.
86+
The basic classes defined by the module, together with their attributes and
87+
methods, are listed in the sections below.
8788

8889
* Loggers expose the interface that application code directly uses.
8990
* Handlers send the log records (created by loggers) to the appropriate

0 commit comments

Comments
 (0)