1
0
mirror of https://github.com/mariadb-corporation/mariadb-columnstore-engine.git synced 2026-10-23 21:49:05 +03:00
Files
mariadb-columnstore-engine/oamapps/resourceMonitor/resourceMonitor.cpp
2019-08-07 14:43:25 -05:00

349 lines
8.8 KiB
C++

/* Copyright (C) 2014 InfiniDB, Inc.
Copyright (C) 2016 MariaDB Corporation
This program 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; version 2 of
the License.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA. */
/***************************************************************************
* $Id: resourceMonitor.cpp 3072 2013-04-04 19:04:45Z rdempsey $
*
* Author: Zhixuan Zhu
***************************************************************************/
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#include <cerrno>
#include <exception>
#include <stdexcept>
#include "liboamcpp.h"
using namespace std;
using namespace oam;
/**
* constants define
*/
enum HOST_INFO
{
USER = 0,
SYSTEM,
NICE,
IDLE
};
const string FE_MOUNT_DIR = "/var/log/mariadb/columnstore/"; // FE mount dir
const int MONITOR_FREQ = 15; // monitor frequency in sec
const int LOG_FREQ = 900; // log frequency in sec
const int DEBUG = false;
/**
* global variables
*/
static char cpu[5];
static unsigned int usage[LOG_FREQ / MONITOR_FREQ];
static int usageCount = 0;
/**
* @brief get cpu usage for cpuNo
*/
unsigned int* getUsage(char* cpuNo);
/**
* @brief get cpu usage diffence over 3 seconds
*/
unsigned int* diffUsage();
/**
* @brief calculate overall cpu usage
*/
unsigned int calcCPUusage(unsigned int* times);
/**
* @brief log cpu usage to active log file
*/
void logCPUactive (unsigned int);
/**
* @brief log cpu peak and average to stat file
*/
void logCPUstat ();
/*****************************************************************************************
* @brief main function
*
* purpose: Get current CPU usage and return current state
*
*****************************************************************************************/
int main (int argc, char** argv)
{
unsigned int* times;
unsigned int cpuUsage = 0;
// set defaults
unsigned int cpuCritical = 9000,
cpuMajor = 8000,
cpuMinor = 7000,
cpuMinorClear = 6000;
strcpy (cpu, "cpu");
// get specific CPU info
times = diffUsage();
// no cpus available on the system
if (times == NULL)
{
cout << "No cpus on the system" << endl;
return 0;
}
cpuUsage = calcCPUusage(times);
logCPUactive(cpuUsage);
cout << "cpuUsage: " << cpuUsage << endl;
// Get CPU usage water mark from server configuration and compare
ServerConfig serverConfig;
Oam oam;
try
{
oam.getSystemConfig (serverConfig);
cpuCritical = serverConfig.ServerCPUCriticalThreshold;
cpuMajor = serverConfig.ServerCPUMajorThreshold;
cpuMinor = serverConfig.ServerCPUMinorThreshold;
cpuMinorClear = serverConfig.ServerCPUMinorClearThreshold;
}
catch (runtime_error e)
{
throw e;
}
cout << "critical water: " << serverConfig.ServerCPUCriticalThreshold << endl;
if (cpuUsage >= cpuCritical)
{
cout << "return critical: " << CRITICAL << endl;
return CRITICAL;
}
else if (cpuUsage >= cpuMajor)
{
cout << "return major: " << MAJOR << endl;
return MAJOR;
}
else if (cpuUsage >= cpuMinor)
{
cout << "return Minor: " << MINOR << endl;
return MINOR;
}
else if (cpuUsage >= cpuMinorClear)
{
cout << "return MinorClear: " << WARNING << endl;
return WARNING;
}
else
{
cout << "return Below MinorClear: " << NO_SEVERITY << endl;
return NO_SEVERITY;
}
}
/*****************************************************************************************
* @brief diffUsage
*
* purpose: Compare usage different for changes
*
*****************************************************************************************/
unsigned int* diffUsage()
{
static unsigned int times1[4];
unsigned int* times;
int i;
times = getUsage(cpu);
if (times == NULL)
return NULL;
memcpy(times1, getUsage(cpu), sizeof(unsigned int) * 4);
sleep(3);
times = getUsage(cpu);
for (i = 0; i < 4; i++)
times1[i] = times[i] - times1[i];
return times1;
}
/*****************************************************************************************
* @brief diffUsage
*
* purpose: Compare usage different for changes
*
*****************************************************************************************/
unsigned int* getUsage(char* cpuNo)
{
static unsigned int times[4];
char tmp[5];
char str[80];
FILE* file;
file = fopen("/proc/stat", "r");
while (fgets(str, 80, file))
{
// search for cpuNo
if ((strstr (str, cpuNo) != NULL))
{
sscanf(str, "%s %u %u %u %u", tmp,
&times[0], &times[1], &times[2], &times[3]);
fclose(file);
return times;
}
}
fclose(file);
return NULL;
}
/*****************************************************************************************
* @brief calcCPUusage
*
* purpose: Calculate CPU usage
*
*****************************************************************************************/
unsigned int calcCPUusage (unsigned int* times)
{
unsigned int total = 0;
for (int i = 0; i < 4; i++)
total += times[i];
double load = (double)times[IDLE] * 100.0 / (double)total;
return (int)((100.0 - load));
}
/*****************************************************************************************
* @brief logCPUactive
*
* purpose: Log Peak and Average CPU usage
*
*****************************************************************************************/
void logCPUactive (unsigned int cpuUsage)
{
// determin the active log file name
string usageLogFileName = FE_MOUNT_DIR;
usageLogFileName = usageLogFileName + cpu + ".log";
if (DEBUG)
cout << usageLogFileName << endl;
fstream usageLogFile;
usageLogFile.open (usageLogFileName.c_str(), ios::in | ios::out);
if (usageLogFile.fail())
{
ofstream file (usageLogFileName.c_str());
file.close();
usageLogFile.open(usageLogFileName.c_str(), ios::in | ios::out);
if (!usageLogFile) cout << "--error" << endl;
}
// get the counter
usageLogFile.seekg(0, ios::beg);
usageLogFile.read (reinterpret_cast<char*>(&usageCount), sizeof (int));
if (usageLogFile.eof()) usageLogFile.clear();
// new iteration
if (usageCount == 0)
{
usageLogFile.seekp(0, ios::beg);
usageLogFile.write (reinterpret_cast<char*>(&usageCount), sizeof (int));
}
usageCount ++;
// append new usage data to the end
usageLogFile.seekp (0, ios::end);
usageLogFile.write (reinterpret_cast<char*>(&cpuUsage), sizeof (int));
if (DEBUG)
cout << "usage: " << usageCount << endl;
// calculate peak and average if it's time to log usage data
if (usageCount >= LOG_FREQ / MONITOR_FREQ)
{
usageLogFile.seekg (4, ios::beg);
usageLogFile.read ((char*)usage, sizeof(unsigned int) * LOG_FREQ / MONITOR_FREQ);
if (usageLogFile.eof()) usageLogFile.clear();
if (DEBUG)
{
for (int i = 0; i < usageCount; i++)
{
cout << usage [i] << endl;
}
}
logCPUstat();
// delete the file
usageLogFile.close();
unlink (usageLogFileName.c_str());
}
// else, update usageCount
else
{
usageLogFile.seekp(0, ios::beg);
usageLogFile.write (reinterpret_cast<char*>(&usageCount), sizeof (int));
usageLogFile.close();
}
}
/*****************************************************************************************
* @brief logCPUstat
*
* purpose: Log CPU stat using system API
*
*****************************************************************************************/
void logCPUstat ()
{
unsigned int max = 0;
unsigned int sum = 0;
float average = 0.0;
for (int i = 0; i < usageCount; i++)
{
if (usage[i] > max)
max = usage[i];
sum += usage[i];
}
average = sum / usageCount;
// Call system log api to store stats.
// for now, write on local for testing purpose.
string statFileName = FE_MOUNT_DIR;
statFileName = statFileName + cpu + "stat.log";
ofstream file (statFileName.c_str(), ios::app);
file << max << " " << average << endl;
file.close();
}