Logging dan monitoring

Kanal log dan posisi Telescope dalam observabilitas aplikasi.

Daftar isi

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.

env Konfigurasi log bawaan pada berkas .env
LOG_CHANNEL=stack
LOG_STACK=single
LOG_LEVEL=debug

Nilai 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.

php Definisi kanal stack, single, dan daily pada config/logging.php
// 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.

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.

bash
# 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/^\[[^]]*\] //"
text Keluaran
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 catatan

Awalan 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.

bash
# 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/^\[[^]]*\] //"
text Keluaran
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.

bash
# tidak-dijalankan
# menginstal Telescope sebagai dependensi pengembangan
composer require laravel/telescope --dev
php artisan telescope:install
php artisan migrate

Ketiga alat observabilitas pada aplikasi catatan memiliki posisi yang berbeda sebagaimana dirangkum diagram berikut.

aplikasi catatanLog::info, exception,job, querykanal logrekaman otomatiskirim lalu alertlog berkasstorage/logs/laravel.logteks per kejadian, produksiTelescopedashboard /telescopepermintaan, query, exception, devlayanan monitoringagregasi error, alert, uptimeeksternal, produksiLog, Telescope, dan layanan monitoring mengamati aplikasi yang sama dengan cakupan berbeda.
Tiga tujuan observabilitas pada aplikasi catatan
Perbedaan posisinya dapat dirangkum dalam satu tabel perbandingan.

AspekLog berkasTelescopeLayanan monitoring
Isi catatanKejadian yang ditulis LogPermintaan, query, job, exceptionAgregasi log dan error terkirim
Lingkungan utamaProduksiPengembanganProduksi
Tempat penyimpananBerkas teks di serverTabel database aplikasiLayanan eksternal
KekuatanRingan, bertahan lamaAlur lengkap tanpa kode tambahanAlert 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, dengan stack yang meneruskan entri ke beberapa kanal, single yang menulis satu berkas, dan daily yang memutar berkas per hari dengan batas LOG_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#