Xem logs như các luồng sự kiện, không phải file riêng của ứng dụng
- Theo Twelve-Factor, logs là dòng sự kiện đã được tổng hợp và sắp theo thời gian, đến từ output streams của tất cả các process đang chạy và các backing services; logs không có “điểm bắt đầu/kết thúc” cố định mà chảy liên tục khi app hoạt động.
- Một ứng dụng Twelve-Factor không nên tự lo chuyện routing hay lưu trữ log files. App chỉ nên ghi log chưa format hoặc minimally formatted ra stdout/stderr, rồi để execution environment thu thập, gom, lưu, index và chuyển tiếp chúng.
- Trong local, developer có thể xem log ngay trên terminal. Trong staging hoặc production, platform thường gom log từ nhiều process và backing services thành một dòng log tập trung để xem realtime, tìm kiếm dài hạn hoặc alerting.
- Trong thực tế hiện đại, Heroku ghi nhận mọi thứ app viết ra
stdoutvàstderr, còn Kubernetes container runtimes cũng capture output từstdout/stderrrồi để kubelet cung cấp quakubectl logs.
1) Mở bài: vì sao factor này rất dễ bị làm sai?
Đây là một cảnh rất quen: app tự tạo thư mục logs/, xoay file theo ngày, rồi production lại chạy trên nhiều instance nên mỗi máy có một mớ file log khác nhau. Muốn tìm một lỗi xuyên qua nhiều request hoặc nhiều instance thì phải SSH vào từng máy, grep từng file, rồi cầu mong timestamp còn khớp. Twelve-Factor xem kiểu tư duy này là lỗi thiết kế: ứng dụng không nên coi log là file riêng của mình để quản. Nó nên coi log là một event stream được đẩy ra ngoài.
2) Định nghĩa gốc của Factor XI
Tên chính thức của factor này là:
“Logs — Treat logs as event streams.”
Tài liệu gốc mô tả rất rõ:
- logs là stream của các sự kiện đã được tổng hợp, theo thứ tự thời gian, thu thập từ output streams của tất cả running processes và backing services;
- log thô thường là text, mỗi event một dòng, dù backtrace có thể kéo dài nhiều dòng;
- logs không có điểm bắt đầu hay kết thúc cố định, mà chảy liên tục miễn là app còn chạy.
Diễn giải thật dễ hiểu cho junior:
App của bạn không nên nghĩ “mình có file log”. Nó nên nghĩ “mình phát ra các sự kiện vận hành”, còn chuyện thu gom và tiêu thụ các sự kiện đó là việc của môi trường chạy.
3) Factor này thật sự muốn giải quyết điều gì?
Factor XI giải quyết 3 vấn đề rất thật:
a) Logs bị rải rác khắp nơi
Nếu mỗi instance có file log riêng, việc debug hệ thống nhiều process hoặc nhiều máy sẽ rất mệt. Twelve-Factor muốn logs được coi là một luồng tập trung, không phải nhiều “hố file” rời rạc.
b) App ôm cả việc logging infrastructure
Tài liệu gốc nói app never concerns itself với routing hay lưu trữ output stream. Nó chỉ ghi ra stdout, còn execution environment mới là nơi capture, collate, archive và route stream đó tới đích phù hợp.
c) Khó ghép logs với giám sát hiện đại
Khi logs được phát ra stdout/stderr, platform như Heroku hay Kubernetes có thể gom chúng lại, cho xem realtime, forward sang dịch vụ lưu trữ/tìm kiếm, hoặc gắn vào pipeline observability. Heroku nói rõ logging infrastructure của họ có thể forward logs tới archival, search và alerting services; Kubernetes thì chuẩn hóa việc capture stdout/stderr qua CRI và cho xem qua kubectl logs.
4) “Event stream” nghĩa là gì?
Hãy chú ý điểm này: Twelve-Factor không nói “logs là file văn bản”. Nó nói logs là stream các sự kiện. Điều đó nghĩa là:
- log là thứ được phát sinh liên tục trong lúc app chạy;
- không nên bị khóa vào file path cố định;
- không gắn với một node hay một máy cụ thể;
- và hoàn toàn có thể được nhiều bên tiêu thụ cùng lúc.
Tài liệu gốc còn mô tả các kiểu “consumer” rất cụ thể:
- developer xem realtime stream trên terminal để debug local hoặc staging;
- ops có thể tail stream trên production và search một giờ log gần nhất;
- long-term archive có thể ghi toàn bộ stream vào S3 hoặc HDFS để phân tích sau.
Đây là cách nhìn rất hiện đại dù nguyên lý đã khá lâu: log không phải là vật sở hữu riêng của app, mà là dữ liệu vận hành chảy qua hệ thống.
5) App cần làm gì, và không cần làm gì?
App cần làm
Theo Twelve-Factor, app chỉ cần:
- ghi từng event ra
stdout, - càng ít “ôm hạ tầng log” càng tốt.
Heroku cũng nói rất rõ: logs của app sẽ capture bất cứ thứ gì app ghi ra stdout hoặc stderr.
App không cần làm
App không nên:
- tự route log đi nhiều nơi,
- tự mở file log và quản rotation như trách nhiệm cốt lõi của app,
- tự coi log storage là một phần business logic. Twelve-Factor nói các routing, storage, indexing, analysis chỉ là “concern of the execution environment.”
6) Ví dụ cực dễ hiểu
Hãy tưởng tượng ứng dụng của bạn là một đầu bếp trong bếp mở.
- Logs giống như những câu thông báo đầu bếp nói ra: “Món A bắt đầu”, “Món B xong”, “Thiếu nguyên liệu”, “Lò nướng lỗi”.
- Platform/logging system giống như hệ thống loa, camera và sổ trực của nhà hàng, nơi thu lại toàn bộ thông báo đó, sắp xếp, lưu trữ và cho quản lý tra cứu.
Điều không hợp lý là bắt đầu bếp vừa nấu ăn vừa tự đi đóng sổ, photocopy báo cáo, cất hồ sơ và gửi mail cho quản lý. Twelve-Factor muốn tách đúng như vậy: app phát sự kiện, môi trường chạy quản phần thu gom và tiêu thụ. Ý này là diễn giải trực quan từ nguyên lý gốc “treat logs as event streams”.
7) Ví dụ xuyên suốt với ứng dụng mẫu TaskFlow
Ta tiếp tục dùng ứng dụng mẫu TaskFlow.
TaskFlow có các process:
webworkerclock
Theo đúng tinh thần Factor XI:
weblog request bắt đầu, request lỗi, timeout, response status;workerlog job picked, job completed, job failed;clocklog các tác vụ định kỳ được kích hoạt.
Tất cả những log này nên được ghi ra stdout/stderr như các event streams. Execution environment mới là nơi gom chúng lại theo thời gian. Đây đúng với mô tả gốc của Twelve-Factor về logs đến từ output streams của all running processes và backing services.
Cách làm đúng
- Mỗi process ghi log ra stdout/stderr.
- Platform gom logs từ
web,worker,clock, thậm chí cả backing services nếu tích hợp được. - Team xem realtime stream khi debug, và forward sang hệ thống tìm kiếm/alerting khi cần. Điều này đúng với cả Twelve-Factor lẫn Heroku/Kubernetes logging model.
Cách làm sai
webghi vào./logs/web.log,workerghi vào./logs/worker.log,- mỗi container giữ một file riêng,
- rotation và cleanup để mặc cho “sau này xử lý”.
Cách này đi ngược trực tiếp với tinh thần Twelve-Factor vì app đã ôm luôn cả routing/storage concerns của logs.
8) Case thực tế đã được xác minh: Heroku
Heroku là ví dụ gần như “sách giáo khoa” cho Factor XI.
Tài liệu chính thức nói:
- logs sẽ capture mọi thứ app viết ra
stdoutvàstderr; - Heroku treats logs as streams;
- và hạ tầng logging của Heroku có thể forward logs tới dịch vụ archival, search và alerting thông qua log drains hoặc telemetry drains tùy runtime.
Một chi tiết rất đáng nhớ là nhiều framework cũ mặc định ghi log vào local directory, nhưng trên Heroku điều này không lý tưởng vì filesystem là ephemeral và platform coi logs là event streams qua stdout/stderr. Tài liệu Symfony trên Heroku nói đúng điều này.
9) Case thực tế đã được xác minh: Kubernetes
Kubernetes cũng phản ánh rất sát tư tưởng Factor XI.
Tài liệu observability và logging architecture của Kubernetes cho biết:
- container runtimes capture output của ứng dụng từ
stdoutvàstderr; - kubelet làm các logs này có thể truy cập được qua
kubectl logs; - sidecar cũng có thể đọc log từ file/socket/journald rồi in lại ra stdout/stderr để tận dụng pipeline sẵn có của kubelet và logging agent.
Đây là ví dụ rất hay vì nó cho thấy ngay cả khi ứng dụng cũ hoặc thành phần phụ không tự ghi stdout/stderr đẹp được, platform hiện đại vẫn cố kéo mọi thứ về log stream model mà Twelve-Factor khuyến khích.
10) Structured logging có liên quan gì?
Twelve-Factor gốc không bắt app phải dùng JSON logs hay structured logs. Nội dung gốc chỉ yêu cầu treat logs as event streams.
Tuy vậy, trong thực tế hiện đại, Kubernetes docs về system logs nói structured logging giúp trích xuất thông tin programmatically dễ hơn, đồng thời giảm effort và cost khi lưu trữ/xử lý logs. Đây là một diễn giải hiện đại hữu ích, nhưng không phải nội dung bắt buộc của Factor XI gốc.
Nói ngắn gọn:
- Nguyên lý gốc: stream logs ra ngoài.
- Thực hành hiện đại thường tốt: log có cấu trúc, dễ parse, nhất quán.
11) Junior thường hiểu sai ở đâu?
Hiểu sai 1: “Factor này bảo không được có file log ở đâu cả”
Không hẳn. Twelve-Factor không cấm execution environment ghi xuống file, archive hay object storage. Nó chỉ nói app không nên tự coi việc quản file log là trách nhiệm của mình. Execution environment hoàn toàn có thể capture stream rồi lưu ở nơi khác.
Hiểu sai 2: “Logs chỉ để debug local”
Không. Tài liệu gốc mô tả rõ logs được dùng cho realtime tail, troubleshooting production, long-term archive, thậm chí batch analysis sau này.
Hiểu sai 3: “Chỉ cần log nhiều là tốt”
Factor XI nói về mô hình vận hành logs, không phải “càng nhiều càng tốt”. Nếu bạn log bừa bãi, không nhất quán, hoặc trộn nhiều format vào một stream, chính platform sau này cũng khó xử lý. Kubernetes logging architecture còn khuyên không nên viết nhiều format khác nhau vào cùng một log stream.
Hiểu sai 4: “Secrets lỡ log ra cũng không sao vì chỉ là internal”
Không đúng. Heroku cảnh báo tránh dùng trực tiếp các tham chiếu tới sensitive environment variables ở nơi app ghi ra stdout/stderr, vì các giá trị đó có thể xuất hiện trong logs phục vụ audit.
12) Làm sai thì hậu quả gì?
- Khó debug hệ thống nhiều instance, vì logs bị chia thành nhiều file trên nhiều máy thay vì một stream tập trung. Đây là điều Twelve-Factor muốn tránh trực tiếp.
- App ôm thêm gánh nặng vận hành, khi tự lo file paths, rotation, retention, forwarding, search pipeline. Twelve-Factor nói đây không nên là concern của app.
- Mất log khi môi trường là ephemeral, như trên Heroku nếu bạn ghi xuống local filesystem của dyno thay vì stdout/stderr thì đó không phải mô hình phù hợp.
- Rò rỉ dữ liệu nhạy cảm, nếu app log thẳng secrets hoặc các biến môi trường nhạy cảm ra stdout/stderr. Heroku docs cảnh báo điều này rất rõ.
13) Áp dụng đúng trong team như thế nào?
Bước 1: Chuẩn hóa nguyên tắc “app chỉ emit log events”
Đây là nguyên tắc cốt lõi nhất. App nên coi logging như việc phát ra sự kiện, không phải mở file và quản lý hạ tầng log. Twelve-Factor nêu điều này rất trực diện.
Bước 2: Mọi process ghi ra stdout/stderr
web, worker, clock, script ngắn hạn… đều nên đi theo một hướng nhất quán. Heroku và Kubernetes đều xây hạ tầng logging dựa rất mạnh trên stdout/stderr.
Bước 3: Để platform gom và forward
- Trên Heroku, dùng logging infrastructure / log drains.
- Trên Kubernetes, tận dụng kubelet,
kubectl logs, node-level logging agent hoặc sidecar nếu thật sự cần.
Bước 4: Giữ format log nhất quán
Đây không phải yêu cầu gốc của Twelve-Factor, nhưng là thực hành rất nên làm. Nếu team dùng structured logs thì càng dễ query và phân tích hơn. Kubernetes docs xác nhận structured logging giúp giảm công sức xử lý log.
Bước 5: Không log secrets
Đây là nguyên tắc an toàn cơ bản nhưng rất hay bị quên. Heroku docs cảnh báo cụ thể về việc references tới sensitive env vars có thể bị xuất hiện trong logs.
14) Diễn giải trong bối cảnh hiện đại
Trong bối cảnh cloud-native, Factor XI gần như còn đúng hơn trước:
- container và Pod là ephemeral,
- số lượng instance tăng giảm liên tục,
- logs cần được thu gom xuyên qua nhiều process, nhiều node, nhiều service.
Kubernetes observability docs mô tả rõ logs là bản ghi theo thời gian của events trong ứng dụng và system components, còn runtimes capture stdout/stderr theo chuẩn CRI để kubelet cung cấp lại qua kubectl logs. Heroku cũng xây logging như một stream tập trung có thể forward tiếp.
Nói cách khác:
- Nguyên lý gốc: app treat logs as event streams.
- Diễn giải hiện đại: stream đó có thể chảy vào log platform, SIEM, search, alerting, OpenTelemetry pipeline hoặc object archive do platform quản.
15) Checklist tự đánh giá
Hãy tự hỏi về ứng dụng của bạn:
- App có đang tự mở và quản lý file log như trách nhiệm chính không? Nếu có, đó là tín hiệu ngược Twelve-Factor.
web,worker,clockcó ghi log thống nhất ra stdout/stderr không?- Platform của bạn có thu gom logs tập trung và cho xem/tìm kiếm được không? Heroku và Kubernetes đều hỗ trợ mô hình này.
- Team có đang log secrets hoặc dữ liệu nhạy cảm không?
- Nếu một instance biến mất, bạn có còn truy được log liên quan mà không phải SSH vào máy đó không? Đây là cách kiểm tra thực hành rất sát với tinh thần “event streams thay vì local files”.
Nếu bạn thấy 2–3 câu ở trên chưa ổn, Factor XI của app đó đang còn yếu.
16) Tóm tắt nhanh
- Twelve-Factor xem logs là event streams, không phải file riêng của từng app instance.
- App chỉ nên emit logs ra stdout/stderr; execution environment mới lo chuyện capture, collate, archive, route và analyze.
- Heroku và Kubernetes đều hiện thực hóa rất rõ mô hình này.
- Structured logging là thực hành hiện đại hữu ích, nhưng không phải nội dung bắt buộc của Factor XI gốc.
- Không log secrets là một nguyên tắc an toàn cực quan trọng.
17) Nguồn tham khảo
- The Twelve-Factor App — XI. Logs.