You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

283 lines
8.1 KiB

/**
* Debug configuration implementation
* Runtime debug configuration system for flexible debug output control
*/
#include "debug_config.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <pthread.h>
#include <stdarg.h>
#include <stdio.h>
/* Global debug configuration */
debug_config_t g_debug_config = {
.level = DEBUG_LEVEL_ERROR,
.categories = DEBUG_CATEGORY_ALL,
.timestamp_enabled = 1,
.function_name_enabled = 1,
.file_line_enabled = 1,
.color_enabled = 1,
.max_output_per_second = 0,
.output_file = NULL
};
/* Output file handle */
FILE* debug_output_file = NULL;
/* Rate limiting */
static size_t output_count = 0;
static time_t last_output_time = 0;
static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER;
/* ANSI color codes */
static const char* color_red = "\033[31m";
static const char* color_yellow = "\033[33m";
static const char* color_green = "\033[32m";
static const char* color_blue = "\033[34m";
static const char* color_magenta = "\033[35m";
static const char* color_cyan = "\033[36m";
static const char* color_reset = "\033[0m";
/* Initialize debug system with default settings */
void debug_config_init(void) {
pthread_mutex_lock(&debug_mutex);
g_debug_config.level = DEBUG_LEVEL_ERROR;
g_debug_config.categories = DEBUG_CATEGORY_ALL;
g_debug_config.timestamp_enabled = 1;
g_debug_config.function_name_enabled = 1;
g_debug_config.file_line_enabled = 1;
g_debug_config.color_enabled = 1;
g_debug_config.max_output_per_second = 0;
g_debug_config.output_file = NULL;
if (debug_output_file && debug_output_file != stderr && debug_output_file != stdout) {
fclose(debug_output_file);
}
debug_output_file = stderr;
output_count = 0;
last_output_time = 0;
pthread_mutex_unlock(&debug_mutex);
}
/* Set debug level */
void debug_set_level(debug_level_t level) {
pthread_mutex_lock(&debug_mutex);
g_debug_config.level = level;
pthread_mutex_unlock(&debug_mutex);
}
/* Enable/disable specific categories */
void debug_enable_category(debug_category_t category) {
pthread_mutex_lock(&debug_mutex);
g_debug_config.categories |= category;
pthread_mutex_unlock(&debug_mutex);
}
void debug_disable_category(debug_category_t category) {
pthread_mutex_lock(&debug_mutex);
g_debug_config.categories &= ~category;
pthread_mutex_unlock(&debug_mutex);
}
void debug_set_categories(uint32_t categories) {
pthread_mutex_lock(&debug_mutex);
g_debug_config.categories = categories;
pthread_mutex_unlock(&debug_mutex);
}
/* Configure output options */
void debug_enable_timestamp(int enable) {
pthread_mutex_lock(&debug_mutex);
g_debug_config.timestamp_enabled = enable;
pthread_mutex_unlock(&debug_mutex);
}
void debug_enable_function_name(int enable) {
pthread_mutex_lock(&debug_mutex);
g_debug_config.function_name_enabled = enable;
pthread_mutex_unlock(&debug_mutex);
}
void debug_enable_file_line(int enable) {
pthread_mutex_lock(&debug_mutex);
g_debug_config.file_line_enabled = enable;
pthread_mutex_unlock(&debug_mutex);
}
void debug_enable_color(int enable) {
pthread_mutex_lock(&debug_mutex);
g_debug_config.color_enabled = enable;
pthread_mutex_unlock(&debug_mutex);
}
void debug_set_rate_limit(size_t max_per_second) {
pthread_mutex_lock(&debug_mutex);
g_debug_config.max_output_per_second = max_per_second;
pthread_mutex_unlock(&debug_mutex);
}
void debug_set_output_file(const char* file_path) {
pthread_mutex_lock(&debug_mutex);
if (file_path == NULL) {
if (debug_output_file && debug_output_file != stderr && debug_output_file != stdout) {
fclose(debug_output_file);
}
debug_output_file = stderr;
g_debug_config.output_file = NULL;
} else {
FILE* new_file = fopen(file_path, "a");
if (new_file) {
if (debug_output_file && debug_output_file != stderr && debug_output_file != stdout) {
fclose(debug_output_file);
}
debug_output_file = new_file;
g_debug_config.output_file = file_path;
}
}
pthread_mutex_unlock(&debug_mutex);
}
/* Check if debug output should be shown for given level and category */
int debug_should_output(debug_level_t level, debug_category_t category) {
pthread_mutex_lock(&debug_mutex);
/* Check if category is enabled */
if (!(g_debug_config.categories & category)) {
pthread_mutex_unlock(&debug_mutex);
return 0;
}
/* Check if level is sufficient */
if (level > g_debug_config.level) {
pthread_mutex_unlock(&debug_mutex);
return 0;
}
/* Rate limiting check */
if (g_debug_config.max_output_per_second > 0) {
time_t current_time = time(NULL);
if (current_time != last_output_time) {
output_count = 0;
last_output_time = current_time;
}
if (output_count >= g_debug_config.max_output_per_second) {
pthread_mutex_unlock(&debug_mutex);
return 0;
}
output_count++;
}
pthread_mutex_unlock(&debug_mutex);
return 1;
}
/* Get current debug level for a category */
debug_level_t debug_get_effective_level(debug_category_t category) {
pthread_mutex_lock(&debug_mutex);
debug_level_t level = g_debug_config.level;
pthread_mutex_unlock(&debug_mutex);
return level;
}
/* Get color for debug level */
static const char* get_level_color(debug_level_t level) {
if (!g_debug_config.color_enabled) {
return "";
}
switch (level) {
case DEBUG_LEVEL_ERROR: return color_red;
case DEBUG_LEVEL_WARN: return color_yellow;
case DEBUG_LEVEL_INFO: return color_green;
case DEBUG_LEVEL_DEBUG: return color_blue;
case DEBUG_LEVEL_TRACE: return color_magenta;
default: return "";
}
}
/* Get level name */
static const char* get_level_name(debug_level_t level) {
switch (level) {
case DEBUG_LEVEL_ERROR: return "ERROR";
case DEBUG_LEVEL_WARN: return "WARN";
case DEBUG_LEVEL_INFO: return "INFO";
case DEBUG_LEVEL_DEBUG: return "DEBUG";
case DEBUG_LEVEL_TRACE: return "TRACE";
default: return "UNKNOWN";
}
}
/* Format and output debug message */
void debug_output(debug_level_t level, debug_category_t category,
const char* function, const char* file, int line,
const char* format, ...) {
pthread_mutex_lock(&debug_mutex);
va_list args;
FILE* output = debug_output_file ? debug_output_file : stderr;
/* Print timestamp if enabled */
if (g_debug_config.timestamp_enabled) {
time_t now = time(NULL);
struct tm* tm_info = localtime(&now);
char time_str[32];
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", tm_info);
fprintf(output, "[%s] ", time_str);
}
/* Print level and color */
if (g_debug_config.color_enabled) {
fprintf(output, "%s[%s]%s ", get_level_color(level), get_level_name(level), color_reset);
} else {
fprintf(output, "[%s] ", get_level_name(level));
}
/* Print category */
fprintf(output, "[%d] ", category);
/* Print function name if enabled */
if (g_debug_config.function_name_enabled && function) {
fprintf(output, "%s() ", function);
}
/* Print file:line if enabled */
if (g_debug_config.file_line_enabled && file) {
fprintf(output, "(%s:%d) ", file, line);
}
/* Print the actual message */
va_start(args, format);
vfprintf(output, format, args);
va_end(args);
fprintf(output, "\n");
fflush(output);
pthread_mutex_unlock(&debug_mutex);
}
/* Stub implementations for advanced features */
int debug_parse_config(const char* config_string) {
/* Simple parser - for now just return success */
return 0;
}
int debug_parse_config_file(const char* file_path) {
/* Stub implementation */
return 0;
}
int debug_enable_config_reload(const char* file_path, int interval_seconds) {
/* Stub implementation */
return 0;
}