#include <stdlib.h>
#include <string.h>
#include "metrics.h"
#define MAX_WARNINGS_LOGGED 5
#define MAX_ERRORS_LOGGED 5
#define WARN_FIRST -1
#ifndef ROUNDUP
#define ROUNDUP(COUNT, MULTIPLE) ((((COUNT) + (MULTIPLE) - 1) / (MULTIPLE)) * (MULTIPLE))
#endif
typedef struct failure_info {
int location;
int code;
} failure_info_t;
typedef struct metrics {
FILE *file;
time_t start_time;
int warning_count;
failure_info_t warnings[MAX_WARNINGS_LOGGED];
int error_count;
failure_info_t errors[MAX_ERRORS_LOGGED];
int last_error_location;
char *path;
int result;
} metrics_t;
metrics_t metrics = {};
void
set_metrics_file(FILE *file)
{
metrics.file = file;
}
void
set_metric_start_time(time_t time)
{
metrics.start_time = time;
}
void
set_metric_path(char *path)
{
metrics.path = strdup(path);
}
void
mtree_record_failure(int location, int code)
{
if (code <= WARN_FIRST) {
if (metrics.warning_count < MAX_WARNINGS_LOGGED) {
metrics.warning_count++;
} else {
for (int index = 0; index < MAX_ERRORS_LOGGED - 1; index++) {
metrics.warnings[index] = metrics.warnings[index + 1];
}
}
metrics.warnings[metrics.warning_count - 1].location = location;
metrics.warnings[metrics.warning_count - 1].code = code;
} else {
int error_index = -1;
if (metrics.error_count <= MAX_ERRORS_LOGGED) {
if (metrics.error_count > 0) {
error_index = metrics.error_count - 1;
}
metrics.error_count++;
} else {
for (int index = 0; index < MAX_ERRORS_LOGGED - 1; index++) {
metrics.errors[index] = metrics.errors[index + 1];
}
error_index = MAX_ERRORS_LOGGED - 1;
}
if (error_index >= 0) {
metrics.errors[error_index].location = metrics.last_error_location;
metrics.errors[error_index].code = metrics.result;
}
metrics.last_error_location = location;
metrics.result = code;
}
}
void
print_metrics_to_file(void)
{
if (metrics.file == NULL) {
return;
}
fprintf(metrics.file, "dev=%s result=%d ",
metrics.path ? metrics.path : "", metrics.result);
if (metrics.warning_count) {
fprintf(metrics.file, "w:");
for (int index = 0; index < metrics.warning_count; index++) {
fprintf(metrics.file, "(%d:%d)",
metrics.warnings[index].location, metrics.warnings[index].code);
}
fprintf(metrics.file, " ");
}
if (metrics.error_count > 1) {
fprintf(metrics.file, "e:");
for (int index = 0; index < metrics.error_count - 1; index++) {
fprintf(metrics.file, "(%d:%d)",
metrics.errors[index].location, metrics.errors[index].code);
}
fprintf(metrics.file, " ");
}
fprintf(metrics.file, "fl=%d time=%ld\n",
metrics.last_error_location, ROUNDUP((time(NULL) - metrics.start_time), 60) / 60);
fclose(metrics.file);
if (metrics.path) {
free(metrics.path);
metrics.path = NULL;
}
}