Trong ứng dụng lớn C, việc ghi nhật ký là một công cụ quan trọng để gỡ lỗi, giám sát và bảo trì sức khỏe hệ thống. Trong khi cơ bản [FLT: 0] những lời phát biểu hoặc thư viện như có thể đủ cho dự án nhỏ, họ thường bị lỗi khi hiệu suất, linh hoạt, và khả năng tăng cường không tái tạo. Xây dựng hệ thống ghi chép tự chọn (FLT: 0) cho bạn khả năng điều khiển mức độ ghi nhật ký, đích, định dạng và an toàn sợi chỉ. Bài này đi qua hệ thống thiết kế và thực hiện việc ghi nhật ký, sẵn sàng trong mã hoá, với các tập hợp công việc thực tế và môi trường doanh nghiệp tốt nhất.

Tại sao phải xây dựng một hệ thống ghi chép riêng

Cơ chế ghi nhật ký chuẩn, như hoặc PSIX ATI, thường thiếu các hạt và hiệu suất cần thiết bởi ứng dụng lớn. Một bộ ghi chép tùy chỉnh cung cấp:

  • Hiệu suất được làm báp têm:) tránh định vị và định dạng không cần thiết khi mức độ ghi nhật ký bị đàn áp.
  • Định dạng thời gian [FLT:] định dạng có thể đọc và phân tích thời gian nhất định , chỉ nhận diện, và mô- đun đầu đề làm tăng khả năng đọc bản ghi và phân tích.
  • Điều khiển đa số:) Bật cấp bản ghi đặc trưng cho chạy vào thời gian không cần sửa lại.
  • Điểm đến đa thức: Ghi vào bàn điều khiển, tập tin, lỗ hổng mạng, hoặc hệ thống giám sát bên ngoài cùng một lúc.
  • an toàn:) Dùng soundxes hoặc nguyên tử để ngăn chặn đầu ra lẫn nhau trong ứng dụng đa đọc.

Xem xét bản thiết kế lõi

Trước khi viết bất kỳ mã lệnh nào, xác định các thành phần cốt lõi của hệ thống ghi nhật ký của bạn. Những quyết định này định định định định định hình mọi thứ từ thiết kế ARI để chạy hiệu suất thời gian.

Cấp ghi lưu

Xác định mức độ nghiêm trọng theo nhu cầu của ứng dụng. Mức độ thông thường bao gồm ), , , , , , và . Hãy dùng để bảo đảm loại an toàn. Mỗi cấp nên có một ngưỡng ít nhất; thông điệp bên dưới thì bị bỏ qua để giảm bớt chi tiết trong sản xuất.

Đích ghi lưu

Hãy xem nơi nào sẽ được viết.

  • Console ) – phát triển và sửa lỗi nhanh chóng.
  • File – với quay và hình phổ để quản lý không gian đĩa.
  • Syslog ) – ghi chép trung tâm trên hệ thống Unix.
  • Network – UDP hay TCP cho các lỗ hổng từ xa (v. d., Graylog, ELK slop).

Một người viết nhật ký được thiết kế kỹ sử dụng một sự trừu tượng về bóng rửa mà cho phép bạn thêm hay xóa bỏ các điểm đến vào thời gian chạy.

Định dạng và hội nghị

Quyết định theo định dạng bản ghi sớm để giữ sự nhất quán. Một định dạng điển hình bao gồm nhãn thời gian, mức ghi lưu, tập tin/ dòng nguồn, tên mô- đun và thông điệp. Dạng thức cấu trúc như JSON đơn giản hoá phân loại tự động nhưng thêm trên. Để tính năng, hãy dùng định giới hạn định trường (v. d., ống hay tab) và tránh định vị bộ nhớ động theo đường dẫn nóng.

An toàn theo lối mòn

Trong ứng dụng đa đọc, việc viết có thể tạo ra kết xuất đã có sẵn. Hãy dùng [trên hệ thống PISIX] hoặc một phần quan trọng (trên Windows) xung quanh thao tác I/O thật. Để chuyển tiếp, hãy xem một hàng đợi không có file lưu sẵn hoặc một bộ đệm ghi đè lên được.

Thi hành một bộ sưu tập tài liệu cơ bản

Bắt đầu với một việc thực hiện đơn giản bao gồm những điều thiết yếu: mức độ ghi lưu, định dạng nhãn thời gian và biến đổi cấu trúc thông điệp cấu trúc. Những mã sau cung cấp một nền tảng.

Name

#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;

Định dạng thông điệp

Chức năng ghi nhật ký lõi dùng để định dạng thông điệp một cách an toàn. Một bộ đệm tĩnh tránh sự phân chia chồng trên đường nóng, nhưng hãy lưu ý đến bộ đệm tràn ngập cho những thông điệp rất dài.

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);
}

Để tiện lợi, hãy xác định vĩ mô tự động thu lại tập tin và dòng nguồn:

#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

Ví dụ sử dụng:

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;
}

Đang thêm kết xuất và xoay tập tin

Kết xuất bàn điều khiển là hữu ích trong quá trình phát triển, nhưng hệ thống sản xuất cần phải có bản ghi bền bỉ. Thêm một đĩa tập tin có khả năng xoay tập tin.

Ghi lưu tập tin

Mở rộng bộ ghi lưu bằng một con trỏ tập tin. Bạn có thể cố mã hoá một đường dẫn, hoặc làm cho nó có thể cấu hình lại. Cùng một tập tin itx bảo vệ được ghi.

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
 // ...
}

Name

Để ngăn cản các tập tin ghi lưu không chiếm hết chỗ trên đĩa, hãy thực hiện quay dựa trên kích cỡ tập tin, ngày tháng hoặc cả hai. Một chiến lược đơn giản:

  • Theo dõi kích cỡ tập tin hiện thời bằng cách kiểm tra sau mỗi chữ viết (hoặc định kỳ).
  • Khi tập tin vượt quá ngưỡng (v. d., 100 MB), thay đổi tên nó (, sau đó nén các tập tin cũ lại và mở lại .
  • Giữ số tập tin đã xoay tối đa; xoá những tập tin cũ nhất.

Bộ xương ví dụ:

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");
 }
}

Name

Trực tiếp I/O trong đường dẫn nóng có thể chặn các chỉ và hiệu suất bị giảm. Việc ghi chép achnrunous dechind decples định dạng thông điệp từ đĩa hoặc mạng viết bằng một hàng đợi máy in.

Mẫu sản xuất- consumer

Dùng một bộ đệm vòng có giới hạn hoặc hàng đợi miễn phí khoá (v. d., [LT:23] hoặc một danh sách đơn giản liên kết với tex) để lưu thông điệp đăng nhập. Một luồng đặc biệt sẽ dội hàng đợi.

Lợi ích:

  • Chỉ ứng dụng không bao giờ đợi lệnh "I/O".
  • Những tin nhắn bị thả xuống có thể được xử lý một cách duyên dáng (v. d., tăng cường một máy đếm).
  • Viết thơ Batching giảm bớt việc gọi hệ thống trên.

Vẽ hình đầy đủ

#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;
}

Tính năng nâng cao

Một khi hệ thống cơ bản hoạt động, hãy xem xét những cải tiến cho ứng dụng lớn hơn.

Ghi chép được cấu trúc (JSON)

Bản ghi đã cấu trúc cho phép phân tích tự động. Dùng thư viện JSON nhẹ như [FLT: 0] [FLT: 1] để xây dựng đối tượng. Định dạng ví dụ:

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

Trong khi đó, dạng thức này hòa trộn liên tục với các công cụ như ElAstic search and Splunk.

Ghi lưu từ xa qua Syslog hoặc mạng

Để phân phối hệ thống, bản ghi tới một nhà sưu tập trung tâm. Chức năng PSISX ([FLT: 0] trang ) đơn giản nhưng giới hạn. Hoặc là gửi các ký tự dữ liệu UDP đến một điểm màu xám hoặc các bản ghi bằng các lỗ hổng thô.

Tập tin cấu hình

Cho phép người điều khiển chỉnh tham số ghi lưu mà không cần sửa lại: cấp ghi lưu, đường dẫn tập tin, cỡ quay và điểm đến. Hãy phân tích một tập tin kiểu INIP đơn giản hoặc sử dụng biến môi trường. Cấu hình có thể được tải lại bằng tín hiệu (v. d., .].

Những thực hành tốt nhất và cạm bẫy

Tránh những lỗi thông thường làm suy yếu giá trị của việc khai thác gỗ.

Quá trình làm việc

Ghi lưu không nên trở thành cổ chai. Luôn luôn kiểm tra mức độ ghi lưu trước khi định dạng đối số. Hãy dùng vĩ mô để đánh giá cấp. Tránh trong đường dẫn quan trọng; thay vào đó hãy dùng bộ đệm chồng.

Mối quan tâm về sự an toàn

Không bao giờ ghi lại thông tin nhạy cảm như mật khẩu, số thẻ tín dụng, hay dữ liệu cá nhân. Làm sạch đầu vào người dùng và xem xét việc biên dịch trường đang xây dựng. Cũng bảo vệ tập tin ghi lưu từ truy cập trái phép.

Hợp nhất qua môđun

Thiết lập một hội nghị ghi chép rộng rãi. Hãy dùng những tiền tố mô- đun độc đáo (v. d., [LT:29], và một định dạng nhãn thời gian chuẩn (UTC được ưu tiên cho hệ thống phân phối). Tài liệu này có thể phân tích định dạng bản ghi để các đội tác vụ có thể phân tích nó một cách đáng tin cậy.

Kết luận

Một hệ thống ghi nhật ký tuỳ chỉnh ở C cung cấp sự linh hoạt và hiệu suất cần thiết cho ứng dụng cỡ lớn. Bắt đầu với một thiết kế chắc chắn bao gồm mức độ ghi nhật ký, chìm, an toàn sợi và định dạng, bạn có thể dần dần thêm tính năng nâng cao như arynchominous đầu ra, kết quả có cấu trúc và chuyển động từ xa. Những ví dụ trong bài này là một nền tảng (cho môi trường riêng của bạn, và luôn đo lường chi phí trên đầu. Với việc thực hiện, việc ghi nhật ký trở thành một tài sản mạnh hơn là một đường dẫn nước. Để tham khảo ý thêm [FL: 0] người đàn ông [FL] [FL] [FL] [FL] và thư viện]: 1].