mirror of
https://github.com/netdata/netdata.git
synced 2025-04-06 14:35:32 +00:00
better randomness for heartbeat (#18930)
* add 10ms buffering to streaming senders * queue for 1ms * added jitter to heartbeat and sender * remove jitter and add os_random in libnetdata * cleanup * cleanup * fix random for all operating systems * simpler random number generator * make microsleep wait at least 1 nsec * detect random number generators * use libnetdata os_random() * use the buffer versions of the random generators; fallback to using random() * provide random functions per size * getrandom() can fail; handle this case too * fix for wrong params
This commit is contained in:
parent
1635f9bb35
commit
4aba1a3c07
13 changed files with 326 additions and 54 deletions
|
@ -388,6 +388,9 @@ check_function_exists(sched_get_priority_max HAVE_SCHED_GET_PRIORITY_MAX)
|
|||
check_function_exists(close_range HAVE_CLOSE_RANGE)
|
||||
check_function_exists(backtrace HAVE_BACKTRACE)
|
||||
|
||||
check_function_exists(arc4random_buf HAVE_ARC4RANDOM_BUF)
|
||||
check_function_exists(getrandom HAVE_GETRANDOM)
|
||||
|
||||
#
|
||||
# check source compilation
|
||||
#
|
||||
|
@ -539,6 +542,17 @@ int my_function() {
|
|||
}
|
||||
" HAVE_FUNC_ATTRIBUTE_WARN_UNUSED_RESULT)
|
||||
|
||||
# Windows MSVCRT random number generator
|
||||
# used only when compiling natively (not MSYS/CYGWIN)
|
||||
check_c_source_compiles("
|
||||
#define _CRT_RAND_S
|
||||
#include <stdlib.h>
|
||||
int main() {
|
||||
unsigned int x;
|
||||
return rand_s(&x);
|
||||
}
|
||||
" HAVE_RAND_S)
|
||||
|
||||
if(OS_FREEBSD OR OS_MACOS)
|
||||
set(HAVE_BUILTIN_ATOMICS True)
|
||||
endif()
|
||||
|
@ -759,8 +773,8 @@ set(LIBNETDATA_FILES
|
|||
src/libnetdata/os/os-windows-wrappers.h
|
||||
src/libnetdata/os/get_system_cpus.c
|
||||
src/libnetdata/os/get_system_cpus.h
|
||||
src/libnetdata/os/tinysleep.c
|
||||
src/libnetdata/os/tinysleep.h
|
||||
src/libnetdata/os/sleep.c
|
||||
src/libnetdata/os/sleep.h
|
||||
src/libnetdata/os/uuid_generate.c
|
||||
src/libnetdata/os/uuid_generate.h
|
||||
src/libnetdata/os/setenv.c
|
||||
|
@ -862,6 +876,8 @@ set(LIBNETDATA_FILES
|
|||
src/libnetdata/log/nd_log-to-windows-common.h
|
||||
src/libnetdata/common.h
|
||||
src/libnetdata/xxHash/xxhash.h
|
||||
src/libnetdata/os/random.c
|
||||
src/libnetdata/os/random.h
|
||||
)
|
||||
|
||||
if(ENABLE_PLUGIN_EBPF)
|
||||
|
|
|
@ -69,6 +69,10 @@
|
|||
#cmakedefine HAVE_DLSYM
|
||||
#cmakedefine HAVE_LIBCURL
|
||||
|
||||
#cmakedefine HAVE_ARC4RANDOM_BUF
|
||||
#cmakedefine HAVE_RAND_S
|
||||
#cmakedefine HAVE_GETRANDOM
|
||||
|
||||
#cmakedefine HAVE_BACKTRACE
|
||||
#cmakedefine HAVE_CLOSE_RANGE
|
||||
#cmakedefine HAVE_SCHED_GETSCHEDULER
|
||||
|
|
|
@ -342,15 +342,13 @@ unsigned long int aclk_tbeb_delay(int reset, int base, unsigned long int min, un
|
|||
|
||||
attempt++;
|
||||
|
||||
if (attempt == 0) {
|
||||
srandom(time(NULL));
|
||||
if (attempt == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long int delay = pow(base, attempt - 1);
|
||||
delay *= MSEC_PER_SEC;
|
||||
|
||||
delay += (random() % (MAX(1000, delay/2)));
|
||||
delay += (os_random32() % (MAX(1000, delay/2)));
|
||||
|
||||
if (delay <= min * MSEC_PER_SEC)
|
||||
return min;
|
||||
|
|
|
@ -260,6 +260,9 @@ void sleep_to_absolute_time(usec_t usec) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#define HEARTBEAT_MIN_OFFSET_UT (150 * USEC_PER_MS)
|
||||
#define HEARTBEAT_RANDOM_OFFSET_UT (350 * USEC_PER_MS)
|
||||
|
||||
#define HEARTBEAT_ALIGNMENT_STATISTICS_SIZE 20
|
||||
static SPINLOCK heartbeat_alignment_spinlock = NETDATA_SPINLOCK_INITIALIZER;
|
||||
static size_t heartbeat_alignment_id = 0;
|
||||
|
@ -306,22 +309,27 @@ void heartbeat_statistics(usec_t *min_ptr, usec_t *max_ptr, usec_t *average_ptr,
|
|||
memcpy(old, current, sizeof(struct heartbeat_thread_statistics) * HEARTBEAT_ALIGNMENT_STATISTICS_SIZE);
|
||||
}
|
||||
|
||||
static usec_t heartbeat_randomness(usec_t step __maybe_unused, size_t statistics_id) {
|
||||
static XXH64_hash_t heartbeat_hash(usec_t step, size_t statistics_id) {
|
||||
struct {
|
||||
usec_t step;
|
||||
pid_t pid;
|
||||
pid_t tid;
|
||||
usec_t now_ut;
|
||||
size_t statistics_id;
|
||||
char tag[ND_THREAD_TAG_MAX + 1];
|
||||
} key = {
|
||||
.step = step,
|
||||
.pid = getpid(),
|
||||
.tid = os_gettid(),
|
||||
.now_ut = now_realtime_usec(),
|
||||
.statistics_id = statistics_id,
|
||||
};
|
||||
strncpyz(key.tag, nd_thread_tag(), sizeof(key.tag) - 1);
|
||||
XXH64_hash_t hash = XXH3_64bits(&key, sizeof(key));
|
||||
usec_t offset_ut = (100 * USEC_PER_MS) + (hash % (400 * USEC_PER_MS));
|
||||
return XXH3_64bits(&key, sizeof(key));
|
||||
}
|
||||
|
||||
static usec_t heartbeat_randomness(XXH64_hash_t hash) {
|
||||
usec_t offset_ut = HEARTBEAT_MIN_OFFSET_UT + (hash % HEARTBEAT_RANDOM_OFFSET_UT);
|
||||
|
||||
// Calculate the scheduler tick interval in microseconds
|
||||
usec_t scheduler_step_ut = USEC_PER_SEC / (usec_t)system_hz;
|
||||
|
@ -345,7 +353,8 @@ inline void heartbeat_init(heartbeat_t *hb, usec_t step) {
|
|||
|
||||
hb->step = step;
|
||||
hb->realtime = 0ULL;
|
||||
hb->randomness = heartbeat_randomness(hb->step, hb->statistics_id);
|
||||
hb->hash = heartbeat_hash(hb->step, hb->statistics_id);
|
||||
hb->randomness = heartbeat_randomness(hb->hash);
|
||||
|
||||
if(hb->statistics_id < HEARTBEAT_ALIGNMENT_STATISTICS_SIZE) {
|
||||
heartbeat_alignment_values[hb->statistics_id].dt = 0;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#define NETDATA_CLOCKS_H 1
|
||||
|
||||
#include "../libnetdata.h"
|
||||
#include "libnetdata/os/random.h"
|
||||
|
||||
#ifndef HAVE_CLOCK_GETTIME
|
||||
struct timespec {
|
||||
|
@ -30,6 +31,7 @@ typedef struct heartbeat {
|
|||
usec_t realtime;
|
||||
usec_t randomness;
|
||||
size_t statistics_id;
|
||||
XXH64_hash_t hash;
|
||||
} heartbeat_t;
|
||||
|
||||
/* Linux value is as good as any other */
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <sys/syscall.h>
|
||||
#endif
|
||||
|
||||
#include "random.h"
|
||||
#include "timestamps.h"
|
||||
#include "setproctitle.h"
|
||||
#include "close_range.h"
|
||||
|
@ -17,7 +18,7 @@
|
|||
#include "gettid.h"
|
||||
#include "get_pid_max.h"
|
||||
#include "get_system_cpus.h"
|
||||
#include "tinysleep.h"
|
||||
#include "sleep.h"
|
||||
#include "uuid_generate.h"
|
||||
#include "setenv.h"
|
||||
#include "os-freebsd-wrappers.h"
|
||||
|
|
214
src/libnetdata/os/random.c
Normal file
214
src/libnetdata/os/random.c
Normal file
|
@ -0,0 +1,214 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "libnetdata/libnetdata.h"
|
||||
|
||||
#if !defined(HAVE_ARC4RANDOM_BUF) && !defined(HAVE_RAND_S)
|
||||
static SPINLOCK random_lock = NETDATA_SPINLOCK_INITIALIZER;
|
||||
static __attribute__((constructor)) void seed_random() {
|
||||
// Use current time and process ID to create a high-entropy seed
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
uint32_t seed = (uint32_t)(tv.tv_sec ^ tv.tv_usec ^ getpid());
|
||||
|
||||
// Seed the random number generator
|
||||
srandom(seed);
|
||||
}
|
||||
|
||||
#if defined(HAVE_GETRANDOM)
|
||||
#include <sys/random.h>
|
||||
void getrandom_helper(void *buf, size_t buflen) {
|
||||
ssize_t result;
|
||||
while (buflen > 0) {
|
||||
result = getrandom(buf, buflen, 0);
|
||||
if (result == -1) {
|
||||
if (errno == EINTR) {
|
||||
// Interrupted, retry
|
||||
continue;
|
||||
} else if (errno == EAGAIN) {
|
||||
// Insufficient entropy; wait and retry
|
||||
tinysleep();
|
||||
continue;
|
||||
} else {
|
||||
// Fallback to using random() with a spinlock
|
||||
spinlock_lock(&random_lock);
|
||||
while (buflen > 0) {
|
||||
if (buflen >= sizeof(uint32_t)) {
|
||||
// Generate 4 bytes at a time
|
||||
uint32_t temp = random();
|
||||
memcpy(buf, &temp, sizeof(uint32_t));
|
||||
buf = (uint8_t *)buf + sizeof(uint32_t);
|
||||
buflen -= sizeof(uint32_t);
|
||||
} else if (buflen >= sizeof(uint16_t)) {
|
||||
// Generate 2 bytes at a time
|
||||
uint16_t temp = random();
|
||||
memcpy(buf, &temp, sizeof(uint16_t));
|
||||
buf = (uint8_t *)buf + sizeof(uint16_t);
|
||||
buflen -= sizeof(uint16_t);
|
||||
} else {
|
||||
// Generate remaining bytes
|
||||
uint32_t temp = random();
|
||||
for (size_t i = 0; i < buflen; i++) {
|
||||
((uint8_t *)buf)[i] = temp & 0xFF;
|
||||
temp >>= 8;
|
||||
}
|
||||
buflen = 0;
|
||||
}
|
||||
}
|
||||
spinlock_unlock(&random_lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
buf = (uint8_t *)buf + result;
|
||||
buflen -= result;
|
||||
}
|
||||
}
|
||||
#endif // HAVE_GETRANDOM
|
||||
#endif // !HAVE_ARC4RANDOM_BUF && !HAVE_RAND_S
|
||||
|
||||
// return a random number 0 to max - 1
|
||||
uint64_t os_random(uint64_t max) {
|
||||
if (max <= 1) return 0;
|
||||
|
||||
uint64_t value;
|
||||
|
||||
#if defined(HAVE_ARC4RANDOM_BUF)
|
||||
if (max <= UINT8_MAX) {
|
||||
uint8_t v;
|
||||
arc4random_buf(&v, sizeof(v));
|
||||
value = v;
|
||||
} else if(max <= UINT16_MAX) {
|
||||
uint16_t v;
|
||||
arc4random_buf(&v, sizeof(v));
|
||||
value = v;
|
||||
} else if (max <= UINT32_MAX) {
|
||||
uint32_t v;
|
||||
arc4random_buf(&v, sizeof(v));
|
||||
value = v;
|
||||
} else
|
||||
arc4random_buf(&value, sizeof(value));
|
||||
|
||||
#elif defined(HAVE_RAND_S)
|
||||
if (max <= UINT_MAX) {
|
||||
unsigned int temp;
|
||||
rand_s(&temp);
|
||||
value = temp;
|
||||
} else {
|
||||
unsigned int temp_lo, temp_hi;
|
||||
rand_s(&temp_lo);
|
||||
rand_s(&temp_hi);
|
||||
value = ((uint64_t)temp_hi << 32) + (uint64_t)temp_lo;
|
||||
}
|
||||
|
||||
#elif defined(HAVE_GETRANDOM)
|
||||
if (max <= UINT8_MAX) {
|
||||
uint8_t v;
|
||||
getrandom_helper(&v, sizeof(v));
|
||||
value = v;
|
||||
} else if(max <= UINT16_MAX) {
|
||||
uint16_t v;
|
||||
getrandom_helper(&v, sizeof(v));
|
||||
value = v;
|
||||
} else if (max <= UINT32_MAX) {
|
||||
uint32_t v;
|
||||
getrandom_helper(&v, sizeof(v));
|
||||
value = v;
|
||||
} else
|
||||
getrandom_helper(&value, sizeof(value));
|
||||
|
||||
#else
|
||||
spinlock_lock(&random_lock);
|
||||
if(max <= INT32_MAX)
|
||||
value = random();
|
||||
else
|
||||
value = ((uint64_t) random() << 33) | ((uint64_t) random() << 2) | (random() & 0x3);
|
||||
spinlock_unlock(&random_lock);
|
||||
#endif
|
||||
|
||||
return value % max;
|
||||
}
|
||||
|
||||
// Generate an 8-bit random number
|
||||
uint8_t os_random8(void) {
|
||||
uint8_t value;
|
||||
|
||||
#if defined(HAVE_ARC4RANDOM_BUF)
|
||||
arc4random_buf(&value, sizeof(value));
|
||||
#elif defined(HAVE_GETRANDOM)
|
||||
getrandom_helper(&value, sizeof(value));
|
||||
#elif defined(HAVE_RAND_S)
|
||||
unsigned int temp;
|
||||
rand_s(&temp);
|
||||
value = (uint8_t)temp;
|
||||
#else
|
||||
spinlock_lock(&random_lock);
|
||||
value = (uint8_t)random();
|
||||
spinlock_unlock(&random_lock);
|
||||
#endif
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// Generate a 16-bit random number
|
||||
uint16_t os_random16(void) {
|
||||
uint16_t value;
|
||||
|
||||
#if defined(HAVE_ARC4RANDOM_BUF)
|
||||
arc4random_buf(&value, sizeof(value));
|
||||
#elif defined(HAVE_GETRANDOM)
|
||||
getrandom_helper(&value, sizeof(value));
|
||||
#elif defined(HAVE_RAND_S)
|
||||
unsigned int temp;
|
||||
rand_s(&temp);
|
||||
value = (uint16_t)temp;
|
||||
#else
|
||||
spinlock_lock(&random_lock);
|
||||
value = (uint16_t)random();
|
||||
spinlock_unlock(&random_lock);
|
||||
#endif
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// Generate a 32-bit random number
|
||||
uint32_t os_random32(void) {
|
||||
uint32_t value;
|
||||
|
||||
#if defined(HAVE_ARC4RANDOM_BUF)
|
||||
arc4random_buf(&value, sizeof(value));
|
||||
#elif defined(HAVE_GETRANDOM)
|
||||
getrandom_helper(&value, sizeof(value));
|
||||
#elif defined(HAVE_RAND_S)
|
||||
unsigned int temp;
|
||||
rand_s(&temp);
|
||||
value = temp;
|
||||
#else
|
||||
spinlock_lock(&random_lock);
|
||||
value = random();
|
||||
spinlock_unlock(&random_lock);
|
||||
#endif
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// Generate a 64-bit random number
|
||||
uint64_t os_random64(void) {
|
||||
uint64_t value;
|
||||
|
||||
#if defined(HAVE_ARC4RANDOM_BUF)
|
||||
arc4random_buf(&value, sizeof(value));
|
||||
#elif defined(HAVE_GETRANDOM)
|
||||
getrandom_helper(&value, sizeof(value));
|
||||
#elif defined(HAVE_RAND_S)
|
||||
unsigned int temp_lo, temp_hi;
|
||||
rand_s(&temp_lo);
|
||||
rand_s(&temp_hi);
|
||||
value = ((uint64_t)temp_hi << 32) | (uint64_t)temp_lo;
|
||||
#else
|
||||
spinlock_lock(&random_lock);
|
||||
value = ((uint64_t)random() << 33) | ((uint64_t)random() << 2) | (random() & 0x3);
|
||||
spinlock_unlock(&random_lock);
|
||||
#endif
|
||||
|
||||
return value;
|
||||
}
|
16
src/libnetdata/os/random.h
Normal file
16
src/libnetdata/os/random.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef NETDATA_RANDOM_H
|
||||
#define NETDATA_RANDOM_H
|
||||
|
||||
#include "libnetdata/common.h"
|
||||
|
||||
// return a random number 0 to max - 1
|
||||
uint64_t os_random(uint64_t max);
|
||||
|
||||
uint8_t os_random8(void);
|
||||
uint16_t os_random16(void);
|
||||
uint32_t os_random32(void);
|
||||
uint64_t os_random64(void);
|
||||
|
||||
#endif //NETDATA_RANDOM_H
|
36
src/libnetdata/os/sleep.c
Normal file
36
src/libnetdata/os/sleep.c
Normal file
|
@ -0,0 +1,36 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "../libnetdata.h"
|
||||
|
||||
#ifdef OS_WINDOWS
|
||||
void tinysleep(void) {
|
||||
Sleep(1);
|
||||
}
|
||||
#else
|
||||
void tinysleep(void) {
|
||||
static const struct timespec ns = { .tv_sec = 0, .tv_nsec = 1 };
|
||||
nanosleep(&ns, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OS_WINDOWS
|
||||
void microsleep(usec_t ut) {
|
||||
size_t ms = ut / USEC_PER_MS + ((ut == 0 || (ut % USEC_PER_MS)) ? 1 : 0);
|
||||
Sleep(ms);
|
||||
}
|
||||
#else
|
||||
void microsleep(usec_t ut) {
|
||||
time_t secs = (time_t)(ut / USEC_PER_SEC);
|
||||
nsec_t nsec = (ut % USEC_PER_SEC) * NSEC_PER_USEC + ((ut == 0) ? 1 : 0);
|
||||
|
||||
struct timespec remaining = {
|
||||
.tv_sec = secs,
|
||||
.tv_nsec = nsec,
|
||||
};
|
||||
|
||||
errno_clear();
|
||||
while (nanosleep(&remaining, &remaining) == -1 && errno == EINTR && (remaining.tv_sec || remaining.tv_nsec)) {
|
||||
// Loop continues if interrupted by a signal
|
||||
}
|
||||
}
|
||||
#endif
|
9
src/libnetdata/os/sleep.h
Normal file
9
src/libnetdata/os/sleep.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef NETDATA_SLEEP_H
|
||||
#define NETDATA_SLEEP_H
|
||||
|
||||
void tinysleep(void);
|
||||
void microsleep(usec_t ut);
|
||||
|
||||
#endif //NETDATA_SLEEP_H
|
|
@ -1,21 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "../libnetdata.h"
|
||||
|
||||
#ifdef OS_WINDOWS
|
||||
void tinysleep(void) {
|
||||
// Improve the system timer resolution to 1 ms
|
||||
timeBeginPeriod(1);
|
||||
|
||||
// Sleep for the desired duration
|
||||
Sleep(1);
|
||||
|
||||
// Reset the system timer resolution
|
||||
timeEndPeriod(1);
|
||||
}
|
||||
#else
|
||||
void tinysleep(void) {
|
||||
static const struct timespec ns = { .tv_sec = 0, .tv_nsec = 1 };
|
||||
nanosleep(&ns, NULL);
|
||||
}
|
||||
#endif
|
|
@ -1,8 +0,0 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#ifndef NETDATA_TINYSLEEP_H
|
||||
#define NETDATA_TINYSLEEP_H
|
||||
|
||||
void tinysleep(void);
|
||||
|
||||
#endif //NETDATA_TINYSLEEP_H
|
|
@ -395,21 +395,17 @@ size_t rrdpush_decompress(struct decompressor_state *state, const char *compress
|
|||
// ----------------------------------------------------------------------------
|
||||
// unit test
|
||||
|
||||
static inline long int my_random (void) {
|
||||
return random();
|
||||
}
|
||||
|
||||
void unittest_generate_random_name(char *dst, size_t size) {
|
||||
if(size < 7)
|
||||
size = 7;
|
||||
|
||||
size_t len = 5 + my_random() % (size - 6);
|
||||
size_t len = 5 + os_random32() % (size - 6);
|
||||
|
||||
for(size_t i = 0; i < len ; i++) {
|
||||
if(my_random() % 2 == 0)
|
||||
dst[i] = 'A' + my_random() % 26;
|
||||
if(os_random8() % 2 == 0)
|
||||
dst[i] = 'A' + os_random8() % 26;
|
||||
else
|
||||
dst[i] = 'a' + my_random() % 26;
|
||||
dst[i] = 'a' + os_random8() % 26;
|
||||
}
|
||||
|
||||
dst[len] = '\0';
|
||||
|
@ -423,9 +419,9 @@ void unittest_generate_message(BUFFER *wb, time_t now_s, size_t counter) {
|
|||
time_t point_end_time_s = now_s;
|
||||
time_t wall_clock_time_s = now_s;
|
||||
size_t chart_slot = counter + 1;
|
||||
size_t dimensions = 2 + my_random() % 5;
|
||||
size_t dimensions = 2 + os_random8() % 5;
|
||||
char chart[RRD_ID_LENGTH_MAX + 1] = "name";
|
||||
unittest_generate_random_name(chart, 5 + my_random() % 30);
|
||||
unittest_generate_random_name(chart, 5 + os_random8() % 30);
|
||||
|
||||
buffer_fast_strcat(wb, PLUGINSD_KEYWORD_BEGIN_V2, sizeof(PLUGINSD_KEYWORD_BEGIN_V2) - 1);
|
||||
|
||||
|
@ -451,10 +447,10 @@ void unittest_generate_message(BUFFER *wb, time_t now_s, size_t counter) {
|
|||
for(size_t d = 0; d < dimensions ;d++) {
|
||||
size_t dim_slot = d + 1;
|
||||
char dim_id[RRD_ID_LENGTH_MAX + 1] = "dimension";
|
||||
unittest_generate_random_name(dim_id, 10 + my_random() % 20);
|
||||
int64_t last_collected_value = (my_random() % 2 == 0) ? (int64_t)(counter + d) : (int64_t)my_random();
|
||||
NETDATA_DOUBLE value = (my_random() % 2 == 0) ? (NETDATA_DOUBLE)my_random() / ((NETDATA_DOUBLE)my_random() + 1) : (NETDATA_DOUBLE)last_collected_value;
|
||||
SN_FLAGS flags = (my_random() % 1000 == 0) ? SN_FLAG_NONE : SN_FLAG_NOT_ANOMALOUS;
|
||||
unittest_generate_random_name(dim_id, 10 + os_random8() % 20);
|
||||
int64_t last_collected_value = (os_random8() % 2 == 0) ? (int64_t)(counter + d) : (int64_t)os_random32();
|
||||
NETDATA_DOUBLE value = (os_random8() % 2 == 0) ? (NETDATA_DOUBLE)os_random64() / ((NETDATA_DOUBLE)os_random64() + 1) : (NETDATA_DOUBLE)last_collected_value;
|
||||
SN_FLAGS flags = (os_random16() % 1000 == 0) ? SN_FLAG_NONE : SN_FLAG_NOT_ANOMALOUS;
|
||||
|
||||
buffer_fast_strcat(wb, PLUGINSD_KEYWORD_SET_V2, sizeof(PLUGINSD_KEYWORD_SET_V2) - 1);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue