Log Rotation là cơ chế tự động quản lý tệp nhật ký giúp ngăn tràn đĩa thông qua việc lưu trữ, nén và xóa các bản ghi cũ. Trong ứng dụng di động, nhật ký tích tụ trên thiết bị của người dùng và nếu không có luân chuyển, chúng có thể chiếm gigabyte bộ nhớ chỉ sau vài tuần sử dụng. Theo Tài liệu Redis, cấu hình log rotation đúng cách giảm 99% nguy cơ hệ thống hỏng do đĩa đầy so với tăng trưởng nhật ký không kiểm soát. Các chiến lược luân chuyển chính là: theo kích thước tệp, theo thời gian và theo số lượng tệp — mỗi chiến lược được chọn tùy theo kịch bản sử dụng: logrotate trên Linux, CocoaLumberjack trên iOS và Timber trên Android đều hỗ trợ cả ba phương pháp.
Những điểm chính
Log Rotation là quá trình định kỳ chuyển tệp nhật ký đang hoạt động sang tệp mới, đồng thời lưu trữ, nén hoặc xóa tệp cũ. Nếu không có luân chuyển, một tệp nhật ký duy nhất sẽ phát triển vô hạn cho đến khi lấp đầy toàn bộ phân vùng đĩa, dẫn đến hỏng ứng dụng và mất dữ liệu.
Kịch bản điển hình: ứng dụng ghi nhật ký vào tệp app.log. Khi app.log đạt 100 MB, hệ thống đổi tên thành app.log.1, nén thành app.log.1.gz và tạo app.log mới trống. Ở lần đầy tiếp theo, app.log.1 trở thành app.log.2, app.log.1.gz trở thành app.log.2.gz và app.log.2.gz cũ bị xóa. Cơ chế này được gọi là luân chuyển với số lượng giữ lại — số bản sao lưu trữ cố định.
Theo Splunk (2023), cấu hình luân chuyển không đúng là nguyên nhân của 40% sự cố liên quan đến hết dung lượng đĩa trên máy chủ ứng dụng. Đối với thiết bị di động, luân chuyển càng quan trọng hơn vì người dùng không thể và không nên quản lý nhật ký thủ công.
Log Rotation hỗ trợ ba chiến lược cơ bản có thể kết hợp. Việc chọn chiến lược phụ thuộc vào loại ứng dụng: hệ thống máy chủ thường dùng luân chuyển theo thời gian, di động — theo kích thước, hệ thống nhúng — theo số lượng tệp.
| Chiến lược | Kích hoạt | Khi nào sử dụng |
|---|---|---|
| Theo kích thước | Tệp đạt N byte | Hệ thống tải cao với khối lượng nhật ký không dự đoán được |
| Theo thời gian | Đã qua N giờ/ngày | Kết xuất hàng ngày, yêu cầu tuân thủ |
| Theo số lượng tệp | Đã tạo N tệp | Thiết bị di động có dung lượng đĩa hạn chế |
Luân chuyển theo kích thước đảm bảo không tệp nhật ký nào vượt quá giới hạn đã đặt. Giới hạn được chọn dựa trên dung lượng đĩa khả dụng và tần suất ghi nhật ký. Đối với máy chủ, giới hạn điển hình là 100–500 MB mỗi tệp, đối với thiết bị di động — 1–10 MB. Nếu ứng dụng ghi nhật ký quá nhiều, cần giảm giới hạn, nếu không luân chuyển sẽ xảy ra sau mỗi vài phút.
Luân chuyển theo thời gian độc lập với khối lượng nhật ký — tệp được chuyển theo đúng lịch trình. Thuận tiện cho các hệ thống nơi nhật ký phải được lưu trữ trong số ngày cố định: luân chuyển hàng ngày với số lượng giữ lại = 30 nghĩa là lưu trữ 30 ngày. Nhược điểm — một tệp duy nhất có thể tăng lên một gigabyte mỗi ngày dưới tải nặng.
logrotate là tiện ích Linux tiêu chuẩn để tự động luân chuyển nhật ký. Nó chạy qua cron và xử lý các tệp cấu hình từ /etc/logrotate.d/. Mỗi dịch vụ (nginx, postgresql, ứng dụng) tạo cấu hình riêng chỉ định đường dẫn nhật ký, chiến lược luân chuyển và hành động sau luân chuyển.
# /etc/logrotate.d/myapp — luân chuyển nhật ký ứng dụng
/var/log/myapp/*.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 0640 www-data www-data
postrotate
kill -HUP $(cat /var/run/myapp.pid)
endscript
}
Cấu hình này luân chuyển nhật ký hàng ngày, giữ 7 bản sao lưu trữ, nén tệp cũ bằng gzip (trừ tệp cuối — delaycompress), không báo lỗi nếu thiếu nhật ký (missingok), không luân chuyển tệp rỗng (notifempty) và tạo lại tệp với quyền 0640. Sau khi luân chuyển, nó gửi tín hiệu HUP đến tiến trình ứng dụng qua script postrotate.
size — luân chuyển khi đạt kích thước (size 100M). rotate — số bản sao lưu trữ (rotate 7). compress — nén gzip. dateext — thêm ngày vào tên tệp thay vì số thứ tự. sharedscripts — chạy postrotate một lần cho tất cả tệp, không chạy riêng từng tệp. maxage — xóa bản lưu trữ cũ hơn N ngày.
Trên thiết bị di động, Log Rotation rất quan trọng vì người dùng không quản lý hệ thống tệp và không mong đợi ứng dụng chiếm gigabyte với nhật ký. iOS và Android có cơ chế tích hợp: os_log trên iOS sử dụng bộ đệm vòng kích thước cố định (luân chuyển bằng ghi đè), Android Logcat có bộ đệm giới hạn trong kernel.
Đối với nhật ký tệp tùy chỉnh trên iOS, sử dụng CocoaLumberjack với lớp DDFileLogger, hỗ trợ luân chuyển theo kích thước và thời gian. Trên Android — Logback hoặc triển khai tùy chỉnh qua RollingFileAppender. Cả hai công cụ đều cho phép đặt kích thước tệp tối đa và số lượng bản lưu trữ.
// CocoaLumberjack — luân chuyển tệp trên iOS
import CocoaLumberjack
let fileLogger = DDFileLogger()
fileLogger.maximumFileSize = 1024 * 1024 // 1 MB
fileLogger.logFileManager.maximumNumberOfLogFiles = 5
DDLog.add(fileLogger)
iOS: os_log không yêu cầu luân chuyển — tin nhắn bị ghi đè trong bộ đệm vòng. Nhưng nếu ứng dụng ghi nhật ký tệp tùy chỉnh (để gỡ lỗi hoặc gửi lên máy chủ), luân chuyển phải được cấu hình thủ công. CocoaLumberjack là lựa chọn tiêu chuẩn cho nhóm iOS — nó tự động nén bản lưu trữ thành .gz và xóa tệp cũ khi vượt quá giới hạn.
Android không hạn chế ứng dụng ghi nhật ký vào thư mục riêng của chúng. Nếu nhà phát triển ghi nhật ký gỡ lỗi vào tệp mà không luân chuyển, sau một tháng sử dụng tích cực, chúng có thể chiếm 500 MB đến 1 GB. Người dùng sẽ phát hiện vấn đề khi hệ thống hiển thị cảnh báo dung lượng thấp và sẽ xóa ứng dụng. Logback với RollingFileAppender giải quyết vấn đề này: giới hạn 5 MB với 3 bản lưu trữ đảm bảo nhật ký không bao giờ vượt quá 20 MB.
Dưới đây là các ví dụ về cấu hình luân chuyển nhật ký trên cả hai nền tảng. Trên iOS sử dụng CocoaLumberjack, trên Android — Logback với cấu hình XML.
// Logback trên Android — cấu hình luân chuyển trong logback.xml
// Kích thước tệp 5MB, 3 bản sao lưu trữ
@file:Suppress("unused")
// Trong logback.xml:
// <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
// <file>${DATA_DIR}/logs/app.log</file>
// <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
// <fileNamePattern>app.%i.log.gz</fileNamePattern>
// <minIndex>1</minIndex>
// <maxIndex>3</maxIndex>
// </rollingPolicy>
// <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
// <maxFileSize>5MB</maxFileSize>
// </triggeringPolicy>
// </appender>
CocoaLumberjack trên iOS hỗ trợ không chỉ luân chuyển theo kích thước mà còn xóa nhật ký cũ theo ngày bằng logFileManager.maximumLogFiles. Nếu đặt maximumLogFiles = 0, giới hạn bị loại bỏ — nhật ký sẽ tích tụ vô hạn, rất nguy hiểm cho môi trường production.
// Luân chuyển tùy chỉnh với kiểm tra tổng khối lượng
class SizeAwareLogger {
let maxTotalSize: Int64 = 20 * 1024 * 1024
func enforceQuota(at logDirectory: URL) {
let files = (try? FileManager.default
.contentsOfDirectory(
at: logDirectory,
includingPropertiesForKeys: [.fileSize]
)) ?? []
let total = files.reduce(0) {
$0 + (try? $1.resourceValues(forKeys: [.fileSize])
.fileSize).map(Int64.init) ?? 0
}
if total > maxTotalSize {
// Xóa tệp cũ nhất
files.sorted { $0.path < $1.path }.first.map {
try? FileManager.default.removeItem(at: $0)
}
}
}
}
Log Rotation không chỉ là lưu trữ tự động mà còn là chỉ báo sức khỏe hệ thống. Nếu nhật ký luân chuyển quá thường xuyên (vài phút một lần), đó là dấu hiệu ghi nhật ký quá mức hoặc vòng lặp ghi nhật ký lỗi. Thiết lập cảnh báo về tần suất luân chuyển: hơn 10 lần luân chuyển mỗi giờ là lý do cần kiểm tra.
Hệ thống giám sát (Prometheus, Grafana, Datadog) có thể theo dõi số liệu luân chuyển qua bộ xuất hệ thống tệp. Prometheus node_exporter cung cấp số liệu kích thước tệp và thời gian sửa đổi. Trên thiết bị di động, giám sát luân chuyển thường được tích hợp trong SDK: CocoaLumberjack ghi sự kiện luân chuyển qua DDLog và Logback gửi trạng thái qua appender.
Cảnh báo: nếu có nhiều bản lưu trữ hơn dự kiến (số lần luân chuyển vượt quá giới hạn) hoặc tổng khối lượng nhật ký vượt quá hạn ngạch — hệ thống phải thông báo cho quản trị viên. Đối với máy chủ, ngưỡng tiêu chuẩn là 80% kích thước phân vùng; đối với thiết bị di động — cảnh báo khi vượt quá 50 MB mỗi ứng dụng.
Câu hỏi thường gặp
Đối với máy chủ — 100–500 MB, đối với ứng dụng di động — 1–10 MB. Giới hạn quá nhỏ (dưới 1 MB) gây luân chuyển thường xuyên và thao tác I/O không cần thiết. Giới hạn quá lớn (trên 500 MB) làm tăng thời gian mở và tìm kiếm trong tệp.
Đối với production — tối thiểu 7 ngày (luân chuyển hàng ngày) hoặc 3–5 bản lưu trữ (luân chuyển theo kích thước). Đối với yêu cầu tuân thủ — 30–90 ngày, nhưng hãy sử dụng bộ nhớ riêng với nén và chính sách lưu giữ, không phải luân chuyển trên cùng phân vùng.
logrotate là tiện ích Linux — không khả dụng trên iOS hay Android. Trên thiết bị di động, luân chuyển được triển khai qua thư viện: CocoaLumberjack cho iOS và Logback cho Android. Chúng không yêu cầu quyền root và hoạt động trong môi trường sandbox của ứng dụng.
Kiểm tra xem có ghi nhật ký vòng không — khi xử lý lỗi tự tạo ra lỗi mới. Thêm bảo vệ: bộ đếm ghi nhật ký lặp lại cùng loại với ngưỡng (không quá 100 tin nhắn giống nhau mỗi phút) và khóa tạm thời sau khi vượt quá.
Không bắt buộc, nhưng được khuyến nghị. gzip nén nhật ký văn bản 10–20 lần mà không mất dữ liệu. Trên thiết bị di động, nén giảm dung lượng từ 50 MB xuống 3–5 MB. Nhược điểm duy nhất — không thể đọc bản lưu trữ mà không giải nén, nhưng để phân tích thường chỉ cần tệp hiện tại.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm