From a6baf60a30c39cbf0e79fac4b15a35ac0f15ce59 Mon Sep 17 00:00:00 2001 From: Vladimir Kotal Date: Wed, 14 Dec 2022 00:14:30 +0100 Subject: [PATCH 1/7] add MQTT handler example --- examples/logging_mqtt_handler.py | 43 ++++++++++++++++++++++++++++++++ examples/mqtt_handler.py | 38 ++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100755 examples/logging_mqtt_handler.py create mode 100644 examples/mqtt_handler.py diff --git a/examples/logging_mqtt_handler.py b/examples/logging_mqtt_handler.py new file mode 100755 index 0000000..f75d64f --- /dev/null +++ b/examples/logging_mqtt_handler.py @@ -0,0 +1,43 @@ +""" +Demonstrate how to use a single logger to emit log records to +both console and MQTT broker, in this case Adafruit IO. +""" + +import json +import socket +import ssl + +import adafruit_logging as logging +import adafruit_minimqtt.adafruit_minimqtt as MQTT + +from mqtt_handler import MQTTHandler + +logger = logging.getLogger(__name__) + +broker = "io.adafruit.com" +port = 8883 +username = "Adafruit_IO_username" +password = "Adafruit_IO_key" +feedname = "Adafruit_feed_name" +mqtt_topic = f"{username}/feeds/{feedname}" +mqtt_client = MQTT.MQTT( + broker=broker, + port=port, + username=username, + password=password, + socket_pool=socket, + ssl_context=ssl.create_default_context(), +) +mqtt_client.connect() +mqtt_handler = MQTTHandler(mqtt_client, mqtt_topic) +print("adding MQTT handler") +logger.addHandler(mqtt_handler) + +stream_handler = logging.StreamHandler() +print("adding Stream handler") +logger.addHandler(stream_handler) + +data = "foo bar" +print("logging begins !") +# This should emit both to the console as well as to the MQTT broker. +logger.warning(json.dumps(data)) diff --git a/examples/mqtt_handler.py b/examples/mqtt_handler.py new file mode 100644 index 0000000..ccb6ff9 --- /dev/null +++ b/examples/mqtt_handler.py @@ -0,0 +1,38 @@ +""" +MQTT logging handler - log records will be published as MQTT messages +""" + +import adafruit_minimqtt.adafruit_minimqtt as MQTT +# adafruit_logging defines log levels dynamically. +# pylint: disable=no-name-in-module +from adafruit_logging import NOTSET, Handler, LogRecord + + +class MQTTHandler(Handler): + """ + Log handler that emits log records as MQTT PUBLISH messages. + """ + def __init__(self, mqtt_client: MQTT.MQTT, topic: str) -> None: + """ + Assumes that the MQTT client object is already connected. + """ + super().__init__() + + self._mqtt_client = mqtt_client + self._topic = topic + + # To make it work also in CPython. + self.level = NOTSET + + def emit(self, record: LogRecord) -> None: + """ + Publish message from the LogRecord to the MQTT broker. + """ + self._mqtt_client.publish(self._topic, record.msg) + + # To make this work also in CPython's logging. + def handle(self, record: LogRecord) -> None: + """ + Handle the log record. Here, it means just emit. + """ + self.emit(record) From e35bf212b8c25ab5f6d89ce709e6e3f69f9ea650 Mon Sep 17 00:00:00 2001 From: Vladimir Kotal Date: Wed, 14 Dec 2022 00:26:09 +0100 Subject: [PATCH 2/7] reorder imports per pylint --- examples/logging_mqtt_handler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/logging_mqtt_handler.py b/examples/logging_mqtt_handler.py index f75d64f..9a22999 100755 --- a/examples/logging_mqtt_handler.py +++ b/examples/logging_mqtt_handler.py @@ -7,11 +7,11 @@ import socket import ssl -import adafruit_logging as logging import adafruit_minimqtt.adafruit_minimqtt as MQTT - from mqtt_handler import MQTTHandler +import adafruit_logging as logging + logger = logging.getLogger(__name__) broker = "io.adafruit.com" From 99587f0ce11f3b581962e10f5ec8b9b9ec95f3c3 Mon Sep 17 00:00:00 2001 From: Vladimir Kotal Date: Wed, 14 Dec 2022 00:28:58 +0100 Subject: [PATCH 3/7] use black --- examples/mqtt_handler.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/mqtt_handler.py b/examples/mqtt_handler.py index ccb6ff9..a7b3bed 100644 --- a/examples/mqtt_handler.py +++ b/examples/mqtt_handler.py @@ -3,6 +3,7 @@ """ import adafruit_minimqtt.adafruit_minimqtt as MQTT + # adafruit_logging defines log levels dynamically. # pylint: disable=no-name-in-module from adafruit_logging import NOTSET, Handler, LogRecord @@ -12,6 +13,7 @@ class MQTTHandler(Handler): """ Log handler that emits log records as MQTT PUBLISH messages. """ + def __init__(self, mqtt_client: MQTT.MQTT, topic: str) -> None: """ Assumes that the MQTT client object is already connected. From 31cb6107f319e8e258e984293dc05ae109f1ff89 Mon Sep 17 00:00:00 2001 From: Vladimir Kotal Date: Wed, 14 Dec 2022 00:31:18 +0100 Subject: [PATCH 4/7] add copyright/lincense headers --- examples/logging_mqtt_handler.py | 2 ++ examples/mqtt_handler.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/examples/logging_mqtt_handler.py b/examples/logging_mqtt_handler.py index 9a22999..79344eb 100755 --- a/examples/logging_mqtt_handler.py +++ b/examples/logging_mqtt_handler.py @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2022 vladak +# SPDX-License-Identifier: Unlicense """ Demonstrate how to use a single logger to emit log records to both console and MQTT broker, in this case Adafruit IO. diff --git a/examples/mqtt_handler.py b/examples/mqtt_handler.py index a7b3bed..febd479 100644 --- a/examples/mqtt_handler.py +++ b/examples/mqtt_handler.py @@ -1,3 +1,5 @@ +# SPDX-FileCopyrightText: 2022 vladak +# SPDX-License-Identifier: Unlicense """ MQTT logging handler - log records will be published as MQTT messages """ From 722fef9f016bbf4505ec5191710e04765b230c65 Mon Sep 17 00:00:00 2001 From: Vladimir Kotal Date: Wed, 14 Dec 2022 23:01:00 +0100 Subject: [PATCH 5/7] make the handler a bit more resilient --- examples/mqtt_handler.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/mqtt_handler.py b/examples/mqtt_handler.py index febd479..11e183b 100644 --- a/examples/mqtt_handler.py +++ b/examples/mqtt_handler.py @@ -30,9 +30,13 @@ def __init__(self, mqtt_client: MQTT.MQTT, topic: str) -> None: def emit(self, record: LogRecord) -> None: """ - Publish message from the LogRecord to the MQTT broker. + Publish message from the LogRecord to the MQTT broker, if connected. """ - self._mqtt_client.publish(self._topic, record.msg) + try: + if self._mqtt_client.is_connected(): + self._mqtt_client.publish(self._topic, record.msg) + except MQTT.MMQTTException: + pass # To make this work also in CPython's logging. def handle(self, record: LogRecord) -> None: From 068c585f85a43cf5de317891e0a957d0c85a1605 Mon Sep 17 00:00:00 2001 From: Vladimir Kotal Date: Tue, 20 Dec 2022 12:29:11 +0100 Subject: [PATCH 6/7] fold MQTTHandler to logging_mqtt_handler.py --- examples/logging_mqtt_handler.py | 106 ++++++++++++++++++++++--------- examples/mqtt_handler.py | 46 -------------- 2 files changed, 76 insertions(+), 76 deletions(-) delete mode 100644 examples/mqtt_handler.py diff --git a/examples/logging_mqtt_handler.py b/examples/logging_mqtt_handler.py index 79344eb..c408ae4 100755 --- a/examples/logging_mqtt_handler.py +++ b/examples/logging_mqtt_handler.py @@ -10,36 +10,82 @@ import ssl import adafruit_minimqtt.adafruit_minimqtt as MQTT -from mqtt_handler import MQTTHandler import adafruit_logging as logging +# adafruit_logging defines log levels dynamically. +# pylint: disable=no-name-in-module +from adafruit_logging import NOTSET, Handler, LogRecord -logger = logging.getLogger(__name__) - -broker = "io.adafruit.com" -port = 8883 -username = "Adafruit_IO_username" -password = "Adafruit_IO_key" -feedname = "Adafruit_feed_name" -mqtt_topic = f"{username}/feeds/{feedname}" -mqtt_client = MQTT.MQTT( - broker=broker, - port=port, - username=username, - password=password, - socket_pool=socket, - ssl_context=ssl.create_default_context(), -) -mqtt_client.connect() -mqtt_handler = MQTTHandler(mqtt_client, mqtt_topic) -print("adding MQTT handler") -logger.addHandler(mqtt_handler) - -stream_handler = logging.StreamHandler() -print("adding Stream handler") -logger.addHandler(stream_handler) - -data = "foo bar" -print("logging begins !") -# This should emit both to the console as well as to the MQTT broker. -logger.warning(json.dumps(data)) + +class MQTTHandler(Handler): + """ + Log handler that emits log records as MQTT PUBLISH messages. + """ + + def __init__(self, mqtt_client: MQTT.MQTT, topic: str) -> None: + """ + Assumes that the MQTT client object is already connected. + """ + super().__init__() + + self._mqtt_client = mqtt_client + self._topic = topic + + # To make it work also in CPython. + self.level = NOTSET + + def emit(self, record: LogRecord) -> None: + """ + Publish message from the LogRecord to the MQTT broker, if connected. + """ + try: + if self._mqtt_client.is_connected(): + self._mqtt_client.publish(self._topic, record.msg) + except MQTT.MMQTTException: + pass + + # To make this work also in CPython's logging. + def handle(self, record: LogRecord) -> None: + """ + Handle the log record. Here, it means just emit. + """ + self.emit(record) + + +def main(): + """ + Demonstrate how to use MQTT log handler. + """ + logger = logging.getLogger(__name__) + + broker = "io.adafruit.com" + port = 8883 + username = "Adafruit_IO_username" + password = "Adafruit_IO_key" + feedname = "Adafruit_feed_name" + mqtt_topic = f"{username}/feeds/{feedname}" + mqtt_client = MQTT.MQTT( + broker=broker, + port=port, + username=username, + password=password, + socket_pool=socket, + ssl_context=ssl.create_default_context(), + ) + mqtt_client.connect() + mqtt_handler = MQTTHandler(mqtt_client, mqtt_topic) + print("adding MQTT handler") + logger.addHandler(mqtt_handler) + + stream_handler = logging.StreamHandler() + print("adding Stream handler") + logger.addHandler(stream_handler) + + data = "foo bar" + print("logging begins !") + # This should emit both to the console as well as to the MQTT broker. + logger.warning(json.dumps(data)) + + +if __name__ == "__main__": + main() diff --git a/examples/mqtt_handler.py b/examples/mqtt_handler.py deleted file mode 100644 index 11e183b..0000000 --- a/examples/mqtt_handler.py +++ /dev/null @@ -1,46 +0,0 @@ -# SPDX-FileCopyrightText: 2022 vladak -# SPDX-License-Identifier: Unlicense -""" -MQTT logging handler - log records will be published as MQTT messages -""" - -import adafruit_minimqtt.adafruit_minimqtt as MQTT - -# adafruit_logging defines log levels dynamically. -# pylint: disable=no-name-in-module -from adafruit_logging import NOTSET, Handler, LogRecord - - -class MQTTHandler(Handler): - """ - Log handler that emits log records as MQTT PUBLISH messages. - """ - - def __init__(self, mqtt_client: MQTT.MQTT, topic: str) -> None: - """ - Assumes that the MQTT client object is already connected. - """ - super().__init__() - - self._mqtt_client = mqtt_client - self._topic = topic - - # To make it work also in CPython. - self.level = NOTSET - - def emit(self, record: LogRecord) -> None: - """ - Publish message from the LogRecord to the MQTT broker, if connected. - """ - try: - if self._mqtt_client.is_connected(): - self._mqtt_client.publish(self._topic, record.msg) - except MQTT.MMQTTException: - pass - - # To make this work also in CPython's logging. - def handle(self, record: LogRecord) -> None: - """ - Handle the log record. Here, it means just emit. - """ - self.emit(record) From da733596e59582af628d552ba069ac0e0d3368ac Mon Sep 17 00:00:00 2001 From: Vladimir Kotal Date: Tue, 20 Dec 2022 12:46:34 +0100 Subject: [PATCH 7/7] apply black --- examples/logging_mqtt_handler.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/logging_mqtt_handler.py b/examples/logging_mqtt_handler.py index c408ae4..9db578e 100755 --- a/examples/logging_mqtt_handler.py +++ b/examples/logging_mqtt_handler.py @@ -12,6 +12,7 @@ import adafruit_minimqtt.adafruit_minimqtt as MQTT import adafruit_logging as logging + # adafruit_logging defines log levels dynamically. # pylint: disable=no-name-in-module from adafruit_logging import NOTSET, Handler, LogRecord