1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "common.h"
21 #include "db.h"
22 #include "log.h"
23 #include "zbxserver.h"
24 #include "valuecache.h"
25 #include "evalfunc.h"
26 #include "zbxregexp.h"
27
28 typedef enum
29 {
30 ZBX_PARAM_OPTIONAL,
31 ZBX_PARAM_MANDATORY
32 }
33 zbx_param_type_t;
34
35 typedef enum
36 {
37 ZBX_VALUE_SECONDS,
38 ZBX_VALUE_NVALUES
39 }
40 zbx_value_type_t;
41
zbx_type_string(zbx_value_type_t type)42 static const char *zbx_type_string(zbx_value_type_t type)
43 {
44 switch (type)
45 {
46 case ZBX_VALUE_SECONDS:
47 return "sec";
48 case ZBX_VALUE_NVALUES:
49 return "num";
50 default:
51 THIS_SHOULD_NEVER_HAPPEN;
52 return "unknown";
53 }
54 }
55
56 /******************************************************************************
57 * *
58 * Function: get_function_parameter_int *
59 * *
60 * Purpose: get the value of sec|#num trigger function parameter *
61 * *
62 * Parameters: hostid - [IN] hostid of the host trigger function *
63 * belongs to *
64 * parameters - [IN] trigger function parameters *
65 * Nparam - [IN] specifies which parameter to extract *
66 * parameter_type - [IN] specifies whether parameter is mandatory *
67 * or optional *
68 * value - [OUT] parameter value (preserved as is if the *
69 * parameter is optional and empty) *
70 * type - [OUT] parameter value type (number of seconds *
71 * or number of values) *
72 * *
73 * Return value: SUCCEED - parameter is valid *
74 * FAIL - otherwise *
75 * *
76 ******************************************************************************/
get_function_parameter_int(zbx_uint64_t hostid,const char * parameters,int Nparam,zbx_param_type_t parameter_type,int * value,zbx_value_type_t * type)77 static int get_function_parameter_int(zbx_uint64_t hostid, const char *parameters, int Nparam,
78 zbx_param_type_t parameter_type, int *value, zbx_value_type_t *type)
79 {
80 const char *__function_name = "get_function_parameter_int";
81 char *parameter;
82 int ret = FAIL;
83
84 zabbix_log(LOG_LEVEL_DEBUG, "In %s() parameters:'%s' Nparam:%d", __function_name, parameters, Nparam);
85
86 if (NULL == (parameter = zbx_function_get_param_dyn(parameters, Nparam)))
87 goto out;
88
89 if (SUCCEED == substitute_simple_macros(NULL, NULL, NULL, NULL, &hostid, NULL, NULL, NULL,
90 ¶meter, MACRO_TYPE_COMMON, NULL, 0))
91 {
92 if ('\0' == *parameter)
93 {
94 switch (parameter_type)
95 {
96 case ZBX_PARAM_OPTIONAL:
97 ret = SUCCEED;
98 break;
99 case ZBX_PARAM_MANDATORY:
100 break;
101 default:
102 THIS_SHOULD_NEVER_HAPPEN;
103 }
104 }
105 else if ('#' == *parameter)
106 {
107 *type = ZBX_VALUE_NVALUES;
108 if (SUCCEED == is_uint31(parameter + 1, value) && 0 < *value)
109 ret = SUCCEED;
110 }
111 else if ('-' == *parameter)
112 {
113 if (SUCCEED == is_time_suffix(parameter + 1, value))
114 {
115 *value = -(*value);
116 *type = ZBX_VALUE_SECONDS;
117 ret = SUCCEED;
118 }
119 }
120 else if (SUCCEED == is_time_suffix(parameter, value))
121 {
122 *type = ZBX_VALUE_SECONDS;
123 ret = SUCCEED;
124 }
125 }
126
127 if (SUCCEED == ret)
128 zabbix_log(LOG_LEVEL_DEBUG, "%s() type:%s value:%d", __function_name, zbx_type_string(*type), *value);
129
130 zbx_free(parameter);
131 out:
132 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
133
134 return ret;
135 }
136
get_function_parameter_uint64(zbx_uint64_t hostid,const char * parameters,int Nparam,zbx_uint64_t * value)137 static int get_function_parameter_uint64(zbx_uint64_t hostid, const char *parameters, int Nparam,
138 zbx_uint64_t *value)
139 {
140 const char *__function_name = "get_function_parameter_uint64";
141 char *parameter;
142 int ret = FAIL;
143
144 zabbix_log(LOG_LEVEL_DEBUG, "In %s() parameters:'%s' Nparam:%d", __function_name, parameters, Nparam);
145
146 if (NULL == (parameter = zbx_function_get_param_dyn(parameters, Nparam)))
147 goto out;
148
149 if (SUCCEED == substitute_simple_macros(NULL, NULL, NULL, NULL, &hostid, NULL, NULL, NULL,
150 ¶meter, MACRO_TYPE_COMMON, NULL, 0))
151 {
152 if (SUCCEED == is_uint64(parameter, value))
153 ret = SUCCEED;
154 }
155
156 if (SUCCEED == ret)
157 zabbix_log(LOG_LEVEL_DEBUG, "%s() value:" ZBX_FS_UI64, __function_name, *value);
158
159 zbx_free(parameter);
160 out:
161 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
162
163 return ret;
164 }
165
get_function_parameter_float(zbx_uint64_t hostid,const char * parameters,int Nparam,unsigned char flags,double * value)166 static int get_function_parameter_float(zbx_uint64_t hostid, const char *parameters, int Nparam,
167 unsigned char flags, double *value)
168 {
169 const char *__function_name = "get_function_parameter_float";
170 char *parameter;
171 int ret = FAIL;
172
173 zabbix_log(LOG_LEVEL_DEBUG, "In %s() parameters:'%s' Nparam:%d", __function_name, parameters, Nparam);
174
175 if (NULL == (parameter = zbx_function_get_param_dyn(parameters, Nparam)))
176 goto out;
177
178 if (SUCCEED == substitute_simple_macros(NULL, NULL, NULL, NULL, &hostid, NULL, NULL, NULL,
179 ¶meter, MACRO_TYPE_COMMON, NULL, 0))
180 {
181 if (SUCCEED != is_double_suffix(parameter, flags))
182 goto clean;
183
184 *value = str2double(parameter);
185
186 ret = SUCCEED;
187 }
188
189 if (SUCCEED == ret)
190 zabbix_log(LOG_LEVEL_DEBUG, "%s() value:" ZBX_FS_DBL, __function_name, *value);
191 clean:
192 zbx_free(parameter);
193 out:
194 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
195
196 return ret;
197 }
198
get_function_parameter_str(zbx_uint64_t hostid,const char * parameters,int Nparam,char ** value)199 static int get_function_parameter_str(zbx_uint64_t hostid, const char *parameters, int Nparam, char **value)
200 {
201 const char *__function_name = "get_function_parameter_str";
202 int ret = FAIL;
203
204 zabbix_log(LOG_LEVEL_DEBUG, "In %s() parameters:'%s' Nparam:%d", __function_name, parameters, Nparam);
205
206 if (NULL == (*value = zbx_function_get_param_dyn(parameters, Nparam)))
207 goto out;
208
209 ret = substitute_simple_macros(NULL, NULL, NULL, NULL, &hostid, NULL, NULL, NULL,
210 value, MACRO_TYPE_COMMON, NULL, 0);
211
212 if (SUCCEED == ret)
213 zabbix_log(LOG_LEVEL_DEBUG, "%s() value:'%s'", __function_name, *value);
214 else
215 zbx_free(*value);
216 out:
217 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
218
219 return ret;
220 }
221
222 /******************************************************************************
223 * *
224 * Function: evaluate_LOGEVENTID *
225 * *
226 * Purpose: evaluate function 'logeventid' for the item *
227 * *
228 * Parameters: item - item (performance metric) *
229 * parameter - regex string for event id matching *
230 * *
231 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
232 * FAIL - failed to evaluate function *
233 * *
234 ******************************************************************************/
evaluate_LOGEVENTID(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now,char ** error)235 static int evaluate_LOGEVENTID(char *value, DC_ITEM *item, const char *function, const char *parameters,
236 time_t now, char **error)
237 {
238 const char *__function_name = "evaluate_LOGEVENTID";
239
240 char *arg1 = NULL;
241 int ret = FAIL;
242 zbx_vector_ptr_t regexps;
243 zbx_history_record_t vc_value;
244 zbx_timespec_t ts = {now, 999999999};
245
246 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
247
248 zbx_vector_ptr_create(®exps);
249
250 if (ITEM_VALUE_TYPE_LOG != item->value_type)
251 goto out;
252
253 if (1 < num_param(parameters))
254 goto out;
255
256 if (SUCCEED != get_function_parameter_str(item->host.hostid, parameters, 1, &arg1))
257 goto out;
258
259 if ('@' == *arg1)
260 {
261 DCget_expressions_by_name(®exps, arg1 + 1);
262
263 if (0 == regexps.values_num)
264 {
265 *error = zbx_dsprintf(*error, "global regular expression \"%s\" does not exist", arg1 + 1);
266 goto out;
267 }
268 }
269
270 if (SUCCEED == zbx_vc_get_value(item->itemid, item->value_type, &ts, &vc_value))
271 {
272 char logeventid[16];
273
274 zbx_snprintf(logeventid, sizeof(logeventid), "%d", vc_value.value.log->logeventid);
275 if (SUCCEED == regexp_match_ex(®exps, logeventid, arg1, ZBX_CASE_SENSITIVE))
276 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
277 else
278 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
279 zbx_history_record_clear(&vc_value, item->value_type);
280
281 ret = SUCCEED;
282 }
283 else
284 zabbix_log(LOG_LEVEL_DEBUG, "result for LOGEVENTID is empty");
285 out:
286 zbx_free(arg1);
287
288 zbx_regexp_clean_expressions(®exps);
289 zbx_vector_ptr_destroy(®exps);
290
291 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
292
293 return ret;
294 }
295
296 /******************************************************************************
297 * *
298 * Function: evaluate_LOGSOURCE *
299 * *
300 * Purpose: evaluate function 'logsource' for the item *
301 * *
302 * Parameters: item - item (performance metric) *
303 * parameter - ignored *
304 * *
305 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
306 * FAIL - failed to evaluate function *
307 * *
308 ******************************************************************************/
evaluate_LOGSOURCE(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now)309 static int evaluate_LOGSOURCE(char *value, DC_ITEM *item, const char *function, const char *parameters, time_t now)
310 {
311 const char *__function_name = "evaluate_LOGSOURCE";
312
313 char *arg1 = NULL;
314 int ret = FAIL;
315 zbx_history_record_t vc_value;
316 zbx_timespec_t ts = {now, 999999999};
317
318 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
319
320 if (ITEM_VALUE_TYPE_LOG != item->value_type)
321 goto out;
322
323 if (1 < num_param(parameters))
324 goto out;
325
326 if (SUCCEED != get_function_parameter_str(item->host.hostid, parameters, 1, &arg1))
327 goto out;
328
329 if (SUCCEED == zbx_vc_get_value(item->itemid, item->value_type, &ts, &vc_value))
330 {
331 if (0 == strcmp(NULL == vc_value.value.log->source ? "" : vc_value.value.log->source, arg1))
332 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
333 else
334 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
335 zbx_history_record_clear(&vc_value, item->value_type);
336
337 ret = SUCCEED;
338 }
339 else
340 zabbix_log(LOG_LEVEL_DEBUG, "result for LOGSOURCE is empty");
341
342 zbx_free(arg1);
343 out:
344 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
345
346 return ret;
347 }
348
349 /******************************************************************************
350 * *
351 * Function: evaluate_LOGSEVERITY *
352 * *
353 * Purpose: evaluate function 'logseverity' for the item *
354 * *
355 * Parameters: item - item (performance metric) *
356 * parameter - ignored *
357 * *
358 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
359 * FAIL - failed to evaluate function *
360 * *
361 ******************************************************************************/
evaluate_LOGSEVERITY(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now)362 static int evaluate_LOGSEVERITY(char *value, DC_ITEM *item, const char *function, const char *parameters,
363 time_t now)
364 {
365 const char *__function_name = "evaluate_LOGSEVERITY";
366
367 int ret = FAIL;
368 zbx_history_record_t vc_value;
369 zbx_timespec_t ts = {now, 999999999};
370
371 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
372
373 if (ITEM_VALUE_TYPE_LOG != item->value_type)
374 goto out;
375
376 if (SUCCEED == zbx_vc_get_value(item->itemid, item->value_type, &ts, &vc_value))
377 {
378 zbx_snprintf(value, MAX_BUFFER_LEN, "%d", vc_value.value.log->severity);
379 zbx_history_record_clear(&vc_value, item->value_type);
380
381 ret = SUCCEED;
382 }
383 else
384 zabbix_log(LOG_LEVEL_DEBUG, "result for LOGSEVERITY is empty");
385 out:
386 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
387
388 return ret;
389 }
390
391 #define OP_UNKNOWN -1
392 #define OP_EQ 0
393 #define OP_NE 1
394 #define OP_GT 2
395 #define OP_GE 3
396 #define OP_LT 4
397 #define OP_LE 5
398 #define OP_LIKE 6
399 #define OP_BAND 7
400 #define OP_MAX 8
401
evaluate_COUNT_one(unsigned char value_type,int op,history_value_t * value,const char * arg2,const char * arg2_2)402 static int evaluate_COUNT_one(unsigned char value_type, int op, history_value_t *value, const char *arg2,
403 const char *arg2_2)
404 {
405 zbx_uint64_t arg2_uint64, arg2_2_uint64;
406 double arg2_double;
407
408 switch (value_type)
409 {
410 case ITEM_VALUE_TYPE_UINT64:
411 if (SUCCEED != str2uint64(arg2, "KMGTsmhdw", &arg2_uint64))
412 return FAIL;
413
414 switch (op)
415 {
416 case OP_EQ:
417 if (value->ui64 == arg2_uint64)
418 return SUCCEED;
419 break;
420 case OP_NE:
421 if (value->ui64 != arg2_uint64)
422 return SUCCEED;
423 break;
424 case OP_GT:
425 if (value->ui64 > arg2_uint64)
426 return SUCCEED;
427 break;
428 case OP_GE:
429 if (value->ui64 >= arg2_uint64)
430 return SUCCEED;
431 break;
432 case OP_LT:
433 if (value->ui64 < arg2_uint64)
434 return SUCCEED;
435 break;
436 case OP_LE:
437 if (value->ui64 <= arg2_uint64)
438 return SUCCEED;
439 break;
440 case OP_BAND:
441 if (NULL != arg2_2)
442 {
443 if (SUCCEED != is_uint64(arg2_2, &arg2_2_uint64))
444 return FAIL;
445 }
446 else
447 arg2_2_uint64 = arg2_uint64;
448
449 if (arg2_uint64 == (value->ui64 & arg2_2_uint64))
450 return SUCCEED;
451 break;
452 }
453
454 break;
455 case ITEM_VALUE_TYPE_FLOAT:
456 if (SUCCEED != is_double_suffix(arg2, ZBX_FLAG_DOUBLE_SUFFIX))
457 return FAIL;
458 arg2_double = str2double(arg2);
459
460 switch (op)
461 {
462 case OP_EQ:
463 if (value->dbl > arg2_double - ZBX_DOUBLE_EPSILON &&
464 value->dbl < arg2_double + ZBX_DOUBLE_EPSILON)
465 {
466 return SUCCEED;
467 }
468 break;
469 case OP_NE:
470 if (!(value->dbl > arg2_double - ZBX_DOUBLE_EPSILON &&
471 value->dbl < arg2_double + ZBX_DOUBLE_EPSILON))
472 {
473 return SUCCEED;
474 }
475 break;
476 case OP_GT:
477 if (value->dbl >= arg2_double + ZBX_DOUBLE_EPSILON)
478 return SUCCEED;
479 break;
480 case OP_GE:
481 if (value->dbl > arg2_double - ZBX_DOUBLE_EPSILON)
482 return SUCCEED;
483 break;
484 case OP_LT:
485 if (value->dbl <= arg2_double - ZBX_DOUBLE_EPSILON)
486 return SUCCEED;
487 break;
488 case OP_LE:
489 if (value->dbl < arg2_double + ZBX_DOUBLE_EPSILON)
490 return SUCCEED;
491 break;
492 }
493
494 break;
495 case ITEM_VALUE_TYPE_LOG:
496 switch (op)
497 {
498 case OP_EQ:
499 if (0 == strcmp(value->log->value, arg2))
500 return SUCCEED;
501 break;
502 case OP_NE:
503 if (0 != strcmp(value->log->value, arg2))
504 return SUCCEED;
505 break;
506 case OP_LIKE:
507 if (NULL != strstr(value->log->value, arg2))
508 return SUCCEED;
509 break;
510 }
511
512 break;
513 default:
514 switch (op)
515 {
516 case OP_EQ:
517 if (0 == strcmp(value->str, arg2))
518 return SUCCEED;
519 break;
520 case OP_NE:
521 if (0 != strcmp(value->str, arg2))
522 return SUCCEED;
523 break;
524 case OP_LIKE:
525 if (NULL != strstr(value->str, arg2))
526 return SUCCEED;
527 break;
528 }
529 }
530
531 return FAIL;
532 }
533
534 /******************************************************************************
535 * *
536 * Function: evaluate_COUNT *
537 * *
538 * Purpose: evaluate function 'count' for the item *
539 * *
540 * Parameters: item - item (performance metric) *
541 * parameters - up to four comma-separated fields: *
542 * (1) number of seconds/values *
543 * (2) value to compare with (optional) *
544 * Becomes mandatory for numeric items if 3rd *
545 * parameter is specified. With "band" can *
546 * take one of 2 forms: *
547 * - value_to_compare_with/mask *
548 * - mask *
549 * (3) comparison operator (optional) *
550 * (4) time shift (optional) *
551 * *
552 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
553 * FAIL - failed to evaluate function *
554 * *
555 ******************************************************************************/
evaluate_COUNT(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now)556 static int evaluate_COUNT(char *value, DC_ITEM *item, const char *function, const char *parameters, time_t now)
557 {
558 const char *__function_name = "evaluate_COUNT";
559 int arg1, op = OP_UNKNOWN, numeric_search, nparams, count = 0, i, ret = FAIL;
560 int seconds = 0, nvalues = 0;
561 zbx_value_type_t arg1_type;
562 char *arg2 = NULL, *arg2_2 = NULL, *arg3 = NULL;
563 zbx_vector_history_record_t values;
564
565 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
566
567 zbx_history_record_vector_create(&values);
568
569 numeric_search = (ITEM_VALUE_TYPE_UINT64 == item->value_type || ITEM_VALUE_TYPE_FLOAT == item->value_type);
570
571 if (4 < (nparams = num_param(parameters)))
572 goto out;
573
574 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
575 &arg1_type) || 0 >= arg1)
576 {
577 goto out;
578 }
579
580 if (2 <= nparams && SUCCEED != get_function_parameter_str(item->host.hostid, parameters, 2, &arg2))
581 goto out;
582
583 if (3 <= nparams && SUCCEED != get_function_parameter_str(item->host.hostid, parameters, 3, &arg3))
584 goto out;
585
586 if (4 <= nparams)
587 {
588 int time_shift = 0;
589 zbx_value_type_t time_shift_type = ZBX_VALUE_SECONDS;
590
591 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 4, ZBX_PARAM_OPTIONAL,
592 &time_shift, &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type || 0 > time_shift)
593 {
594 goto out;
595 }
596
597 now -= time_shift;
598 }
599
600 if (NULL == arg3 || '\0' == *arg3)
601 op = (0 != numeric_search ? OP_EQ : OP_LIKE);
602 else if (0 == strcmp(arg3, "eq"))
603 op = OP_EQ;
604 else if (0 == strcmp(arg3, "ne"))
605 op = OP_NE;
606 else if (0 == strcmp(arg3, "gt"))
607 op = OP_GT;
608 else if (0 == strcmp(arg3, "ge"))
609 op = OP_GE;
610 else if (0 == strcmp(arg3, "lt"))
611 op = OP_LT;
612 else if (0 == strcmp(arg3, "le"))
613 op = OP_LE;
614 else if (0 == strcmp(arg3, "like"))
615 op = OP_LIKE;
616 else if (0 == strcmp(arg3, "band"))
617 op = OP_BAND;
618
619 if (OP_UNKNOWN == op)
620 {
621 zabbix_log(LOG_LEVEL_DEBUG, "operator \"%s\" is not supported for function COUNT", arg3);
622 goto out;
623 }
624
625 if (0 != numeric_search)
626 {
627 if (NULL != arg3 && '\0' != *arg3 && '\0' == *arg2)
628 {
629 zabbix_log(LOG_LEVEL_DEBUG, "pattern must be provided along with operator for numeric values");
630 goto out;
631 }
632
633 if (OP_LIKE == op)
634 {
635 zabbix_log(LOG_LEVEL_DEBUG, "operator \"like\" is not supported for counting numeric values");
636 goto out;
637 }
638
639 if (OP_BAND == op && ITEM_VALUE_TYPE_FLOAT == item->value_type)
640 {
641 zabbix_log(LOG_LEVEL_DEBUG, "operator \"band\" is not supported for counting float values");
642 goto out;
643 }
644
645 if (OP_BAND == op && NULL != (arg2_2 = strchr(arg2, '/')))
646 {
647 *arg2_2 = '\0'; /* end of the 1st part of the 2nd parameter (number to compare with) */
648 arg2_2++; /* start of the 2nd part of the 2nd parameter (mask) */
649 }
650 }
651 else if (OP_LIKE != op && OP_EQ != op && OP_NE != op)
652 {
653 zabbix_log(LOG_LEVEL_DEBUG, "operator \"%s\" is not supported for counting textual values", arg3);
654 goto out;
655 }
656
657 switch (arg1_type)
658 {
659 case ZBX_VALUE_SECONDS:
660 seconds = arg1;
661 break;
662 case ZBX_VALUE_NVALUES:
663 nvalues = arg1;
664 break;
665 default:
666 THIS_SHOULD_NEVER_HAPPEN;
667 }
668
669 if (FAIL == zbx_vc_get_value_range(item->itemid, item->value_type, &values, seconds, nvalues, now))
670 goto out;
671
672 /* skip counting values one by one if both pattern and operator are empty or "" is searched in text values */
673 if ((NULL != arg2 && '\0' != *arg2) || (NULL != arg3 && '\0' != *arg3 && OP_LIKE != op))
674 {
675 for (i = 0; i < values.values_num; i++)
676 {
677 if (SUCCEED == evaluate_COUNT_one(item->value_type, op, &values.values[i].value, arg2, arg2_2))
678 count++;
679 }
680 }
681 else
682 count = values.values_num;
683
684 zbx_snprintf(value, MAX_BUFFER_LEN, "%d", count);
685
686 ret = SUCCEED;
687 out:
688 zbx_free(arg2);
689 zbx_free(arg3);
690
691 zbx_history_record_vector_destroy(&values, item->value_type);
692
693 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
694
695 return ret;
696 }
697
698 #undef OP_UNKNOWN
699 #undef OP_EQ
700 #undef OP_NE
701 #undef OP_GT
702 #undef OP_GE
703 #undef OP_LT
704 #undef OP_LE
705 #undef OP_LIKE
706 #undef OP_BAND
707 #undef OP_MAX
708
709 /******************************************************************************
710 * *
711 * Function: evaluate_SUM *
712 * *
713 * Purpose: evaluate function 'sum' for the item *
714 * *
715 * Parameters: item - item (performance metric) *
716 * parameters - number of seconds/values and time shift (optional)*
717 * *
718 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
719 * FAIL - failed to evaluate function *
720 * *
721 ******************************************************************************/
evaluate_SUM(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now)722 static int evaluate_SUM(char *value, DC_ITEM *item, const char *function, const char *parameters, time_t now)
723 {
724 const char *__function_name = "evaluate_SUM";
725 int nparams, arg1, i, ret = FAIL, seconds = 0, nvalues = 0;
726 zbx_value_type_t arg1_type;
727 zbx_vector_history_record_t values;
728 history_value_t result;
729
730 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
731
732 zbx_history_record_vector_create(&values);
733
734 if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
735 goto out;
736
737 if (2 < (nparams = num_param(parameters)))
738 goto out;
739
740 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
741 &arg1_type) || 0 >= arg1)
742 {
743 goto out;
744 }
745
746 if (2 == nparams)
747 {
748 int time_shift = 0;
749 zbx_value_type_t time_shift_type = ZBX_VALUE_SECONDS;
750
751 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL,
752 &time_shift, &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type || 0 > time_shift)
753 {
754 goto out;
755 }
756
757 now -= time_shift;
758 }
759
760 switch (arg1_type)
761 {
762 case ZBX_VALUE_SECONDS:
763 seconds = arg1;
764 break;
765 case ZBX_VALUE_NVALUES:
766 nvalues = arg1;
767 break;
768 default:
769 THIS_SHOULD_NEVER_HAPPEN;
770 }
771
772 if (FAIL == zbx_vc_get_value_range(item->itemid, item->value_type, &values, seconds, nvalues, now))
773 goto out;
774
775 if (ITEM_VALUE_TYPE_FLOAT == item->value_type)
776 {
777 result.dbl = 0;
778
779 for (i = 0; i < values.values_num; i++)
780 result.dbl += values.values[i].value.dbl;
781 }
782 else
783 {
784 result.ui64 = 0;
785
786 for (i = 0; i < values.values_num; i++)
787 result.ui64 += values.values[i].value.ui64;
788 }
789
790 zbx_vc_history_value2str(value, MAX_BUFFER_LEN, &result, item->value_type);
791 ret = SUCCEED;
792 out:
793 zbx_history_record_vector_destroy(&values, item->value_type);
794
795 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
796
797 return ret;
798 }
799
800 /******************************************************************************
801 * *
802 * Function: evaluate_AVG *
803 * *
804 * Purpose: evaluate function 'avg' for the item *
805 * *
806 * Parameters: item - item (performance metric) *
807 * parameters - number of seconds/values and time shift (optional)*
808 * *
809 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
810 * FAIL - failed to evaluate function *
811 * *
812 ******************************************************************************/
evaluate_AVG(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now)813 static int evaluate_AVG(char *value, DC_ITEM *item, const char *function, const char *parameters, time_t now)
814 {
815 const char *__function_name = "evaluate_AVG";
816 int nparams, arg1, ret = FAIL, i, seconds = 0, nvalues = 0;
817 zbx_value_type_t arg1_type;
818 zbx_vector_history_record_t values;
819
820 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
821
822 zbx_history_record_vector_create(&values);
823
824 if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
825 goto out;
826
827 if (2 < (nparams = num_param(parameters)))
828 goto out;
829
830 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
831 &arg1_type) || 0 >= arg1)
832 {
833 goto out;
834 }
835
836 if (2 == nparams)
837 {
838 int time_shift = 0;
839 zbx_value_type_t time_shift_type = ZBX_VALUE_SECONDS;
840
841 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL,
842 &time_shift, &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type || 0 > time_shift)
843 {
844 goto out;
845 }
846
847 now -= time_shift;
848 }
849
850 switch (arg1_type)
851 {
852 case ZBX_VALUE_SECONDS:
853 seconds = arg1;
854 break;
855 case ZBX_VALUE_NVALUES:
856 nvalues = arg1;
857 break;
858 default:
859 THIS_SHOULD_NEVER_HAPPEN;
860 }
861
862 if (FAIL == zbx_vc_get_value_range(item->itemid, item->value_type, &values, seconds, nvalues, now))
863 goto out;
864
865 if (0 < values.values_num)
866 {
867 double sum = 0;
868
869 if (ITEM_VALUE_TYPE_FLOAT == item->value_type)
870 {
871 for (i = 0; i < values.values_num; i++)
872 sum += values.values[i].value.dbl;
873 }
874 else
875 {
876 for (i = 0; i < values.values_num; i++)
877 sum += values.values[i].value.ui64;
878 }
879 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_DBL, sum / values.values_num);
880
881 ret = SUCCEED;
882 }
883 else
884 zabbix_log(LOG_LEVEL_DEBUG, "result for AVG is empty");
885 out:
886 zbx_history_record_vector_destroy(&values, item->value_type);
887
888 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
889
890 return ret;
891 }
892
893 /******************************************************************************
894 * *
895 * Function: evaluate_LAST *
896 * *
897 * Purpose: evaluate functions 'last' and 'prev' for the item *
898 * *
899 * Parameters: value - buffer of size MAX_BUFFER_LEN *
900 * item - item (performance metric) *
901 * parameters - Nth last value and time shift (optional) *
902 * *
903 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
904 * FAIL - failed to evaluate function *
905 * *
906 ******************************************************************************/
evaluate_LAST(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now)907 static int evaluate_LAST(char *value, DC_ITEM *item, const char *function, const char *parameters, time_t now)
908 {
909 const char *__function_name = "evaluate_LAST";
910 int arg1 = 1, ret = FAIL;
911 zbx_value_type_t arg1_type = ZBX_VALUE_NVALUES;
912 zbx_vector_history_record_t values;
913
914 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
915
916 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_OPTIONAL, &arg1,
917 &arg1_type))
918 {
919 goto out;
920 }
921
922 if (ZBX_VALUE_NVALUES != arg1_type)
923 arg1 = 1; /* non-# first parameter is ignored to support older syntax "last(0)" */
924
925 if (2 == num_param(parameters))
926 {
927 int time_shift = 0;
928 zbx_value_type_t time_shift_type = ZBX_VALUE_SECONDS;
929
930 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL,
931 &time_shift, &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type || 0 > time_shift)
932 {
933 goto out;
934 }
935
936 now -= time_shift;
937 }
938
939 zbx_history_record_vector_create(&values);
940
941 if (SUCCEED == zbx_vc_get_value_range(item->itemid, item->value_type, &values, 0, arg1, now))
942 {
943 if (arg1 <= values.values_num)
944 {
945 zbx_vc_history_value2str(value, MAX_BUFFER_LEN, &values.values[arg1 - 1].value,
946 item->value_type);
947 ret = SUCCEED;
948 }
949 }
950
951 zbx_history_record_vector_destroy(&values, item->value_type);
952 out:
953 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
954
955 return ret;
956 }
957
958 /******************************************************************************
959 * *
960 * Function: evaluate_MIN *
961 * *
962 * Purpose: evaluate function 'min' for the item *
963 * *
964 * Parameters: item - item (performance metric) *
965 * parameters - number of seconds/values and time shift (optional)*
966 * *
967 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
968 * FAIL - failed to evaluate function *
969 * *
970 ******************************************************************************/
evaluate_MIN(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now)971 static int evaluate_MIN(char *value, DC_ITEM *item, const char *function, const char *parameters, time_t now)
972 {
973 const char *__function_name = "evaluate_MIN";
974 int nparams, arg1, i, ret = FAIL, seconds = 0, nvalues = 0;
975 zbx_value_type_t arg1_type;
976 zbx_vector_history_record_t values;
977
978 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
979
980 zbx_history_record_vector_create(&values);
981
982 if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
983 goto out;
984
985 if (2 < (nparams = num_param(parameters)))
986 goto out;
987
988 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
989 &arg1_type) || 0 >= arg1)
990 {
991 goto out;
992 }
993
994 if (2 == nparams)
995 {
996 int time_shift = 0;
997 zbx_value_type_t time_shift_type = ZBX_VALUE_SECONDS;
998
999 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL,
1000 &time_shift, &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type || 0 > time_shift)
1001 {
1002 goto out;
1003 }
1004
1005 now -= time_shift;
1006 }
1007
1008 switch (arg1_type)
1009 {
1010 case ZBX_VALUE_SECONDS:
1011 seconds = arg1;
1012 break;
1013 case ZBX_VALUE_NVALUES:
1014 nvalues = arg1;
1015 break;
1016 default:
1017 THIS_SHOULD_NEVER_HAPPEN;
1018 }
1019
1020 if (FAIL == zbx_vc_get_value_range(item->itemid, item->value_type, &values, seconds, nvalues, now))
1021 goto out;
1022
1023 if (0 < values.values_num)
1024 {
1025 int index = 0;
1026
1027 if (ITEM_VALUE_TYPE_UINT64 == item->value_type)
1028 {
1029 for (i = 1; i < values.values_num; i++)
1030 {
1031 if (values.values[i].value.ui64 < values.values[index].value.ui64)
1032 index = i;
1033 }
1034 }
1035 else
1036 {
1037 for (i = 1; i < values.values_num; i++)
1038 {
1039 if (values.values[i].value.dbl < values.values[index].value.dbl)
1040 index = i;
1041 }
1042 }
1043 zbx_vc_history_value2str(value, MAX_BUFFER_LEN, &values.values[index].value, item->value_type);
1044
1045 ret = SUCCEED;
1046 }
1047 else
1048 zabbix_log(LOG_LEVEL_DEBUG, "result for MIN is empty");
1049 out:
1050 zbx_history_record_vector_destroy(&values, item->value_type);
1051
1052 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1053
1054 return ret;
1055 }
1056
1057 /******************************************************************************
1058 * *
1059 * Function: evaluate_MAX *
1060 * *
1061 * Purpose: evaluate function 'max' for the item *
1062 * *
1063 * Parameters: item - item (performance metric) *
1064 * parameters - number of seconds/values and time shift (optional)*
1065 * *
1066 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1067 * FAIL - failed to evaluate function *
1068 * *
1069 ******************************************************************************/
evaluate_MAX(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now)1070 static int evaluate_MAX(char *value, DC_ITEM *item, const char *function, const char *parameters, time_t now)
1071 {
1072 const char *__function_name = "evaluate_MAX";
1073 int nparams, arg1, ret = FAIL, i, seconds = 0, nvalues = 0;
1074 zbx_value_type_t arg1_type;
1075 zbx_vector_history_record_t values;
1076
1077 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1078
1079 zbx_history_record_vector_create(&values);
1080
1081 if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
1082 goto out;
1083
1084 if (2 < (nparams = num_param(parameters)))
1085 goto out;
1086
1087 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
1088 &arg1_type) || 0 >= arg1)
1089 {
1090 goto out;
1091 }
1092
1093 if (2 == nparams)
1094 {
1095 int time_shift = 0;
1096 zbx_value_type_t time_shift_type = ZBX_VALUE_SECONDS;
1097
1098 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL,
1099 &time_shift, &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type || 0 > time_shift)
1100 {
1101 goto out;
1102 }
1103
1104 now -= time_shift;
1105 }
1106
1107 switch (arg1_type)
1108 {
1109 case ZBX_VALUE_SECONDS:
1110 seconds = arg1;
1111 break;
1112 case ZBX_VALUE_NVALUES:
1113 nvalues = arg1;
1114 break;
1115 default:
1116 THIS_SHOULD_NEVER_HAPPEN;
1117 }
1118
1119 if (FAIL == zbx_vc_get_value_range(item->itemid, item->value_type, &values, seconds, nvalues, now))
1120 goto out;
1121
1122 if (0 < values.values_num)
1123 {
1124 int index = 0;
1125
1126 if (ITEM_VALUE_TYPE_UINT64 == item->value_type)
1127 {
1128 for (i = 1; i < values.values_num; i++)
1129 {
1130 if (values.values[i].value.ui64 > values.values[index].value.ui64)
1131 index = i;
1132 }
1133 }
1134 else
1135 {
1136 for (i = 1; i < values.values_num; i++)
1137 {
1138 if (values.values[i].value.dbl > values.values[index].value.dbl)
1139 index = i;
1140 }
1141 }
1142 zbx_vc_history_value2str(value, MAX_BUFFER_LEN, &values.values[index].value, item->value_type);
1143
1144 ret = SUCCEED;
1145 }
1146 else
1147 zabbix_log(LOG_LEVEL_DEBUG, "result for MAX is empty");
1148 out:
1149 zbx_history_record_vector_destroy(&values, item->value_type);
1150
1151 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1152
1153 return ret;
1154 }
1155
__history_record_float_compare(const zbx_history_record_t * d1,const zbx_history_record_t * d2)1156 static int __history_record_float_compare(const zbx_history_record_t *d1, const zbx_history_record_t *d2)
1157 {
1158 ZBX_RETURN_IF_NOT_EQUAL(d1->value.dbl, d2->value.dbl);
1159
1160 return 0;
1161 }
1162
__history_record_uint64_compare(const zbx_history_record_t * d1,const zbx_history_record_t * d2)1163 static int __history_record_uint64_compare(const zbx_history_record_t *d1, const zbx_history_record_t *d2)
1164 {
1165 ZBX_RETURN_IF_NOT_EQUAL(d1->value.ui64, d2->value.ui64);
1166
1167 return 0;
1168 }
1169
1170 /******************************************************************************
1171 * *
1172 * Function: evaluate_PERCENTILE *
1173 * *
1174 * Purpose: evaluate function 'percentile' for the item *
1175 * *
1176 * Parameters: item - [IN] item (performance metric) *
1177 * parameters - [IN] seconds/values, time shift (optional), *
1178 * percentage *
1179 * *
1180 * Return value: SUCCEED - evaluated successfully, result is stored in *
1181 * 'value' *
1182 * FAIL - failed to evaluate function *
1183 * *
1184 ******************************************************************************/
evaluate_PERCENTILE(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now,char ** error)1185 static int evaluate_PERCENTILE(char *value, DC_ITEM *item, const char *function, const char *parameters,
1186 time_t now, char **error)
1187 {
1188 const char *__function_name = "evaluate_PERCENTILE";
1189
1190 int nparams, arg1, time_shift = 0, ret = FAIL, seconds = 0, nvalues = 0;
1191 zbx_value_type_t arg1_type, time_shift_type = ZBX_VALUE_SECONDS;
1192 double percentage;
1193 zbx_vector_history_record_t values;
1194
1195 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1196
1197 zbx_history_record_vector_create(&values);
1198
1199 if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
1200 {
1201 *error = zbx_strdup(*error, "invalid value type");
1202 goto out;
1203 }
1204
1205 if (3 != (nparams = num_param(parameters)))
1206 {
1207 *error = zbx_strdup(*error, 3 < nparams ? "too many parameters" : "invalid number of parameters");
1208 goto out;
1209 }
1210
1211 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
1212 &arg1_type) || 0 >= arg1)
1213 {
1214 *error = zbx_strdup(*error, "invalid first parameter");
1215 goto out;
1216 }
1217
1218 switch (arg1_type)
1219 {
1220 case ZBX_VALUE_SECONDS:
1221 seconds = arg1;
1222 break;
1223 case ZBX_VALUE_NVALUES:
1224 nvalues = arg1;
1225 break;
1226 default:
1227 THIS_SHOULD_NEVER_HAPPEN;
1228 }
1229
1230 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL, &time_shift,
1231 &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type || 0 > time_shift)
1232 {
1233 *error = zbx_strdup(*error, "invalid second parameter");
1234 goto out;
1235 }
1236
1237 now -= time_shift;
1238
1239 if (SUCCEED != get_function_parameter_float(item->host.hostid, parameters, 3, ZBX_FLAG_DOUBLE_PLAIN,
1240 &percentage) || 0.0 > percentage || 100.0 < percentage)
1241 {
1242 *error = zbx_strdup(*error, "invalid third parameter");
1243 goto out;
1244 }
1245
1246 if (FAIL == zbx_vc_get_value_range(item->itemid, item->value_type, &values, seconds, nvalues, now))
1247 goto out;
1248
1249 if (0 < values.values_num)
1250 {
1251 int index;
1252
1253 if (ITEM_VALUE_TYPE_FLOAT == item->value_type)
1254 zbx_vector_history_record_sort(&values, (zbx_compare_func_t)__history_record_float_compare);
1255 else
1256 zbx_vector_history_record_sort(&values, (zbx_compare_func_t)__history_record_uint64_compare);
1257
1258 if (0 == percentage)
1259 index = 1;
1260 else
1261 index = (int)ceil(values.values_num * (percentage / 100));
1262
1263 zbx_vc_history_value2str(value, MAX_BUFFER_LEN, &values.values[index - 1].value, item->value_type);
1264
1265 ret = SUCCEED;
1266 }
1267 else
1268 *error = zbx_strdup(*error, "not enough data");
1269 out:
1270 zbx_history_record_vector_destroy(&values, item->value_type);
1271
1272 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1273
1274 return ret;
1275 }
1276
1277 /******************************************************************************
1278 * *
1279 * Function: evaluate_DELTA *
1280 * *
1281 * Purpose: evaluate function 'delta' for the item *
1282 * *
1283 * Parameters: item - item (performance metric) *
1284 * parameters - number of seconds/values and time shift (optional)*
1285 * *
1286 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1287 * FAIL - failed to evaluate function *
1288 * *
1289 ******************************************************************************/
evaluate_DELTA(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now)1290 static int evaluate_DELTA(char *value, DC_ITEM *item, const char *function, const char *parameters, time_t now)
1291 {
1292 const char *__function_name = "evaluate_DELTA";
1293 int nparams, arg1, ret = FAIL, i, seconds = 0, nvalues = 0;
1294 zbx_value_type_t arg1_type;
1295 zbx_vector_history_record_t values;
1296
1297 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1298
1299 zbx_history_record_vector_create(&values);
1300
1301 if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
1302 goto out;
1303
1304 if (2 < (nparams = num_param(parameters)))
1305 goto out;
1306
1307 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
1308 &arg1_type) || 0 >= arg1)
1309 {
1310 goto out;
1311 }
1312
1313 if (2 == nparams)
1314 {
1315 int time_shift = 0;
1316 zbx_value_type_t time_shift_type = ZBX_VALUE_SECONDS;
1317
1318 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL,
1319 &time_shift, &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type || 0 > time_shift)
1320 {
1321 goto out;
1322 }
1323
1324 now -= time_shift;
1325 }
1326
1327 switch (arg1_type)
1328 {
1329 case ZBX_VALUE_SECONDS:
1330 seconds = arg1;
1331 break;
1332 case ZBX_VALUE_NVALUES:
1333 nvalues = arg1;
1334 break;
1335 default:
1336 THIS_SHOULD_NEVER_HAPPEN;
1337 }
1338
1339 if (FAIL == zbx_vc_get_value_range(item->itemid, item->value_type, &values, seconds, nvalues, now))
1340 goto out;
1341
1342 if (0 < values.values_num)
1343 {
1344 history_value_t result;
1345 int index_min = 0, index_max = 0;
1346
1347 if (ITEM_VALUE_TYPE_UINT64 == item->value_type)
1348 {
1349 for (i = 1; i < values.values_num; i++)
1350 {
1351 if (values.values[i].value.ui64 > values.values[index_max].value.ui64)
1352 index_max = i;
1353
1354 if (values.values[i].value.ui64 < values.values[index_min].value.ui64)
1355 index_min = i;
1356 }
1357
1358 result.ui64 = values.values[index_max].value.ui64 - values.values[index_min].value.ui64;
1359 }
1360 else
1361 {
1362 for (i = 1; i < values.values_num; i++)
1363 {
1364 if (values.values[i].value.dbl > values.values[index_max].value.dbl)
1365 index_max = i;
1366
1367 if (values.values[i].value.dbl < values.values[index_min].value.dbl)
1368 index_min = i;
1369 }
1370
1371 result.dbl = values.values[index_max].value.dbl - values.values[index_min].value.dbl;
1372 }
1373
1374 zbx_vc_history_value2str(value, MAX_BUFFER_LEN, &result, item->value_type);
1375
1376 ret = SUCCEED;
1377 }
1378 else
1379 zabbix_log(LOG_LEVEL_DEBUG, "result for DELTA is empty");
1380 out:
1381 zbx_history_record_vector_destroy(&values, item->value_type);
1382
1383 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1384
1385 return ret;
1386 }
1387
1388 /******************************************************************************
1389 * *
1390 * Function: evaluate_NODATA *
1391 * *
1392 * Purpose: evaluate function 'nodata' for the item *
1393 * *
1394 * Parameters: item - item (performance metric) *
1395 * parameter - number of seconds *
1396 * *
1397 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1398 * FAIL - failed to evaluate function *
1399 * *
1400 ******************************************************************************/
evaluate_NODATA(char * value,DC_ITEM * item,const char * function,const char * parameters,char ** error)1401 static int evaluate_NODATA(char *value, DC_ITEM *item, const char *function, const char *parameters, char **error)
1402 {
1403 const char *__function_name = "evaluate_NODATA";
1404 int arg1, now, ret = FAIL;
1405 zbx_value_type_t arg1_type;
1406 zbx_vector_history_record_t values;
1407
1408 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1409
1410 zbx_history_record_vector_create(&values);
1411
1412 if (1 < num_param(parameters))
1413 {
1414 *error = zbx_strdup(*error, "too many parameters");
1415 goto out;
1416 }
1417
1418 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
1419 &arg1_type) || ZBX_VALUE_SECONDS != arg1_type || 0 >= arg1)
1420 {
1421 *error = zbx_strdup(*error, "invalid first parameter");
1422 goto out;
1423 }
1424
1425 now = (int)time(NULL);
1426
1427 if (SUCCEED == zbx_vc_get_value_range(item->itemid, item->value_type, &values, arg1, 1, now) &&
1428 1 == values.values_num)
1429 {
1430 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1431 }
1432 else
1433 {
1434 int seconds;
1435
1436 if (SUCCEED != DCget_data_expected_from(item->itemid, &seconds))
1437 {
1438 *error = zbx_strdup(*error, "item does not exist, is disabled or belongs to a disabled host");
1439 goto out;
1440 }
1441
1442 if (seconds + arg1 > now)
1443 {
1444 *error = zbx_strdup(*error,
1445 "item does not have enough data after server start or item creation");
1446 goto out;
1447 }
1448
1449 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1450 }
1451
1452 ret = SUCCEED;
1453 out:
1454 zbx_history_record_vector_destroy(&values, item->value_type);
1455
1456 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1457
1458 return ret;
1459 }
1460
1461 /******************************************************************************
1462 * *
1463 * Function: evaluate_ABSCHANGE *
1464 * *
1465 * Purpose: evaluate function 'abschange' for the item *
1466 * *
1467 * Parameters: item - item (performance metric) *
1468 * parameter - number of seconds *
1469 * *
1470 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1471 * FAIL - failed to evaluate function *
1472 * *
1473 ******************************************************************************/
evaluate_ABSCHANGE(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now)1474 static int evaluate_ABSCHANGE(char *value, DC_ITEM *item, const char *function, const char *parameters, time_t now)
1475 {
1476 const char *__function_name = "evaluate_ABSCHANGE";
1477 int ret = FAIL;
1478 zbx_vector_history_record_t values;
1479
1480 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1481
1482 zbx_history_record_vector_create(&values);
1483
1484 if (SUCCEED != zbx_vc_get_value_range(item->itemid, item->value_type, &values, 0, 2, now) ||
1485 2 > values.values_num)
1486 {
1487 goto out;
1488 }
1489
1490 switch (item->value_type)
1491 {
1492 case ITEM_VALUE_TYPE_FLOAT:
1493 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_DBL,
1494 fabs(values.values[0].value.dbl - values.values[1].value.dbl));
1495 break;
1496 case ITEM_VALUE_TYPE_UINT64:
1497 /* to avoid overflow */
1498 if (values.values[0].value.ui64 >= values.values[1].value.ui64)
1499 {
1500 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_UI64,
1501 values.values[0].value.ui64 - values.values[1].value.ui64);
1502 }
1503 else
1504 {
1505 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_UI64,
1506 values.values[1].value.ui64 - values.values[0].value.ui64);
1507 }
1508 break;
1509 case ITEM_VALUE_TYPE_LOG:
1510 if (0 == strcmp(values.values[0].value.log->value, values.values[1].value.log->value))
1511 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1512 else
1513 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1514 break;
1515
1516 case ITEM_VALUE_TYPE_STR:
1517 case ITEM_VALUE_TYPE_TEXT:
1518 if (0 == strcmp(values.values[0].value.str, values.values[1].value.str))
1519 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1520 else
1521 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1522 break;
1523 default:
1524 goto out;
1525 }
1526 ret = SUCCEED;
1527 out:
1528 zbx_history_record_vector_destroy(&values, item->value_type);
1529
1530 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1531
1532 return ret;
1533 }
1534
1535 /******************************************************************************
1536 * *
1537 * Function: evaluate_CHANGE *
1538 * *
1539 * Purpose: evaluate function 'change' for the item *
1540 * *
1541 * Parameters: item - item (performance metric) *
1542 * parameter - number of seconds *
1543 * *
1544 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1545 * FAIL - failed to evaluate function *
1546 * *
1547 ******************************************************************************/
evaluate_CHANGE(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now)1548 static int evaluate_CHANGE(char *value, DC_ITEM *item, const char *function, const char *parameters, time_t now)
1549 {
1550 const char *__function_name = "evaluate_CHANGE";
1551 int ret = FAIL;
1552 zbx_vector_history_record_t values;
1553
1554 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1555
1556 zbx_history_record_vector_create(&values);
1557
1558 if (SUCCEED != zbx_vc_get_value_range(item->itemid, item->value_type, &values, 0, 2, now) ||
1559 2 > values.values_num)
1560 {
1561 goto out;
1562 }
1563
1564 switch (item->value_type)
1565 {
1566 case ITEM_VALUE_TYPE_FLOAT:
1567 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_DBL,
1568 values.values[0].value.dbl - values.values[1].value.dbl);
1569 break;
1570 case ITEM_VALUE_TYPE_UINT64:
1571 /* to avoid overflow */
1572 if (values.values[0].value.ui64 >= values.values[1].value.ui64)
1573 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_UI64,
1574 values.values[0].value.ui64 - values.values[1].value.ui64);
1575 else
1576 zbx_snprintf(value, MAX_BUFFER_LEN, "-" ZBX_FS_UI64,
1577 values.values[1].value.ui64 - values.values[0].value.ui64);
1578 break;
1579 case ITEM_VALUE_TYPE_LOG:
1580 if (0 == strcmp(values.values[0].value.log->value, values.values[1].value.log->value))
1581 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1582 else
1583 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1584 break;
1585
1586 case ITEM_VALUE_TYPE_STR:
1587 case ITEM_VALUE_TYPE_TEXT:
1588 if (0 == strcmp(values.values[0].value.str, values.values[1].value.str))
1589 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1590 else
1591 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1592 break;
1593 default:
1594 goto out;
1595 }
1596
1597 ret = SUCCEED;
1598 out:
1599 zbx_history_record_vector_destroy(&values, item->value_type);
1600
1601 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1602
1603 return ret;
1604 }
1605
1606 /******************************************************************************
1607 * *
1608 * Function: evaluate_DIFF *
1609 * *
1610 * Purpose: evaluate function 'diff' for the item *
1611 * *
1612 * Parameters: item - item (performance metric) *
1613 * parameter - number of seconds *
1614 * *
1615 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1616 * FAIL - failed to evaluate function *
1617 * *
1618 ******************************************************************************/
evaluate_DIFF(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now)1619 static int evaluate_DIFF(char *value, DC_ITEM *item, const char *function, const char *parameters, time_t now)
1620 {
1621 const char *__function_name = "evaluate_DIFF";
1622 int ret = FAIL;
1623 zbx_vector_history_record_t values;
1624
1625 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1626
1627 zbx_history_record_vector_create(&values);
1628
1629 if (SUCCEED != zbx_vc_get_value_range(item->itemid, item->value_type, &values, 0, 2, now) ||
1630 2 > values.values_num)
1631 goto out;
1632
1633 switch (item->value_type)
1634 {
1635 case ITEM_VALUE_TYPE_FLOAT:
1636 if (SUCCEED == zbx_double_compare(values.values[0].value.dbl, values.values[1].value.dbl))
1637 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1638 else
1639 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1640 break;
1641 case ITEM_VALUE_TYPE_UINT64:
1642 if (values.values[0].value.ui64 == values.values[1].value.ui64)
1643 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1644 else
1645 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1646 break;
1647 case ITEM_VALUE_TYPE_LOG:
1648 if (0 == strcmp(values.values[0].value.log->value, values.values[1].value.log->value))
1649 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1650 else
1651 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1652 break;
1653 case ITEM_VALUE_TYPE_STR:
1654 case ITEM_VALUE_TYPE_TEXT:
1655 if (0 == strcmp(values.values[0].value.str, values.values[1].value.str))
1656 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1657 else
1658 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1659 break;
1660 default:
1661 goto out;
1662 }
1663
1664 ret = SUCCEED;
1665 out:
1666 zbx_history_record_vector_destroy(&values, item->value_type);
1667
1668 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1669
1670 return ret;
1671 }
1672
1673 /******************************************************************************
1674 * *
1675 * Function: evaluate_STR *
1676 * *
1677 * Purpose: evaluate function 'str' for the item *
1678 * *
1679 * Parameters: item - item (performance metric) *
1680 * parameters - <string>[,seconds] *
1681 * *
1682 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1683 * FAIL - failed to evaluate function *
1684 * *
1685 ******************************************************************************/
1686
1687 #define ZBX_FUNC_STR 1
1688 #define ZBX_FUNC_REGEXP 2
1689 #define ZBX_FUNC_IREGEXP 3
1690
evaluate_STR_one(int func,zbx_vector_ptr_t * regexps,const char * value,const char * arg1)1691 static int evaluate_STR_one(int func, zbx_vector_ptr_t *regexps, const char *value, const char *arg1)
1692 {
1693 switch (func)
1694 {
1695 case ZBX_FUNC_STR:
1696 if (NULL != strstr(value, arg1))
1697 return SUCCEED;
1698 break;
1699 case ZBX_FUNC_REGEXP:
1700 return regexp_match_ex(regexps, value, arg1, ZBX_CASE_SENSITIVE);
1701 case ZBX_FUNC_IREGEXP:
1702 return regexp_match_ex(regexps, value, arg1, ZBX_IGNORE_CASE);
1703 }
1704
1705 return FAIL;
1706 }
1707
evaluate_STR(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now,char ** error)1708 static int evaluate_STR(char *value, DC_ITEM *item, const char *function, const char *parameters, time_t now,
1709 char **error)
1710 {
1711 const char *__function_name = "evaluate_STR";
1712 char *arg1 = NULL;
1713 int arg2 = 1, func, found = 0, i, ret = FAIL, seconds = 0, nvalues = 0, nparams;
1714 zbx_value_type_t arg2_type = ZBX_VALUE_NVALUES;
1715 zbx_vector_ptr_t regexps;
1716 zbx_vector_history_record_t values;
1717
1718 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1719
1720 zbx_vector_ptr_create(®exps);
1721 zbx_history_record_vector_create(&values);
1722
1723 if (ITEM_VALUE_TYPE_STR != item->value_type && ITEM_VALUE_TYPE_TEXT != item->value_type &&
1724 ITEM_VALUE_TYPE_LOG != item->value_type)
1725 {
1726 goto out;
1727 }
1728
1729 if (0 == strcmp(function, "str"))
1730 func = ZBX_FUNC_STR;
1731 else if (0 == strcmp(function, "regexp"))
1732 func = ZBX_FUNC_REGEXP;
1733 else if (0 == strcmp(function, "iregexp"))
1734 func = ZBX_FUNC_IREGEXP;
1735 else
1736 goto out;
1737
1738 if (2 < (nparams = num_param(parameters)))
1739 goto out;
1740
1741 if (SUCCEED != get_function_parameter_str(item->host.hostid, parameters, 1, &arg1))
1742 goto out;
1743
1744 if (2 == nparams)
1745 {
1746 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL, &arg2,
1747 &arg2_type) || 0 >= arg2)
1748 {
1749 goto out;
1750 }
1751 }
1752
1753 if ((ZBX_FUNC_REGEXP == func || ZBX_FUNC_IREGEXP == func) && '@' == *arg1)
1754 {
1755 DCget_expressions_by_name(®exps, arg1 + 1);
1756
1757 if (0 == regexps.values_num)
1758 {
1759 *error = zbx_dsprintf(*error, "global regular expression \"%s\" does not exist", arg1 + 1);
1760 goto out;
1761 }
1762 }
1763
1764 switch (arg2_type)
1765 {
1766 case ZBX_VALUE_SECONDS:
1767 seconds = arg2;
1768 break;
1769 case ZBX_VALUE_NVALUES:
1770 nvalues = arg2;
1771 break;
1772 default:
1773 THIS_SHOULD_NEVER_HAPPEN;
1774 }
1775
1776 if (FAIL == zbx_vc_get_value_range(item->itemid, item->value_type, &values, seconds, nvalues, now))
1777 goto out;
1778
1779 if (0 != values.values_num)
1780 {
1781 /* at this point the value type can be only str, text or log */
1782 if (ITEM_VALUE_TYPE_LOG == item->value_type)
1783 {
1784 for (i = 0; i < values.values_num; i++)
1785 {
1786 if (SUCCEED == evaluate_STR_one(func, ®exps, values.values[i].value.log->value, arg1))
1787 {
1788 found = 1;
1789 break;
1790 }
1791 }
1792 }
1793 else
1794 {
1795 for (i = 0; i < values.values_num; i++)
1796 {
1797 if (SUCCEED == evaluate_STR_one(func, ®exps, values.values[i].value.str, arg1))
1798 {
1799 found = 1;
1800 break;
1801 }
1802 }
1803 }
1804 }
1805
1806 zbx_snprintf(value, MAX_BUFFER_LEN, "%d", found);
1807 ret = SUCCEED;
1808 out:
1809 zbx_regexp_clean_expressions(®exps);
1810 zbx_vector_ptr_destroy(®exps);
1811
1812 zbx_history_record_vector_destroy(&values, item->value_type);
1813
1814 zbx_free(arg1);
1815
1816 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1817
1818 return ret;
1819 }
1820
1821 #undef ZBX_FUNC_STR
1822 #undef ZBX_FUNC_REGEXP
1823 #undef ZBX_FUNC_IREGEXP
1824
1825 /******************************************************************************
1826 * *
1827 * Function: evaluate_STRLEN *
1828 * *
1829 * Purpose: evaluate function 'strlen' for the item *
1830 * *
1831 * Parameters: value - buffer of size MAX_BUFFER_LEN *
1832 * item - item (performance metric) *
1833 * parameters - Nth last value and time shift (optional) *
1834 * *
1835 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1836 * FAIL - failed to evaluate function *
1837 * *
1838 ******************************************************************************/
evaluate_STRLEN(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now)1839 static int evaluate_STRLEN(char *value, DC_ITEM *item, const char *function, const char *parameters, time_t now)
1840 {
1841 const char *__function_name = "evaluate_STRLEN";
1842 int ret = FAIL;
1843
1844 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1845
1846 if (ITEM_VALUE_TYPE_STR != item->value_type && ITEM_VALUE_TYPE_TEXT != item->value_type &&
1847 ITEM_VALUE_TYPE_LOG != item->value_type)
1848 goto clean;
1849
1850 if (SUCCEED == evaluate_LAST(value, item, "last", parameters, now))
1851 {
1852 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_SIZE_T, (zbx_fs_size_t)zbx_strlen_utf8(value));
1853 ret = SUCCEED;
1854 }
1855 clean:
1856 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1857
1858 return ret;
1859 }
1860
1861 /******************************************************************************
1862 * *
1863 * Function: evaluate_FUZZYTIME *
1864 * *
1865 * Purpose: evaluate function 'fuzzytime' for the item *
1866 * *
1867 * Parameters: item - item (performance metric) *
1868 * parameter - number of seconds *
1869 * *
1870 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1871 * FAIL - failed to evaluate function *
1872 * *
1873 ******************************************************************************/
evaluate_FUZZYTIME(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now)1874 static int evaluate_FUZZYTIME(char *value, DC_ITEM *item, const char *function, const char *parameters, time_t now)
1875 {
1876 const char *__function_name = "evaluate_FUZZYTIME";
1877
1878 int arg1, ret = FAIL;
1879 zbx_value_type_t arg1_type;
1880 zbx_history_record_t vc_value;
1881 zbx_uint64_t fuzlow, fuzhig;
1882 zbx_timespec_t ts = {now, 999999999};
1883
1884 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1885
1886 if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
1887 goto out;
1888
1889 if (1 < num_param(parameters))
1890 goto out;
1891
1892 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
1893 &arg1_type) || 0 >= arg1)
1894 {
1895 goto out;
1896 }
1897
1898 if (ZBX_VALUE_SECONDS != arg1_type || now <= arg1)
1899 goto out;
1900
1901 if (SUCCEED != zbx_vc_get_value(item->itemid, item->value_type, &ts, &vc_value))
1902 goto out;
1903
1904 fuzlow = (int)(now - arg1);
1905 fuzhig = (int)(now + arg1);
1906
1907 if (ITEM_VALUE_TYPE_UINT64 == item->value_type)
1908 {
1909 if (vc_value.value.ui64 >= fuzlow && vc_value.value.ui64 <= fuzhig)
1910 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1911 else
1912 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1913 }
1914 else
1915 {
1916 if (vc_value.value.dbl >= fuzlow && vc_value.value.dbl <= fuzhig)
1917 zbx_strlcpy(value, "1", MAX_BUFFER_LEN);
1918 else
1919 zbx_strlcpy(value, "0", MAX_BUFFER_LEN);
1920 }
1921
1922 zbx_history_record_clear(&vc_value, item->value_type);
1923
1924 ret = SUCCEED;
1925 out:
1926 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1927
1928 return ret;
1929 }
1930
1931 /******************************************************************************
1932 * *
1933 * Function: evaluate_BAND *
1934 * *
1935 * Purpose: evaluate logical bitwise function 'and' for the item *
1936 * *
1937 * Parameters: value - buffer of size MAX_BUFFER_LEN *
1938 * item - item (performance metric) *
1939 * parameters - up to 3 comma-separated fields: *
1940 * (1) same as the 1st parameter for function *
1941 * evaluate_LAST() (see documentation of *
1942 * trigger function last()), *
1943 * (2) mask to bitwise AND with (mandatory), *
1944 * (3) same as the 2nd parameter for function *
1945 * evaluate_LAST() (see documentation of *
1946 * trigger function last()). *
1947 * *
1948 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1949 * FAIL - failed to evaluate function *
1950 * *
1951 ******************************************************************************/
evaluate_BAND(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now)1952 static int evaluate_BAND(char *value, DC_ITEM *item, const char *function, const char *parameters, time_t now)
1953 {
1954 const char *__function_name = "evaluate_BAND";
1955 char *last_parameters = NULL;
1956 int nparams, ret = FAIL;
1957 zbx_uint64_t last_uint64, mask;
1958
1959 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
1960
1961 if (ITEM_VALUE_TYPE_UINT64 != item->value_type)
1962 goto clean;
1963
1964 if (3 < (nparams = num_param(parameters)))
1965 goto clean;
1966
1967 if (SUCCEED != get_function_parameter_uint64(item->host.hostid, parameters, 2, &mask))
1968 goto clean;
1969
1970 /* prepare the 1st and the 3rd parameter for passing to evaluate_LAST() */
1971 last_parameters = zbx_strdup(NULL, parameters);
1972 remove_param(last_parameters, 2);
1973
1974 if (SUCCEED == evaluate_LAST(value, item, "last", last_parameters, now))
1975 {
1976 ZBX_STR2UINT64(last_uint64, value);
1977 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_UI64, last_uint64 & (zbx_uint64_t)mask);
1978 ret = SUCCEED;
1979 }
1980
1981 zbx_free(last_parameters);
1982 clean:
1983 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
1984
1985 return ret;
1986 }
1987
1988 /******************************************************************************
1989 * *
1990 * Function: evaluate_FORECAST *
1991 * *
1992 * Purpose: evaluate function 'forecast' for the item *
1993 * *
1994 * Parameters: item - item (performance metric) *
1995 * parameters - number of seconds/values and time shift (optional)*
1996 * *
1997 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
1998 * FAIL - failed to evaluate function *
1999 * *
2000 ******************************************************************************/
evaluate_FORECAST(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now,char ** error)2001 static int evaluate_FORECAST(char *value, DC_ITEM *item, const char *function, const char *parameters, time_t now,
2002 char **error)
2003 {
2004 const char *__function_name = "evaluate_FORECAST";
2005 char *fit_str = NULL, *mode_str = NULL;
2006 double *t = NULL, *x = NULL;
2007 int nparams, time, arg1, i, ret = FAIL, seconds = 0, nvalues = 0, time_shift = 0;
2008 zbx_value_type_t time_type, time_shift_type = ZBX_VALUE_SECONDS, arg1_type;
2009 unsigned int k = 0;
2010 zbx_vector_history_record_t values;
2011 zbx_timespec_t zero_time;
2012 zbx_fit_t fit;
2013 zbx_mode_t mode;
2014
2015 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2016
2017 zbx_history_record_vector_create(&values);
2018
2019 if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
2020 goto out;
2021
2022 if (5 < (nparams = num_param(parameters)))
2023 goto out;
2024
2025 if (3 > nparams)
2026 goto out;
2027
2028 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
2029 &arg1_type) || 0 >= arg1)
2030 {
2031 goto out;
2032 }
2033
2034 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL, &time_shift,
2035 &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type || 0 > time_shift)
2036 {
2037 goto out;
2038 }
2039
2040 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 3, ZBX_PARAM_MANDATORY, &time,
2041 &time_type) || ZBX_VALUE_SECONDS != time_type)
2042 {
2043 goto out;
2044 }
2045
2046 if (4 <= nparams)
2047 {
2048 if (SUCCEED != get_function_parameter_str(item->host.hostid, parameters, 4, &fit_str) ||
2049 SUCCEED != zbx_fit_code(fit_str, &fit, &k, error))
2050 {
2051 goto out;
2052 }
2053 }
2054 else
2055 {
2056 fit = FIT_LINEAR;
2057 }
2058
2059 if (5 == nparams)
2060 {
2061 if (SUCCEED != get_function_parameter_str(item->host.hostid, parameters, 5, &mode_str) ||
2062 SUCCEED != zbx_mode_code(mode_str, &mode, error))
2063 goto out;
2064 }
2065 else
2066 {
2067 mode = MODE_VALUE;
2068 }
2069
2070 switch (arg1_type)
2071 {
2072 case ZBX_VALUE_SECONDS:
2073 seconds = arg1;
2074 break;
2075 case ZBX_VALUE_NVALUES:
2076 nvalues = arg1;
2077 break;
2078 default:
2079 THIS_SHOULD_NEVER_HAPPEN;
2080 }
2081
2082 if (FAIL == zbx_vc_get_value_range(item->itemid, item->value_type, &values, seconds, nvalues, now - time_shift))
2083 {
2084 *error = zbx_strdup(*error, "unable to get values from value cache");
2085 goto out;
2086 }
2087
2088 if (0 < values.values_num)
2089 {
2090 t = zbx_malloc(t, values.values_num * sizeof(double));
2091 x = zbx_malloc(x, values.values_num * sizeof(double));
2092
2093 zero_time.sec = values.values[values.values_num - 1].timestamp.sec;
2094 zero_time.ns = values.values[values.values_num - 1].timestamp.ns;
2095
2096 if (ITEM_VALUE_TYPE_FLOAT == item->value_type)
2097 {
2098 for (i = 0; i < values.values_num; i++)
2099 {
2100 t[i] = values.values[i].timestamp.sec - zero_time.sec + 1.0e-9 *
2101 (values.values[i].timestamp.ns - zero_time.ns + 1);
2102 x[i] = values.values[i].value.dbl;
2103 }
2104 }
2105 else
2106 {
2107 for (i = 0; i < values.values_num; i++)
2108 {
2109 t[i] = values.values[i].timestamp.sec - zero_time.sec + 1.0e-9 *
2110 (values.values[i].timestamp.ns - zero_time.ns + 1);
2111 x[i] = values.values[i].value.ui64;
2112 }
2113 }
2114
2115 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_DBL, zbx_forecast(t, x, values.values_num,
2116 now - zero_time.sec - 1.0e-9 * (zero_time.ns + 1), time, fit, k, mode));
2117 }
2118 else
2119 {
2120 zabbix_log(LOG_LEVEL_DEBUG, "no data available");
2121 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_DBL, ZBX_MATH_ERROR);
2122 }
2123
2124 ret = SUCCEED;
2125 out:
2126 zbx_history_record_vector_destroy(&values, item->value_type);
2127
2128 zbx_free(fit_str);
2129 zbx_free(mode_str);
2130
2131 zbx_free(t);
2132 zbx_free(x);
2133
2134 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
2135
2136 return ret;
2137 }
2138
2139 /******************************************************************************
2140 * *
2141 * Function: evaluate_TIMELEFT *
2142 * *
2143 * Purpose: evaluate function 'timeleft' for the item *
2144 * *
2145 * Parameters: item - item (performance metric) *
2146 * parameters - number of seconds/values and time shift (optional)*
2147 * *
2148 * Return value: SUCCEED - evaluated successfully, result is stored in 'value'*
2149 * FAIL - failed to evaluate function *
2150 * *
2151 ******************************************************************************/
evaluate_TIMELEFT(char * value,DC_ITEM * item,const char * function,const char * parameters,time_t now,char ** error)2152 static int evaluate_TIMELEFT(char *value, DC_ITEM *item, const char *function, const char *parameters, time_t now,
2153 char **error)
2154 {
2155 const char *__function_name = "evaluate_TIMELEFT";
2156 char *fit_str = NULL;
2157 double *t = NULL, *x = NULL, threshold;
2158 int nparams, arg1, i, ret = FAIL, seconds = 0, nvalues = 0, time_shift = 0;
2159 zbx_value_type_t arg1_type, time_shift_type = ZBX_VALUE_SECONDS;
2160 unsigned k = 0;
2161 zbx_vector_history_record_t values;
2162 zbx_timespec_t zero_time;
2163 zbx_fit_t fit;
2164
2165 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2166
2167 zbx_history_record_vector_create(&values);
2168
2169 if (ITEM_VALUE_TYPE_FLOAT != item->value_type && ITEM_VALUE_TYPE_UINT64 != item->value_type)
2170 goto out;
2171
2172 if (4 < (nparams = num_param(parameters)))
2173 goto out;
2174
2175 if (3 > nparams)
2176 goto out;
2177
2178 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 1, ZBX_PARAM_MANDATORY, &arg1,
2179 &arg1_type) || 0 >= arg1)
2180 {
2181 goto out;
2182 }
2183
2184 if (SUCCEED != get_function_parameter_int(item->host.hostid, parameters, 2, ZBX_PARAM_OPTIONAL, &time_shift,
2185 &time_shift_type) || ZBX_VALUE_SECONDS != time_shift_type || 0 > time_shift)
2186 {
2187 goto out;
2188 }
2189
2190 if (SUCCEED != get_function_parameter_float(item->host.hostid, parameters, 3, ZBX_FLAG_DOUBLE_SUFFIX,
2191 &threshold))
2192 {
2193 goto out;
2194 }
2195
2196 if (4 == nparams)
2197 {
2198 if (SUCCEED != get_function_parameter_str(item->host.hostid, parameters, 4, &fit_str) ||
2199 SUCCEED != zbx_fit_code(fit_str, &fit, &k, error))
2200 {
2201 goto out;
2202 }
2203 }
2204 else
2205 {
2206 fit = FIT_LINEAR;
2207 }
2208
2209 if ((FIT_EXPONENTIAL == fit || FIT_POWER == fit) && 0.0 >= threshold)
2210 {
2211 *error = zbx_strdup(*error, "exponential and power functions are always positive");
2212 goto out;
2213 }
2214
2215 switch (arg1_type)
2216 {
2217 case ZBX_VALUE_SECONDS:
2218 seconds = arg1;
2219 break;
2220 case ZBX_VALUE_NVALUES:
2221 nvalues = arg1;
2222 break;
2223 default:
2224 THIS_SHOULD_NEVER_HAPPEN;
2225 }
2226
2227 if (FAIL == zbx_vc_get_value_range(item->itemid, item->value_type, &values, seconds, nvalues, now - time_shift))
2228 {
2229 *error = zbx_strdup(*error, "unable to get values from value cache");
2230 goto out;
2231 }
2232
2233 if (0 < values.values_num)
2234 {
2235 t = zbx_malloc(t, values.values_num * sizeof(double));
2236 x = zbx_malloc(x, values.values_num * sizeof(double));
2237
2238 zero_time.sec = values.values[values.values_num - 1].timestamp.sec;
2239 zero_time.ns = values.values[values.values_num - 1].timestamp.ns;
2240
2241 if (ITEM_VALUE_TYPE_FLOAT == item->value_type)
2242 {
2243 for (i = 0; i < values.values_num; i++)
2244 {
2245 t[i] = values.values[i].timestamp.sec - zero_time.sec + 1.0e-9 *
2246 (values.values[i].timestamp.ns - zero_time.ns + 1);
2247 x[i] = values.values[i].value.dbl;
2248 }
2249 }
2250 else
2251 {
2252 for (i = 0; i < values.values_num; i++)
2253 {
2254 t[i] = values.values[i].timestamp.sec - zero_time.sec + 1.0e-9 *
2255 (values.values[i].timestamp.ns - zero_time.ns + 1);
2256 x[i] = values.values[i].value.ui64;
2257 }
2258 }
2259
2260 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_DBL, zbx_timeleft(t, x, values.values_num,
2261 now - zero_time.sec - 1.0e-9 * (zero_time.ns + 1), threshold, fit, k));
2262 }
2263 else
2264 {
2265 zabbix_log(LOG_LEVEL_DEBUG, "no data available");
2266 zbx_snprintf(value, MAX_BUFFER_LEN, ZBX_FS_DBL, ZBX_MATH_ERROR);
2267 }
2268
2269 ret = SUCCEED;
2270 out:
2271 zbx_history_record_vector_destroy(&values, item->value_type);
2272
2273 zbx_free(fit_str);
2274
2275 zbx_free(t);
2276 zbx_free(x);
2277
2278 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __function_name, zbx_result_string(ret));
2279
2280 return ret;
2281 }
2282
2283 /******************************************************************************
2284 * *
2285 * Function: evaluate_function *
2286 * *
2287 * Purpose: evaluate function *
2288 * *
2289 * Parameters: item - item to calculate function for *
2290 * function - function (for example, 'max') *
2291 * parameter - parameter of the function *
2292 * *
2293 * Return value: SUCCEED - evaluated successfully, value contains its value *
2294 * FAIL - evaluation failed *
2295 * *
2296 ******************************************************************************/
evaluate_function(char * value,DC_ITEM * item,const char * function,const char * parameter,time_t now,char ** error)2297 int evaluate_function(char *value, DC_ITEM *item, const char *function, const char *parameter, time_t now,
2298 char **error)
2299 {
2300 const char *__function_name = "evaluate_function";
2301
2302 int ret;
2303 struct tm *tm = NULL;
2304
2305 zabbix_log(LOG_LEVEL_DEBUG, "In %s() function:'%s:%s.%s(%s)'", __function_name,
2306 item->host.host, item->key_orig, function, parameter);
2307
2308 *value = '\0';
2309
2310 if (0 == strcmp(function, "last"))
2311 {
2312 ret = evaluate_LAST(value, item, function, parameter, now);
2313 }
2314 else if (0 == strcmp(function, "prev"))
2315 {
2316 ret = evaluate_LAST(value, item, "last", "#2", now);
2317 }
2318 else if (0 == strcmp(function, "min"))
2319 {
2320 ret = evaluate_MIN(value, item, function, parameter, now);
2321 }
2322 else if (0 == strcmp(function, "max"))
2323 {
2324 ret = evaluate_MAX(value, item, function, parameter, now);
2325 }
2326 else if (0 == strcmp(function, "avg"))
2327 {
2328 ret = evaluate_AVG(value, item, function, parameter, now);
2329 }
2330 else if (0 == strcmp(function, "sum"))
2331 {
2332 ret = evaluate_SUM(value, item, function, parameter, now);
2333 }
2334 else if (0 == strcmp(function, "percentile"))
2335 {
2336 ret = evaluate_PERCENTILE(value, item, function, parameter, now, error);
2337 }
2338 else if (0 == strcmp(function, "count"))
2339 {
2340 ret = evaluate_COUNT(value, item, function, parameter, now);
2341 }
2342 else if (0 == strcmp(function, "delta"))
2343 {
2344 ret = evaluate_DELTA(value, item, function, parameter, now);
2345 }
2346 else if (0 == strcmp(function, "nodata"))
2347 {
2348 ret = evaluate_NODATA(value, item, function, parameter, error);
2349 }
2350 else if (0 == strcmp(function, "date"))
2351 {
2352 tm = localtime(&now);
2353 zbx_snprintf(value, MAX_BUFFER_LEN, "%.4d%.2d%.2d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
2354 ret = SUCCEED;
2355 }
2356 else if (0 == strcmp(function, "dayofweek"))
2357 {
2358 tm = localtime(&now);
2359 zbx_snprintf(value, MAX_BUFFER_LEN, "%d", 0 == tm->tm_wday ? 7 : tm->tm_wday);
2360 ret = SUCCEED;
2361 }
2362 else if (0 == strcmp(function, "dayofmonth"))
2363 {
2364 tm = localtime(&now);
2365 zbx_snprintf(value, MAX_BUFFER_LEN, "%d", tm->tm_mday);
2366 ret = SUCCEED;
2367 }
2368 else if (0 == strcmp(function, "time"))
2369 {
2370 tm = localtime(&now);
2371 zbx_snprintf(value, MAX_BUFFER_LEN, "%.2d%.2d%.2d", tm->tm_hour, tm->tm_min, tm->tm_sec);
2372 ret = SUCCEED;
2373 }
2374 else if (0 == strcmp(function, "abschange"))
2375 {
2376 ret = evaluate_ABSCHANGE(value, item, function, parameter, now);
2377 }
2378 else if (0 == strcmp(function, "change"))
2379 {
2380 ret = evaluate_CHANGE(value, item, function, parameter, now);
2381 }
2382 else if (0 == strcmp(function, "diff"))
2383 {
2384 ret = evaluate_DIFF(value, item, function, parameter, now);
2385 }
2386 else if (0 == strcmp(function, "str") || 0 == strcmp(function, "regexp") || 0 == strcmp(function, "iregexp"))
2387 {
2388 ret = evaluate_STR(value, item, function, parameter, now, error);
2389 }
2390 else if (0 == strcmp(function, "strlen"))
2391 {
2392 ret = evaluate_STRLEN(value, item, function, parameter, now);
2393 }
2394 else if (0 == strcmp(function, "now"))
2395 {
2396 zbx_snprintf(value, MAX_BUFFER_LEN, "%d", (int)now);
2397 ret = SUCCEED;
2398 }
2399 else if (0 == strcmp(function, "fuzzytime"))
2400 {
2401 ret = evaluate_FUZZYTIME(value, item, function, parameter, now);
2402 }
2403 else if (0 == strcmp(function, "logeventid"))
2404 {
2405 ret = evaluate_LOGEVENTID(value, item, function, parameter, now, error);
2406 }
2407 else if (0 == strcmp(function, "logseverity"))
2408 {
2409 ret = evaluate_LOGSEVERITY(value, item, function, parameter, now);
2410 }
2411 else if (0 == strcmp(function, "logsource"))
2412 {
2413 ret = evaluate_LOGSOURCE(value, item, function, parameter, now);
2414 }
2415 else if (0 == strcmp(function, "band"))
2416 {
2417 ret = evaluate_BAND(value, item, function, parameter, now);
2418 }
2419 else if (0 == strcmp(function, "forecast"))
2420 {
2421 ret = evaluate_FORECAST(value, item, function, parameter, now, error);
2422 }
2423 else if (0 == strcmp(function, "timeleft"))
2424 {
2425 ret = evaluate_TIMELEFT(value, item, function, parameter, now, error);
2426 }
2427 else
2428 {
2429 *error = zbx_strdup(*error, "function is not supported");
2430 ret = FAIL;
2431 }
2432
2433 if (SUCCEED == ret)
2434 del_zeroes(value);
2435
2436 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s value:'%s'", __function_name, zbx_result_string(ret), value);
2437
2438 return ret;
2439 }
2440
2441 /******************************************************************************
2442 * *
2443 * Function: add_value_suffix_uptime *
2444 * *
2445 * Purpose: Process suffix 'uptime' *
2446 * *
2447 * Parameters: value - value for adjusting *
2448 * max_len - max len of the value *
2449 * *
2450 ******************************************************************************/
add_value_suffix_uptime(char * value,size_t max_len)2451 static void add_value_suffix_uptime(char *value, size_t max_len)
2452 {
2453 const char *__function_name = "add_value_suffix_uptime";
2454
2455 double secs, days;
2456 size_t offset = 0;
2457 int hours, mins;
2458
2459 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2460
2461 if (0 > (secs = round(atof(value))))
2462 {
2463 offset += zbx_snprintf(value, max_len, "-");
2464 secs = -secs;
2465 }
2466
2467 days = floor(secs / SEC_PER_DAY);
2468 secs -= days * SEC_PER_DAY;
2469
2470 hours = (int)(secs / SEC_PER_HOUR);
2471 secs -= (double)hours * SEC_PER_HOUR;
2472
2473 mins = (int)(secs / SEC_PER_MIN);
2474 secs -= (double)mins * SEC_PER_MIN;
2475
2476 if (0 != days)
2477 {
2478 if (1 == days)
2479 offset += zbx_snprintf(value + offset, max_len - offset, ZBX_FS_DBL_EXT(0) " day, ", days);
2480 else
2481 offset += zbx_snprintf(value + offset, max_len - offset, ZBX_FS_DBL_EXT(0) " days, ", days);
2482 }
2483
2484 zbx_snprintf(value + offset, max_len - offset, "%02d:%02d:%02d", hours, mins, (int)secs);
2485
2486 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2487 }
2488
2489 /******************************************************************************
2490 * *
2491 * Function: add_value_suffix_s *
2492 * *
2493 * Purpose: Process suffix 's' *
2494 * *
2495 * Parameters: value - value for adjusting *
2496 * max_len - max len of the value *
2497 * *
2498 ******************************************************************************/
add_value_suffix_s(char * value,size_t max_len)2499 static void add_value_suffix_s(char *value, size_t max_len)
2500 {
2501 const char *__function_name = "add_value_suffix_s";
2502
2503 double secs, n;
2504 size_t offset = 0;
2505 int n_unit = 0;
2506
2507 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2508
2509 secs = atof(value);
2510
2511 if (0 == floor(fabs(secs) * 1000))
2512 {
2513 zbx_snprintf(value, max_len, "%s", (0 == secs ? "0s" : "< 1ms"));
2514 goto clean;
2515 }
2516
2517 if (0 > (secs = round(secs * 1000) / 1000))
2518 {
2519 offset += zbx_snprintf(value, max_len, "-");
2520 secs = -secs;
2521 }
2522 else
2523 *value = '\0';
2524
2525 if (0 != (n = floor(secs / SEC_PER_YEAR)))
2526 {
2527 offset += zbx_snprintf(value + offset, max_len - offset, ZBX_FS_DBL_EXT(0) "y ", n);
2528 secs -= n * SEC_PER_YEAR;
2529 if (0 == n_unit)
2530 n_unit = 4;
2531 }
2532
2533 if (0 != (n = floor(secs / SEC_PER_MONTH)))
2534 {
2535 offset += zbx_snprintf(value + offset, max_len - offset, "%dm ", (int)n);
2536 secs -= n * SEC_PER_MONTH;
2537 if (0 == n_unit)
2538 n_unit = 3;
2539 }
2540
2541 if (0 != (n = floor(secs / SEC_PER_DAY)))
2542 {
2543 offset += zbx_snprintf(value + offset, max_len - offset, "%dd ", (int)n);
2544 secs -= n * SEC_PER_DAY;
2545 if (0 == n_unit)
2546 n_unit = 2;
2547 }
2548
2549 if (4 > n_unit && 0 != (n = floor(secs / SEC_PER_HOUR)))
2550 {
2551 offset += zbx_snprintf(value + offset, max_len - offset, "%dh ", (int)n);
2552 secs -= n * SEC_PER_HOUR;
2553 if (0 == n_unit)
2554 n_unit = 1;
2555 }
2556
2557 if (3 > n_unit && 0 != (n = floor(secs / SEC_PER_MIN)))
2558 {
2559 offset += zbx_snprintf(value + offset, max_len - offset, "%dm ", (int)n);
2560 secs -= n * SEC_PER_MIN;
2561 }
2562
2563 if (2 > n_unit && 0 != (n = floor(secs)))
2564 {
2565 offset += zbx_snprintf(value + offset, max_len - offset, "%ds ", (int)n);
2566 secs -= n;
2567 }
2568
2569 if (1 > n_unit && 0 != (n = round(secs * 1000)))
2570 offset += zbx_snprintf(value + offset, max_len - offset, "%dms", (int)n);
2571
2572 if (0 != offset && ' ' == value[--offset])
2573 value[offset] = '\0';
2574 clean:
2575 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2576 }
2577
2578 /******************************************************************************
2579 * *
2580 * Function: add_value_suffix_normal *
2581 * *
2582 * Purpose: Process normal values and add K,M,G,T *
2583 * *
2584 * Parameters: value - value for adjusting *
2585 * max_len - max len of the value *
2586 * units - units (bps, b, B, etc) *
2587 * *
2588 ******************************************************************************/
add_value_suffix_normal(char * value,size_t max_len,const char * units)2589 static void add_value_suffix_normal(char *value, size_t max_len, const char *units)
2590 {
2591 const char *__function_name = "add_value_suffix_normal";
2592
2593 const char *minus = "";
2594 char kmgt[8];
2595 char tmp[64];
2596 double base;
2597 double value_double;
2598
2599 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2600
2601 if (0 > (value_double = atof(value)))
2602 {
2603 minus = "-";
2604 value_double = -value_double;
2605 }
2606
2607 base = (0 == strcmp(units, "B") || 0 == strcmp(units, "Bps") ? 1024 : 1000);
2608
2609 if (value_double < base || SUCCEED == str_in_list("%,ms,rpm,RPM", units, ','))
2610 {
2611 strscpy(kmgt, "");
2612 }
2613 else if (value_double < base * base)
2614 {
2615 strscpy(kmgt, "K");
2616 value_double /= base;
2617 }
2618 else if (value_double < base * base * base)
2619 {
2620 strscpy(kmgt, "M");
2621 value_double /= base * base;
2622 }
2623 else if (value_double < base * base * base * base)
2624 {
2625 strscpy(kmgt, "G");
2626 value_double /= base * base * base;
2627 }
2628 else
2629 {
2630 strscpy(kmgt, "T");
2631 value_double /= base * base * base * base;
2632 }
2633
2634 if (SUCCEED != zbx_double_compare(round(value_double), value_double))
2635 {
2636 zbx_snprintf(tmp, sizeof(tmp), ZBX_FS_DBL_EXT(2), value_double);
2637 del_zeroes(tmp);
2638 }
2639 else
2640 zbx_snprintf(tmp, sizeof(tmp), ZBX_FS_DBL_EXT(0), value_double);
2641
2642 zbx_snprintf(value, max_len, "%s%s %s%s", minus, tmp, kmgt, units);
2643
2644 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2645 }
2646
2647 /******************************************************************************
2648 * *
2649 * Function: add_value_suffix *
2650 * *
2651 * Purpose: Add suffix for value *
2652 * *
2653 * Parameters: value - value for replacing *
2654 * *
2655 * Return value: SUCCEED - suffix added successfully, value contains new value*
2656 * FAIL - adding failed, value contains old value *
2657 * *
2658 ******************************************************************************/
add_value_suffix(char * value,size_t max_len,const char * units,unsigned char value_type)2659 static void add_value_suffix(char *value, size_t max_len, const char *units, unsigned char value_type)
2660 {
2661 const char *__function_name = "add_value_suffix";
2662
2663 struct tm *local_time;
2664 time_t time;
2665
2666 zabbix_log(LOG_LEVEL_DEBUG, "In %s() value:'%s' units:'%s' value_type:%d",
2667 __function_name, value, units, (int)value_type);
2668
2669 switch (value_type)
2670 {
2671 case ITEM_VALUE_TYPE_UINT64:
2672 if (0 == strcmp(units, "unixtime"))
2673 {
2674 time = (time_t)atoi(value);
2675 local_time = localtime(&time);
2676 strftime(value, max_len, "%Y.%m.%d %H:%M:%S", local_time);
2677 break;
2678 }
2679 case ITEM_VALUE_TYPE_FLOAT:
2680 if (0 == strcmp(units, "s"))
2681 add_value_suffix_s(value, max_len);
2682 else if (0 == strcmp(units, "uptime"))
2683 add_value_suffix_uptime(value, max_len);
2684 else if (0 != strlen(units))
2685 add_value_suffix_normal(value, max_len, units);
2686 break;
2687 default:
2688 ;
2689 }
2690
2691 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() value:'%s'", __function_name, value);
2692 }
2693
2694 /******************************************************************************
2695 * *
2696 * Function: replace_value_by_map *
2697 * *
2698 * Purpose: replace value by mapping value *
2699 * *
2700 * Parameters: value - value for replacing *
2701 * valuemapid - index of value map *
2702 * *
2703 * Return value: SUCCEED - evaluated successfully, value contains new value *
2704 * FAIL - evaluation failed, value contains old value *
2705 * *
2706 ******************************************************************************/
replace_value_by_map(char * value,size_t max_len,zbx_uint64_t valuemapid)2707 static int replace_value_by_map(char *value, size_t max_len, zbx_uint64_t valuemapid)
2708 {
2709 const char *__function_name = "replace_value_by_map";
2710
2711 DB_RESULT result;
2712 DB_ROW row;
2713 char *value_esc, *value_tmp;
2714 int ret = FAIL;
2715
2716 zabbix_log(LOG_LEVEL_DEBUG, "In %s() value:'%s' valuemapid:" ZBX_FS_UI64, __function_name, value, valuemapid);
2717
2718 if (0 == valuemapid)
2719 goto clean;
2720
2721 value_esc = DBdyn_escape_string(value);
2722 result = DBselect(
2723 "select newvalue"
2724 " from mappings"
2725 " where valuemapid=" ZBX_FS_UI64
2726 " and value='%s'",
2727 valuemapid, value_esc);
2728 zbx_free(value_esc);
2729
2730 if (NULL != (row = DBfetch(result)) && FAIL == DBis_null(row[0]))
2731 {
2732 del_zeroes(row[0]);
2733
2734 value_tmp = zbx_dsprintf(NULL, "%s (%s)", row[0], value);
2735 zbx_strlcpy_utf8(value, value_tmp, max_len);
2736 zbx_free(value_tmp);
2737
2738 ret = SUCCEED;
2739 }
2740 DBfree_result(result);
2741 clean:
2742 zabbix_log(LOG_LEVEL_DEBUG, "End of %s() value:'%s'", __function_name, value);
2743
2744 return ret;
2745 }
2746
2747 /******************************************************************************
2748 * *
2749 * Function: zbx_format_value *
2750 * *
2751 * Purpose: replace value by value mapping or by units *
2752 * *
2753 * Parameters: value - [IN/OUT] value for replacing *
2754 * valuemapid - [IN] identificator of value map *
2755 * units - [IN] units *
2756 * value_type - [IN] value type; ITEM_VALUE_TYPE_* *
2757 * *
2758 ******************************************************************************/
zbx_format_value(char * value,size_t max_len,zbx_uint64_t valuemapid,const char * units,unsigned char value_type)2759 void zbx_format_value(char *value, size_t max_len, zbx_uint64_t valuemapid,
2760 const char *units, unsigned char value_type)
2761 {
2762 const char *__function_name = "zbx_format_value";
2763
2764 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __function_name);
2765
2766 switch (value_type)
2767 {
2768 case ITEM_VALUE_TYPE_STR:
2769 replace_value_by_map(value, max_len, valuemapid);
2770 break;
2771 case ITEM_VALUE_TYPE_FLOAT:
2772 del_zeroes(value);
2773 case ITEM_VALUE_TYPE_UINT64:
2774 if (SUCCEED != replace_value_by_map(value, max_len, valuemapid))
2775 add_value_suffix(value, max_len, units, value_type);
2776 break;
2777 default:
2778 ;
2779 }
2780
2781 zabbix_log(LOG_LEVEL_DEBUG, "End of %s()", __function_name);
2782 }
2783
2784 /******************************************************************************
2785 * *
2786 * Function: evaluate_macro_function *
2787 * *
2788 * Purpose: evaluate function used as a macro (e.g., in notifications) *
2789 * *
2790 * Parameters: value - [OUT] evaluation result (if it's successful) *
2791 * host - [IN] host the key belongs to *
2792 * key - [IN] item's key *
2793 * (for example, 'system.cpu.load[,avg1]') *
2794 * function - [IN] function name (for example, 'max') *
2795 * parameter - [IN] function parameter list *
2796 * *
2797 * Return value: SUCCEED - evaluated successfully, value contains its value *
2798 * FAIL - evaluation failed *
2799 * *
2800 * Comments: used for evaluation of notification macros *
2801 * output buffer size should be MAX_BUFFER_LEN *
2802 * *
2803 ******************************************************************************/
evaluate_macro_function(char * value,const char * host,const char * key,const char * function,const char * parameter)2804 int evaluate_macro_function(char *value, const char *host, const char *key, const char *function, const char *parameter)
2805 {
2806 const char *__function_name = "evaluate_macro_function";
2807
2808 zbx_host_key_t host_key = {host, key};
2809 DC_ITEM item;
2810 char *error = NULL;
2811 int ret = FAIL, errcode;
2812
2813 zabbix_log(LOG_LEVEL_DEBUG, "In %s() function:'%s:%s.%s(%s)'", __function_name, host, key, function, parameter);
2814
2815 DCconfig_get_items_by_keys(&item, &host_key, &errcode, 1);
2816
2817 if (SUCCEED != errcode)
2818 {
2819 zabbix_log(LOG_LEVEL_DEBUG,
2820 "cannot evaluate function \"%s:%s.%s(%s)\": item does not exist",
2821 host, key, function, parameter);
2822 goto out;
2823 }
2824
2825 if (SUCCEED == (ret = evaluate_function(value, &item, function, parameter, time(NULL), &error)))
2826 {
2827 if (SUCCEED == str_in_list("last,prev", function, ','))
2828 {
2829 zbx_format_value(value, MAX_BUFFER_LEN, item.valuemapid, item.units, item.value_type);
2830 }
2831 else if (SUCCEED == str_in_list("abschange,avg,change,delta,max,min,percentile,sum,forecast", function, ','))
2832 {
2833 switch (item.value_type)
2834 {
2835 case ITEM_VALUE_TYPE_FLOAT:
2836 case ITEM_VALUE_TYPE_UINT64:
2837 add_value_suffix(value, MAX_BUFFER_LEN, item.units, item.value_type);
2838 break;
2839 default:
2840 ;
2841 }
2842 }
2843 else if (SUCCEED == str_in_list("timeleft", function, ','))
2844 {
2845 add_value_suffix(value, MAX_BUFFER_LEN, "s", ITEM_VALUE_TYPE_FLOAT);
2846 }
2847 }
2848
2849 zbx_free(error);
2850 out:
2851 DCconfig_clean_items(&item, &errcode, 1);
2852
2853 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s value:'%s'", __function_name, zbx_result_string(ret), value);
2854
2855 return ret;
2856 }
2857