blob: ffc47a952da60a3e88cd05c4e7be8a3c910eac85 [file] [log] [blame]
/*
* 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,
const struct http_request_ctx *request_ctx,
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;
}