Troubleshooting 02 Aug 2026 45 views 0 komentar

Debug CodeIgniter 4 di Production - Panduan Lengkap Cari Bug Tanpa Panik

Debug CodeIgniter 4 di Production - Panduan Lengkap Cari Bug Tanpa Panik

Pernah nggak sih, kamu deploy aplikasi CodeIgniter 4 ke server production, eh malah muncul halaman putih kosong? Atau error 500 yang nggak jelas asal-usulnya? Kalau kamu pernah mengalami ini, tenang kamu nggak sendirian. Saya juga pernah, bahkan sampai 3 kali dalam seminggu pas awal-awal pakai CI4.

Debugging di production itu beda banget sama di localhost. Di localhost, kamu bisa dd() seenaknya, enable full error reporting, bahkan pasang Xdebug tanpa khawatir. Di production? Salah-salah, user bisa lihat stack trace lengkap beserta password database kamu. Nah, di artikel ini saya mau share cara debug aplikasi CI4 di production dengan aman dan efisien.

1. Kenali Dulu: Environment CI4

CI4 punya sistem environment yang penting banget untuk debugging. Ada 3 mode utama: development, testing, dan production. Bedanya apa? Di production, error detail disembunyiin dari user. Di development, semua error ditampilkan lengkap.

Cek environment kamu di file app/Config/Boot/production.php:


// app/Config/Boot/production.php
error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED & ~E_STRICT);
ini_set('display_errors', '0');

Kalau kamu butuh debug sementara di production, kamu bisa ubah environment lewat file .env:


# Ubah di .env (SEMENTARA SAJA!)
CI_ENVIRONMENT = development

# Setelah selesai debug, kembalikan ke:
CI_ENVIRONMENT = production

PERINGATAN: Jangan pernah biarkan CI_ENVIRONMENT = development di production lebih dari yang dibutuhkan. Error messages di mode development bisa expose informasi sensitif ke publik.

2. Membaca CI4 Log dengan Benar

Ini senjata pertama dan paling aman untuk debug di production. CI4 mencatat semua error di writable/logs/. Log file menggunakan format log-YYYY-MM-DD.php.


# Cek log terbaru
ls -la writable/logs/

# Baca log hari ini
cat writable/logs/log-$(date +%Y-%m-%d).php

# Cari error spesifik
grep -i "error\|exception\|critical" writable/logs/log-$(date +%Y-%m-%d).php

# Monitor log secara real-time
tail -f writable/logs/log-$(date +%Y-%m-%d).php

CI4 punya beberapa level log: emergency, alert, critical, error, warning, notice, info, dan debug. Level log bisa dikonfigurasi di app/Config/Logger.php:


// app/Config/Logger.php
public array $threshold = [
 1, // Emergency
 2, // Alert 
 3, // Critical
 4, // Error
 // Uncomment untuk log lebih verbose:
 // 5, // Warning
 // 6, // Notice
];

Tips: kalau kamu sedang debugging, naikkan threshold sampai level 6 (Notice). Ini bakal nangkep error yang lebih halus seperti missing variables atau deprecated function calls.

3. Custom Error Handler untuk CI4

CI4 punya sistem exception handler yang bisa kamu custom. Di production, error 500 biasanya menampilkan halaman error default yang kurang informatif. Kamu bisa buat custom error page yang lebih informatif (tanpa expose sensitif data).

Buat file app/Views/errors/html/error_500.php:


<?php
// app/Views/errors/html/error_500.php
// Custom 500 error page - log detail, tampilkan user-friendly message

// Log detail error ke file
$log_message = date('Y-m-d H:i:s') . " | ";
$log_message .= ($_SERVER['REQUEST_URI'] ?? 'unknown') . " | ";
$log_message .= ($exception->getMessage() ?? 'No message') . " | ";
$log_message .= ($exception->getFile() ?? 'unknown') . ":" . ($exception->getLine() ?? 0);

log_message('error', $log_message);
?>
<!DOCTYPE html>
<html lang="id">
<head>
 <meta charset="UTF-8">
 <title>Terjadi Kesalahan</title>
 <style>
 body { font-family: 'Segoe UI', sans-serif; background: #1a1a2e; color: #eee; display: flex; justify-content: center; align-items: center; height: 100vh; }
 .error-box { text-align: center; max-width: 500px; }
 h1 { font-size: 72px; color: #e94560; margin: 0; }
 p { color: #adb5bd; line-height: 1.6; }
 </style>
</head>
<body>
 <div class="error-box">
 <h1>500</h1>
 <p>Maaf, terjadi kesalahan di server. Tim kami sudah diberitahu dan sedang menanganinya.</p>
 <p><a href="/" style="color:#e94560;">Kembali ke Beranda</a></p>
 </div>
</body>
</html>

Dengan cara ini, user melihat pesan yang ramah sementara detail error tetap tercatat di log file untuk kamu analisis.

4. Debugging Database Query di CI4

Error database itu tricky. Kadang query gagal tapi nggak ada error message yang jelas. CI4 punya beberapa tools untuk ini.

Last Query: Untuk melihat query terakhir yang dijalankan:


// Di controller atau model
$db = \Config\Database::connect();
$query = $db->getLastQuery();
echo $query->getQuery(); // Tampilkan SQL string

// Atau dengan query builder
$builder = $db->table('blog_posting');
$builder->where('Not_Active', 0);
$result = $builder->get();

// Debug: lihat query yang di-generate
echo $db->getLastQuery()->getQuery();
// Output: SELECT * FROM blog_posting WHERE Not_Active = 0

Simple Query Logging: Aktifkan query logging di app/Config/Database.php:


// app/Config/Database.php
public bool $debug = true; // Aktifkan di production SEMENTARA

// Query akan tercatat di:
// $db->getQueries() array of query strings

Gunakan getQueries() untuk melihat semua query yang dijalankan dalam satu request:


// Di controller, setelah semua query selesai
$db = \Config\Database::connect();
$queries = $db->getQueries();

// Log semua query (aman untuk production)
log_message('debug', 'Queries executed: ' . count($queries));
foreach ($queries as $i => $q) {
 log_message('debug', "Q{$i}: {$q}");
}

5. SSH Tunneling untuk Debug Remote Database

Kadang kamu perlu cek database production langsung, tapi port MySQL nggak boleh dibuka ke publik. Solusinya: SSH tunneling.


# Buka SSH tunnel dari laptop kamu
ssh -L 3307:127.0.0.1:3306 [email protected]

# Di terminal lain, connect ke database lewat tunnel
mysql -h 127.0.0.1 -P 3307 -u appuser -p nama_database

# Atau pakai MySQL Workbench / DBeaver:
# Host: 127.0.0.1
# Port: 3307
# (bukan 3306!)

Dengan SSH tunnel, kamu bisa pakai GUI tools seperti DBeaver atau MySQL Workbench untuk query database production dengan aman. Semua traffic ter-encrypt lewat SSH.

6. Debugging Nginx + PHP-FPM Issues

Error 500 di CI4 kadang bukan dari PHP-nya, tapi dari konfigurasi Nginx atau PHP-FPM. Ini pattern yang sering saya temui:

Cek Nginx error log:


# Nginx error log
sudo tail -f /var/log/nginx/error.log

# PHP-FPM error log
sudo tail -f /var/log/php8.1-fpm.log

# Cek apakah PHP-FPM running
sudo systemctl status php8.1-fpm

# Cek Nginx config syntax
sudo nginx -t

# Restart setelah perubahan config
sudo systemctl restart nginx php8.1-fpm

Common issue: permission denied


# CI4 writable/ folder harus bisa ditulis oleh PHP-FPM
sudo chown -R www-data:www-data writable/
sudo chmod -R 755 writable/

# Cek owner dan permission
ls -la writable/
# Harus: drwxr-xr-x www-data www-data

# Kalau masih error, cek SELinux (di CentOS/RHEL)
getenforce
# Kalau Enforcing, tambahkan:
sudo setsebool -P httpd_can_network_connect 1

Common issue: PHP-FPM pool exhausted


# Cek apakah PHP-FPM pool habis
sudo grep "max_children" /var/log/php8.1-fpm.log

# Naikkan limit di /etc/php/8.1/fpm/pool.d/www.conf
pm.max_children = 50 # Default biasanya 5
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20

# Restart PHP-FPM
sudo systemctl restart php8.1-fpm

7. Remote Debugging dengan Xdebug + SSH

Ini teknik advanced yang sangat powerful. Kamu bisa debug kode production langsung dari VS Code di laptop kamu, dengan breakpoint dan step-through.

Setup di server production:


# Install Xdebug (jika belum)
sudo pecl install xdebug

# Tambahkan di php.ini (HAPUS SETELAH SELESAI!)
zend_extension=xdebug
xdebug.mode=debug
xdebug.client_host=127.0.0.1
xdebug.client_port=9003
xdebug.start_with_request=yes

# Restart PHP-FPM
sudo systemctl restart php8.1-fpm

Setup SSH tunnel untuk Xdebug:


# Dari laptop kamu, buka tunnel untuk Xdebug
ssh -R 9003:127.0.0.1:9003 [email protected]

# Artinya: traffic dari server port 9003 laptop port 9003
# Xdebug di server akan "menelpon" laptop kamu

Setup VS Code:


// .vscode/launch.json
{
 "version": "0.2.0",
 "configurations": [
 {
 "name": "Listen for Xdebug",
 "type": "php",
 "request": "launch",
 "port": 9003,
 "pathMappings": {
 "/var/www/html": "${workspaceFolder}"
 }
 }
 ]
}

Sekarang kamu bisa set breakpoint di VS Code, dan ketika server production menjalankan kode sampai breakpoint tersebut, VS Code akan berhenti dan menampilkan semua variable state. Ini jauh lebih powerful daripada dd() atau print_r().

PENTING: Hapus Xdebug dari production setelah selesai debug! Xdebug menambah overhead signifikan pada performa PHP.

8. Debugging CI4 Route Issues

Route 404 padahal kamu yakin sudah benar? Ini masalah klasik di CI4. Beberapa kemungkinan:


# Cek semua registered routes
php spark routes

# Output akan menampilkan:
# +--------+-----------------------------------+...
# | Method | Route |...
# +--------+-----------------------------------+...
# | GET | / |...
# | GET | blog/post/(:any) |...
# | GET | blog/category/(:any) |...
# +--------+-----------------------------------+...

Kalau route tidak muncul di php spark routes, berarti belum ter-register. Cek app/Config/Routes.php:


// app/Config/Routes.php
// Cek apakah route sudah benar
$routes->get('blog/post/(:any)', 'Blog::post/$1');
$routes->get('blog/category/(:any)', 'Blog::category/$1');

// Pitfall: urusan trailing slash!
// '/blog/about' dan '/blog/about/' beda route di CI4
// Gunakan redirect untuk handle keduanya:
$routes->get('blog/about', 'Blog::about');
$routes->get('blog/about/', 'Blog::about');

Tips: kalau kamu pakai Nginx sebagai reverse proxy, pastikan Nginx mengirim REQUEST_URI yang benar ke PHP-FPM. Seringkali Nginx menghapus prefix /blog/ sebelum dikirim ke CI4, sehingga CI4 melihat /post/slug bukan /blog/post/slug.

9. Performance Debugging: Profiling CI4

Kadang aplikasi jalan tapi lambat. CI4 punya built-in profiler yang sangat berguna:


// Aktifkan profiler di controller
$this->benchmark->mark('start_query');
$result = $model->getAllPosts();
$this->benchmark->mark('end_query');

// Hitung waktu eksekusi
$elapsed = $this->benchmark->getElapsedTime('start_query', 'end_query');
log_message('info', "Query took {$elapsed} seconds");

// Atau gunakan CI4 Toolbar (development only)
// Ditampilkan otomatis di mode development

Query profiling dengan MySQL:


-- Aktifkan slow query log
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1; -- Query > 1 detik dicatat

-- Cek slow queries
-- File: /var/log/mysql/slow.log

-- Analisis query dengan EXPLAIN
EXPLAIN SELECT * FROM blog_posting WHERE Not_Active = 0 ORDER BY Created_Date DESC;
-- Cek kolom "type" kalau "ALL" berarti full table scan (buruk!)
-- Tambahkan index:
ALTER TABLE blog_posting ADD INDEX idx_active_date (Not_Active, Created_Date);

10. Checklist Debug Production CI4

Sebelum panic saat error terjadi, ikuti checklist ini:

  • Step 1: Cek log CI4 di writable/logs/ ini sumber informasi pertama dan paling aman
  • Step 2: Cek Nginx error log di /var/log/nginx/error.log
  • Step 3: Cek PHP-FPM log di /var/log/php8.1-fpm.log
  • Step 4: Cek permission folder writable/ harus bisa ditulis oleh www-data
  • Step 5: Jalankan php spark routes pastikan route terdaftar
  • Step 6: Cek .env file pastikan database credentials benar
  • Step 7: Restart PHP-FPM dan Nginx kadang cache bikin aneh
  • Step 8: Kalau semua gagal, nyalakan CI_ENVIRONMENT = development SEBENTAR untuk lihat detail error

Kesimpulan>

Debugging di production memang stressful, tapi dengan workflow yang benar, kamu bisa menemukan dan fix bug dengan cepat tanpa mengganggu user. Kuncinya: selalu mulai dari log, jangan langsung ubah environment ke development, dan pastikan kamu punya akses yang aman ke server (SSH tunnel).

Satu hal yang sering dilupakan developer: dokumentasikan setiap bug yang kamu temui dan cara menyelesaikannya. Tambahkan ke internal wiki atau notes. Dalam 3 bulan ke depan, kemungkinan besar kamu akan menghadapi error yang sama lagi, dan notes ini bisa menghemat berjam-jam debugging.

Punya tips debugging CI4 production yang lain? Atau pernah mengalami bug aneh yang bikin kamu geleng-geleng? Share di kolom komentar siapa tahu bisa membantu developer lain yang sedang struggle dengan masalah serupa.


Bagikan artikel ini:

Komentar (0)

Belum ada komentar. Jadilah yang pertama memberikan tanggapan!

Tinggalkan Komentar