Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion Doc/library/logging.handlers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -613,9 +613,9 @@
supports sending logging messages to a remote or local Unix syslog.


.. class:: SysLogHandler(address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER, socktype=socket.SOCK_DGRAM)
.. class:: SysLogHandler(address=('localhost', SYSLOG_UDP_PORT), facility=LOG_USER, socktype=socket.SOCK_DGRAM, timeout=None)

Returns a new instance of the :class:`SysLogHandler` class intended to

Check warning on line 618 in Doc/library/logging.handlers.rst

View workflow job for this annotation

GitHub Actions / Docs / Docs

py:const reference target not found: LOG_USER [ref.const]
communicate with a remote Unix machine whose address is given by *address* in
the form of a ``(host, port)`` tuple. If *address* is not specified,
``('localhost', 514)`` is used. The address is used to open a socket. An
Expand All @@ -626,6 +626,11 @@
*socktype* argument, which defaults to :const:`socket.SOCK_DGRAM` and thus
opens a UDP socket. To open a TCP socket (for use with the newer syslog
daemons such as rsyslog), specify a value of :const:`socket.SOCK_STREAM`.
If *timeout* is specified, it sets a timeout (in seconds) for the socket operations.
This can help prevent the program from hanging indefinitely if the syslog server is
unreachable. By default, *timeout* is `None`, meaning no timeout is applied.



Note that if your server is not listening on UDP port 514,
:class:`SysLogHandler` may appear not to work. In that case, check what
Expand All @@ -645,6 +650,8 @@
.. versionchanged:: 3.2
*socktype* was added.

.. versionchanged:: 3.x
*timeout* was added.

.. method:: close()

Expand Down
5 changes: 4 additions & 1 deletion Lib/logging/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,7 @@ class SysLogHandler(logging.Handler):
}

def __init__(self, address=('localhost', SYSLOG_UDP_PORT),
facility=LOG_USER, socktype=None):
facility=LOG_USER, socktype=None, timeout=None):
"""
Initialize a handler.

Expand All @@ -872,6 +872,7 @@ def __init__(self, address=('localhost', SYSLOG_UDP_PORT),
self.address = address
self.facility = facility
self.socktype = socktype
self.timeout = timeout
self.socket = None
self.createSocket()

Expand Down Expand Up @@ -933,6 +934,8 @@ def createSocket(self):
err = sock = None
try:
sock = socket.socket(af, socktype, proto)
if self.timeout:
sock.settimeout(self.timeout)
if socktype == socket.SOCK_STREAM:
sock.connect(sa)
break
Expand Down
13 changes: 13 additions & 0 deletions Lib/test/test_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import logging.handlers
import logging.config


import codecs
import configparser
import copy
Expand Down Expand Up @@ -2098,6 +2099,18 @@ def test_udp_reconnection(self):
self.handled.wait(support.LONG_TIMEOUT)
self.assertEqual(self.log_output, b'<11>sp\xc3\xa4m\x00')

@patch('socket.socket')
def test_tcp_timeout(self, mock_socket):
instance_mock_sock = mock_socket.return_value
instance_mock_sock.connect.side_effect = socket.timeout

with self.assertRaises(socket.timeout):
logging.handlers.SysLogHandler(address=('localhost', 514),
socktype=socket.SOCK_STREAM,
timeout=1)

instance_mock_sock.close.assert_called()

@unittest.skipUnless(hasattr(socket, "AF_UNIX"), "Unix sockets required")
class UnixSysLogHandlerTest(SysLogHandlerTest):

Expand Down
Loading