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, 1,
43 10, 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 1, 10, NULL, sec_tag_list_verify_none, sizeof(sec_tag_list_verify_none));
103
104 HTTP_RESOURCE_DEFINE(index_html_gz_resource_https, test_https_service, "/metrics",
105 &dyn_resource_detail);
106
107 #endif /* CONFIG_NET_SAMPLE_HTTPS_SERVICE */
108
setup_tls(void)109 static void setup_tls(void)
110 {
111 #if defined(CONFIG_NET_SAMPLE_HTTPS_SERVICE)
112 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
113 int err;
114
115 #if defined(CONFIG_NET_SAMPLE_CERTS_WITH_SC)
116 err = tls_credential_add(HTTP_SERVER_CERTIFICATE_TAG, TLS_CREDENTIAL_CA_CERTIFICATE,
117 ca_certificate, sizeof(ca_certificate));
118 if (err < 0) {
119 LOG_ERR("Failed to register CA certificate: %d", err);
120 }
121 #endif /* defined(CONFIG_NET_SAMPLE_CERTS_WITH_SC) */
122
123 err = tls_credential_add(HTTP_SERVER_CERTIFICATE_TAG, TLS_CREDENTIAL_SERVER_CERTIFICATE,
124 server_certificate, sizeof(server_certificate));
125 if (err < 0) {
126 LOG_ERR("Failed to register public certificate: %d", err);
127 }
128
129 err = tls_credential_add(HTTP_SERVER_CERTIFICATE_TAG, TLS_CREDENTIAL_PRIVATE_KEY,
130 private_key, sizeof(private_key));
131 if (err < 0) {
132 LOG_ERR("Failed to register private key: %d", err);
133 }
134
135 #if defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
136 err = tls_credential_add(PSK_TAG, TLS_CREDENTIAL_PSK, psk, sizeof(psk));
137 if (err < 0) {
138 LOG_ERR("Failed to register PSK: %d", err);
139 }
140
141 err = tls_credential_add(PSK_TAG, TLS_CREDENTIAL_PSK_ID, psk_id, sizeof(psk_id) - 1);
142 if (err < 0) {
143 LOG_ERR("Failed to register PSK ID: %d", err);
144 }
145 #endif /* defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) */
146 #endif /* defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) */
147 #endif /* defined(CONFIG_NET_SAMPLE_HTTPS_SERVICE) */
148 }
149
150 PROMETHEUS_COUNTER_DEFINE(http_request_counter, "HTTP request counter",
151 ({ .key = "http_request", .value = "request_count" }), NULL);
152
153 PROMETHEUS_COLLECTOR_DEFINE(test_collector);
154
main(void)155 int main(void)
156 {
157 /* Create a mock collector with different types of metrics */
158 prom_context.collector = &test_collector;
159
160 prom_context.counter = &http_request_counter;
161 prometheus_counter_inc(prom_context.counter);
162
163 prometheus_collector_register_metric(prom_context.collector, &prom_context.counter->base);
164
165 #if defined(CONFIG_NET_STATISTICS_VIA_PROMETHEUS)
166 (void)init_stats(prom_context.counter);
167 #endif
168
169 setup_tls();
170
171 http_server_start();
172
173 return 0;
174 }
175