diff --git a/include/zephyr/zbus/zbus.h b/include/zephyr/zbus/zbus.h index 84dc8afdecd..4eb247ad5eb 100644 --- a/include/zephyr/zbus/zbus.h +++ b/include/zephyr/zbus/zbus.h @@ -62,6 +62,13 @@ struct zbus_channel_data { */ struct net_buf_pool *msg_subscriber_pool; #endif /* ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION */ + +#if defined(CONFIG_ZBUS_CHANNEL_PUBLISH_STATS) || defined(__DOXYGEN__) + /** Kernel timestamp of the last publish action on this channel */ + k_ticks_t publish_timestamp; + /** Number of times data has been published to this channel */ + uint32_t publish_count; +#endif /* CONFIG_ZBUS_CHANNEL_PUBLISH_STATS */ }; /** @@ -722,6 +729,89 @@ static inline void zbus_chan_set_msg_sub_pool(const struct zbus_channel *chan, #endif /* ZBUS_MSG_SUBSCRIBER_NET_BUF_POOL_ISOLATION */ +#if defined(CONFIG_ZBUS_CHANNEL_PUBLISH_STATS) || defined(__DOXYGEN__) + +/** + * @brief Update the publishing statistics for a channel + * + * This function updates the publishing statistics for the @ref zbus_chan_claim -> + * @ref zbus_chan_finish workflow, which cannot automatically determine whether + * new data has been published or not. + * + * @warning This function must only be used directly for already locked channels. + * + * @param chan The channel's reference. + */ +static inline void zbus_chan_pub_stats_update(const struct zbus_channel *chan) +{ + __ASSERT(chan != NULL, "chan is required"); + + chan->data->publish_timestamp = k_uptime_ticks(); + chan->data->publish_count += 1; +} + +/** + * @brief Get the time a channel was last published to. + * + * @note Will return 0 if channel has not yet been published to. + * + * @param chan The channel's reference. + * + * @return The kernel timestamp of the last publishing action. + */ +static inline k_ticks_t zbus_chan_pub_stats_last_time(const struct zbus_channel *chan) +{ + __ASSERT(chan != NULL, "chan is required"); + + return chan->data->publish_timestamp; +} + +/** + * @brief Get the number of times a channel has been published to. + * + * @note Will return 0 if channel has not yet been published to. + * + * @param chan The channel's reference. + * + * @return The number of times a channel has been published to. + */ +static inline uint32_t zbus_chan_pub_stats_count(const struct zbus_channel *chan) +{ + __ASSERT(chan != NULL, "chan is required"); + + return chan->data->publish_count; +} + +/** + * @brief Get the average period between publishes to a channel. + * + * @note Will return 0 if channel has not yet been published to. + * + * @param chan The channel's reference. + * + * @return Average duration in milliseconds between publishes. + */ +static inline uint32_t zbus_chan_pub_stats_avg_period(const struct zbus_channel *chan) +{ + __ASSERT(chan != NULL, "chan is required"); + + /* Not yet published, period = 0ms */ + if (chan->data->publish_count == 0) { + return 0; + } + /* Average period across application runtime */ + return k_uptime_get() / chan->data->publish_count; +} + +#else + +static inline void zbus_chan_pub_stats_update(const struct zbus_channel *chan) +{ + (void)chan; +} + +#endif /* CONFIG_ZBUS_CHANNEL_PUBLISH_STATS */ + #if defined(CONFIG_ZBUS_RUNTIME_OBSERVERS) || defined(__DOXYGEN__) /** diff --git a/subsys/zbus/Kconfig b/subsys/zbus/Kconfig index 2f7040cf2fc..8f742b8bd99 100644 --- a/subsys/zbus/Kconfig +++ b/subsys/zbus/Kconfig @@ -19,6 +19,9 @@ config ZBUS_CHANNEL_NAME config ZBUS_OBSERVER_NAME bool "Observer name field" +config ZBUS_CHANNEL_PUBLISH_STATS + bool "Channel publishing statistics (Timestamp and count)" + config ZBUS_MSG_SUBSCRIBER select NET_BUF bool "Message subscribers will receive all messages in sequence." diff --git a/subsys/zbus/zbus.c b/subsys/zbus/zbus.c index b55c8498ad4..78f8ce99fd4 100644 --- a/subsys/zbus/zbus.c +++ b/subsys/zbus/zbus.c @@ -355,6 +355,11 @@ int zbus_chan_pub(const struct zbus_channel *chan, const void *msg, k_timeout_t return err; } +#if defined(CONFIG_ZBUS_CHANNEL_PUBLISH_STATS) + chan->data->publish_timestamp = k_uptime_ticks(); + chan->data->publish_count += 1; +#endif /* CONFIG_ZBUS_CHANNEL_PUBLISH_STATS */ + memcpy(chan->message, msg, chan->message_size); err = _zbus_vded_exec(chan, end_time);