metrics are not displayed on localhost:9091
Hello everyone. I am writing code to remove metrics from a remote server and output them to localhost:9091. My problem is that I can't understand why the metrics are not displayed on localhost:9091 despite the fact that there is a connection to the server and the removed metrics are selected in the console. Who is not difficult to help or tell me how to solve my problem.
my code:
#include <libssh/libssh.h>
#include <prometheus/registry.h>
#include <prometheus/exposer.h>
#include <prometheus/counter.h>
#include <prometheus/gauge.h>
#include
// Function to execute a command on an SSH channel and return the output std::string execute_ssh_command(ssh_session session, const std::string& command) { ssh_channel channel = ssh_channel_new(session); if (channel == NULL) { throw std::runtime_error("Error creating SSH channel"); } if (ssh_channel_open_session(channel) != SSH_OK) { throw std::runtime_error("Error opening SSH channel"); } if (ssh_channel_request_exec(channel, command.c_str()) != SSH_OK) { throw std::runtime_error("Error executing SSH command"); } char buffer[256]; std::stringstream output; while (ssh_channel_read(channel, buffer, sizeof(buffer), 0) > 0) { output << buffer; } ssh_channel_send_eof(channel); ssh_channel_close(channel); ssh_channel_free(channel); return output.str(); }
int verify_knownhost(ssh_session session) { enum ssh_known_hosts_e state; unsigned char *hash = NULL; ssh_key srv_pubkey = NULL; size_t hlen; char buf[10]; char *hexa; char *p; int cmp; int rc;
rc = ssh_get_server_publickey(session, &srv_pubkey);
if (rc < 0) {
return -1;
}
rc = ssh_get_publickey_hash(srv_pubkey,
SSH_PUBLICKEY_HASH_SHA1,
&hash,
&hlen);
ssh_key_free(srv_pubkey);
if (rc < 0) {
return -1;
}
state = ssh_session_is_known_server(session);
switch (state) {
case SSH_KNOWN_HOSTS_OK:
/* OK */
break;
case SSH_KNOWN_HOSTS_CHANGED:
fprintf(stderr, "Host key for server changed: it is now:\n");
ssh_print_hexa("Public key hash", hash, hlen);
fprintf(stderr, "For security reasons, connection will be stopped\n");
ssh_clean_pubkey_hash(&hash);
return -1;
case SSH_KNOWN_HOSTS_OTHER:
fprintf(stderr, "The host key for this server was not found but an other"
"type of key exists.\n");
fprintf(stderr, "An attacker might change the default server key to"
"confuse your client into thinking the key does not exist\n");
ssh_clean_pubkey_hash(&hash);
return -1;
case SSH_KNOWN_HOSTS_NOT_FOUND:
fprintf(stderr, "Could not find known host file.\n");
fprintf(stderr, "If you accept the host key here, the file will be"
"automatically created.\n");
/* FALL THROUGH to SSH_SERVER_NOT_KNOWN behavior */
case SSH_KNOWN_HOSTS_UNKNOWN:
hexa = ssh_get_hexa(hash, hlen);
fprintf(stderr,"The server is unknown. Do you trust the host key?\n");
fprintf(stderr, "Public key hash: %s\n", hexa);
ssh_string_free_char(hexa);
ssh_clean_pubkey_hash(&hash);
p = fgets(buf, sizeof(buf), stdin);
if (p == NULL) {
return -1;
}
cmp = strncasecmp(buf, "yes", 3);
if (cmp != 0) {
return -1;
}
rc = ssh_session_update_known_hosts(session);
if (rc < 0) {
fprintf(stderr, "Error %s\n", strerror(errno));
return -1;
}
break;
case SSH_KNOWN_HOSTS_ERROR:
fprintf(stderr, "Error %s", ssh_get_error(session));
ssh_clean_pubkey_hash(&hash);
return -1;
}
ssh_clean_pubkey_hash(&hash);
return 0;
}
int main() {
int port[]={22};
char *password;
char pswrd[]={"password"};
char ip[]={"id"};
char login[]={"name"};
int rc;
ssh_session session;
session = ssh_new();
if(session == NULL)
{
std::cout << "Session cannot be created. Exiting.." << std::endl;
exit(EXIT_FAILURE);
}
ssh_options_set(session, SSH_OPTIONS_HOST, ip);
ssh_options_set(session, SSH_OPTIONS_USER, login);
rc = ssh_connect(session);
if (rc != SSH_OK)
{
fprintf(stderr, "Error connecting to localhost: %s\n",
ssh_get_error(session));
ssh_free(session);
exit(-1);
}
if (verify_knownhost(session) < 0) { ssh_disconnect(session); ssh_free(session); exit(-1); }
password=pswrd;
rc = ssh_userauth_password(session, NULL, password);
if (rc != SSH_AUTH_SUCCESS)
{
fprintf(stderr, "Error authenticating with password: %s\n",
ssh_get_error(session));
ssh_disconnect(session);
ssh_free(session);
exit(-1);
}
//creating the prometheus registry
auto registry = std::make_shared<prometheus::Registry>();
auto& ram_usage_gauge = prometheus::BuildGauge()
.Name("node_memory_usage_bytes")
.Help("RAM usage")
.Register(*registry);
prometheus::Exposer exposer{"localhost:9091"};
// collecting indicators every 1 seconds
while (true) {
try {
// getting data about RAM on the server
std::string output = execute_ssh_command(session, "free | grep Mem | awk '{print $3}'");
int node_memory_usage_bytes = std::stoi(output);
std::cout<< node_memory_usage_bytes<< std::endl;
ram_usage_gauge.Add({{"name","id"}})
.Set(node_memory_usage_bytes);
} catch (std::exception& e) {
std::cerr << "Error getting RAM usage: " << e.what() << std::endl;
}
// transferring metrics to port 9091
exposer.RegisterCollectable(registry);
std::this_thread::sleep_for(std::chrono::seconds(1));
}
// completion of work
ssh_disconnect(session);
ssh_free(session);
}
You should register the registry in the exposer only once and prior to your while-loop. For debugging I'd suggest that you set some breakpoints in the exposer code like here: https://github.com/jupp0r/prometheus-cpp/blob/99e4d5085e4557fc9f3bea8db0c69bb1727c3d56/pull/src/exposer.cc#L54
But if I look at the complexity with an SSH access to a remote machine, I wonder if installing something like Telegraf on the remote machine would be the easier option. Telegraf is a statically linked Go binary with no dependencies and easy to handle.