LogBox: log berstruktur dalam aplikasi CFML
LogBox dalam Lucee: kategori, tahap log, appender fail dan cara mencari log berstruktur dengan pantas, dengan contoh sebenar dijalankan dalam rig ujian.

Kandungan
- LogBox: log berstruktur dalam aplikasi CFML
- Apa itu LogBox dan bila anda memerlukannya
- Aras log dalam LogBox
- Memulakan LogBox tanpa ColdBox
- Kategori: pisahkan log mengikut bahagian aplikasi
- Appender: ke mana mesej pergi
- Konfigurasi berstruktur dengan struct
- Appender fail dan format CSV
- Menulis log berstruktur dengan extraInfo
- Mencari dan menapis log berstruktur
- Bila tidak menggunakan LogBox
- Soalan Lazim
- Sumber
LogBox: log berstruktur dalam aplikasi CFML
Penulis: Thalhah · Tarikh: 14 Oktober 2026
LogBox ialah pustaka logging daripada keluarga ColdBox yang membahagikan log kepada kategori, aras, dan appender yang boleh anda konfigurasi sepenuhnya. Ia boleh berjalan sendiri dalam aplikasi Lucee biasa, tanpa memasang rangka kerja ColdBox penuh. Artikel ini menunjukkan cara memulakan LogBox, memilih aras, membahagikan log mengikut kategori, menulis log berstruktur, dan mencari kembali mesej tertentu. Semua blok kod diuji dalam rig Lucee dengan ColdBox 8.3.0.
Apa itu LogBox dan bila anda memerlukannya
LogBox ialah perpustakaan log yang dibangunkan oleh Ortus Solutions, pasukan yang sama di belakang ColdBox dan CommandBox. Perbezaannya dengan cflog dan writeLog ialah struktur: dua fungsi teras Lucee itu menulis satu mesej rata ke satu fail, manakala LogBox memberi anda aras keterukan, kategori bernama, dan appender yang memutuskan ke mana setiap mesej pergi.
Anda memerlukan LogBox apabila log aplikasi anda mula bercabang. Satu aplikasi kedai dalam talian mahu mengasingkan log pembayaran daripada log stok, menyimpan ralat dalam fail berasingan, dan mencari mesej tanpa membaca satu fail besar secara manual. Panduan log dan pemantauan aplikasi CFML menerangkan fungsi teras cflog dan writeLog; LogBox ialah lapisan di atasnya apabila keperluan anda melebihi satu fail rata.
Aras log dalam LogBox
Setiap mesej LogBox membawa satu aras keterukan, daripada paling teruk kepada paling ringan, sama seperti pustaka log lain seperti Log4j. Jadual berikut menyenaraikan aras mengikut susunan menaik:
| Aras | Nilai | Kegunaan biasa |
|---|---|---|
| FATAL | 0 | Ralat teruk yang menamatkan proses, contohnya pangkalan data tidak dapat dihubungi |
| ERROR | 1 | Ralat masa jalan yang perlu tindakan segera |
| WARN | 2 | Keadaan hampir silap, contohnya stok hampir habis |
| INFO | 3 | Peristiwa biasa yang patut direkodkan, aras lalai |
| DEBUG | 4 | Butiran dalaman untuk penyahpepijatan sahaja |
Aras membolehkan anda menapis pada masa tulis, bukan pada masa baca. Apabila anda menetapkan aras maksimum sesuatu logger kepada INFO, semua mesej DEBUG daripada logger itu dibuang sebelum sempat menyentuh appender, jadi ia tidak memenuhi fail log atau memperlahankan aplikasi.
Memulakan LogBox tanpa ColdBox
LogBox boleh dicipta sebagai objek biasa dalam mana-mana templat CFML. Anda tidak perlu Application.cfc khas, tidak perlu rangka kerja, dan tidak perlu pemetaan tambahan selain pemetaan coldbox yang disediakan oleh pemasangan ColdBox. Blok berikut mencipta satu tika LogBox, meminta logger untuk kategori kedai, dan mencatat satu mesej pada setiap aras:
<cfscript>
lb = new coldbox.system.logging.LogBox();
logger = lb.getLogger("kedai");
logger.debug("Butiran dalaman untuk penyahpepijatan");
logger.info("Pesanan 123 disahkan");
logger.warn("Stok produk 45 hampir habis");
logger.error("Gagal memproses bayaran pesanan 124");
logger.fatal("Pangkalan data tidak dapat dihubungi");
writeOutput("Lima aras log dicatat tanpa ralat.");
</cfscript>
Dengan konfigurasi lalai, LogBox mendaftarkan satu appender konsol, jadi mesej ini ditulis ke output standard enjin servlet dan bukannya dipaparkan dalam halaman. Blok ini membuktikan lima aras itu sah dan berjalan; ia belum memberitahu anda ke mana mesej pergi. Untuk itu anda perlukan konfigurasi.
Kategori: pisahkan log mengikut bahagian aplikasi
Argumen kepada getLogger() ialah nama kategori, bukan nama fail. Kategori ialah label bebas yang anda pilih, dan ia menjadi medan dalam setiap mesej. Aplikasi boleh memanggil getLogger("pembayaran") dalam modul pembayaran dan getLogger("stok") dalam modul inventori, kemudian menapis log mengikutnya.
Apabila anda meminta kategori yang tidak dikonfigurasi, logger itu mewarisi tetapan root logger. Ini bermakna anda boleh memulakan dengan root yang longgar dan hanya mengetatkan atau melonggarkan kategori tertentu kemudian, tanpa menyentuh kod yang memanggil getLogger().
Appender: ke mana mesej pergi
Appender ialah destinasi mesej. LogBox membekalkan beberapa appender siap guna: ConsoleAppender untuk output standard, FileAppender untuk fail di cakera, ScopeAppender untuk menyimpan mesej dalam skop CFML seperti request atau application, DBAppender untuk jadual pangkalan data, dan EmailAppender untuk menghantar mesej melalui mel. Setiap appender boleh diberi aras minimum dan maksimum sendiri, jadi satu appender boleh menerima hanya ralat manakala satu lagi menerima semuanya.
Satu logger boleh menghantar mesej kepada lebih daripada satu appender. Corak biasa ialah menulis mesej ke fail untuk arkib jangka panjang dan pada masa yang sama menyimpannya dalam skop untuk pemeriksaan segera. Konfigurasi struct di bawah menunjukkan cara menggabungkan kedua-duanya.
Konfigurasi berstruktur dengan struct
Cara paling mudah untuk mengkonfigurasi LogBox tanpa fail konfigurasi berasingan ialah menghantar struct kepada pembina. Struct itu mempunyai tiga kunci utama: appenders, root, dan categories. Blok berikut mendaftarkan dua appender, satu fail dan satu skop, kemudian menulis tiga mesej berstruktur dan membacanya kembali daripada skop:
<cfscript>
config = {
appenders = {
"failApl" = {
class = "FileAppender",
properties = { filePath = "/tmp", fileName = "kedai", autoExpand = false },
levelMax = "DEBUG"
},
"skop" = {
class = "ScopeAppender",
properties = { scope = "request", key = "logKedai", limit = 20 },
levelMax = "DEBUG"
}
},
root = { levelMax = "INFO", appenders = "*" },
categories = {
"pembayaran" = { levelMax = "DEBUG", appenders = "*" }
}
};
lb = new coldbox.system.logging.LogBox(config);
logger = lb.getLogger("pembayaran");
logger.debug("Mula sahkan bayaran");
logger.info("Bayaran diterima", { pesanan = 123, gerbang = "FPX", jumlah = 19.90 });
logger.error("Bayaran ditolak", { pesanan = 124, sebab = "dana tidak cukup" });
for (entri in request.logKedai) {
writeOutput(entri.severity & " | " & entri.category & " | " & entri.message & "<br>");
}
</cfscript>
Kategori pembayaran ditetapkan pada aras maksimum DEBUG, jadi mesej debug juga dicatat, manakala kategori lain yang jatuh kepada root kekal pada aras INFO. Keluaran blok ini menunjukkan tiga baris, satu untuk setiap mesej, dengan medan keterukan dan kategori yang boleh ditapis.
Appender fail dan format CSV
FileAppender menulis fail teks dalam format CSV, dengan baris pengepala Severity, Appender, Date, Time, Category, dan Message. Fail ini dicipta serta-merta apabila appender didaftarkan. Dalam aplikasi ColdBox penuh, baris mesej ditulis oleh pendengar latar belakang yang memproses baris gilir, jadi mesej sampai ke fail dalam masa singkat tanpa menyekat permintaan.
Dua sifat penting dalam konfigurasi fail ialah filePath dan fileName. filePath ialah direktori tujuan, manakala fileName ialah nama asas tanpa sambungan, kerana LogBox menambah .log sendiri. Sifat autoExpand mengawal sama ada laluan itu diperluas dengan expandPath(). Dalam contoh di atas, autoExpand ditetapkan false kerana laluan /tmp sudah mutlak; untuk laluan relatif seperti logs, biarkan ia true. Jangan masukkan laluan atau rahsia terus ke dalam kod; simpan dalam pemboleh ubah persekitaran seperti yang diterangkan dalam panduan rahsia dan pemboleh ubah persekitaran.
Menulis log berstruktur dengan extraInfo
Argumen kedua kepada setiap kaedah log ialah extraInfo, satu struct yang disimpan bersama mesej. Dalam contoh di atas, mesej bayaran membawa struct { pesanan = 123, gerbang = "FPX", jumlah = 19.90 }. Dengan tetapan lalai, struct ini diserikan sebagai JSON sebelum disimpan, jadi anda boleh menyimpan data berstruktur tanpa membina rentetan secara manual.
Ini kunci kepada log yang boleh dicari. Daripada menulis mesej seperti "Bayaran 123 gagal sebab dana tidak cukup", anda menulis mesej ringkas "Bayaran ditolak" dan meletakkan 123 serta sebabnya dalam extraInfo. Carian kemudian boleh menapis mengikut medan dan bukannya menghuraikan rentetan. Konsep ini sama dengan log audit, cuma log audit menyimpan rekod kekal dalam pangkalan data; baca log audit dalam CFML untuk perbezaan penuh antara kedua-duanya.
Mencari dan menapis log berstruktur
Sebab anda menyimpan log dalam struct berstruktur ialah carian. ScopeAppender menyimpan setiap entri sebagai struct dengan medan severity, category, message, dan extraInfo, jadi anda boleh menapis dengan fungsi filter() sebelum memaparkan. Blok berikut mencatat tiga mesej daripada dua kategori, kemudian menapis hanya yang beraras ERROR:
<cfscript>
config = {
appenders = {
"skop" = {
class = "ScopeAppender",
properties = { scope = "request", key = "logCarian", limit = 50 },
levelMax = "DEBUG"
}
},
root = { levelMax = "INFO", appenders = "*" },
categories = {
"pembayaran" = { levelMax = "DEBUG", appenders = "*" }
}
};
lb = new coldbox.system.logging.LogBox(config);
pembayaran = lb.getLogger("pembayaran");
stok = lb.getLogger("stok");
pembayaran.info("Bayaran diterima", { pesanan = 123, gerbang = "FPX" });
pembayaran.error("Bayaran ditolak", { pesanan = 124 });
stok.warn("Stok produk 45 hampir habis");
ralat = request.logCarian.filter(function(entri) {
return entri.severity == "ERROR";
});
for (entri in ralat) {
writeOutput(entri.severity & " | " & entri.category & " | " & entri.message & "<br>");
}
</cfscript>
Satu baris ralat sahaja yang dipaparkan, walaupun tiga mesej dicatat. Corak yang sama boleh dibaca daripada FileAppender dengan menghuraikan CSV atau daripada DBAppender dengan pertanyaan SQL, jadi pilihan appender tidak mengubah cara anda mencari, hanya tempat data disimpan.
Bila tidak menggunakan LogBox
LogBox bukan pengganti untuk mengendalikan ralat. Ia merekodkan ralat, tetapi ia tidak menangkap dan memulihkan ralat itu. Untuk menangkap pengecualian dan memutuskan apa yang berlaku seterusnya, gunakan cftry dan cfcatch seperti dalam panduan pengendalian ralat dengan cftry.
LogBox juga bukan alat untuk mencatat setiap baris dalam gelung panas. Setiap panggilan log membina objek peristiwa dan menyalurkannya melalui appender, jadi DEBUG dalam gelung panas menambah beban yang boleh diukur. Kekalkan aras yang sesuai dan matikan DEBUG pada pengeluaran. Apabila log menjadi punca kelambatan, pertimbangkan dahulu strategi caching dan prestasi sebelum menyalahkan enjin.
Soalan Lazim
Apakah perbezaan antara LogBox dan cflog?
cflog dan writeLog ialah fungsi teras Lucee yang menulis satu mesej rata ke satu fail. LogBox ialah pustaka berasingan yang memberi aras keterukan, kategori bernama, dan appender berbilang, jadi ia sesuai apabila log anda perlu dibahagikan dan dicari secara berstruktur.
Bolehkah LogBox berjalan tanpa ColdBox?
Boleh. Anda mencipta tika dengan new coldbox.system.logging.LogBox() dalam mana-mana templat CFML, selagi pemetaan coldbox tersedia. Anda tidak perlu memasang rangka kerja ColdBox penuh.
Apakah itu kategori dalam LogBox?
Kategori ialah label bernama yang anda hantar kepada getLogger(), contohnya pembayaran atau stok. Ia menjadi medan dalam setiap mesej dan membolehkan anda menapis log mengikut bahagian aplikasi.
Apakah itu appender dan bagaimana memilihnya?
Appender ialah destinasi mesej log. Pilih FileAppender untuk arkib di cakera, ScopeAppender untuk pemeriksaan segera dalam skop CFML, DBAppender untuk carian SQL, dan ConsoleAppender untuk output standard semasa pembangunan.
Bagaimana cara menulis mesej log yang boleh dicari?
Guna argumen extraInfo untuk menyimpan data berstruktur seperti { pesanan = 123, gerbang = "FPX" } bersama mesej ringkas. Kemudian tapis mengikut medan seperti severity atau category, dan bukannya menghuraikan rentetan mesej.