Compare commits

..
2 Commits
Author SHA1 Message Date
Alex Jaramillo d8d3cdee49 Release v2.0.1
Signed-off-by: Alex Jaramillo <alex.v.jaramillo@intel.com>
2018-09-25 15:57:03 +00:00
Alex Jaramillo 839ee5c126 Retry logic for post failure on boot
This change alters the logic of post telemetry message to backend to
handle cases when the network or name resolution service is not
available when the daemon starts. Currently if a message is not
delivered it will be spooled and it should have to wait 900 seconds
(default value) for a future loop to process this message. With this
change when the daemon is started and is unable to deliver telemetry
messages it will atempt to re-send those messages using a t*t delay in
seconds up to t = 7 (or 1, 4, 9, 16, 25, 36, 49 seconds).

Signed-off-by: Alex Jaramillo <alex.v.jaramillo@intel.com>
2018-09-24 15:18:12 -07:00
4 changed files with 65 additions and 29 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([telemetrics-client], [2.0.0], [https://clearlinux.org/])
AC_INIT([telemetrics-client], [2.0.1], [https://clearlinux.org/])
AC_CONFIG_AUX_DIR([build-aux])
AM_INIT_AUTOMAKE([1.14 -Wall -Werror -Wno-extra-portability foreign subdir-objects])
AM_SILENT_RULES([yes])
+54 -22
View File
@@ -275,10 +275,10 @@ bool post_record_http(char *headers[], char *body)
if (res) {
size_t len = strlen(errorbuf);
if (len) {
telem_log(LOG_ERR, "Failed sending record: %s%s", errorbuf,
telem_log(LOG_DEBUG, "Failed sending record: %s%s", errorbuf,
((errorbuf[len - 1] != '\n') ? "\n" : ""));
} else {
telem_log(LOG_ERR, "Failed sending record: %s\n",
telem_log(LOG_DEBUG, "Failed sending record: %s\n",
curl_easy_strerror(res));
}
} else if (http_response != 201 && http_response != 200) {
@@ -396,12 +396,8 @@ static void rate_limit_checks(TelemPostDaemon *daemon, bool *record_check_passed
}
/* Wrapper for save local copy */
static void apply_retention_policies(TelemPostDaemon *daemon, char *headers[], char *body)
static void apply_retention_policies(TelemPostDaemon *daemon, char *body)
{
time_t temp = time(NULL);
save_entry_to_journal(daemon, temp, headers);
if (daemon->record_retention_enabled) {
save_local_copy(daemon, body);
}
@@ -467,7 +463,7 @@ static bool deliver_record(TelemPostDaemon *daemon, char *headers[], char *body)
return ret;
}
bool process_staged_record(char *filename, TelemPostDaemon *daemon)
bool process_staged_record(char *filename, bool is_retry, TelemPostDaemon *daemon)
{
int k;
bool ret = false;
@@ -506,8 +502,13 @@ bool process_staged_record(char *filename, TelemPostDaemon *daemon)
goto end_processing_file;
}
/** Record retention **/
apply_retention_policies(daemon, headers, body);
/* Retries should not be recorded */
if (is_retry == false) {
/** Journal entry **/
save_entry_to_journal(daemon, current_time, headers);
/** Record retention **/
apply_retention_policies(daemon, body);
}
/** Record delivery **/
if (!daemon->record_server_delivery_enabled) {
@@ -570,20 +571,22 @@ static int directory_dot_filter(const struct dirent *entry)
}
}
void staging_records_loop(TelemPostDaemon *daemon)
int staging_records_loop(TelemPostDaemon *daemon)
{
int ret;
int processed;
int numentries;
struct dirent **namelist;
numentries = scandir(spool_dir_config(), &namelist, directory_dot_filter, NULL);
processed = 0;
if (numentries == 0) {
telem_log(LOG_DEBUG, "No entries in staging\n");
return;
return numentries;
} else if (numentries < 0) {
telem_perror("Error while scanning staging");
return;
return numentries;
}
for (int i = 0; i < numentries; i++) {
@@ -595,8 +598,9 @@ void staging_records_loop(TelemPostDaemon *daemon)
telem_log(LOG_ERR, "Failed to allocate memory for staging record full path\n");
exit(EXIT_FAILURE);
}
if (process_staged_record(record_path, daemon)) {
if (process_staged_record(record_path, true, daemon)) {
unlink(record_path);
processed++;
}
free(record_path);
}
@@ -605,11 +609,14 @@ void staging_records_loop(TelemPostDaemon *daemon)
free(namelist[i]);
}
free(namelist);
return numentries - processed;
}
void run_daemon(TelemPostDaemon *daemon)
{
int ret;
int retry_attempt = MAX_RETRY_ATTEMPTS;
int spool_process_time = spool_process_time_config();
bool daemon_recycling_enabled = daemon_recycling_enabled_config();
time_t last_spool_run_time = time(NULL);
@@ -620,9 +627,23 @@ void run_daemon(TelemPostDaemon *daemon)
assert(daemon->pollfds[signlfd].fd);
assert(daemon->pollfds[watchfd].fd);
/* Post at boot failed initialize retries variable */
if (daemon->bypass_http_post_ts != 0) {
retry_attempt = 1;
}
while (1) {
int retry_delay = spool_process_time;
malloc_trim(0);
ret = poll(daemon->pollfds, NFDS, spool_process_time * 1000);
if (retry_attempt < MAX_RETRY_ATTEMPTS) {
retry_delay = retry_attempt * retry_attempt;
daemon->bypass_http_post_ts = 0;
telem_log(LOG_INFO, "Record delivery failed will retry in %d seconds",
retry_delay);
}
ret = poll(daemon->pollfds, NFDS, retry_delay * 1000);
if (ret == -1) {
telem_perror("Failed to poll daemon file descriptors");
break;
@@ -671,7 +692,7 @@ void run_daemon(TelemPostDaemon *daemon)
exit(EXIT_FAILURE);
}
/* Process inotify event */
if (process_staged_record(record_name, daemon)) {
if (process_staged_record(record_name, false, daemon)) {
unlink(record_name);
}
free(record_name);
@@ -690,14 +711,25 @@ void run_daemon(TelemPostDaemon *daemon)
telem_log(LOG_INFO, "Telemetry post daemon exiting for recycling\n");
break;
}
/* Check if this is a retry */
if (retry_attempt < MAX_RETRY_ATTEMPTS) {
if (staging_records_loop(daemon) == 0) {
retry_attempt = MAX_RETRY_ATTEMPTS + 1;
} else {
retry_attempt++;
}
} else if (retry_attempt == MAX_RETRY_ATTEMPTS) {
retry_attempt = MAX_RETRY_ATTEMPTS + 1;
telem_log(LOG_ERR, "Record deliver failed after %d attempts",
MAX_RETRY_ATTEMPTS);
}
/* Check spool */
if (difftime(now, last_spool_run_time) >= spool_process_time) {
spool_records_loop(&(daemon->current_spool_size));
last_spool_run_time = time(NULL);
}
}
/* Check spool */
time_t now = time(NULL);
if (difftime(now, last_spool_run_time) >= spool_process_time) {
spool_records_loop(&(daemon->current_spool_size));
last_spool_run_time = time(NULL);
}
/* Check journal records and prune if needed */
ret = prune_journal(daemon->record_journal, JOURNAL_TMPDIR);
if (ret != 0) {
+6 -2
View File
@@ -19,6 +19,7 @@
#define NFDS 2
#define TM_RATE_LIMIT_SLOTS (1 /*h*/ * 60 /*m*/)
#define TM_RECORD_COUNTER (1)
#define MAX_RETRY_ATTEMPTS 8
#include <poll.h>
#include <stdbool.h>
@@ -83,17 +84,20 @@ void close_daemon(TelemPostDaemon *daemon);
* Processed record written on disk
*
* @param filename a pointor to record on disk
* @param is_retry a boolean value that indicates if
* the record has been previously processed.
* @param daemon post to telemetry post daemon
*/
bool process_staged_record(char *filename, TelemPostDaemon *daemon);
bool process_staged_record(char *filename, bool is_retry, TelemPostDaemon *daemon);
/**
* Scans staging directory to process files that were
* missed by file watcher
*
* @param daemon a pointer to telemetry post daemon
* @return the number of records that were removed from spool
*/
void staging_records_loop(TelemPostDaemon *daemon);
int staging_records_loop(TelemPostDaemon *daemon);
/**
* Posts a record to backend
+4 -4
View File
@@ -62,7 +62,7 @@ START_TEST(check_handle_client_with_no_data)
bool success;
char *filename = ABSTOPSRCDIR "/tests/telempostd/empty_message";
success = process_staged_record(filename, &tdaemon);
success = process_staged_record(filename, false, &tdaemon);
// Return true to remove corrupted record
ck_assert(success == true);
}
@@ -75,7 +75,7 @@ START_TEST(check_handle_client_with_incorrect_data)
bool success;
char *filename = ABSTOPSRCDIR "/tests/telempostd/incorrect_message";
success = process_staged_record(filename, &tdaemon);
success = process_staged_record(filename, false, &tdaemon);
// Return true to remove corrupted record
ck_assert(success == true);
}
@@ -88,7 +88,7 @@ START_TEST(check_process_record_with_correct_size_and_data)
bool success;
char *filename = ABSTOPSRCDIR "/tests/telempostd/correct_message";
success = process_staged_record(filename, &tdaemon);
success = process_staged_record(filename, false, &tdaemon);
ck_assert(success == true);
}
END_TEST
@@ -100,7 +100,7 @@ START_TEST(check_process_record_with_incorrect_headers)
bool success;
char *filename = ABSTOPSRCDIR "/tests/telempostd/incorrect_headers";
success = process_staged_record(filename, &tdaemon);
success = process_staged_record(filename, false, &tdaemon);
// Return true to remove corrupted record
ck_assert(success == true);
}