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:
parent
99abfda5ba
commit
2bc7b07f5c
4 changed files with 111 additions and 2 deletions
|
@ -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/)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
98
samples/net/prometheus/src/stats.c
Normal file
98
samples/net/prometheus/src/stats.c
Normal 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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue