Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

metrics are not displayed on localhost:9091 #642

Open
paffosx opened this issue Mar 15, 2023 · 1 comment
Open

metrics are not displayed on localhost:9091 #642

paffosx opened this issue Mar 15, 2023 · 1 comment

Comments

@paffosx
Copy link

paffosx commented Mar 15, 2023

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
#include
#include
#include
#include
#include "string.h"

// 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);

}

@gjasny
Copy link
Collaborator

gjasny commented Mar 15, 2023

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:

detail::Endpoint& Exposer::GetEndpointForUri(const std::string& uri) {

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants