Aplikasi yang sudah berjalan di server tidak lagi dapat diamati dengan debugger, melainkan melalui jejak yang dicatatnya sendiri. Topik ini membahas kanal log pada Laravel beserta konfigurasi stack, single, dan daily, cara menulis entri log dengan konteks, serta posisi Telescope dan layanan monitoring dalam observabilitas aplikasi. Setelah topik ini dibaca, berkas laravel.log pada aplikasi catatan dapat ditulis dan dibaca secara terstruktur, dan alat yang tepat untuk tiap lingkungan dapat dipilih dengan alasannya.
Kanal log dan konfigurasinya#
Kanal log adalah satu tujuan penulisan log dengan driver tertentu, misalnya berkas tunggal, berkas per hari, atau stderr. Seluruh konfigurasinya berada pada berkas config/logging.php, dan kanal yang aktif ditentukan oleh kunci default yang membaca variabel lingkungan LOG_CHANNEL. Aplikasi catatan menggunakan nilai bawaan berikut, yang membuat log ditulis ke storage/logs/laravel.log.
LOG_CHANNEL=stack
LOG_STACK=single
LOG_LEVEL=debugNilai stack berarti kanal yang aktif adalah kanal penumpuk (stack), yaitu kanal yang meneruskan satu entri log ke beberapa kanal sekaligus. Isi daftarnya dibaca dari LOG_STACK, yang pada aplikasi catatan hanya berisi single, yakni driver yang menulis ke satu berkas tanpa rotasi. Bagian konfigurasi kanal pada config/logging.php yang bersangkutan berbentuk berikut.
// tidak-dijalankan
'stack' => [
'driver' => 'stack',
'channels' => explode(',', (string) env('LOG_STACK', 'single')),
'ignore_exceptions' => false,
],
'single' => [
'driver' => 'single',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
],
'daily' => [
'driver' => 'daily',
'path' => storage_path('logs/laravel.log'),
'level' => env('LOG_LEVEL', 'debug'),
'max_files' => env('LOG_DAILY_DAYS', 14),
],Setiap baris log yang dihasilkan oleh ketiga driver tersebut menggunakan format yang sama, yaitu stempel waktu diapit tanda kurung, nama kanal diikuti level, pesan, lalu konteks berbentuk JSON. Kunci level pada setiap kanal membatasi entri yang dicatat, karena level log tersusun dari debug, info, notice, warning, error, critical, alert, hingga emergency, dan entri yang levelnya di bawah batas kanal tidak ditulis.
Menulis dan membaca entri log#
Penulisan log dilakukan melalui facade Log dengan satu method per level, yaitu Log::info(), Log::warning(), dan Log::error() untuk tiga level yang paling sering digunakan. Argumen pertamanya adalah pesan, sedangkan argumen kedua yang bersifat opsional adalah array konteks, yakni data tambahan yang mengikat pesan ke kejadian konkret. Blok berikut menulis tiga entri uji ke kanal aktif, lalu membaca kembali hasilnya dari berkas laravel.log. Pesan uji disaring dan stempel waktunya dihapus agar keluarannya ringkas.
# menulis tiga entri log dan membacanya kembali dari laravel.log
cd ~/aplikasi-catatan
php artisan tinker --execute='
use Illuminate\Support\Facades\Log;
Log::info("Uji kanal: aplikasi catatan dimulai");
Log::warning("Uji kanal: stok cadangan menipis", ["sisa" => 3]);
Log::error("Uji kanal: gagal mengekspor catatan");
echo "Tiga entri ditulis." . PHP_EOL;
'
# menampilkan entri uji tanpa stempel waktunya
grep "Uji kanal" storage/logs/laravel.log | tail -n 3 | sed -E "s/^\[[^]]*\] //"Tiga entri ditulis.
local.INFO: Uji kanal: aplikasi catatan dimulai
local.WARNING: Uji kanal: stok cadangan menipis {"sisa":3}
local.ERROR: Uji kanal: gagal mengekspor catatanAwalan local pada setiap baris adalah nama kanal Monolog, yaitu library log yang mendasari Laravel, dan namanya diambil dari lingkungan aplikasi pada APP_ENV. Konteks {"sisa":3} menyatu dengan pesan tanpa perlu dirangkai manual, sehingga pesan tetap kalimat utuh yang mudah dicari dengan grep. Pola yang sama digunakan ketika satu kejadian menghasilkan beberapa entri yang harus saling terkait.
Log::withContext() menyematkan konteks yang berlaku untuk seluruh entri berikutnya pada proses tersebut, sehingga penanda yang sama tidak perlu diulang pada setiap panggilan. Kasus yang lazim adalah penanda permintaan atau id pengguna yang aktif.
# menyematkan konteks yang berlaku untuk beberapa entri sekaligus
cd ~/aplikasi-catatan
php artisan tinker --execute='
use Illuminate\Support\Facades\Log;
Log::withContext(["permintaan" => "ekspor-catatan"]);
Log::info("Uji kanal: ekspor dimulai");
Log::info("Uji kanal: ekspor selesai");
echo "Dua entri dengan konteks ditulis." . PHP_EOL;
'
# menampilkan entri uji tanpa stempel waktunya
grep "Uji kanal: ekspor" storage/logs/laravel.log | tail -n 2 | sed -E "s/^\[[^]]*\] //"Dua entri dengan konteks ditulis.
local.INFO: Uji kanal: ekspor dimulai {"permintaan":"ekspor-catatan"}
local.INFO: Uji kanal: ekspor selesai {"permintaan":"ekspor-catatan"}Konteks bersama tersebut digabungkan dengan konteks per entri, sehingga Log::info("pesan", ["sisa" => 1]) setelahnya membawa keduanya pada baris yang sama. Apabila satu entri perlu ditulis ke kanal lain tanpa mengubah LOG_CHANNEL, method Log::channel("daily") mengarahkan pemanggilan berikutnya ke kanal yang disebutkan.
Rotasi berkas dengan kanal daily#
Kanal single menulis ke satu berkas yang tumbuh tanpa batas, sedangkan aplikasi produksi yang sehat memutar berkasnya secara berkala. Kanal daily menyelesaikannya dengan membuat satu berkas per hari, misalnya laravel-2026-11-04.log, lalu menghapus berkas-berkas yang lebih tua daripada batas penyimpanannya. Batas tersebut diatur oleh LOG_DAILY_DAYS dan bawaannya 14 hari.
Nama berkasnya mengikuti tanggal penerbitan menurut zona waktu aplikasi, sehingga seluruh entri pada hari yang sama menumpuk di satu berkas dan berkas baru terbentuk begitu harinya berganti. Rotasi ini menjaga ruang disk tetap terkendali tanpa tugas cron tambahan, karena penghapusan berkas kedaluwarsa menjadi bagian dari driver-nya. Perintah penelusuran pun menjadi ringan, karena berkas yang dibaca kecil dan isinya terbatas pada hari itu saja, sedangkan daftar berkas yang masih ada dapat dilihat dengan ls storage/logs.
Peralihan ke kanal daily cukup dilakukan dengan mengubah LOG_CHANNEL=daily pada berkas .env, atau dengan menambahkannya ke daftar LOG_STACK apabila penulisan ke kanal single juga perlu diteruskan. Konfigurasi produksi yang lazim menempatkan daily sebagai satu-satunya anggota stack, sedangkan lingkungan yang berjalan dalam kontainer menambahkan stderr agar log ikut dialirkan ke pengelola proses.
Posisi Telescope dalam observabilitas#
Log hanya memuat kejadian yang secara sadar ditulis, sedangkan banyak pertanyaan debugging menuntut rekaman lengkap atas apa yang terjadi di dalam aplikasi. Telescope adalah package resmi Laravel yang merekam permintaan HTTP, query, job, dan exception ke dalam tabel database, kemudian menyajikannya sebagai dashboard pada rute /telescope. Rekaman itu tersedia tanpa satu pun pemanggilan Log tambahan, sehingga alur yang tidak terduga dapat ditelusuri mundur dari daftarnya.
# tidak-dijalankan
# menginstal Telescope sebagai dependensi pengembangan
composer require laravel/telescope --dev
php artisan telescope:install
php artisan migrateKetiga alat observabilitas pada aplikasi catatan memiliki posisi yang berbeda sebagaimana dirangkum diagram berikut.
| Aspek | Log berkas | Telescope | Layanan monitoring |
|---|---|---|---|
| Isi catatan | Kejadian yang ditulis Log | Permintaan, query, job, exception | Agregasi log dan error terkirim |
| Lingkungan utama | Produksi | Pengembangan | Produksi |
| Tempat penyimpanan | Berkas teks di server | Tabel database aplikasi | Layanan eksternal |
| Kekuatan | Ringan, bertahan lama | Alur lengkap tanpa kode tambahan | Alert dan tren lintas waktu |
Telescope tidak dimaksudkan untuk menjadi pengganti log pada produksi, karena rekamannya memenuhi database dan tidak memicu peringatan apa pun saat terjadi error. Pola penggunaannya adalah Telescope untuk menyelidiki alur pada lingkungan pengembangan, log sebagai jejak utama produksi, dan layanan monitoring untuk agregasi serta alert ketika pencarian log manual tidak lagi memadai.
Kesalahan umum#
Kesalahan pertama adalah mencatat data sensitif ke dalam konteks log, misalnya kata sandi, token, atau isi penuh header. Berkas laravel.log dibaca banyak pihak dan disalin ke berbagai tempat saat masalah diselidiki, sehingga data rahasia ikut menyebar. Konteks yang dicatat cukup berupa penanda, seperti id pengguna dan nama tindakan, sementara nilai rahasia tidak ditulis sama sekali.
Kesalahan kedua adalah memasang Telescope pada produksi sebagai alat observabilitas utama. Tabelnya membengkak seiring trafik, setiap permintaan ditulis ulang ke database, dan error yang muncul tidak menimbulkan notifikasi apa pun. Telescope sebaiknya dipasang sebagai dependensi pengembangan, sedangkan jejak produksi diserahkan pada log dan layanan pelaporan error.
Kesalahan ketiga adalah terus menelusuri laravel.log setelah kanal beralih ke daily. Berkas dengan nama itu berhenti ditulis karena entri harian berpindah ke berkas bertanggal, sehingga perintah tail pada berkas lama tidak lagi menampilkan entri baru. Pastikan kanal yang aktif sebelum menelusuri, atau gunakan php artisan config:show logging untuk melihat konfigurasi yang berlaku.
Ringkasan#
- Kanal log aktif ditentukan oleh
LOG_CHANNEL, denganstackyang meneruskan entri ke beberapa kanal,singleyang menulis satu berkas, dandailyyang memutar berkas per hari dengan batasLOG_DAILY_DAYS. - Baris log memuat stempel waktu, kanal beserta levelnya, pesan, dan konteks JSON, sedangkan
Log::withContext()menyematkan konteks yang berlaku untuk entri berikutnya. - Telescope merekam permintaan, query, job, dan exception untuk diselidiki pada dashboard pengembangan, tanpa menggantikan log produksi.
- Log berkas, Telescope, dan layanan monitoring memiliki posisi berbeda, yaitu jejak produksi, rekaman pengembangan, dan agregasi beserta alert.
Referensi#
- Logging — Laravel
— Dokumentasi kanal log, stack, daily, dan
Log::withContext(). - Telescope — Laravel — Dokumentasi pemasangan Telescope beserta cakupan rekamannya.
- Monolog — GitHub — Library log yang dipakai Laravel, termasuk handler single dan rotating file-nya.