/* ** ZABBIX ** Copyright (C) 2000-2005 SIA Zabbix ** ** 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; either version 2 of the License, or ** (at your option) any later version. ** ** 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., 675 Mass Ave, Cambridge, MA 02139, USA. **/ #include "common.h" #include "db.h" #include "log.h" #include "zlog.h" #include "evalfunc.h" /****************************************************************************** * * * Function: evaluate_LOGSOURCE * * * * Purpose: evaluate function 'logsource' for the item * * * * Parameters: item - item (performance metric) * * parameter - ignored * * * * Return value: SUCCEED - evaluated succesfully, result is stored in 'value' * * FAIL - failed to evaluate function * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static int evaluate_LOGSOURCE(char *value, DB_ITEM *item, char *parameter) { DB_RESULT result; DB_ROW row; char sql[MAX_STRING_LEN]; int now; int res = SUCCEED; if(item->value_type != ITEM_VALUE_TYPE_LOG) { return FAIL; } now=time(NULL); zbx_snprintf(sql,sizeof(sql),"select source from history_log where itemid=" ZBX_FS_UI64 " order by clock desc", item->itemid); result = DBselectN(sql,1); row = DBfetch(result); if(!row || DBis_null(row[0])==SUCCEED) { zabbix_log(LOG_LEVEL_DEBUG, "Result for LOGSOURCE is empty" ); res = FAIL; } else { if(strcmp(row[0], parameter) == 0) { strcpy(value,"1"); } else { strcpy(value,"0"); } } DBfree_result(result); return res; } /****************************************************************************** * * * Function: evaluate_LOGSEVERITY * * * * Purpose: evaluate function 'logseverity' for the item * * * * Parameters: item - item (performance metric) * * parameter - ignored * * * * Return value: SUCCEED - evaluated succesfully, result is stored in 'value' * * FAIL - failed to evaluate function * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static int evaluate_LOGSEVERITY(char *value, DB_ITEM *item, char *parameter) { DB_RESULT result; DB_ROW row; char sql[MAX_STRING_LEN]; int now; int res = SUCCEED; if(item->value_type != ITEM_VALUE_TYPE_LOG) { return FAIL; } now=time(NULL); zbx_snprintf(sql,sizeof(sql),"select severity from history_log where itemid=" ZBX_FS_UI64 " order by clock desc", item->itemid); result = DBselectN(sql,1); row = DBfetch(result); if(!row || DBis_null(row[0])==SUCCEED) { zabbix_log(LOG_LEVEL_DEBUG, "Result for LOGSEVERITY is empty" ); res = FAIL; } else { strcpy(value,row[0]); } DBfree_result(result); return res; } /****************************************************************************** * * * Function: evaluate_COUNT * * * * Purpose: evaluate function 'count' for the item * * * * Parameters: item - item (performance metric) * * parameter - number of seconds * * * * Return value: SUCCEED - evaluated succesfully, result is stored in 'value' * * FAIL - failed to evaluate function * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static int evaluate_COUNT(char *value, DB_ITEM *item, char *parameter) { DB_RESULT result; DB_ROW row; char period[MAX_STRING_LEN+1]; char op[MAX_STRING_LEN+1]; char cmp[MAX_STRING_LEN+1]; char cmp_esc[MAX_STRING_LEN+1]; int now; int res = SUCCEED; char *table = NULL; char table_ui64[] = "history_uint"; char table_float[] = "history"; char table_log[] = "history_log"; char table_str[] = "history_str"; zabbix_log( LOG_LEVEL_DEBUG, "In evaluate_COUNT(param:%s)", parameter); switch(item->value_type) { case ITEM_VALUE_TYPE_FLOAT: table = table_float; break; case ITEM_VALUE_TYPE_UINT64: table = table_ui64; break; case ITEM_VALUE_TYPE_LOG: table = table_log; break; case ITEM_VALUE_TYPE_STR: table = table_str; break; default: return FAIL; } now=time(NULL); if(get_param(parameter, 1, period, MAX_STRING_LEN) != 0) { return FAIL; } if(get_param(parameter, 2, cmp, MAX_STRING_LEN) != 0) { result = DBselect("select count(value) from %s where clock>%d and itemid=" ZBX_FS_UI64, table, now-atoi(period), item->itemid); } else { if(get_param(parameter, 3, op, MAX_STRING_LEN) != 0) { strscpy(op,"eq"); } DBescape_string(cmp, cmp_esc, sizeof(cmp_esc)); /* ITEM_VALUE_TYPE_UINT64 */ if( (item->value_type == ITEM_VALUE_TYPE_UINT64) && (strcmp(op,"eq") == 0)) { result = DBselect("select count(value) from history_uint where clock>%d and value=" ZBX_FS_UI64 " and itemid=" ZBX_FS_UI64, now-atoi(period), zbx_atoui64(cmp_esc), item->itemid); } else if( (item->value_type == ITEM_VALUE_TYPE_UINT64) && (strcmp(op,"ne") == 0)) { result = DBselect("select count(value) from history_uint where clock>%d and value<>" ZBX_FS_UI64 " and itemid=" ZBX_FS_UI64, now-atoi(period), zbx_atoui64(cmp_esc), item->itemid); } else if( (item->value_type == ITEM_VALUE_TYPE_UINT64) && (strcmp(op,"gt") == 0)) { result = DBselect("select count(value) from history_uint where clock>%d and value>" ZBX_FS_UI64 " and itemid=" ZBX_FS_UI64, now-atoi(period), zbx_atoui64(cmp_esc), item->itemid); } else if( (item->value_type == ITEM_VALUE_TYPE_UINT64) && (strcmp(op,"lt") == 0)) { result = DBselect("select count(value) from history_uint where clock>%d and value<" ZBX_FS_UI64 " and itemid=" ZBX_FS_UI64, now-atoi(period), zbx_atoui64(cmp_esc), item->itemid); } else if( (item->value_type == ITEM_VALUE_TYPE_UINT64) && (strcmp(op,"ge") == 0)) { result = DBselect("select count(value) from history_uint where clock>%d and value>=" ZBX_FS_UI64 " and itemid=" ZBX_FS_UI64, now-atoi(period), zbx_atoui64(cmp_esc), item->itemid); } else if( (item->value_type == ITEM_VALUE_TYPE_UINT64) && (strcmp(op,"le") == 0)) { result = DBselect("select count(value) from history_uint where clock>%d and value<=" ZBX_FS_UI64 " and itemid=" ZBX_FS_UI64, now-atoi(period), zbx_atoui64(cmp_esc), item->itemid); } /* ITEM_VALUE_TYPE_FLOAT */ else if( (item->value_type == ITEM_VALUE_TYPE_FLOAT) && (strcmp(op,"eq") == 0)) { result = DBselect("select count(value) from history where clock>%d and value+0.00001>" ZBX_FS_DBL " and value-0.0001<" ZBX_FS_DBL " and itemid=" ZBX_FS_UI64, now-atoi(period), atof(cmp_esc), atof(cmp_esc), item->itemid); } else if( (item->value_type == ITEM_VALUE_TYPE_FLOAT) && (strcmp(op,"ne") == 0)) { result = DBselect("select count(value) from history where clock>%d and ((value+0.00001<" ZBX_FS_DBL ") or (value-0.0001>" ZBX_FS_DBL ")) and itemid=" ZBX_FS_UI64, now-atoi(period), atof(cmp_esc), atof(cmp_esc), item->itemid); } else if( (item->value_type == ITEM_VALUE_TYPE_FLOAT) && (strcmp(op,"gt") == 0)) { result = DBselect("select count(value) from history where clock>%d and value>" ZBX_FS_DBL " and itemid=" ZBX_FS_UI64, now-atoi(period), atof(cmp_esc), item->itemid); } else if( (item->value_type == ITEM_VALUE_TYPE_FLOAT) && (strcmp(op,"ge") == 0)) { result = DBselect("select count(value) from history where clock>=%d and value>" ZBX_FS_DBL " and itemid=" ZBX_FS_UI64, now-atoi(period), atof(cmp_esc), item->itemid); } else if( (item->value_type == ITEM_VALUE_TYPE_FLOAT) && (strcmp(op,"lt") == 0)) { result = DBselect("select count(value) from history where clock>%d and value<" ZBX_FS_DBL " and itemid=" ZBX_FS_UI64, now-atoi(period), atof(cmp_esc), item->itemid); } else if( (item->value_type == ITEM_VALUE_TYPE_FLOAT) && (strcmp(op,"le") == 0)) { result = DBselect("select count(value) from history where clock>%d and value<=" ZBX_FS_DBL " and itemid=" ZBX_FS_UI64, now-atoi(period), atof(cmp_esc), item->itemid); } else if(item->value_type == ITEM_VALUE_TYPE_LOG) { result = DBselect("select count(value) from history_log where clock>%d and value like '%s' and itemid=" ZBX_FS_UI64, now-atoi(period), cmp_esc, item->itemid); } else { result = DBselect("select count(value) from history_str where clock>%d and value like '%s' and itemid=" ZBX_FS_UI64, now-atoi(period), cmp_esc, item->itemid); } } row = DBfetch(result); if(!row || DBis_null(row[0])==SUCCEED) { zabbix_log(LOG_LEVEL_DEBUG, "Result for COUNT is empty" ); res = FAIL; } else { strcpy(value,row[0]); } DBfree_result(result); zabbix_log( LOG_LEVEL_DEBUG, "End evaluate_COUNT"); return res; } /****************************************************************************** * * * Function: evaluate_SUM * * * * Purpose: evaluate function 'sum' for the item * * * * Parameters: item - item (performance metric) * * parameter - number of seconds * * * * Return value: SUCCEED - evaluated succesfully, result is stored in 'value' * * FAIL - failed to evaluate function * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static int evaluate_SUM(char *value, DB_ITEM *item, int parameter, int flag) { DB_RESULT result; DB_ROW row; char sql[MAX_STRING_LEN]; int now; int res = SUCCEED; int rows = 0; double sum=0; zbx_uint64_t sum_uint64=0; zbx_uint64_t value_uint64; char *table = NULL; char table_ui64[] = "history_uint"; char table_float[] = "history"; switch(item->value_type) { case ITEM_VALUE_TYPE_FLOAT: table = table_float; break; case ITEM_VALUE_TYPE_UINT64: table = table_ui64; break; default: return FAIL; } now=time(NULL); if(flag == ZBX_FLAG_SEC) { result = DBselect("select sum(value) from %s where clock>%d and itemid=" ZBX_FS_UI64, table, now-parameter, item->itemid); row = DBfetch(result); if(!row || DBis_null(row[0])==SUCCEED) { zabbix_log(LOG_LEVEL_DEBUG, "Result for SUM is empty" ); res = FAIL; } else { strcpy(value,row[0]); } } else if(flag == ZBX_FLAG_VALUES) { zbx_snprintf(sql,sizeof(sql),"select value from %s where itemid=" ZBX_FS_UI64 " order by clock desc", table, item->itemid); result = DBselectN(sql, parameter); if(item->value_type == ITEM_VALUE_TYPE_UINT64) { while((row=DBfetch(result))) { ZBX_STR2UINT64(value_uint64,row[0]); sum_uint64+=value_uint64; rows++; } if(rows>0) zbx_snprintf(value,MAX_STRING_LEN,ZBX_FS_UI64, sum_uint64); } else { while((row=DBfetch(result))) { sum+=atof(row[0]); rows++; } if(rows>0) zbx_snprintf(value,MAX_STRING_LEN, ZBX_FS_DBL, sum); } if(0 == rows) { zabbix_log(LOG_LEVEL_DEBUG, "Result for SUM is empty" ); res = FAIL; } } else { zabbix_log(LOG_LEVEL_WARNING, "Unknown flag [%d] Expected [%d] or [%d]", flag, ZBX_FLAG_SEC, ZBX_FLAG_VALUES); return FAIL; } DBfree_result(result); return res; } /****************************************************************************** * * * Function: evaluate_AVG * * * * Purpose: evaluate function 'avg' for the item * * * * Parameters: item - item (performance metric) * * parameter - number of seconds * * * * Return value: SUCCEED - evaluated succesfully, result is stored in 'value' * * FAIL - failed to evaluate function * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static int evaluate_AVG(char *value,DB_ITEM *item,int parameter,int flag) { DB_RESULT result; DB_ROW row; char sql[MAX_STRING_LEN]; int now; int res = SUCCEED; int rows; double sum=0; char *table = NULL; char table_ui64[] = "history_uint"; char table_float[] = "history"; switch(item->value_type) { case ITEM_VALUE_TYPE_FLOAT: table = table_float; break; case ITEM_VALUE_TYPE_UINT64: table = table_ui64; break; default: return FAIL; } now=time(NULL); if(flag == ZBX_FLAG_SEC) { result = DBselect("select avg(value) from %s where clock>%d and itemid=" ZBX_FS_UI64, table, now-parameter, item->itemid); row = DBfetch(result); if(!row || DBis_null(row[0])==SUCCEED) { zabbix_log(LOG_LEVEL_DEBUG, "Result for AVG is empty" ); res = FAIL; } else { strcpy(value,row[0]); del_zeroes(value); } } else if(flag == ZBX_FLAG_VALUES) { zbx_snprintf(sql,sizeof(sql),"select value from %s where itemid=" ZBX_FS_UI64 " order by clock desc", table, item->itemid); result = DBselectN(sql, parameter); rows=0; while((row=DBfetch(result))) { sum+=atof(row[0]); rows++; } if(rows == 0) { zabbix_log(LOG_LEVEL_DEBUG, "Result for AVG is empty" ); res = FAIL; } else { zbx_snprintf(value,MAX_STRING_LEN, ZBX_FS_DBL, sum/(double)rows); } } else { zabbix_log(LOG_LEVEL_WARNING, "Unknown flag [%d] Expected [%d] or [%d]", flag, ZBX_FLAG_SEC, ZBX_FLAG_VALUES); return FAIL; } DBfree_result(result); return res; } /****************************************************************************** * * * Function: evaluate_MIN * * * * Purpose: evaluate function 'min' for the item * * * * Parameters: item - item (performance metric) * * parameter - number of seconds * * * * Return value: SUCCEED - evaluated succesfully, result is stored in 'value' * * FAIL - failed to evaluate function * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static int evaluate_MIN(char *value,DB_ITEM *item,int parameter, int flag) { DB_RESULT result; DB_ROW row; char sql[MAX_STRING_LEN]; int now; int rows; int res = SUCCEED; char *table = NULL; char table_ui64[] = "history_uint"; char table_float[] = "history"; zbx_uint64_t min_uint64=0; zbx_uint64_t l; double min=0; double f; switch(item->value_type) { case ITEM_VALUE_TYPE_FLOAT: table = table_float; break; case ITEM_VALUE_TYPE_UINT64: table = table_ui64; break; default: return FAIL; } now=time(NULL); if(flag == ZBX_FLAG_SEC) { result = DBselect("select min(value) from %s where clock>%d and itemid=" ZBX_FS_UI64, table, now-parameter, item->itemid); row = DBfetch(result); if(!row || DBis_null(row[0])==SUCCEED) { zabbix_log(LOG_LEVEL_DEBUG, "Result for MIN is empty" ); res = FAIL; } else { strcpy(value,row[0]); del_zeroes(value); } } else if(flag == ZBX_FLAG_VALUES) { zbx_snprintf(sql,sizeof(sql),"select value from %s where itemid=" ZBX_FS_UI64 " order by clock desc", table, item->itemid); result = DBselectN(sql,parameter); rows=0; while((row=DBfetch(result))) { if(item->value_type == ITEM_VALUE_TYPE_UINT64) { ZBX_STR2UINT64(l,row[0]); if(rows==0) min_uint64 = l; else if(lvalue_type == ITEM_VALUE_TYPE_UINT64) { zbx_snprintf(value,MAX_STRING_LEN,ZBX_FS_UI64, min_uint64); } else { zbx_snprintf(value,MAX_STRING_LEN, ZBX_FS_DBL, min); } } } else { zabbix_log(LOG_LEVEL_WARNING, "Unknown flag [%d] Expected [%d] or [%d]", flag, ZBX_FLAG_SEC, ZBX_FLAG_VALUES); return FAIL; } DBfree_result(result); return res; } /****************************************************************************** * * * Function: evaluate_MAX * * * * Purpose: evaluate function 'max' for the item * * * * Parameters: item - item (performance metric) * * parameter - number of seconds * * * * Return value: SUCCEED - evaluated succesfully, result is stored in 'value' * * FAIL - failed to evaluate function * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static int evaluate_MAX(char *value,DB_ITEM *item,int parameter,int flag) { DB_RESULT result; DB_ROW row; char sql[MAX_STRING_LEN]; int now; int res = SUCCEED; int rows; double f; double max = 0; char *table = NULL; char table_ui64[] = "history_uint"; char table_float[] = "history"; zbx_uint64_t max_uint64=0; zbx_uint64_t l; zabbix_log( LOG_LEVEL_DEBUG, "In evaluate_MAX()"); switch(item->value_type) { case ITEM_VALUE_TYPE_FLOAT: table = table_float; break; case ITEM_VALUE_TYPE_UINT64: table = table_ui64; break; default: return FAIL; } now=time(NULL); if(flag == ZBX_FLAG_SEC) { result = DBselect("select max(value) from %s where clock>%d and itemid=" ZBX_FS_UI64, table, now-parameter, item->itemid); row = DBfetch(result); if(!row || DBis_null(row[0])==SUCCEED) { zabbix_log(LOG_LEVEL_DEBUG, "Result for MAX is empty" ); res = FAIL; } else { strcpy(value,row[0]); del_zeroes(value); } } else if(flag == ZBX_FLAG_VALUES) { zbx_snprintf(sql,sizeof(sql),"select value from %s where itemid=" ZBX_FS_UI64 " order by clock desc", table, item->itemid); result = DBselectN(sql,parameter); rows=0; while((row=DBfetch(result))) { if(item->value_type == ITEM_VALUE_TYPE_UINT64) { ZBX_STR2UINT64(l,row[0]); if(rows==0) max_uint64 = l; else if(l>max_uint64) max_uint64 = l; } else { f=atof(row[0]); if(rows==0) max=f; else if(f>max) max=f; } rows++; } if(rows == 0) { zabbix_log(LOG_LEVEL_DEBUG, "Result for MAX is empty" ); res = FAIL; } else { if(item->value_type == ITEM_VALUE_TYPE_UINT64) { zbx_snprintf(value,MAX_STRING_LEN,ZBX_FS_UI64, max_uint64); } else { zbx_snprintf(value,MAX_STRING_LEN, ZBX_FS_DBL, max); } } } else { zabbix_log(LOG_LEVEL_WARNING, "Unknown flag [%d] Expected [%d] or [%d]", flag, ZBX_FLAG_SEC, ZBX_FLAG_VALUES); return FAIL; } DBfree_result(result); zabbix_log( LOG_LEVEL_DEBUG, "End of evaluate_MAX()"); return res; } /****************************************************************************** * * * Function: evaluate_DELTA * * * * Purpose: evaluate function 'delat' for the item * * * * Parameters: item - item (performance metric) * * parameter - number of seconds * * * * Return value: SUCCEED - evaluated succesfully, result is stored in 'value' * * FAIL - failed to evaluate function * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static int evaluate_DELTA(char *value,DB_ITEM *item,int parameter, int flag) { DB_RESULT result; DB_ROW row; char sql[MAX_STRING_LEN]; int now; int res = SUCCEED; int rows; double f; double min = 0,max = 0; zbx_uint64_t max_uint64=0,min_uint64=0; zbx_uint64_t l; char *table = NULL; char table_ui64[] = "history_uint"; char table_float[] = "history"; zabbix_log( LOG_LEVEL_DEBUG, "In evaluate_DELTA()"); switch(item->value_type) { case ITEM_VALUE_TYPE_FLOAT: table = table_float; break; case ITEM_VALUE_TYPE_UINT64: table = table_ui64; break; default: return FAIL; } now=time(NULL); if(flag == ZBX_FLAG_SEC) { result = DBselect("select max(value)-min(value) from %s where clock>%d and itemid=" ZBX_FS_UI64, table, now-parameter, item->itemid); row = DBfetch(result); if(!row || DBis_null(row[0])==SUCCEED) { zabbix_log(LOG_LEVEL_DEBUG, "Result for DELTA is empty" ); res = FAIL; } else { strcpy(value,row[0]); del_zeroes(value); } } else if(flag == ZBX_FLAG_VALUES) { zbx_snprintf(sql,sizeof(sql),"select value from %s where itemid=" ZBX_FS_UI64 " order by clock desc", table, item->itemid); result = DBselectN(sql,parameter); rows=0; while((row=DBfetch(result))) { if(item->value_type == ITEM_VALUE_TYPE_UINT64) { ZBX_STR2UINT64(l,row[0]); if(rows==0) { max_uint64 = l; min_uint64 = l; } else { if(l>max_uint64) max_uint64 = l; if(lmax) max=f; if(fvalue_type == ITEM_VALUE_TYPE_UINT64) { zbx_snprintf(value,MAX_STRING_LEN,ZBX_FS_UI64, max_uint64-min_uint64); } else { zbx_snprintf(value,MAX_STRING_LEN, ZBX_FS_DBL, max-min); } } } else { zabbix_log(LOG_LEVEL_WARNING, "Unknown flag [%d] Expected [%d] or [%d]", flag, ZBX_FLAG_SEC, ZBX_FLAG_VALUES); return FAIL; } DBfree_result(result); zabbix_log( LOG_LEVEL_DEBUG, "End of evaluate_DELTA()"); return res; } /****************************************************************************** * * * Function: evaluate_NODATA * * * * Purpose: evaluate function 'nodata' for the item * * * * Parameters: item - item (performance metric) * * parameter - number of seconds * * * * Return value: SUCCEED - evaluated succesfully, result is stored in 'value' * * FAIL - failed to evaluate function * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static int evaluate_NODATA(char *value,DB_ITEM *item,int parameter) { int now; int res = SUCCEED; zabbix_log( LOG_LEVEL_DEBUG, "In evaluate_NODATA()"); now = time(NULL); if((CONFIG_SERVER_STARTUP_TIME + parameter > now) || (item->lastclock + parameter > now)) { strcpy(value,"0"); } else { strcpy(value,"1"); } zabbix_log( LOG_LEVEL_DEBUG, "End of evaluate_NODATA()"); return res; } /****************************************************************************** * * * Function: evaluate_STR * * * * Purpose: evaluate function 'str' for the item * * * * Parameters: item - item (performance metric) * * parameters - [,seconds] * * * * Return value: SUCCEED - evaluated succesfully, result is stored in 'value' * * FAIL - failed to evaluate function * * * * Author: Aleksander Vladishev * * * * Comments: * * * ******************************************************************************/ static int evaluate_STR(char *value, DB_ITEM *item, char *function, char *parameters) { DB_RESULT result; DB_ROW row; char str[MAX_STRING_LEN], tmp[MAX_STRING_LEN]; int num = 0, flag, now; int rows; int len; int res = SUCCEED; char *table = NULL; char *key = NULL; char table_str[] = "history_str", key_str[] = "clock"; char table_text[] = "history_text", key_text[] = "id"; char table_log[] = "history_log", key_log[] = "id"; zabbix_log(LOG_LEVEL_DEBUG, "In evaluate_STR()"); switch (item->value_type) { case ITEM_VALUE_TYPE_STR: table = table_str; key = key_str; break; case ITEM_VALUE_TYPE_TEXT: table = table_text; key = key_text; break; case ITEM_VALUE_TYPE_LOG: table = table_log; key = key_log; break; default: return FAIL; } if (0 == num_param(parameters)) return FAIL; if (0 != get_param(parameters, 1, str, sizeof(str))) return FAIL; if (0 == get_param(parameters, 2, tmp, sizeof(tmp))) { if (tmp[0] == '#') { num = atoi(tmp + 1); flag = ZBX_FLAG_VALUES; } else { num = atoi(tmp); flag = ZBX_FLAG_SEC; } } else { num = 1; flag = ZBX_FLAG_VALUES; } now = time(NULL); if (flag == ZBX_FLAG_SEC) { result = DBselect("select value from %s where itemid=" ZBX_FS_UI64 " and clock>%d", table, item->itemid, now - num); } else { /* ZBX_FLAG_VALUES */ zbx_snprintf(tmp, sizeof(tmp), "select value from %s where itemid=" ZBX_FS_UI64 " order by %s desc", table, item->itemid, key); result = DBselectN(tmp, num); } rows = 0; if (0 == strcmp(function, "str")) { while (NULL != (row = DBfetch(result))) { if (NULL != strstr(row[0], str)) { rows = 2; break; } rows = 1; } } else if (0 == strcmp(function, "regexp")) { while (NULL != (row = DBfetch(result))) { if (NULL != zbx_regexp_match(row[0], str, &len)) { rows = 2; break; } rows = 1; } } else if (0 == strcmp(function, "iregexp")) { while (NULL != (row = DBfetch(result))) { if (NULL != zbx_iregexp_match(row[0], str, &len)) { rows = 2; break; } rows = 1; } } if (0 == rows) { zabbix_log(LOG_LEVEL_DEBUG, "Result for STR is empty" ); res = FAIL; } else { if (2 == rows) strcpy(value, "1"); else strcpy(value, "0"); } DBfree_result(result); return res; } /****************************************************************************** * * * Function: evaluate_function * * * * Purpose: evaluate function * * * * Parameters: item - item to calculate function for * * function - function (for example, 'max') * * parameter - parameter of the function) * * flag - if EVALUATE_FUNCTION_SUFFIX, then include units and * * suffix (K,M,G) into result value (for example, 15GB) * * * * Return value: SUCCEED - evaluated succesfully, value contains its value * * FAIL - evaluation failed * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ int evaluate_function(char *value,DB_ITEM *item,char *function,char *parameter) { int ret = SUCCEED; time_t now; struct tm *tm; int fuzlow, fuzhig; int day; zabbix_log( LOG_LEVEL_DEBUG, "In evaluate_function(%s)", function); if(strcmp(function,"last")==0) { if(item->lastvalue_null==1) { ret = FAIL; } else { switch (item->value_type) { case ITEM_VALUE_TYPE_FLOAT: zbx_snprintf(value,MAX_STRING_LEN,ZBX_FS_DBL,item->lastvalue_dbl); del_zeroes(value); break; case ITEM_VALUE_TYPE_UINT64: zbx_snprintf(value,MAX_STRING_LEN,ZBX_FS_UI64,item->lastvalue_uint64); break; default: strcpy(value,item->lastvalue_str); break; } } } else if(strcmp(function,"prev")==0) { if(item->prevvalue_null==1) { ret = FAIL; } else { switch (item->value_type) { case ITEM_VALUE_TYPE_FLOAT: zbx_snprintf(value,MAX_STRING_LEN,ZBX_FS_DBL,item->prevvalue_dbl); del_zeroes(value); break; case ITEM_VALUE_TYPE_UINT64: zbx_snprintf(value,MAX_STRING_LEN,ZBX_FS_UI64,item->prevvalue_uint64); break; default: strcpy(value,item->prevvalue_str); break; } } } else if(strcmp(function,"min")==0) { if(parameter[0]=='#') ret = evaluate_MIN(value,item,atoi(parameter+1),ZBX_FLAG_VALUES); else ret = evaluate_MIN(value,item,atoi(parameter),ZBX_FLAG_SEC); } else if(strcmp(function,"max")==0) { if(parameter[0]=='#') ret = evaluate_MAX(value,item,atoi(parameter+1),ZBX_FLAG_VALUES); else ret = evaluate_MAX(value,item,atoi(parameter),ZBX_FLAG_SEC); } else if(strcmp(function,"avg")==0) { if(parameter[0]=='#') ret = evaluate_AVG(value,item,atoi(parameter+1),ZBX_FLAG_VALUES); else ret = evaluate_AVG(value,item,atoi(parameter),ZBX_FLAG_SEC); } else if(strcmp(function,"sum")==0) { if(parameter[0]=='#') ret = evaluate_SUM(value,item,atoi(parameter+1),ZBX_FLAG_VALUES); else ret = evaluate_SUM(value,item,atoi(parameter),ZBX_FLAG_SEC); } else if(strcmp(function,"count")==0) { ret = evaluate_COUNT(value,item,parameter); } else if(strcmp(function,"delta")==0) { if(parameter[0]=='#') ret = evaluate_DELTA(value,item,atoi(parameter+1),ZBX_FLAG_VALUES); else ret = evaluate_DELTA(value,item,atoi(parameter),ZBX_FLAG_SEC); } else if(strcmp(function,"nodata")==0) { ret = evaluate_NODATA(value,item,atoi(parameter)); } else if(strcmp(function,"date")==0) { now=time(NULL); tm=localtime(&now); zbx_snprintf(value,MAX_STRING_LEN,"%.4d%.2d%.2d", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday); } else if(strcmp(function,"dayofweek")==0) { now=time(NULL); tm=localtime(&now); /* The number of days since Sunday, in the range 0 to 6. */ day=tm->tm_wday; if(0 == day) day=7; zbx_snprintf(value,MAX_STRING_LEN,"%d", day); } else if(strcmp(function,"time")==0) { now=time(NULL); tm=localtime(&now); zbx_snprintf(value,MAX_STRING_LEN,"%.2d%.2d%.2d", tm->tm_hour, tm->tm_min, tm->tm_sec); } else if(strcmp(function,"abschange")==0) { if((item->lastvalue_null==1)||(item->prevvalue_null==1)) { ret = FAIL; } else { switch (item->value_type) { case ITEM_VALUE_TYPE_FLOAT: zbx_snprintf(value,MAX_STRING_LEN,ZBX_FS_DBL, (double)abs(item->lastvalue_dbl-item->prevvalue_dbl)); del_zeroes(value); break; case ITEM_VALUE_TYPE_UINT64: /* To avoid overflow */ if(item->lastvalue_uint64>=item->prevvalue_uint64) { zbx_snprintf(value,MAX_STRING_LEN,ZBX_FS_UI64, labs(item->lastvalue_uint64-item->prevvalue_uint64)); } else { zbx_snprintf(value,MAX_STRING_LEN,"-" ZBX_FS_UI64, labs(item->prevvalue_uint64 - item->lastvalue_uint64)); } break; default: if(strcmp(item->lastvalue_str, item->prevvalue_str) == 0) { strcpy(value,"0"); } else { strcpy(value,"1"); } break; } } } else if(strcmp(function,"change")==0) { if((item->lastvalue_null==1)||(item->prevvalue_null==1)) { ret = FAIL; } else { switch (item->value_type) { case ITEM_VALUE_TYPE_FLOAT: zbx_snprintf(value,MAX_STRING_LEN,ZBX_FS_DBL, item->lastvalue_dbl-item->prevvalue_dbl); del_zeroes(value); break; case ITEM_VALUE_TYPE_UINT64: /* To avoid overflow */ if(item->lastvalue_uint64>=item->prevvalue_uint64) { zbx_snprintf(value,MAX_STRING_LEN,ZBX_FS_UI64, item->lastvalue_uint64-item->prevvalue_uint64); } else { zbx_snprintf(value,MAX_STRING_LEN,"-" ZBX_FS_UI64, item->prevvalue_uint64 - item->lastvalue_uint64); } break; default: if(strcmp(item->lastvalue_str, item->prevvalue_str) == 0) { strcpy(value,"0"); } else { strcpy(value,"1"); } break; } } } else if(strcmp(function,"diff")==0) { if((item->lastvalue_null==1)||(item->prevvalue_null==1)) { ret = FAIL; } else { switch (item->value_type) { case ITEM_VALUE_TYPE_FLOAT: if(cmp_double(item->lastvalue_dbl, item->prevvalue_dbl) == 0) { strcpy(value,"0"); } else { strcpy(value,"1"); } break; case ITEM_VALUE_TYPE_UINT64: if(item->lastvalue_uint64 == item->prevvalue_uint64) { strcpy(value,"0"); } else { strcpy(value,"1"); } break; default: if(strcmp(item->lastvalue_str, item->prevvalue_str) == 0) { strcpy(value,"0"); } else { strcpy(value,"1"); } break; } /* if( (item->value_type==ITEM_VALUE_TYPE_FLOAT) || (item->value_type==ITEM_VALUE_TYPE_UINT64)) { if(cmp_double(item->lastvalue, item->prevvalue) == 0) { strcpy(value,"0"); } else { strcpy(value,"1"); } } else { if(strcmp(item->lastvalue_str, item->prevvalue_str) == 0) { strcpy(value,"0"); } else { strcpy(value,"1"); } }*/ } } else if(0 == strcmp(function, "str") || 0 == strcmp(function, "regexp") || 0 == strcmp(function, "iregexp")) { ret = evaluate_STR(value, item, function, parameter); } else if(strcmp(function,"now")==0) { now=time(NULL); zbx_snprintf(value,MAX_STRING_LEN,"%d",(int)now); } else if(strcmp(function,"fuzzytime")==0) { now=time(NULL); fuzlow=(int)(now-atoi(parameter)); fuzhig=(int)(now+atoi(parameter)); if(item->lastvalue_null==1) { ret = FAIL; } else { switch (item->value_type) { case ITEM_VALUE_TYPE_FLOAT: if((item->lastvalue_dbl>=fuzlow)&&(item->lastvalue_dbl<=fuzhig)) { strcpy(value,"1"); } else { strcpy(value,"0"); } break; case ITEM_VALUE_TYPE_UINT64: if((item->lastvalue_uint64>=fuzlow)&&(item->lastvalue_uint64<=fuzhig)) { strcpy(value,"1"); } else { strcpy(value,"0"); } break; default: ret = FAIL; break; } } } else if(strcmp(function,"logseverity")==0) { ret = evaluate_LOGSEVERITY(value,item,parameter); } else if(strcmp(function,"logsource")==0) { ret = evaluate_LOGSOURCE(value,item,parameter); } else { zabbix_log( LOG_LEVEL_WARNING, "Unsupported function:%s", function); zabbix_syslog("Unsupported function:%s", function); ret = FAIL; } zabbix_log( LOG_LEVEL_DEBUG, "End of evaluate_function(result:%s)", value); return ret; } /****************************************************************************** * * * Function: add_value_suffix_uptime * * * * Purpose: Peocess suffix 'uptime' * * * * Parameters: value - value for adjusting * * max_len - max len of the value * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static void add_value_suffix_uptime(char *value, int max_len) { double value_double; double days, hours, min; zabbix_log( LOG_LEVEL_DEBUG, "In add_value_suffix_uptime(%s)", value); value_double = atof(value); if(value_double <0) return; days=floor(value_double/(24*3600)); if(cmp_double(days,0) != 0) { value_double=value_double-days*(24*3600); } hours=floor(value_double/(3600)); if(cmp_double(hours,0) != 0) { value_double=value_double-hours*3600; } min=floor(value_double/(60)); if( cmp_double(min,0) !=0) { value_double=value_double-min*(60); } if(cmp_double(days,0) == 0) { zbx_snprintf(value, max_len, "%02d:%02d:%02d", (int)hours, (int)min, (int)value_double); } else { zbx_snprintf(value, max_len, "%d days, %02d:%02d:%02d", (int)days, (int)hours, (int)min, (int)value_double); } zabbix_log( LOG_LEVEL_DEBUG, "End of add_value_suffix_uptime(%s)", value); } /****************************************************************************** * * * Function: add_value_suffix_s * * * * Purpose: Peocess suffix 's' * * * * Parameters: value - value for adjusting * * max_len - max len of the value * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static void add_value_suffix_s(char *value, int max_len) { double value_double; double t; char tmp[MAX_STRING_LEN]; zabbix_log( LOG_LEVEL_DEBUG, "In add_value_suffix_s(%s)", value); value_double = atof(value); if(value_double <0) return; value[0]='\0'; t=floor(value_double/(365*24*3600)); if(cmp_double(t,0) != 0) { zbx_snprintf(tmp, sizeof(tmp), "%dy", (int)t); zbx_strlcat(value, tmp, max_len); value_double = value_double-t*(365*24*3600); } t=floor(value_double/(30*24*3600)); if(cmp_double(t,0) != 0) { zbx_snprintf(tmp, sizeof(tmp), "%dm", (int)t); zbx_strlcat(value, tmp, max_len); value_double = value_double-t*(30*24*3600); } t=floor(value_double/(24*3600)); if(cmp_double(t,0) != 0) { zbx_snprintf(tmp, sizeof(tmp), "%dd", (int)t); zbx_strlcat(value, tmp, max_len); value_double = value_double-t*(24*3600); } t=floor(value_double/(3600)); if(cmp_double(t,0) != 0) { zbx_snprintf(tmp, sizeof(tmp), "%dh", (int)t); zbx_strlcat(value, tmp, max_len); value_double = value_double-t*(3600); } t=floor(value_double/(60)); if(cmp_double(t,0) != 0) { zbx_snprintf(tmp, sizeof(tmp), "%dm", (int)t); zbx_strlcat(value, tmp, max_len); value_double = value_double-t*(60); } zbx_snprintf(tmp, sizeof(tmp), "%02.2f", value_double); zbx_rtrim(tmp,"0"); zbx_rtrim(tmp,"."); zbx_strlcat(tmp, "s", sizeof(tmp)); zbx_strlcat(value, tmp, max_len); zabbix_log( LOG_LEVEL_DEBUG, "End of add_value_suffix_s(%s)", value); } /****************************************************************************** * * * Function: add_value_suffix_normsl * * * * Purpose: Peocess normal values and add K,M,G,T * * * * Parameters: value - value for adjusting * * max_len - max len of the value * * units - units (bps, b,B, etc) * * * * Return value: * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ static void add_value_suffix_normal(char *value, int max_len, char *units) { double base = 1024; char kmgt[MAX_STRING_LEN]; zbx_uint64_t value_uint64; double value_double; zabbix_log( LOG_LEVEL_DEBUG, "In add_value_normal(value:%s,units:%s)", value, units); ZBX_STR2UINT64(value_uint64, value); /* value_uint64 = llabs(zbx_atoui64(value));*/ /* SPecial processing for bits */ if(strcmp(units,"b") == 0 || strcmp(units,"bps") == 0) { base = 1000; } if(value_uint64 < base) { strscpy(kmgt,""); value_double = (double)value_uint64; } else if(value_uint64 < base*base) { strscpy(kmgt,"K"); value_double = (double)value_uint64/base; } else if(value_uint64 < base*base*base) { strscpy(kmgt,"M"); value_double = (double)(value_uint64/(base*base)); } else if(value_uint64 < base*base*base*base) { strscpy(kmgt,"G"); value_double = (double)value_uint64/(base*base*base); } else { strscpy(kmgt,"T"); value_double = (double)value_uint64/(base*base*base*base); } if(cmp_double((int)(value_double+0.5), value_double) == 0) { zbx_snprintf(value, MAX_STRING_LEN, ZBX_FS_DBL_EXT(0) " %s%s", value_double, kmgt, units); } else { zbx_snprintf(value, MAX_STRING_LEN, ZBX_FS_DBL_EXT(2) " %s%s", value_double, kmgt, units); } zabbix_log( LOG_LEVEL_DEBUG, "End of add_value_normal(value:%s)", value); } /****************************************************************************** * * * Function: add_value_suffix * * * * Purpose: Add suffix for value * * * * Parameters: value - value to replacing * * valuemapid - index of value map * * * * Return value: SUCCEED - suffix added succesfully, value contains new value * * FAIL - adding failed, value contains old value * * * * Author: Alexei Vladishev * * * * Comments: * * * ******************************************************************************/ /* Do not forget to keep it in sync wiht convert_units in config.inc.php */ int add_value_suffix(char *value, int max_len, char *units, int value_type) { int ret = FAIL; struct tm *local_time = NULL; time_t time; char tmp[MAX_STRING_LEN]; zabbix_log( LOG_LEVEL_DEBUG, "In add_value_suffix(value:%s,units:%s)", value, units); switch(value_type) { case ITEM_VALUE_TYPE_FLOAT: if(strcmp(units,"s") == 0) { add_value_suffix_s(value, max_len); ret = SUCCEED; } else if(strcmp(units,"uptime") == 0) { add_value_suffix_uptime(value, max_len); ret = SUCCEED; } else if(strlen(units) != 0) { add_value_suffix_normal(value, max_len, units); ret = SUCCEED; } else { /* Do nothing if units not set */ } break; case ITEM_VALUE_TYPE_UINT64: if(strcmp(units,"s") == 0) { add_value_suffix_s(value, max_len); ret = SUCCEED; } else if(strcmp(units,"unixtime") == 0) { time = (time_t)zbx_atoui64(value); local_time = localtime(&time); strftime(tmp, MAX_STRING_LEN, "%Y.%m.%d %H:%M:%S", local_time); zbx_strlcpy(value, tmp, max_len); ret = SUCCEED; } else if(strcmp(units,"uptime") == 0) { add_value_suffix_uptime(value, max_len); ret = SUCCEED; } else if(strlen(units) != 0) { add_value_suffix_normal(value, max_len, units); ret = SUCCEED; } else { /* Do nothing if units not set */ } break; default: ret = FAIL; break; } zabbix_log(LOG_LEVEL_DEBUG, "End of add_value_suffix(%s)", value); return ret; } /****************************************************************************** * * * Function: replace_value_by_map * * * * Purpose: replace value by mapping value * * * * Parameters: value - value to replacing * * valuemapid - index of value map * * * * Return value: SUCCEED - evaluated succesfully, value contains new value * * FAIL - evaluation failed, value contains old value * * * * Author: Eugene Grigorjev * * * * Comments: * * * ******************************************************************************/ int replace_value_by_map(char *value, zbx_uint64_t valuemapid) { DB_RESULT result; DB_ROW row; char new_value[MAX_STRING_LEN]; char sql[MAX_STRING_LEN]; char *or_value; zabbix_log(LOG_LEVEL_DEBUG, "In replace_value_by_map()" ); if(valuemapid == 0) return FAIL; result = DBselect("select newvalue from mappings where valuemapid=" ZBX_FS_UI64 " and value='%s'", valuemapid, value); row = DBfetch(result); if(!row || DBis_null(row[0])==SUCCEED) return FAIL; strcpy(new_value,row[0]); DBfree_result(result); del_zeroes(new_value); or_value = sql; /* sql variarbvle used as tmp - original value */ zbx_strlcpy(sql,value,MAX_STRING_LEN); zbx_snprintf(value, MAX_STRING_LEN, "%s (%s)", new_value, or_value); zabbix_log(LOG_LEVEL_DEBUG, "End replace_value_by_map(result:%s)", value); return SUCCEED; } /****************************************************************************** * * * Function: evaluate_function2 * * * * Purpose: evaluate function * * * * Parameters: host - host the key belongs to * * key - item's key (for example, 'max') * * function - function (for example, 'max') * * parameter - parameter of the function) * * * * Return value: SUCCEED - evaluated succesfully, value contains its value * * FAIL - evaluation failed * * * * Author: Alexei Vladishev * * * * Comments: Used for evaluation of notification macros * * * ******************************************************************************/ int evaluate_function2(char *value,char *host,char *key,char *function,char *parameter) { DB_ITEM item; DB_RESULT result; DB_ROW row; char host_esc[MAX_STRING_LEN]; char key_esc[MAX_STRING_LEN]; int res; zabbix_log(LOG_LEVEL_DEBUG, "In evaluate_function2(%s,%s,%s,%s)", host, key, function, parameter); DBescape_string(host, host_esc, MAX_STRING_LEN); DBescape_string(key, key_esc, MAX_STRING_LEN); result = DBselect("select %s where h.host='%s' and h.hostid=i.hostid and i.key_='%s'" DB_NODE, ZBX_SQL_ITEM_SELECT, host_esc, key_esc, DBnode_local("h.hostid")); row = DBfetch(result); if(!row) { DBfree_result(result); zabbix_log(LOG_LEVEL_WARNING, "Query returned empty result"); zabbix_syslog("Query returned empty result"); return FAIL; } DBget_item_from_db(&item,row); res = evaluate_function(value,&item,function,parameter); if(replace_value_by_map(value, item.valuemapid) != SUCCEED) { add_value_suffix(value, MAX_STRING_LEN, item.units, item.value_type); } /* Cannot call DBfree_result until evaluate_FUNC */ DBfree_result(result); zabbix_log(LOG_LEVEL_DEBUG, "End evaluate_function2(result:%s)", value); return res; }