samples: net: prometheus: Add support for network statistics

Add separate URL handling for network statistics.

Signed-off-by: Jukka Rissanen <jukka.rissanen@nordicsemi.no>
This commit is contained in:
Jukka Rissanen 2024-11-21 08:45:30 +02:00 committed by Anas Nashif
commit 2bc7b07f5c
4 changed files with 111 additions and 2 deletions

View file

@ -22,6 +22,7 @@ endif()
target_sources(app PRIVATE src/main.c)
target_sources_ifdef(CONFIG_NET_STATISTICS_VIA_PROMETHEUS app PRIVATE src/stats.c)
set(gen_dir ${ZEPHYR_BINARY_DIR}/include/generated/)

View file

@ -84,3 +84,7 @@ CONFIG_NET_SOCKETS_LOG_LEVEL_DBG=n
CONFIG_NET_HTTP_LOG_LEVEL_DBG=n
CONFIG_NET_IPV6_LOG_LEVEL_DBG=n
CONFIG_NET_IPV6_ND_LOG_LEVEL_DBG=n
# Network statistics Prometheus support
CONFIG_NET_STATISTICS_VIA_PROMETHEUS=y
CONFIG_NET_STATISTICS=y

View file

@ -27,7 +27,9 @@
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG);
struct {
extern int init_stats(struct prometheus_counter *counter);
struct app_context {
struct prometheus_collector *collector;
@ -88,7 +90,7 @@ HTTP_RESOURCE_DEFINE(dyn_resource, test_http_service, "/metrics", &dyn_resource_
#if defined(CONFIG_NET_SAMPLE_HTTPS_SERVICE)
#include "certificate.h"
static const sec_tag_t sec_tag_list_verify_none[] = {
const sec_tag_t sec_tag_list_verify_none[] = {
HTTP_SERVER_CERTIFICATE_TAG,
#if defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
PSK_TAG,
@ -160,6 +162,10 @@ int main(void)
prometheus_collector_register_metric(prom_context.collector, &prom_context.counter->base);
#if defined(CONFIG_NET_STATISTICS_VIA_PROMETHEUS)
(void)init_stats(prom_context.counter);
#endif
setup_tls();
http_server_start();

View file

@ -0,0 +1,98 @@
/*
* Copyright (c) 2024 Nordic Semiconductor
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/logging/log.h>
LOG_MODULE_DECLARE(main, LOG_LEVEL_DBG);
#include <zephyr/kernel.h>
#include <zephyr/kernel.h>
#include <zephyr/net/tls_credentials.h>
#include <zephyr/net/http/server.h>
#include <zephyr/net/http/service.h>
#include <zephyr/net/net_if.h>
#include <zephyr/net/net_ip.h>
#include <zephyr/net/prometheus/formatter.h>
#include <zephyr/net/prometheus/collector.h>
#include <zephyr/net/prometheus/counter.h>
#include <zephyr/net/prometheus/gauge.h>
#include <zephyr/net/prometheus/histogram.h>
#include <zephyr/net/prometheus/summary.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern struct http_service_desc test_http_service;
static struct prometheus_counter *http_request_counter;
static struct prometheus_collector *stats_collector;
static struct prometheus_collector_walk_context walk_ctx;
static int stats_handler(struct http_client_ctx *client, enum http_data_status status,
uint8_t *buffer, size_t len, struct http_response_ctx *response_ctx,
void *user_data)
{
int ret;
static uint8_t prom_buffer[1024];
if (status == HTTP_SERVER_DATA_FINAL) {
/* incrase counter per request */
prometheus_counter_inc(http_request_counter);
(void)memset(prom_buffer, 0, sizeof(prom_buffer));
ret = prometheus_collector_walk_metrics(user_data,
prom_buffer,
sizeof(prom_buffer));
if (ret < 0 && ret != -EAGAIN) {
LOG_ERR("Cannot format exposition data (%d)", ret);
return ret;
}
response_ctx->body = prom_buffer;
response_ctx->body_len = strlen(prom_buffer);
if (ret == 0) {
response_ctx->final_chunk = true;
ret = prometheus_collector_walk_init(&walk_ctx, stats_collector);
if (ret < 0) {
LOG_ERR("Cannot initialize walk context (%d)", ret);
}
}
}
return 0;
}
struct http_resource_detail_dynamic stats_resource_detail = {
.common = {
.type = HTTP_RESOURCE_TYPE_DYNAMIC,
.bitmask_of_supported_http_methods = BIT(HTTP_GET),
.content_type = "text/plain",
},
.cb = stats_handler,
.user_data = &walk_ctx,
};
HTTP_RESOURCE_DEFINE(stats_resource, test_http_service, "/statistics", &stats_resource_detail);
int init_stats(struct prometheus_counter *counter)
{
/* Use a collector from default network interface */
stats_collector = net_if_get_default()->collector;
if (stats_collector == NULL) {
LOG_ERR("Cannot get collector from default network interface");
return -EINVAL;
}
(void)prometheus_collector_walk_init(&walk_ctx, stats_collector);
http_request_counter = counter;
return 0;
}