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 20package zbxlib 21 22/* 23#cgo CFLAGS: -I${SRCDIR}/../../../../../include -I${SRCDIR}/../../../../../build/win32/include 24 25#include "common.h" 26#include "sysinfo.h" 27#include "log.h" 28#include "../src/zabbix_agent/metrics.h" 29#include "../src/zabbix_agent/logfiles/logfiles.h" 30 31extern int CONFIG_EVENTLOG_MAX_LINES_PER_SECOND; 32 33typedef ZBX_ACTIVE_METRIC* ZBX_ACTIVE_METRIC_LP; 34typedef zbx_vector_ptr_t * zbx_vector_ptr_lp_t; 35typedef char * char_lp_t; 36 37void metric_set_refresh(ZBX_ACTIVE_METRIC *metric, int refresh); 38void metric_get_meta(ZBX_ACTIVE_METRIC *metric, zbx_uint64_t *lastlogsize, int *mtime); 39void metric_set_unsupported(ZBX_ACTIVE_METRIC *metric); 40int metric_set_supported(ZBX_ACTIVE_METRIC *metric, zbx_uint64_t lastlogsize_sent, int mtime_sent, 41 zbx_uint64_t lastlogsize_last, int mtime_last); 42 43int process_eventlog_check(char *server, unsigned short port, zbx_vector_ptr_t *regexps, ZBX_ACTIVE_METRIC *metric, 44 zbx_process_value_func_t process_value_cb, zbx_uint64_t *lastlogsize_sent, char **error); 45 46typedef struct 47{ 48 char *value; 49 char *source; 50 int timestamp; 51 int logeventid; 52 int severity; 53 54 int state; 55 zbx_uint64_t lastlogsize; 56} 57eventlog_value_t; 58 59typedef struct 60{ 61 zbx_vector_ptr_t values; 62 int slots; 63} 64eventlog_result_t, *eventlog_result_lp_t; 65 66static eventlog_result_t *new_eventlog_result(int slots) 67{ 68 eventlog_result_t *result; 69 70 result = (eventlog_result_t *)zbx_malloc(NULL, sizeof(eventlog_result_t)); 71 zbx_vector_ptr_create(&result->values); 72 result->slots = slots; 73 return result; 74} 75 76static void add_eventlog_value(eventlog_result_t *result, const char *value, const char *source, int logeventid, int severity, 77 int timestamp, int state, zbx_uint64_t lastlogsize) 78{ 79 eventlog_value_t *log; 80 log = (eventlog_value_t *)zbx_malloc(NULL, sizeof(eventlog_value_t)); 81 log->value = zbx_strdup(NULL, value); 82 log->source = zbx_strdup(NULL, source); 83 log->logeventid = logeventid; 84 log->severity = severity; 85 log->timestamp = timestamp; 86 log->state = state; 87 log->lastlogsize = lastlogsize; 88 zbx_vector_ptr_append(&result->values, log); 89} 90 91static int get_eventlog_value(eventlog_result_t *result, int index, char **value, char **source, int *logeventid, 92 int *severity, int *timestamp, int *state, zbx_uint64_t *lastlogsize) 93{ 94 eventlog_value_t *log; 95 96 if (index == result->values.values_num) 97 return FAIL; 98 99 log = (eventlog_value_t *)result->values.values[index]; 100 *value = log->value; 101 *source = log->source; 102 *logeventid = log->logeventid; 103 *severity = log->severity; 104 *timestamp = log->timestamp; 105 *state = log->state; 106 *lastlogsize = log->lastlogsize; 107 return SUCCEED; 108} 109 110static void free_eventlog_value(eventlog_value_t *log) 111{ 112 zbx_free(log->value); 113 zbx_free(log->source); 114 zbx_free(log); 115} 116 117static void free_eventlog_result(eventlog_result_t *result) 118{ 119 zbx_vector_ptr_clear_ext(&result->values, (zbx_clean_func_t)free_eventlog_value); 120 zbx_vector_ptr_destroy(&result->values); 121 zbx_free(result); 122} 123 124int process_eventlog_value_cb(const char *server, unsigned short port, const char *host, const char *key, 125 const char *value, unsigned char state, zbx_uint64_t *lastlogsize, const int *mtime, 126 unsigned long *timestamp, const char *source, unsigned short *severity, unsigned long *logeventid, 127 unsigned char flags) 128{ 129 eventlog_result_t *result = (eventlog_result_t *)server; 130 if (result->values.values_num == result->slots) 131 return FAIL; 132 133 add_eventlog_value(result, value, source, *logeventid, *severity, *timestamp, state, *lastlogsize); 134 return SUCCEED; 135} 136*/ 137import "C" 138 139import ( 140 "errors" 141 "time" 142 "unsafe" 143) 144 145type EventLogItem struct { 146 LastTs time.Time // the last log value timestamp + 1ns 147 Results []*EventLogResult 148 Output ResultWriter 149} 150 151type EventLogResult struct { 152 Value *string 153 EventSource *string 154 EventID *int 155 EventTimestamp *int 156 EventSeverity *int 157 Ts time.Time 158 Error error 159 LastLogsize uint64 160 Mtime int 161} 162 163func ProcessEventLogCheck(data unsafe.Pointer, item *EventLogItem, refresh int, cblob unsafe.Pointer) { 164 C.metric_set_refresh(C.ZBX_ACTIVE_METRIC_LP(data), C.int(refresh)) 165 166 var clastLogsizeSent, clastLogsizeLast C.zbx_uint64_t 167 var cstate, cmtime C.int 168 C.metric_get_meta(C.ZBX_ACTIVE_METRIC_LP(data), &clastLogsizeSent, &cmtime) 169 clastLogsizeLast = clastLogsizeSent 170 171 result := C.new_eventlog_result(C.int(item.Output.PersistSlotsAvailable())) 172 173 var cerrmsg *C.char 174 ret := C.process_eventlog_check(C.char_lp_t(unsafe.Pointer(result)), 0, C.zbx_vector_ptr_lp_t(cblob), 175 C.ZBX_ACTIVE_METRIC_LP(data), C.zbx_process_value_func_t(C.process_eventlog_value_cb), &clastLogsizeSent, 176 &cerrmsg) 177 178 // add cached results 179 var cvalue, csource *C.char 180 var clogeventid, cseverity, ctimestamp C.int 181 var clastlogsize C.zbx_uint64_t 182 logTs := time.Now() 183 if logTs.Before(item.LastTs) { 184 logTs = item.LastTs 185 } 186 for i := 0; C.get_eventlog_value(result, C.int(i), &cvalue, &csource, &clogeventid, &cseverity, &ctimestamp, &cstate, 187 &clastlogsize) != C.FAIL; i++ { 188 189 var value, source string 190 var logeventid, severity, timestamp int 191 var r EventLogResult 192 if cstate == C.ITEM_STATE_NORMAL { 193 value = C.GoString(cvalue) 194 source = C.GoString(csource) 195 logeventid = int(clogeventid) 196 severity = int(cseverity) 197 timestamp = int(ctimestamp) 198 199 r = EventLogResult{ 200 Value: &value, 201 EventSource: &source, 202 EventID: &logeventid, 203 EventSeverity: &severity, 204 EventTimestamp: ×tamp, 205 Ts: logTs, 206 LastLogsize: uint64(clastlogsize), 207 } 208 209 } else { 210 r = EventLogResult{ 211 Error: errors.New(C.GoString(cvalue)), 212 Ts: logTs, 213 LastLogsize: uint64(clastlogsize), 214 } 215 216 } 217 218 item.Results = append(item.Results, &r) 219 logTs = logTs.Add(time.Nanosecond) 220 } 221 C.free_eventlog_result(result) 222 223 item.LastTs = logTs 224 225 if ret == C.FAIL { 226 C.metric_set_unsupported(C.ZBX_ACTIVE_METRIC_LP(data)) 227 228 var err error 229 if cerrmsg != nil { 230 err = errors.New(C.GoString(cerrmsg)) 231 C.free(unsafe.Pointer(cerrmsg)) 232 } else { 233 err = errors.New("Unknown error.") 234 } 235 result := &EventLogResult{ 236 Ts: time.Now(), 237 Error: err, 238 } 239 item.Results = append(item.Results, result) 240 } else { 241 ret := C.metric_set_supported(C.ZBX_ACTIVE_METRIC_LP(data), clastLogsizeSent, 0, clastLogsizeLast, 0) 242 243 if ret == Succeed { 244 C.metric_get_meta(C.ZBX_ACTIVE_METRIC_LP(data), &clastLogsizeLast, &cmtime) 245 result := EventLogResult{ 246 Ts: time.Now(), 247 LastLogsize: uint64(clastLogsizeLast), 248 } 249 item.Results = append(item.Results, &result) 250 } 251 } 252} 253 254func SetEventlogMaxLinesPerSecond(num int) { 255 C.CONFIG_EVENTLOG_MAX_LINES_PER_SECOND = C.int(num) 256} 257