1 /*
2 * Copyright (c) 2024 Mustafa Abdullah Kus, Sparse Technology
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/drivers/sensor.h>
9 #include <zephyr/kernel.h>
10 #include <zephyr/net/tls_credentials.h>
11 #include <zephyr/net/http/server.h>
12 #include <zephyr/net/http/service.h>
13 #include <zephyr/net/net_ip.h>
14 #include <zephyr/net/socket.h>
15
16 #include <zephyr/net/prometheus/formatter.h>
17 #include <zephyr/net/prometheus/collector.h>
18 #include <zephyr/net/prometheus/counter.h>
19 #include <zephyr/net/prometheus/gauge.h>
20 #include <zephyr/net/prometheus/histogram.h>
21 #include <zephyr/net/prometheus/summary.h>
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include <zephyr/logging/log.h>
28 LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG);
29
30 extern int init_stats(struct prometheus_counter *counter);
31
32 struct app_context {
33
34 struct prometheus_collector *collector;
35
36 struct prometheus_counter *counter;
37
38 } prom_context;
39
40 #if defined(CONFIG_NET_SAMPLE_HTTP_SERVICE)
41 static uint16_t test_http_service_port = CONFIG_NET_SAMPLE_HTTP_SERVER_SERVICE_PORT;
42 HTTP_SERVICE_DEFINE(test_http_service, CONFIG_NET_CONFIG_MY_IPV4_ADDR, &test_http_service_port,
43 CONFIG_HTTP_SERVER_MAX_CLIENTS, 10, NULL, NULL, NULL);
44
dyn_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)45 static int dyn_handler(struct http_client_ctx *client, enum http_data_status status,
46 const struct http_request_ctx *request_ctx,
47 struct http_response_ctx *response_ctx, void *user_data)
48 {
49 int ret;
50 static uint8_t prom_buffer[256];
51
52 if (status == HTTP_SERVER_DATA_FINAL) {
53
54 /* incrase counter per request */
55 prometheus_counter_inc(prom_context.counter);
56
57 /* clear buffer */
58 (void)memset(prom_buffer, 0, sizeof(prom_buffer));
59
60 /* format exposition data */
61 ret = prometheus_format_exposition(prom_context.collector, prom_buffer,
62 sizeof(prom_buffer));
63 if (ret < 0) {
64 LOG_ERR("Cannot format exposition data (%d)", ret);
65 return ret;
66 }
67
68 response_ctx->body = prom_buffer;
69 response_ctx->body_len = strlen(prom_buffer);
70 response_ctx->final_chunk = true;
71 }
72
73 return 0;
74 }
75
76 struct http_resource_detail_dynamic dyn_resource_detail = {
77 .common = {
78 .type = HTTP_RESOURCE_TYPE_DYNAMIC,
79 .bitmask_of_supported_http_methods = BIT(HTTP_GET),
80 .content_type = "text/plain",
81 },
82 .cb = dyn_handler,
83 .user_data = NULL,
84 };
85
86 HTTP_RESOURCE_DEFINE(dyn_resource, test_http_service, "/metrics", &dyn_resource_detail);
87
88 #endif /* CONFIG_NET_SAMPLE_HTTP_SERVICE */
89
90 #if defined(CONFIG_NET_SAMPLE_HTTPS_SERVICE)
91 #include "certificate.h"
92
93 const sec_tag_t sec_tag_list_verify_none[] = {
94 HTTP_SERVER_CERTIFICATE_TAG,
95 #if defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
96 PSK_TAG,
97 #endif
98 };
99
100 static uint16_t test_https_service_port = CONFIG_NET_SAMPLE_HTTPS_SERVER_SERVICE_PORT;
101 HTTPS_SERVICE_DEFINE(test_https_service, CONFIG_NET_CONFIG_MY_IPV4_ADDR, &test_https_service_port,
102 CONFIG_HTTP_SERVER_MAX_CLIENTS, 10, NULL, NULL, NULL, sec_tag_list_verify_none,
103 sizeof(sec_tag_list_verify_none));
104
105 HTTP_RESOURCE_DEFINE(index_html_gz_resource_https, test_https_service, "/metrics",
106 &dyn_resource_detail);
107
108 #endif /* CONFIG_NET_SAMPLE_HTTPS_SERVICE */
109
setup_tls(void)110 static void setup_tls(void)
111 {
112 #if defined(CONFIG_NET_SAMPLE_HTTPS_SERVICE)
113 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
114 int err;
115
116 #if defined(CONFIG_NET_SAMPLE_CERTS_WITH_SC)
117 err = tls_credential_add(HTTP_SERVER_CERTIFICATE_TAG, TLS_CREDENTIAL_CA_CERTIFICATE,
118 ca_certificate, sizeof(ca_certificate));
119 if (err < 0) {
120 LOG_ERR("Failed to register CA certificate: %d", err);
121 }
122 #endif /* defined(CONFIG_NET_SAMPLE_CERTS_WITH_SC) */
123
124 err = tls_credential_add(HTTP_SERVER_CERTIFICATE_TAG, TLS_CREDENTIAL_PUBLIC_CERTIFICATE,
125 server_certificate, sizeof(server_certificate));
126 if (err < 0) {
127 LOG_ERR("Failed to register public certificate: %d", err);
128 }
129
130 err = tls_credential_add(HTTP_SERVER_CERTIFICATE_TAG, TLS_CREDENTIAL_PRIVATE_KEY,
131 private_key, sizeof(private_key));
132 if (err < 0) {
133 LOG_ERR("Failed to register private key: %d", err);
134 }
135
136 #if defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
137 err = tls_credential_add(PSK_TAG, TLS_CREDENTIAL_PSK, psk, sizeof(psk));
138 if (err < 0) {
139 LOG_ERR("Failed to register PSK: %d", err);
140 }
141
142 err = tls_credential_add(PSK_TAG, TLS_CREDENTIAL_PSK_ID, psk_id, sizeof(psk_id) - 1);
143 if (err < 0) {
144 LOG_ERR("Failed to register PSK ID: %d", err);
145 }
146 #endif /* defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) */
147 #endif /* defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) */
148 #endif /* defined(CONFIG_NET_SAMPLE_HTTPS_SERVICE) */
149 }
150
151 PROMETHEUS_COUNTER_DEFINE(http_request_counter, "HTTP request counter",
152 ({ .key = "http_request", .value = "request_count" }), NULL);
153
154 PROMETHEUS_COLLECTOR_DEFINE(test_collector);
155
main(void)156 int main(void)
157 {
158 /* Create a mock collector with different types of metrics */
159 prom_context.collector = &test_collector;
160
161 prom_context.counter = &http_request_counter;
162 prometheus_counter_inc(prom_context.counter);
163
164 prometheus_collector_register_metric(prom_context.collector, &prom_context.counter->base);
165
166 #if defined(CONFIG_NET_STATISTICS_VIA_PROMETHEUS)
167 (void)init_stats(prom_context.counter);
168 #endif
169
170 setup_tls();
171
172 http_server_start();
173
174 return 0;
175 }
176