feat: Initial metrics server

master
Sean McBride 3 years ago
parent 34e8731854
commit 71c99e91bb

@ -0,0 +1,10 @@
#pragma once
#include "tcp_server.h"
extern struct tcp_server metrics_server;
void metrics_server_init();
int metrics_server_listen();
int metrics_server_close();
void metrics_server_handler(int client_socket);

@ -5,6 +5,7 @@
#include "global_request_scheduler.h"
#include "generic_thread.h"
#include "listener_thread.h"
#include "metrics_server.h"
#include "module.h"
#include "runtime.h"
#include "sandbox_functions.h"
@ -134,6 +135,23 @@ listener_thread_register_tenant(struct tenant *tenant)
return rc;
}
int
listener_thread_register_metrics_server()
{
if (unlikely(listener_thread_epoll_file_descriptor == 0)) {
panic("Attempting to register metrics_server before listener thread initialization");
}
int rc = 0;
struct epoll_event accept_evt;
accept_evt.data.ptr = (void *)&metrics_server;
accept_evt.events = EPOLLIN;
rc = epoll_ctl(listener_thread_epoll_file_descriptor, EPOLL_CTL_ADD, metrics_server.socket_descriptor,
&accept_evt);
return rc;
}
static void
panic_on_epoll_error(struct epoll_event *evt)
{
@ -325,6 +343,29 @@ on_tenant_socket_epoll_event(struct epoll_event *evt)
}
}
static void
on_metrics_server_epoll_event(struct epoll_event *evt)
{
assert((evt->events & EPOLLIN) == EPOLLIN);
/* Accept Client Request as a nonblocking socket, saving address information */
struct sockaddr_in client_address;
socklen_t address_length = sizeof(client_address);
/* Accept as many clients requests as possible, returning when we would have blocked */
while (true) {
int client_socket = accept4(metrics_server.socket_descriptor, (struct sockaddr *)&client_address,
&address_length, SOCK_NONBLOCK);
if (unlikely(client_socket < 0)) {
if (errno == EWOULDBLOCK || errno == EAGAIN) return;
panic("accept4: %s", strerror(errno));
}
metrics_server_handler(client_socket);
}
}
static void
on_client_socket_epoll_event(struct epoll_event *evt)
{
@ -370,6 +411,10 @@ listener_thread_main(void *dummy)
generic_thread_initialize();
metrics_server_init();
metrics_server_listen();
listener_thread_register_metrics_server();
/* Set my priority */
// runtime_set_pthread_prio(pthread_self(), 2);
pthread_setschedprio(pthread_self(), -20);
@ -390,7 +435,9 @@ listener_thread_main(void *dummy)
for (int i = 0; i < descriptor_count; i++) {
panic_on_epoll_error(&epoll_events[i]);
if (tenant_database_find_by_ptr(epoll_events[i].data.ptr) != NULL) {
if (epoll_events[i].data.ptr == &metrics_server) {
on_metrics_server_epoll_event(&epoll_events[i]);
} else if (tenant_database_find_by_ptr(epoll_events[i].data.ptr) != NULL) {
on_tenant_socket_epoll_event(&epoll_events[i]);
} else {
on_client_socket_epoll_event(&epoll_events[i]);

@ -0,0 +1,67 @@
#include <stdlib.h>
#include <unistd.h>
#include "tcp_server.h"
#include "http_total.h"
struct tcp_server metrics_server;
void
metrics_server_init()
{
tcp_server_init(&metrics_server, 1776);
}
int
metrics_server_listen()
{
return tcp_server_listen(&metrics_server);
}
int
metrics_server_close()
{
return tcp_server_close(&metrics_server);
}
void
metrics_server_handler(int client_socket)
{
int rc = 0;
char *ostream_base = NULL;
size_t ostream_size = 0;
FILE *ostream = open_memstream(&ostream_base, &ostream_size);
assert(ostream != NULL);
uint32_t total_reqs = atomic_load(&http_total_requests);
uint32_t total_5XX = atomic_load(&http_total_5XX);
fprintf(ostream, "HTTP/1.1 200 OK\r\n\r\n");
fprintf(ostream, "# TYPE total_requests counter\n");
fprintf(ostream, "total_requests: %d\n", total_reqs);
fprintf(ostream, "# TYPE total_rejections counter\n");
fprintf(ostream, "total_rejections: %d\n", total_5XX);
fflush(ostream);
rewind(ostream);
char buf[256] = { 0 };
size_t nread = 0;
do {
nread = fread(buf, 1, 255, ostream);
buf[nread] = '\0';
/* TODO: Deal with blocking here! */
write(client_socket, buf, nread);
} while (nread > 0);
rc = fclose(ostream);
assert(rc == 0);
free(ostream_base);
ostream_size = 0;
close(client_socket);
}
Loading…
Cancel
Save