提交 79331252 编写于 作者: J James Myatt 提交者: Roger Light

Implement support for logging using the standard logging package (see PEP 282) (#95)

Signed-off-by: NJames Myatt <james@jamesmyatt.co.uk>
上级 5a2f0a88
......@@ -268,6 +268,38 @@ Do not use this function in a real system. Setting value to True means there is
Must be called before ``connect*)``.
enable_logger()
'''''''''''''''
::
enable_logger(logger)
Enable logging using the standard python logging package (See PEP 282). This may be used at the same time as the ``on_log`` callback method.
If ``logger`` is specified, then that ``logging.Logger`` object will be used, otherwise one will be created automatically.
Paho logging levels are converted to standard ones according to the following mapping:
==================== ===============
Paho logging
==================== ===============
``MQTT_LOG_ERR`` ``logging.ERROR``
``MQTT_LOG_WARNING`` ``logging.WARNING``
``MQTT_LOG_NOTICE`` ``logging.INFO`` *(no direct equivalent)*
``MQTT_LOG_INFO`` ``logging.INFO``
``MQTT_LOG_DEBUG`` ``logging.DEBUG``
==================== ===============
disable_logger()
''''''''''''''''
::
disable_logger()
Disable logging using standard python logging package. This has no effect on the ``on_log`` callback.
username_pw_set()
'''''''''''''''''
......@@ -865,6 +897,9 @@ Called when the client has log information. Define to allow debugging. The
``MQTT_LOG_INFO``, ``MQTT_LOG_NOTICE``, ``MQTT_LOG_WARNING``, ``MQTT_LOG_ERR``,
and ``MQTT_LOG_DEBUG``. The message itself is in ``buf``.
This may be used at the same time as the standard Python logging, which can be
enabled via the ``enable_logger`` method.
External event loop support
```````````````````````````
......
#!/usr/bin/python
# Copyright (c) 2016 James Myatt <james@jamesmyatt.co.uk>
#
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Distribution License v1.0
# which accompanies this distribution.
#
# The Eclipse Distribution License is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# Contributors:
# James Myatt - initial implementation
# This shows a simple example of standard logging with an MQTT subscriber.
import sys
import logging
try:
import paho.mqtt.client as mqtt
except ImportError:
# This part is only required to run the example from within the examples
# directory when the module itself is not installed.
#
# If you have the module installed, just use "import paho.mqtt.client"
import os
import inspect
cmd_subfolder = os.path.realpath(
os.path.abspath(os.path.join(os.path.split(inspect.getfile(inspect.currentframe()))[0], "../src")))
if cmd_subfolder not in sys.path:
sys.path.insert(0, cmd_subfolder)
import paho.mqtt.client as mqtt
logging.basicConfig(level=logging.DEBUG)
# If you want to use a specific client id, use
# mqttc = mqtt.Client("client-id")
# but note that the client id must be unique on the broker. Leaving the client
# id parameter empty will generate a random id for you.
mqttc = mqtt.Client()
logger = logging.getLogger(__name__)
mqttc.enable_logger(logger)
mqttc.connect("m2m.eclipse.org", 1883, 60)
mqttc.subscribe("$SYS/#", 0)
mqttc.loop_forever()
......@@ -39,6 +39,7 @@ import uuid
import base64
import string
import hashlib
import logging
try:
# Use monotionic clock if available
time_func = time.monotonic
......@@ -91,6 +92,13 @@ MQTT_LOG_NOTICE = 0x02
MQTT_LOG_WARNING = 0x04
MQTT_LOG_ERR = 0x08
MQTT_LOG_DEBUG = 0x10
LOGGING_LEVEL = {
MQTT_LOG_DEBUG: logging.DEBUG,
MQTT_LOG_INFO: logging.INFO,
MQTT_LOG_NOTICE: logging.INFO, # This has no direct equivalent level
MQTT_LOG_WARNING: logging.WARNING,
MQTT_LOG_ERR: logging.ERROR,
}
# CONNACK codes
CONNACK_ACCEPTED = 0
......@@ -521,6 +529,7 @@ class Client(object):
self._tls_ciphers = None
self._tls_version = tls_version
self._tls_insecure = False
self._logger = None
# No default callbacks
self._on_log = None
self._on_connect = None
......@@ -637,6 +646,17 @@ class Client(object):
self._tls_insecure = value
def enable_logger(self, logger=None):
if not logger:
if self._logger:
# Do not replace existing logger
return
logger = logging.getLogger(__name__)
self._logger = logger
def disable_logger(self):
self._logger = None
def connect(self, host, port=1883, keepalive=60, bind_address=""):
"""Connect to a remote broker.
......@@ -1792,6 +1812,9 @@ class Client(object):
if self.on_log:
buf = fmt % args
self.on_log(self, self._userdata, level, buf)
if self._logger:
level_std = LOGGING_LEVEL[level]
self._logger.log(level_std, fmt, *args)
def _check_keepalive(self):
if self._keepalive == 0:
......@@ -1920,8 +1943,11 @@ class Client(object):
packet.extend(struct.pack("!B", command))
if payload is None:
remaining_length = 2+len(utopic)
self._easy_log(MQTT_LOG_DEBUG, "Sending PUBLISH (d%d, q%d, r%d, m%d), '%s' (NULL payload)",
dup, qos, retain, mid, topic)
self._easy_log(
MQTT_LOG_DEBUG,
"Sending PUBLISH (d%d, q%d, r%d, m%d), '%s' (NULL payload)",
dup, qos, retain, mid, topic
)
else:
if isinstance(payload, str):
upayload = payload.encode('utf-8')
......@@ -1933,8 +1959,11 @@ class Client(object):
payloadlen = len(upayload)
remaining_length = 2+len(utopic) + payloadlen
self._easy_log(MQTT_LOG_DEBUG, "Sending PUBLISH (d%d, q%d, r%d, m%d), '%s', ... (%d bytes)",
dup, qos, retain, mid, topic, payloadlen)
self._easy_log(
MQTT_LOG_DEBUG,
"Sending PUBLISH (d%d, q%d, r%d, m%d), '%s', ... (%d bytes)",
dup, qos, retain, mid, topic, payloadlen
)
if qos > 0:
# For message id
......@@ -2035,14 +2064,18 @@ class Client(object):
self._pack_str16(packet, self._password)
self._keepalive = keepalive
self._easy_log(MQTT_LOG_DEBUG, "Sending CONNECT (u%d, p%d, wr%d, wq%d, wf%d, c%d, k%d) client_id=%s",
(connect_flags&0x80)>>7,
(connect_flags&0x40)>>6,
(connect_flags&0x20)>>5,
(connect_flags&0x18)>>3,
(connect_flags&0x4)>>2,
(connect_flags&0x2)>>1,
keepalive, self._client_id)
self._easy_log(
MQTT_LOG_DEBUG,
"Sending CONNECT (u%d, p%d, wr%d, wq%d, wf%d, c%d, k%d) client_id=%s",
(connect_flags & 0x80) >> 7,
(connect_flags & 0x40) >> 6,
(connect_flags & 0x20) >> 5,
(connect_flags & 0x18) >> 3,
(connect_flags & 0x4) >> 2,
(connect_flags & 0x2) >> 1,
keepalive,
self._client_id
)
return self._packet_queue(command, packet, 0, 0)
def _send_disconnect(self):
......@@ -2237,7 +2270,11 @@ class Client(object):
(flags, result) = struct.unpack("!BB", self._in_packet['packet'])
if result == CONNACK_REFUSED_PROTOCOL_VERSION and self._protocol == MQTTv311:
self._easy_log(MQTT_LOG_DEBUG, "Received CONNACK (%s, %s), attempting downgrade to MQTT v3.1.", flags, result)
self._easy_log(
MQTT_LOG_DEBUG,
"Received CONNACK (%s, %s), attempting downgrade to MQTT v3.1.",
flags, result
)
# Downgrade to MQTT v3.1
self._protocol = MQTTv31
return self.reconnect()
......@@ -2361,10 +2398,10 @@ class Client(object):
self._easy_log(
MQTT_LOG_DEBUG,
"Received PUBLISH (d"+str(message.dup)+
", q"+str(message.qos)+", r"+str(message.retain)+
", m"+str(message.mid)+", '"+message.topic+
"', ... ("+str(len(message.payload))+" bytes)")
"Received PUBLISH (d%d, q%d, r%d, m%d), '%s', ... (%d bytes)",
message.dup, message.qos, message.retain, message.mid,
message.topic, len(message.payload)
)
message.timestamp = time_func()
if message.qos == 0:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册