forked from hkc/cc-stuff
Added Prometheus metrics
This commit is contained in:
parent
7d1343a0d7
commit
7533a3bae1
76
wsvpn.c
76
wsvpn.c
|
@ -83,7 +83,13 @@ struct metrics {
|
||||||
uint64_t received_bytes;
|
uint64_t received_bytes;
|
||||||
uint64_t received_messages;
|
uint64_t received_messages;
|
||||||
uint64_t errors;
|
uint64_t errors;
|
||||||
} metrics;
|
|
||||||
|
uint64_t method_calls[5];
|
||||||
|
} metrics = { 0 };
|
||||||
|
|
||||||
|
const char method_names[5][8] = {
|
||||||
|
"open", "isOpen", "close", "closeAll", "transmit"
|
||||||
|
};
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
const char *address = "ws://0.0.0.0:8667";
|
const char *address = "ws://0.0.0.0:8667";
|
||||||
|
@ -104,25 +110,38 @@ static void handle_client(struct mg_connection *connection, int event_type, void
|
||||||
struct mg_http_message *http_message = (struct mg_http_message *) event_data;
|
struct mg_http_message *http_message = (struct mg_http_message *) event_data;
|
||||||
if (mg_http_match_uri(http_message, "/open")) {
|
if (mg_http_match_uri(http_message, "/open")) {
|
||||||
mg_ws_upgrade(connection, http_message, NULL);
|
mg_ws_upgrade(connection, http_message, NULL);
|
||||||
} else if (mg_http_match_uri(http_message, "/stat")) {
|
} else if (mg_http_match_uri(http_message, "/metrics")) {
|
||||||
mg_printf(connection, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
|
mg_printf(connection, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
|
||||||
static char addr_str[256];
|
mg_http_printf_chunk(connection, "# HELP ws_bytes_sent_total Number of bytes sent to clients\n");
|
||||||
for (struct mg_connection *conn = connection->mgr->conns; conn != NULL; conn = conn->next) {
|
mg_http_printf_chunk(connection, "# TYPE ws_bytes_sent_total counter\n");
|
||||||
if (conn->is_websocket) {
|
mg_http_printf_chunk(connection, "ws_bytes_sent_total %ld\n", metrics.sent_bytes);
|
||||||
struct client *client = *(struct client **)&conn->data[0];
|
mg_http_printf_chunk(connection, "# HELP ws_bytes_received_total Number of bytes received to clients\n");
|
||||||
if (client->connection == conn) {
|
mg_http_printf_chunk(connection, "# TYPE ws_bytes_received_total counter\n");
|
||||||
mg_snprintf(addr_str, 256, "%M", mg_print_ip_port, &conn->rem);
|
mg_http_printf_chunk(connection, "ws_bytes_received_total %ld\n", metrics.received_bytes);
|
||||||
mg_http_printf_chunk(connection, "%s - %d ports {", addr_str, client->next_open_channel_index);
|
|
||||||
for (int i = 0; i < MAX_OPEN_CHANNELS; i++) {
|
mg_http_printf_chunk(connection, "# HELP ws_messages_sent_total Number of messages sent to clients\n");
|
||||||
if (i == client->next_open_channel_index) {
|
mg_http_printf_chunk(connection, "# TYPE ws_messages_sent_total counter\n");
|
||||||
mg_http_printf_chunk(connection, "/*end of used*/");
|
mg_http_printf_chunk(connection, "ws_messages_sent_total %ld\n", metrics.sent_messages);
|
||||||
}
|
mg_http_printf_chunk(connection, "# HELP ws_messages_received_total Number of messages received to clients\n");
|
||||||
mg_http_printf_chunk(connection, "%d,", client->open_channels[i]);
|
mg_http_printf_chunk(connection, "# TYPE ws_messages_received_total counter\n");
|
||||||
}
|
mg_http_printf_chunk(connection, "ws_messages_received_total %ld\n", metrics.received_messages);
|
||||||
mg_http_printf_chunk(connection, "}\n");
|
|
||||||
}
|
mg_http_printf_chunk(connection, "# HELP ws_clients Number of active websocket clients\n");
|
||||||
|
mg_http_printf_chunk(connection, "# TYPE ws_clients gauge\n");
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
for (struct mg_connection *conn = connection->mgr->conns; conn != NULL; conn = conn->next) {
|
||||||
|
if (conn->is_websocket) { n++; }
|
||||||
}
|
}
|
||||||
|
mg_http_printf_chunk(connection, "ws_clients %d\n", n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mg_http_printf_chunk(connection, "# HELP method_calls Times each method was called\n");
|
||||||
|
mg_http_printf_chunk(connection, "# TYPE method_calls counter\n");
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
mg_http_printf_chunk(connection, "method_calls{method=\"%s\"} %ld\n", method_names[i], metrics.method_calls[i]);
|
||||||
|
}
|
||||||
|
|
||||||
mg_http_printf_chunk(connection, "");
|
mg_http_printf_chunk(connection, "");
|
||||||
} else {
|
} else {
|
||||||
mg_http_reply(connection, 404, "", "uwu");
|
mg_http_reply(connection, 404, "", "uwu");
|
||||||
|
@ -160,6 +179,8 @@ void ws_send_error(struct mg_connection *connection, uint16_t request_id, const
|
||||||
buffer[4] = text_size & 0xFF;
|
buffer[4] = text_size & 0xFF;
|
||||||
|
|
||||||
metrics.sent_bytes += 5 + text_size;
|
metrics.sent_bytes += 5 + text_size;
|
||||||
|
metrics.sent_messages++;
|
||||||
|
metrics.errors++;
|
||||||
mg_ws_send(connection, buffer, 5 + text_size, WEBSOCKET_OP_BINARY);
|
mg_ws_send(connection, buffer, 5 + text_size, WEBSOCKET_OP_BINARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,6 +199,7 @@ void ws_send_info(struct mg_connection *connection, const char *fmt, ...) {
|
||||||
buffer[2] = text_size & 0xFF;
|
buffer[2] = text_size & 0xFF;
|
||||||
|
|
||||||
metrics.sent_bytes += 3 + text_size;
|
metrics.sent_bytes += 3 + text_size;
|
||||||
|
metrics.sent_messages++;
|
||||||
mg_ws_send(connection, buffer, 3 + text_size, WEBSOCKET_OP_BINARY);
|
mg_ws_send(connection, buffer, 3 + text_size, WEBSOCKET_OP_BINARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,6 +211,7 @@ void ws_respond(struct mg_connection *connection, uint16_t request_id, void *dat
|
||||||
buffer[2] = request_id & 0xFF;
|
buffer[2] = request_id & 0xFF;
|
||||||
if (size != 0) memcpy(&buffer[3], data, size);
|
if (size != 0) memcpy(&buffer[3], data, size);
|
||||||
metrics.sent_bytes += 3 + size;
|
metrics.sent_bytes += 3 + size;
|
||||||
|
metrics.sent_messages++;
|
||||||
mg_ws_send(connection, buffer, size + 3, WEBSOCKET_OP_BINARY);
|
mg_ws_send(connection, buffer, size + 3, WEBSOCKET_OP_BINARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,6 +223,8 @@ static void on_ws_connect(struct mg_connection *connection, struct mg_http_messa
|
||||||
static char buffer[256];
|
static char buffer[256];
|
||||||
buffer[0] = 'A';
|
buffer[0] = 'A';
|
||||||
buffer[1] = snprintf(&buffer[2], 250, "wsvpn_%ld", connection->id);
|
buffer[1] = snprintf(&buffer[2], 250, "wsvpn_%ld", connection->id);
|
||||||
|
metrics.sent_bytes += 2 + buffer[1];
|
||||||
|
metrics.sent_messages++;
|
||||||
mg_ws_send(connection, buffer, 2 + buffer[1], WEBSOCKET_OP_BINARY);
|
mg_ws_send(connection, buffer, 2 + buffer[1], WEBSOCKET_OP_BINARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,6 +239,7 @@ static void on_ws_message(struct mg_connection *connection, struct mg_ws_message
|
||||||
assert(client->connection == connection);
|
assert(client->connection == connection);
|
||||||
|
|
||||||
metrics.received_bytes += message->data.len;
|
metrics.received_bytes += message->data.len;
|
||||||
|
metrics.received_messages++;
|
||||||
|
|
||||||
if (message->data.len == 0) return;
|
if (message->data.len == 0) return;
|
||||||
|
|
||||||
|
@ -224,6 +250,7 @@ static void on_ws_message(struct mg_connection *connection, struct mg_ws_message
|
||||||
break;
|
break;
|
||||||
case 'O': // open
|
case 'O': // open
|
||||||
{
|
{
|
||||||
|
metrics.method_calls[0]++;
|
||||||
uint16_t channel = ntohs(*(uint16_t*)&message->data.ptr[3]);
|
uint16_t channel = ntohs(*(uint16_t*)&message->data.ptr[3]);
|
||||||
printf("%p[%04x] modem.open(%d)\n", client, request_id, channel);
|
printf("%p[%04x] modem.open(%d)\n", client, request_id, channel);
|
||||||
modem_open(client, request_id, channel);
|
modem_open(client, request_id, channel);
|
||||||
|
@ -231,6 +258,7 @@ static void on_ws_message(struct mg_connection *connection, struct mg_ws_message
|
||||||
return;
|
return;
|
||||||
case 'o': // isOpen
|
case 'o': // isOpen
|
||||||
{
|
{
|
||||||
|
metrics.method_calls[1]++;
|
||||||
uint16_t channel = ntohs(*(uint16_t*)&message->data.ptr[3]);
|
uint16_t channel = ntohs(*(uint16_t*)&message->data.ptr[3]);
|
||||||
printf("%p[%04x] modem.isOpen(%d)\n", client, request_id, channel);
|
printf("%p[%04x] modem.isOpen(%d)\n", client, request_id, channel);
|
||||||
modem_isOpen(client, request_id, channel);
|
modem_isOpen(client, request_id, channel);
|
||||||
|
@ -238,6 +266,7 @@ static void on_ws_message(struct mg_connection *connection, struct mg_ws_message
|
||||||
return;
|
return;
|
||||||
case 'c': // close
|
case 'c': // close
|
||||||
{
|
{
|
||||||
|
metrics.method_calls[2]++;
|
||||||
uint16_t channel = ntohs(*(uint16_t*)&message->data.ptr[3]);
|
uint16_t channel = ntohs(*(uint16_t*)&message->data.ptr[3]);
|
||||||
printf("%p[%04x] modem.close(%d)\n", client, request_id, channel);
|
printf("%p[%04x] modem.close(%d)\n", client, request_id, channel);
|
||||||
modem_close(client, request_id, channel);
|
modem_close(client, request_id, channel);
|
||||||
|
@ -245,12 +274,14 @@ static void on_ws_message(struct mg_connection *connection, struct mg_ws_message
|
||||||
return;
|
return;
|
||||||
case 'C': // closeAll
|
case 'C': // closeAll
|
||||||
{
|
{
|
||||||
|
metrics.method_calls[3]++;
|
||||||
printf("%p[%04x] modem.closeAll()\n", client, request_id);
|
printf("%p[%04x] modem.closeAll()\n", client, request_id);
|
||||||
modem_closeAll(client, request_id);
|
modem_closeAll(client, request_id);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 'T': // transmit
|
case 'T': // transmit
|
||||||
{
|
{
|
||||||
|
metrics.method_calls[4]++;
|
||||||
uint16_t channel = ntohs(*(uint16_t*)&message->data.ptr[3]);
|
uint16_t channel = ntohs(*(uint16_t*)&message->data.ptr[3]);
|
||||||
uint16_t reply_channel = ntohs(*(uint16_t*)&message->data.ptr[5]);
|
uint16_t reply_channel = ntohs(*(uint16_t*)&message->data.ptr[5]);
|
||||||
uint16_t data_length = ntohs(*(uint16_t*)&message->data.ptr[7]);
|
uint16_t data_length = ntohs(*(uint16_t*)&message->data.ptr[7]);
|
||||||
|
@ -273,16 +304,15 @@ static void on_ws_disconnect(struct mg_connection *connection, void *data) {
|
||||||
|
|
||||||
|
|
||||||
static void modem_open(struct client *client, uint16_t request_id, uint16_t channel) {
|
static void modem_open(struct client *client, uint16_t request_id, uint16_t channel) {
|
||||||
for (int i = 0; i < client->next_open_channel_index; i++) {
|
if (client_is_open(client, channel)) {
|
||||||
if (client->open_channels[i] == channel) {
|
ws_respond(client->connection, request_id, NULL, 0);
|
||||||
ws_respond(client->connection, request_id, NULL, 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (client->next_open_channel_index == MAX_OPEN_CHANNELS) {
|
if (client->next_open_channel_index == MAX_OPEN_CHANNELS) {
|
||||||
ws_send_error(client->connection, request_id, "Too many open channels");
|
ws_send_error(client->connection, request_id, "Too many open channels");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
client->open_channels[client->next_open_channel_index] = channel;
|
client->open_channels[client->next_open_channel_index] = channel;
|
||||||
client->next_open_channel_index++;
|
client->next_open_channel_index++;
|
||||||
ws_respond(client->connection, request_id, NULL, 0);
|
ws_respond(client->connection, request_id, NULL, 0);
|
||||||
|
@ -332,6 +362,8 @@ static void modem_transmit(struct client *client, uint16_t request_id, uint16_t
|
||||||
struct client *other_client = *(struct client **)&conn->data[0];
|
struct client *other_client = *(struct client **)&conn->data[0];
|
||||||
if (other_client->connection == conn && other_client->connection != client->connection) {
|
if (other_client->connection == conn && other_client->connection != client->connection) {
|
||||||
if (client_is_open(other_client, channel)) {
|
if (client_is_open(other_client, channel)) {
|
||||||
|
metrics.sent_bytes += size + 7;
|
||||||
|
metrics.sent_messages++;
|
||||||
mg_ws_send(other_client->connection, buffer, size + 7, WEBSOCKET_OP_BINARY);
|
mg_ws_send(other_client->connection, buffer, size + 7, WEBSOCKET_OP_BINARY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue