2018-02-17 17:27:17 +01:00
|
|
|
/*
|
|
|
|
* stats.c, SJ
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/types.h>
|
2018-03-11 17:06:49 +01:00
|
|
|
#include <sys/socket.h>
|
2018-02-17 17:27:17 +01:00
|
|
|
#include <sys/stat.h>
|
2018-03-11 17:06:49 +01:00
|
|
|
#include <netdb.h>
|
2018-02-18 14:48:32 +01:00
|
|
|
#include <dirent.h>
|
2018-02-17 17:27:17 +01:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <locale.h>
|
|
|
|
#include <syslog.h>
|
|
|
|
#include <getopt.h>
|
|
|
|
#include <piler.h>
|
|
|
|
|
2018-03-11 17:06:49 +01:00
|
|
|
#define SMTP_TIMEOUT 5
|
2018-02-17 17:27:17 +01:00
|
|
|
|
|
|
|
extern char *optarg;
|
|
|
|
extern int optind;
|
|
|
|
|
2018-02-17 19:36:48 +01:00
|
|
|
struct stats {
|
|
|
|
uint64 rcvd;
|
|
|
|
uint64 size;
|
|
|
|
uint64 ssize;
|
2018-02-17 17:27:17 +01:00
|
|
|
|
2018-02-17 19:36:48 +01:00
|
|
|
uint64 sphx;
|
|
|
|
uint64 ram_bytes;
|
|
|
|
uint64 disk_bytes;
|
2018-02-18 14:48:32 +01:00
|
|
|
|
|
|
|
uint64 error_emails;
|
2018-03-11 17:06:49 +01:00
|
|
|
|
|
|
|
float smtp_response_time;
|
2018-02-17 19:36:48 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int query_counters(struct session_data *sdata, struct stats *stats){
|
2018-02-17 17:27:17 +01:00
|
|
|
int rc=ERR;
|
|
|
|
struct sql sql;
|
|
|
|
|
|
|
|
if(prepare_sql_statement(sdata, &sql, "select rcvd, size, stored_size from counter") == ERR) return rc;
|
|
|
|
|
|
|
|
p_bind_init(&sql);
|
|
|
|
|
|
|
|
if(p_exec_stmt(sdata, &sql) == OK){
|
|
|
|
p_bind_init(&sql);
|
|
|
|
|
2018-02-17 19:36:48 +01:00
|
|
|
sql.sql[sql.pos] = (char *)&(stats->rcvd); sql.type[sql.pos] = TYPE_LONGLONG; sql.len[sql.pos] = sizeof(uint64); sql.pos++;
|
|
|
|
sql.sql[sql.pos] = (char *)&(stats->size); sql.type[sql.pos] = TYPE_LONGLONG; sql.len[sql.pos] = sizeof(uint64); sql.pos++;
|
|
|
|
sql.sql[sql.pos] = (char *)&(stats->ssize); sql.type[sql.pos] = TYPE_LONGLONG; sql.len[sql.pos] = sizeof(uint64); sql.pos++;
|
2018-02-17 17:27:17 +01:00
|
|
|
|
|
|
|
p_store_results(&sql);
|
|
|
|
|
|
|
|
if(p_fetch_results(&sql) == OK) rc = OK;
|
|
|
|
|
|
|
|
p_free_results(&sql);
|
|
|
|
}
|
|
|
|
|
|
|
|
close_prepared_statement(&sql);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-02-17 19:36:48 +01:00
|
|
|
void sphinx_queries(struct session_data *sdata, struct stats *stats){
|
2018-02-17 17:27:17 +01:00
|
|
|
MYSQL_RES *result;
|
|
|
|
MYSQL_ROW row;
|
|
|
|
|
|
|
|
p_query(sdata, "SHOW STATUS LIKE 'queries'");
|
|
|
|
|
|
|
|
result = mysql_store_result(&(sdata->mysql));
|
|
|
|
if(result){
|
|
|
|
row = mysql_fetch_row(result);
|
|
|
|
|
|
|
|
if(row){
|
|
|
|
if(mysql_num_fields(result) == 2){
|
2018-02-17 19:36:48 +01:00
|
|
|
stats->sphx = strtoull(row[1], NULL, 10);
|
2018-02-17 17:27:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mysql_free_result(result);
|
|
|
|
}
|
|
|
|
|
2018-02-17 19:36:48 +01:00
|
|
|
p_query(sdata, "SHOW INDEX main1 STATUS");
|
|
|
|
|
|
|
|
result = mysql_store_result(&(sdata->mysql));
|
|
|
|
if(result){
|
|
|
|
while((row = mysql_fetch_row(result))){
|
|
|
|
if(strcmp((char*)row[0], "ram_bytes") == 0) stats->ram_bytes = strtoull(row[1], NULL, 10);
|
|
|
|
if(strcmp((char*)row[0], "disk_bytes") == 0) stats->disk_bytes = strtoull(row[1], NULL, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
mysql_free_result(result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-02-18 14:48:32 +01:00
|
|
|
void count_error_emails(struct stats *stats){
|
|
|
|
DIR *dir;
|
|
|
|
struct dirent *de;
|
|
|
|
struct stat st;
|
|
|
|
char buf[SMALLBUFSIZE];
|
|
|
|
|
|
|
|
dir = opendir(ERROR_DIR);
|
|
|
|
if(dir){
|
|
|
|
while((de = readdir(dir))){
|
|
|
|
if(strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue;
|
|
|
|
|
|
|
|
snprintf(buf, sizeof(buf)-1, "%s/%s", ERROR_DIR, de->d_name);
|
|
|
|
|
|
|
|
if(stat(buf, &st) == 0 && S_ISREG(st.st_mode)){
|
|
|
|
stats->error_emails++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
closedir(dir);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-11 17:06:49 +01:00
|
|
|
void check_smtp_status(struct stats *stats, struct config *cfg){
|
|
|
|
int sd, rc;
|
|
|
|
char port_string[8];
|
|
|
|
char buf[SMALLBUFSIZE];
|
|
|
|
struct addrinfo hints, *res;
|
|
|
|
struct timezone tz;
|
|
|
|
struct timeval tv1, tv2;
|
|
|
|
|
|
|
|
// Set this to a very high number, 1 hour in ms
|
|
|
|
stats->smtp_response_time = 3600000;
|
|
|
|
|
|
|
|
memset(buf, 0, sizeof(buf));
|
|
|
|
|
|
|
|
snprintf(port_string, sizeof(port_string)-1, "%d", cfg->listen_port);
|
|
|
|
|
|
|
|
memset(&hints, 0, sizeof(hints));
|
|
|
|
hints.ai_family = AF_UNSPEC;
|
|
|
|
hints.ai_socktype = SOCK_STREAM;
|
|
|
|
|
|
|
|
if((rc = getaddrinfo(cfg->listen_addr, port_string, &hints, &res)) != 0){
|
|
|
|
fprintf(stderr, "getaddrinfo for '%s': %s\n", cfg->listen_addr, gai_strerror(rc));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if((sd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1){
|
|
|
|
fprintf(stderr, "cannot create socket\n");
|
|
|
|
goto ENDE_CHECK_SMTP_STATUS;
|
|
|
|
}
|
|
|
|
|
|
|
|
gettimeofday(&tv1, &tz);
|
|
|
|
|
|
|
|
if(connect(sd, res->ai_addr, res->ai_addrlen) == -1){
|
|
|
|
fprintf(stderr, "connect()\n");
|
|
|
|
goto ENDE_CHECK_SMTP_STATUS;
|
|
|
|
}
|
|
|
|
|
|
|
|
recvtimeout(sd, buf, sizeof(buf)-1, SMTP_TIMEOUT);
|
|
|
|
|
|
|
|
close(sd);
|
|
|
|
|
|
|
|
gettimeofday(&tv2, &tz);
|
|
|
|
|
|
|
|
if(strncmp(buf, "220 ", 4) == 0){
|
|
|
|
stats->smtp_response_time = tvdiff(tv2, tv1) / 1000.0; // response time in ms
|
|
|
|
}
|
|
|
|
|
|
|
|
ENDE_CHECK_SMTP_STATUS:
|
|
|
|
freeaddrinfo(res);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-02-17 19:36:48 +01:00
|
|
|
void print_json_results(struct stats *stats){
|
|
|
|
printf("{\n");
|
|
|
|
printf("\t\"rcvd\": %llu,\n", stats->rcvd);
|
|
|
|
printf("\t\"size\": %llu,\n", stats->size);
|
|
|
|
printf("\t\"ssize\": %llu,\n", stats->ssize);
|
|
|
|
printf("\t\"sphx\": %llu,\n", stats->sphx);
|
|
|
|
printf("\t\"ram_bytes\": %llu,\n", stats->ram_bytes);
|
2018-02-18 19:45:54 +01:00
|
|
|
printf("\t\"disk_bytes\": %llu,\n", stats->disk_bytes);
|
2018-03-11 17:06:49 +01:00
|
|
|
printf("\t\"error_emails\": %llu,\n", stats->error_emails);
|
|
|
|
printf("\t\"smtp_response\": %.2f\n", stats->smtp_response_time);
|
|
|
|
|
2018-02-17 19:36:48 +01:00
|
|
|
printf("}\n");
|
2018-02-17 17:27:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char **argv){
|
|
|
|
struct session_data sdata;
|
2018-02-17 19:36:48 +01:00
|
|
|
struct stats stats;
|
2018-02-17 17:27:17 +01:00
|
|
|
struct config cfg;
|
|
|
|
char *configfile=CONFIG_FILE;
|
|
|
|
|
2018-02-17 19:36:48 +01:00
|
|
|
memset(&stats, 0, sizeof(stats));
|
|
|
|
|
2018-02-17 17:27:17 +01:00
|
|
|
srand(getpid());
|
|
|
|
|
|
|
|
(void) openlog("pilerstat", LOG_PID, LOG_MAIL);
|
|
|
|
|
|
|
|
cfg = read_config(configfile);
|
|
|
|
|
|
|
|
if(open_database(&sdata, &cfg) == ERR) return 0;
|
|
|
|
|
2018-02-17 19:36:48 +01:00
|
|
|
query_counters(&sdata, &stats);
|
2018-02-17 17:27:17 +01:00
|
|
|
|
|
|
|
close_database(&sdata);
|
|
|
|
|
|
|
|
|
|
|
|
cfg.mysqlsocket[0] = '\0';
|
|
|
|
snprintf(cfg.mysqlhost, MAXVAL-2, "127.0.0.1");
|
|
|
|
cfg.mysqlport = 9306;
|
|
|
|
|
|
|
|
if(open_database(&sdata, &cfg) == ERR) return 0;
|
|
|
|
|
2018-02-17 19:36:48 +01:00
|
|
|
sphinx_queries(&sdata, &stats);
|
2018-02-17 17:27:17 +01:00
|
|
|
|
|
|
|
close_database(&sdata);
|
|
|
|
|
2018-02-18 14:48:32 +01:00
|
|
|
count_error_emails(&stats);
|
|
|
|
|
2018-03-11 17:06:49 +01:00
|
|
|
check_smtp_status(&stats, &cfg);
|
|
|
|
|
2018-02-17 19:36:48 +01:00
|
|
|
print_json_results(&stats);
|
2018-02-17 17:27:17 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|