W przypadku gdy nie ma możliwości, aby w przypadku gdy w przypadku braku takiego rozwiązania nie ma potrzeby, należy podać powody, aby stwierdzić, że nie ma potrzeby, aby w przypadku braku takiego rozwiązania możliwe było przeprowadzenie badania.

Why Build a Custom Logging System

Standard logging mechanisms, such as ides 1; Xi1; FLT: 2 contribution 3; Xi3; or thee POSIX precision 1; Xi1; FLT: 3 contribution 3; Xiops; API, often lack thee granularity and d performance required by by large applications. A custem logger offers:

  • Xi1; Xi1; FLT: 0 Xi3; Xi3; Optimized performance: Xi1; Xi1; FLT: 1 Xi3; Xi3; Vyr3; Avoid unnecesary allocations andd formatting when log levels are supressed.
  • Xi1; Xi1; FLT: 0 Xi3; Xi3; Flexible formatting: Xi1; Xi1; FLT: 1 Xi3; Xi3; Consistent timestamps, thread identifiers, and module prefiges improwize log readability andd parsing.
  • Support: Support: Support / Support / Support: Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Support / Supply / Support / Support / Supps / Suppc / Suppc.
  • Referencje: 1; FLT: 0; FLT: 0; FLT: 0; FLT: 0; FLT: 0; FLT: 1; FLT: 1; FLT: 1; FLT: 1; FLT: 1; FLT: 0; FLT: 0; FLT: 0; FLT: 0; FLT: 3; FLT: 0; FLT: 0; FLT: 0; FLT: 0; FLT: 3; FLT: 0; FLT: 3; FLT: 0; FLT: 0; FLT: 3; FLT: 3; FLT: FLT: FLT: 0; FLT: FLT: 0: 0: FLS: 0: 0: FLS: FLS: 0: FLS: 3; FLS: FLS: 3; FLS: FLS: FLS: 3; FLS: FLS: FLS: FLS: FLS: FLS
  • W przypadku gdy w wyniku badania nie można uzyskać danych dotyczących działania substancji chemicznej, należy podać dane dotyczące działania substancji chemicznej.

Core Design Consignations

Before writing any code, definite the core contents of your logging system. These decisions shape everything from API designn to runtime performance.

Poziomy log

Definiować searity levels that map tone application 's needs. Common levels include entide1; Common levels include 1; 1; FLT: 4 contribu3; Yel3;, Xel1; FLT: 5 contribute 3; Xel3; FLT: 6 contribute 3; FLT: 1; FLT: 7 contribute 3; FLT: 1; FLT: 8 contribute 3; Xend; Vel1; FLT: 9 contribunal 3; FLT; VE An Britul; Ve; Vell; FLT: 10 contribuilboold are ingired td expetid; in productien; in productien.

Log Destinations

Consider where logs will be written. Typical destinations aree:

  • Xi1; Xi1; FLT: 0 Xi3; Xi3; Console Xi1; Xi1; FLT: 1 Xi3; Xi3; - for development andd quick debugging.
  • Xi1; Xi1; FLT: 0 Xi3; Xi3; File Xi1; Xi1; FLT: 1 Xi3; Xi3; - witch rotation and d archival to manage disk space.
  • Xi1; Xi1; FLT: 0 Xi3; Xi3; Syslog Xi1; Xi1; FLT: 1 Xi3; Xi3; - for centralized logging on Unix systems.
  • Xiv1; Xiv1; FLT: 0 Xiv3; Xiv3; Network Xiv1; Xiv1; FLT: 1 Xiv3; Xiv3; - UDP or TCP sockets for remote acgregation (np., Graylog, ELK stack).

Dobrze zaprojektowany logger używa sink abstraction that pozwala you tu add or remove destinations at runtime.

Formatting andConventions

Decydo a log format early to maintain considency. A typical format includes a timestamp, log level, source file / line, module name, and the message. Structured formats like JSON simplify automate parsing but add overhead. For performance, use a fixed-field delimiter (e.g., pipes or tabs) and avoid dynamic memony allocation ion hot paths.

Trójkąt Safety

In multithreated applications, concurrent writes can produce garbled output. Use a entil; I1; FLT: 11 contribution 3; Ion3; (on POSIX systems) or a critial section (on Windows) around the actual I / O operation. For hiper throutroput, consider a lock-free queue oe or per-thread logging buffers that are flushad periodically.

Wdrożenie logger Basic

Rozpocząć witch a simple implementation that coves the e esentials: log levels, timestamp formatting, and variable-argument message construction. The following code provides a foundation.

Log Level Enum and Helper Functions

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>
#include <pthread.h>

typedef enum {
 LOG_LEVEL_TRACE,
 LOG_LEVEL_DEBUG,
 LOG_LEVEL_INFO,
 LOG_LEVEL_WARN,
 LOG_LEVEL_ERROR,
 LOG_LEVEL_FATAL
} LogLevel;

static const char* level_strings[] = {
 "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL"
};

static LogLevel g_min_level = LOG_LEVEL_INFO;
static pthread_mutex_t g_log_mutex = PTHREAD_MUTEX_INITIALIZER;

Message Formatting

The core logging function uses eng1; Xi1; FLT: 13 context 3; Xi3; to format the message safely. A static buffer avoids heap allocation in thee hot path, but be mindful of buffer overflow for very long messages.

void log_message(LogLevel level, const char* file, int line, const char* func, const char* format, ...) {
 if (level < g_min_level) return;

 time_t now = time(NULL);
 struct tm* tm_info = localtime(&now);
 char time_buf[20];
 strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", tm_info);

 pthread_mutex_lock(&g_log_mutex);

 // Write header
 fprintf(stdout, "[%s] [%s] [%s:%d %s] ", time_buf, level_strings[level], file, line, func);

 va_list args;
 va_start(args, format);
 vfprintf(stdout, format, args);
 va_end(args);

 fprintf(stdout, "\n");
 fflush(stdout); // Ensure immediate output for debugging

 pthread_mutex_unlock(&g_log_mutex);
}

For consumence, definite macros that automatically capture the source file andd line:

#define LOG_TRACE(...) log_message(LOG_LEVEL_TRACE, __FILE__, __LINE__, __func__, __VA_ARGS__)
#define LOG_DEBUG(...) log_message(LOG_LEVEL_DEBUG, __FILE__, __LINE__, __func__, __VA_ARGS__)
// ... similar for INFO, WARN, ERROR, FATAL

Usage example:

int main() {
 LOG_INFO("Application started on port %d", 8080);
 LOG_WARN("Disk usage exceeding %.1f%%", 85.3);
 LOG_ERROR("Failed to open file: %s", "config.dat");
 return 0;
}

Adding File Output andRotation

Console output is useful during development, but production systems need persistent logs. Add a file sink that writes to a rotating set of log files.

File Logging

Extend thee logger wigh a file pointer. You can either hard-code a path or make it configuble. The same mutex protects file writes.

static FILE* g_log_file = NULL;

int log_init_file(const char* path) {
 g_log_file = fopen(path, "a");
 return (g_log_file != NULL) ? 0 : -1;
}

void log_message_file(LogLevel level, const char* file, int line, const char* func, const char* format, ...) {
 // Same timestamp and header logic, but write to g_log_file
 // ...
}

Log Rotation Strategies

Tu prevent log files frem consuming all disk space, implement rotation based on file size, date, or both. A simple strategy:

  • Track thee current file size by checking indi1; Xi1; FLT: 18 Xi3; Xion3; after each write (or periodically).
  • When thee file exceeds a bombold (np., 100 MB), rename it (eng1; eng.1; FLT: 19 ing. 3; eng. 3; → eng. 1; eng.; flT: 20 ing. 3; eng. 3;, then compress old files) and reopen a fresh ingl.
  • Keep a maximum umber of rotated files; delete the oldect.

Zbadaj szkielet:

void log_rotate_if_needed() {
 if (g_log_file && ftell(g_log_file) > MAX_LOG_SIZE) {
 fclose(g_log_file);
 // Rename and compress logic
 g_log_file = fopen(LOG_PATH, "a");
 }
}

Asynkomus Logging for Performance

Direct I / O in the hot path can block threads and degrade de performance. Asyncours logging decouples message formatting frem disk or network writes using a producer-consumer queue.

Producent - Konsumer Pattern

Use a bounded ring buffer or a lock-free queue (np., bell1; fLT: 23 contain3; bell3; or a simple linked litt wigh mutex) to store log messages. A dedicated thread flushes the queue.

Korzyści:

  • Wnioskodawca nie oczekuje na wniosek
  • Dropped messages can be handled gracefuly (np., increment a counter).
  • Batching writes reduces system call overhead.

Wdrażanie programu Sketch

#define QUEUE_SIZE 8192
static char g_log_queue[QUEUE_SIZE][MAX_LOG_LINE];
static volatile int g_queue_head = 0, g_queue_tail = 0;
static pthread_mutex_t g_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t g_queue_notify = PTHREAD_COND_INITIALIZER;

void push_log(const char* logline) {
 pthread_mutex_lock(&g_queue_mutex);
 // Copy and advance head (ring buffer)
 strncpy(g_log_queue[g_queue_head], logline, MAX_LOG_LINE);
 g_queue_head = (g_queue_head + 1) % QUEUE_SIZE;
 pthread_cond_signal(&g_queue_notify);
 pthread_mutex_unlock(&g_queue_mutex);
}

void* log_flush_thread(void* arg) {
 while (1) {
 pthread_mutex_lock(&g_queue_mutex);
 while (g_queue_head == g_queue_tail)
 pthread_cond_wait(&g_queue_notify, &g_queue_mutex);
 // Dequeue and write to file/console
 char buffer[MAX_LOG_LINE];
 strncpy(buffer, g_log_queue[g_queue_tail], MAX_LOG_LINE);
 g_queue_tail = (g_queue_tail + 1) % QUEUE_SIZE;
 pthread_mutex_unlock(&g_queue_mutex);
 // Perform I/O (protected by the same file mutex)
 fputs(buffer, g_log_file);
 }
 return NULL;
}

Zaliczki

Once thee basic system is operational, consider these enhancements s for larger applications.

Structured Logging (JSON)

Structured logs eable automated analysis. Use a lightweight JSON library likie indi.1; British 1; FLT: 0 British 3; British 3; CJSON British 1; British 1; FLT: 1 British 3; British 3; Two build objects. Example format:

{"timestamp":"2025-03-20T10:15:30Z","level":"ERROR","module":"auth","message":"Login failed","user":"john"}

While verbose, this format integrates swallesly with tools like Elasticsearch andd Snak.

Remote Logging via Syslog or Network

For difficed systems, forward logs to a central collector. The POSIX presentation 1; British 11; FLT: 26 contained 3; Significtion (presen1; FLT: 0 contain3; FLT: 0 contain3; man page presentation 1; FLT: 1 contain3; FLT: 1 containfaulforward but limited. Extractively, send UDP dagarams to a Graylog or Logstash endpoint using raw sockets.

Konfiguracja pliku

Allow operators to two logging parameters with out recompiling: log level, file path, rotation size, and output destinations. Parse a simple INI-style file or use environment variables. The configuration can be reloaded via a signal (e.g., Xi1; FLT: 27 X3; Xion3;).

Bett Practices andPitfalls

Avoid color mistakes that undermine the value of logging.

Wykonanie Overheadd

Logging nie powinien być wąskim gardłem. Zawsze sprawdza, że te log level before formatting arguments. Usie macros that evatate te level quickly. Avoid Buffers 1; Avoid; FLT: 28 haftu3; Amend3; in thee critical path; use stack buffers instead.

Koncerny Security

Never log sensitivie information like passwords, condit card numbers, or personal data. Sanitize user input and consider redacting fields in production builds. Also, protect log files from from unauthorized accessions.

Consistency Across Modules

Ustanowienie spółki-wide logging convention. Usie unikalne module prefixe (np., Xi1; Xi1; FLT: 29 Xi3; Xi1; FLT: 30 Xi3; Xi3;) i a standard timestamp format (UTC is preferred for displaced systems). Document the log format so that operations teams can parse it reliable.

Konkluzja

B-1i; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 2; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1; 1