/* Copyright (C) 2014-2022 FastoGT. All right reserved.
This file is part of fastocloud.
fastocloud is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
fastocloud is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with fastocloud. If not, see .
*/
#include "server/daemon/commands_info/service/details/shots.h"
#include
#include
#include
#include
#if defined(OS_LINUX)
#include
#endif
#if defined(OS_MACOSX)
#include
#endif
#if defined(OS_WIN)
#include
#endif
#if defined(OS_MACOSX) || defined(OS_FREEBSD)
#include
#include
#endif
#include
#include
#define CPU_FORMAT "cpu %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64
#if defined(OS_WIN)
namespace {
uint64_t FiletimeToInt(const FILETIME& ft) {
ULARGE_INTEGER i;
i.LowPart = ft.dwLowDateTime;
i.HighPart = ft.dwHighDateTime;
return i.QuadPart;
}
} // namespace
#endif
namespace fastocloud {
namespace server {
namespace service {
double GetCpuMachineLoad(const CpuShot& prev, const CpuShot& next) {
double total = next.cpu_limit - prev.cpu_limit;
if (total == 0.0) {
return 0;
}
double busy = next.cpu_usage - prev.cpu_usage;
return (busy / total) * 100;
}
CpuShot GetMachineCpuShot() {
uint64_t busy = 0, total = 0;
#if defined(OS_LINUX)
FILE* fp = fopen("/proc/stat", "r");
uint64_t user, nice, system, idle;
if (fscanf(fp, CPU_FORMAT, &user, &nice, &system, &idle) != 4) {
// Something bad happened with the information, so assume it's all invalid
user = nice = system = idle = 0;
}
fclose(fp);
busy = user + nice + system;
total = busy + idle;
#elif defined(OS_MACOSX)
host_cpu_load_info_data_t cpuinfo;
mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&cpuinfo, &count) == KERN_SUCCESS) {
for (int i = 0; i < CPU_STATE_MAX; i++) {
total += cpuinfo.cpu_ticks[i];
}
busy = total - cpuinfo.cpu_ticks[CPU_STATE_IDLE];
}
#elif defined(OS_WINDOWS)
FILETIME idle, kernel, user;
if (GetSystemTimes(&idle, &kernel, &user) != 0) {
total = FiletimeToInt(kernel) + FiletimeToInt(user);
busy = total - FiletimeToInt(idle);
}
#else
#pragma message "Please implement"
#endif
return {busy, total};
}
MemoryShot::MemoryShot() : ram_bytes_total(0), ram_bytes_free(0) {}
MemoryShot GetMachineMemoryShot() {
MemoryShot shot;
const auto total = common::system_info::AmountOfTotalRAM();
if (total) {
shot.ram_bytes_total = *total;
}
const auto avail = common::system_info::AmountOfAvailableRAM();
if (avail) {
shot.ram_bytes_free = *avail;
}
return shot;
}
HddShot::HddShot() : hdd_bytes_total(0), hdd_bytes_free(0) {}
HddShot GetMachineHddShot() {
HddShot sh;
const auto total = common::system_info::AmountOfTotalDiskSpace("/");
if (total) {
sh.hdd_bytes_total = *total;
}
const auto avail = common::system_info::AmountOfFreeDiskSpace("/");
if (avail) {
sh.hdd_bytes_free = *avail;
}
return sh;
}
NetShot::NetShot() : bytes_recv(0), bytes_send(0) {}
NetShot GetMachineNetShot() {
NetShot shot;
#if defined(OS_LINUX)
FILE* netinfo = fopen("/proc/net/dev", "r");
if (!netinfo) {
return shot;
}
char line[512];
char interf[128] = {0};
int pos = 0;
while (fgets(line, sizeof(line), netinfo)) {
// face |bytes packets errs drop fifo frame compressed multicast|
// bytes packets errs drop fifo colls carrier compressed
if (pos > 1) {
unsigned long long int r_bytes, r_packets, r_errs, r_drop, r_fifo, r_frame, r_compressed, r_multicast;
unsigned long long int s_bytes, s_packets, s_errs, s_drop, s_fifo, s_colls, s_carrier, s_compressed;
sscanf(line,
"%s %16llu %16llu %16llu %16llu %16llu %16llu %16llu %16llu "
"%16llu %16llu %16llu "
"%16llu %16llu %16llu %16llu %16llu",
interf, &r_bytes, &r_packets, &r_errs, &r_drop, &r_fifo, &r_frame, &r_compressed, &r_multicast, &s_bytes,
&s_packets, &s_errs, &s_drop, &s_fifo, &s_colls, &s_carrier, &s_compressed);
if (strncmp(interf, "lo", 2) != 0) {
shot.bytes_recv += r_bytes;
shot.bytes_send += s_bytes;
}
memset(interf, 0, sizeof(interf));
}
pos++;
}
fclose(netinfo);
return shot;
#else
#pragma message "Please implement"
return shot;
#endif
}
SysinfoShot::SysinfoShot() : loads{0}, uptime(0) {}
SysinfoShot GetMachineSysinfoShot() {
SysinfoShot inf;
#if defined(OS_LINUX)
struct sysinfo info;
int res = sysinfo(&info);
if (res == ERROR_RESULT_VALUE) {
return inf;
}
memcpy(&inf.loads, &info.loads, sizeof(unsigned long) * SIZEOFMASS(info.loads));
inf.uptime = info.uptime;
return inf;
#elif defined(OS_MACOSX) || defined(OS_FREEBSD)
struct loadavg load;
size_t load_len = sizeof(load);
if (sysctlbyname("vm.loadavg", &load, &load_len, nullptr, 0) < 0) {
return inf;
}
inf.loads[0] = load.ldavg[0] / load.fscale;
inf.loads[1] = load.ldavg[1] / load.fscale;
inf.loads[2] = load.ldavg[2] / load.fscale;
struct timeval boottime;
size_t boottime_len = sizeof(boottime);
if (sysctlbyname("kern.boottime", &boottime, &boottime_len, nullptr, 0) < 0) {
return inf;
}
inf.uptime = (common::time::current_utc_mstime() - common::time::timeval2mstime(&boottime)) / 1000;
return inf;
#else
#pragma message "Please implement"
return inf;
#endif
}
} // namespace service
} // namespace server
} // namespace fastocloud