logging: backend: mqtt
Added MQTT logging backend Signed-off-by: Arif Balik <arifbalik@outlook.com>
This commit is contained in:
parent
8b7b2b5e9e
commit
1939ba64c3
5 changed files with 238 additions and 0 deletions
68
include/zephyr/logging/log_backend_mqtt.h
Normal file
68
include/zephyr/logging/log_backend_mqtt.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Arif Balik <arifbalik@outlook.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ZEPHYR_INCLUDE_LOGGING_LOG_BACKEND_MQTT_H_
|
||||
#define ZEPHYR_INCLUDE_LOGGING_LOG_BACKEND_MQTT_H_
|
||||
|
||||
#include <zephyr/net/mqtt.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief MQTT log backend API
|
||||
* @defgroup log_backend_mqtt MQTT log backend API
|
||||
* @ingroup log_backend
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set the MQTT client instance to be able to publish application's log messages to broker.
|
||||
*
|
||||
* This function allows the application to provide its own initialized
|
||||
* MQTT client to the log backend. The backend will use this client
|
||||
* exclusively for publishing log messages via mqtt_publish().
|
||||
*
|
||||
* @param client Pointer to an initialized and connected MQTT client.
|
||||
* The client must remain valid for the lifetime of the
|
||||
* log backend usage. Pass NULL to disable MQTT logging.
|
||||
*
|
||||
* @return 0 on success, negative error code on failure.
|
||||
*
|
||||
* @note The MQTT client must be connected before calling this function.
|
||||
* @note The backend will not manage the client connection - this is the
|
||||
* responsibility of the application.
|
||||
* @note The backend will only use mqtt_publish() and will not perform
|
||||
* any other operations on the client.
|
||||
*/
|
||||
int log_backend_mqtt_client_set(struct mqtt_client *client);
|
||||
|
||||
/**
|
||||
* @brief Set the MQTT topic to which log messages will be published.
|
||||
*
|
||||
* Allows the application to specify the MQTT topic that the log backend
|
||||
* will use for publishing log messages to.
|
||||
*
|
||||
* @param topic Pointer to a null-terminated string containing the MQTT topic.
|
||||
* The topic must remain valid for the lifetime of the log backend usage.
|
||||
*
|
||||
* @return 0 on success, negative error code on failure.
|
||||
*
|
||||
* @note The topic must be a valid UTF-8 string, null-terminated and should not exceed
|
||||
* the maximum length supported by the MQTT broker.
|
||||
*/
|
||||
int log_backend_mqtt_topic_set(const char *topic);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ZEPHYR_INCLUDE_LOGGING_LOG_BACKEND_MQTT_H_ */
|
|
@ -25,6 +25,11 @@ zephyr_sources_ifdef(
|
|||
log_backend_fs.c
|
||||
)
|
||||
|
||||
zephyr_sources_ifdef(
|
||||
CONFIG_LOG_BACKEND_MQTT
|
||||
log_backend_mqtt.c
|
||||
)
|
||||
|
||||
zephyr_sources_ifdef(
|
||||
CONFIG_LOG_BACKEND_NATIVE_POSIX
|
||||
log_backend_native_posix.c
|
||||
|
|
|
@ -8,6 +8,7 @@ rsource "Kconfig.adsp_mtrace"
|
|||
rsource "Kconfig.ble"
|
||||
rsource "Kconfig.efi_console"
|
||||
rsource "Kconfig.fs"
|
||||
rsource "Kconfig.mqtt"
|
||||
rsource "Kconfig.native_posix"
|
||||
rsource "Kconfig.net"
|
||||
rsource "Kconfig.ws"
|
||||
|
|
49
subsys/logging/backends/Kconfig.mqtt
Normal file
49
subsys/logging/backends/Kconfig.mqtt
Normal file
|
@ -0,0 +1,49 @@
|
|||
# Copyright (c) 2024 Arif Balik <arifbalik@outlook.com>
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config LOG_BACKEND_MQTT
|
||||
bool "MQTT backend"
|
||||
depends on MQTT_LIB && !LOG_MODE_IMMEDIATE
|
||||
help
|
||||
Send log messages to an MQTT broker using an external MQTT client.
|
||||
This backend publishes log messages to a configurable MQTT topic
|
||||
using an MQTT client provided by the application via the
|
||||
log_backend_mqtt_client_set() API. The application is responsible
|
||||
for initializing, connecting, and managing the MQTT client lifecycle.
|
||||
|
||||
if LOG_BACKEND_MQTT
|
||||
|
||||
config LOG_BACKEND_MQTT_TOPIC_DEFAULT
|
||||
string "Default MQTT topic for log messages"
|
||||
default "zephyr/logs"
|
||||
help
|
||||
Default MQTT topic for log messages. Use log backend MQTT API to change it at runtime.
|
||||
|
||||
config LOG_BACKEND_MQTT_QOS
|
||||
int "MQTT Quality of Service level"
|
||||
default 0
|
||||
range 0 2
|
||||
help
|
||||
QoS level for published log messages:
|
||||
0 - At most once delivery (fire and forget)
|
||||
1 - At least once delivery (acknowledged delivery)
|
||||
2 - Exactly once delivery (assured delivery)
|
||||
|
||||
config LOG_BACKEND_MQTT_RETAIN
|
||||
bool "Retain MQTT messages"
|
||||
help
|
||||
When enabled, published log messages will be retained by the broker
|
||||
and delivered to new subscribers immediately upon subscription.
|
||||
|
||||
config LOG_BACKEND_MQTT_MAX_MSG_SIZE
|
||||
int "Maximum log message size"
|
||||
default 256
|
||||
range 64 1024
|
||||
help
|
||||
Maximum size of a single log message in bytes.
|
||||
|
||||
backend = MQTT
|
||||
backend-str = mqtt
|
||||
source "subsys/logging/Kconfig.template.log_format_config"
|
||||
|
||||
endif # LOG_BACKEND_MQTT
|
115
subsys/logging/backends/log_backend_mqtt.c
Normal file
115
subsys/logging/backends/log_backend_mqtt.c
Normal file
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Arif Balik <arifbalik@outlook.com>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
LOG_MODULE_REGISTER(log_backend_mqtt, CONFIG_LOG_DEFAULT_LEVEL);
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log_backend.h>
|
||||
#include <zephyr/logging/log_ctrl.h>
|
||||
#include <zephyr/logging/log_backend_std.h>
|
||||
#include <zephyr/logging/log_backend_mqtt.h>
|
||||
#include <zephyr/logging/log_core.h>
|
||||
#include <zephyr/logging/log_output.h>
|
||||
#include <zephyr/net/mqtt.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
#include <zephyr/random/random.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
static bool panic;
|
||||
static char *mqtt_topic = CONFIG_LOG_BACKEND_MQTT_TOPIC_DEFAULT;
|
||||
static uint8_t log_buf[CONFIG_LOG_BACKEND_MQTT_MAX_MSG_SIZE];
|
||||
static uint32_t log_format_current = CONFIG_LOG_BACKEND_MQTT_OUTPUT_DEFAULT;
|
||||
|
||||
static int log_output_func(uint8_t *data, size_t length, void *output_ctx)
|
||||
{
|
||||
__ASSERT(output_ctx != NULL, "Output context must not be NULL");
|
||||
|
||||
struct mqtt_client *client = (struct mqtt_client *)output_ctx;
|
||||
struct mqtt_publish_param param = {0};
|
||||
|
||||
param.message.topic.topic.utf8 = (uint8_t *)mqtt_topic;
|
||||
param.message.topic.topic.size = strlen(mqtt_topic);
|
||||
param.message.topic.qos = CONFIG_LOG_BACKEND_MQTT_QOS;
|
||||
param.message.payload.data = data;
|
||||
param.message.payload.len = length;
|
||||
param.retain_flag = IS_ENABLED(CONFIG_LOG_BACKEND_MQTT_RETAIN);
|
||||
|
||||
#if (CONFIG_LOG_BACKEND_MQTT_QOS > MQTT_QOS_0_AT_MOST_ONCE)
|
||||
param.message_id = sys_rand32_get();
|
||||
#endif
|
||||
|
||||
int ret = mqtt_publish(client, ¶m);
|
||||
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
LOG_OUTPUT_DEFINE(log_output_mqtt, log_output_func, log_buf, sizeof(log_buf));
|
||||
|
||||
static void mqtt_backend_process(const struct log_backend *const backend,
|
||||
union log_msg_generic *msg)
|
||||
{
|
||||
if (panic) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t flags = log_backend_std_get_flags();
|
||||
|
||||
log_format_func_t log_output_func = log_format_func_t_get(log_format_current);
|
||||
|
||||
log_output_ctx_set(&log_output_mqtt, backend->cb->ctx);
|
||||
|
||||
log_output_func(&log_output_mqtt, &msg->log, flags);
|
||||
}
|
||||
|
||||
static int mqtt_backend_format_set(const struct log_backend *const backend, uint32_t log_type)
|
||||
{
|
||||
ARG_UNUSED(backend);
|
||||
log_format_current = log_type;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mqtt_backend_panic(const struct log_backend *const backend)
|
||||
{
|
||||
ARG_UNUSED(backend);
|
||||
panic = true;
|
||||
}
|
||||
|
||||
const struct log_backend_api log_backend_mqtt_api = {
|
||||
.process = mqtt_backend_process,
|
||||
.format_set = mqtt_backend_format_set,
|
||||
.panic = mqtt_backend_panic,
|
||||
};
|
||||
|
||||
LOG_BACKEND_DEFINE(log_backend_mqtt, log_backend_mqtt_api, false);
|
||||
|
||||
int log_backend_mqtt_client_set(struct mqtt_client *client)
|
||||
{
|
||||
log_backend_disable(&log_backend_mqtt);
|
||||
|
||||
if (client != NULL) {
|
||||
log_backend_enable(&log_backend_mqtt, (void *)client, CONFIG_LOG_MAX_LEVEL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int log_backend_mqtt_topic_set(const char *topic)
|
||||
{
|
||||
if (topic == NULL || strlen(topic) == 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mqtt_topic = topic;
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue