Membedah logging dan debugging Rails: log levels, structured log untuk production, gem debug dan breakpoints, byebug sebagai alternatif, serta troubleshooting via console

Setelah di episode 16 kalian mengelola konfigurasi, episode 17 membahas keterampilan yang menentukan cepat tidaknya kalian menemukan bug: logging & debugging. Aplikasi produksi tidak memberi kalian binding.pry — yang kalian punya adalah log. Kemampuan membaca log dan men-debug secara sistematis adalah pembeda developer senior.
Mengapa episode ini penting? Karena sebagian besar waktu kerja software engineer dihabiskan bukan untuk menulis fitur, melainkan mencari tahu mengapa sesuatu tidak bekerja. Log yang terstruktur dan teknik debugging yang benar mengubah proses itu dari menebak-nebak menjadi investigasi terarah.
Setiap request produksi menghasilkan log seperti ini di log/production.log:
Started GET "/posts/1" for 203.0.113.5 at 2026-08-16 08:12:30 +0700
Processing by PostsController#show as HTML
Parameters: {"id"=>"1"}
Post Load (0.8ms) SELECT "posts".* FROM "posts" WHERE "posts"."id" = ? LIMIT ?
Rendered posts/show.html.erb (Duration: 4.2ms)
Completed 200 OK in 15ms (Views: 5ms | ActiveRecord: 1ms)Info kunci di tiap request: waktu, IP, method+path, controller/action, parameters, query SQL + durasi, dan status akhir. Membaca log seperti ini adalah keterampilan dasar — pola Started → Processing → Completed menunjukkan satu siklus request.
Rails mendukung level log standar: debug, info, warn, error, fatal, unknown. Konfigurasi di environment:
config.log_level = :info| Level | Dipakai Untuk |
|---|---|
debug | Detail pengembangan — query, verbose (hanya development) |
info | Informasi umum — request start/completed |
warn | Peringatan yang tidak fatal |
error | Exception & kegagalan |
fatal | Crash yang menghentikan proses |
Membuat log sendiri di aplikasi:
Rails.logger.info("Post #{post.id} dihapus oleh user #{user.id}")
Rails.logger.warn("Rate limit mendekati batas untuk IP #{request.remote_ip}")
Rails.logger.error("Gagal mengirim email: #{error.message}")Gunakan level yang tepat — jangan info untuk semua hal (log banjir = noise) dan jangan debug untuk error penting.
Log teks biasa sulit di-parse otomatis. Structured logging menulis log sebagai JSON — mudah difilter, di-agregasi, dan di-alert oleh tooling (Datadog, Loki, OpenSearch). Rails mendukungnya via lograge:
config.lograge.enabled = true
config.lograge.formatter = Lograge::Formatters::Json.newOutput yang dihasilkan:
{
"method": "GET",
"path": "/posts/1",
"status": 200,
"duration": 15.2,
"controller": "posts",
"action": "show",
"db": 1.0,
"ip": "203.0.113.5"
}Keunggulannya: bisa di-query (status:500 AND controller:payment), di-alert otomatis, dan tidak bergantung pada format teks yang berubah-ubah. Untuk kebutuhan observability penuh (metrics, tracing), episode 24 akan melengkapi.
Rails 8 menyertakan debug gem sebagai debugger default. Titik berhenti disisipkan di kode:
def create
@post = Post.new(post_params)
debugger # <- eksekusi berhenti di sini
if @post.save
redirect_to @post, notice: "Berhasil"
else
render :new, status: :unprocessable_entity
end
endSaat request mencapai debugger, eksekusi berhenti dan kalian masuk REPL — bisa memeriksa @post, params, memanggil method, dan melanjutkan dengan perintah:
[1, 8] in app/controllers/posts_controller.rb
=> 5 debugger
@post.inspect
#<Post id: nil, title: "Judul", body: "Isi", ...>
@post.valid?
# false
@post.errors.full_messages
# ["Title can't be blank"]Kombinasi debugger + @post.errors adalah cara tercepat menemukan kenapa validasi gagal.
Tip
Gunakan debugger hanya saat menulis kode — hapus sebelum commit. Di production, debugger tidak akan bekerja (debug gem hanya di-load di development/test); pastikan pemanggilannya juga hanya aktif di environment non-production.
Sebelum debug gem, standar Rails adalah byebug. Sintaksnya mirip:
def update
@post = Post.find(params[:id])
byebug
@post.update!(post_params)
endKeduanya memberi REPL interaktif dengan command next, step, continue, display, p. debug gem adalah pengganti resmi byebug sejak Rails 7 — pakai debug untuk project baru, pahami byebug karena masih banyak codebase lama memakainya.
bin/rails console adalah senjata utama investigasi produksi (dengan hati-hati):
post = Post.find_by(id: 42)
post.inspect
post.errors.full_messages if post.invalid?
Post.where("created_at > ?", 1.day.ago).count
Rails.logger.warn("investigasi selesai")Console memuat seluruh aplikasi — kalian bisa memanggil model, job, mailer, dan mengecek credentials. Untuk production, console read-only adalah kebiasaan baik: jalankan query untuk investigasi, hindari menulis data langsung.
puts untuk debugging — tidak memberi konteks stack; gunakan Rails.logger atau debugger.debug level di production — banjir log dan mahal; set :info.p/pp di kode — meninggalkan output sampah; gunakan logger yang terkontrol.debugger/byebug sebelum commit.backtrace saat menangkap exception.Episode 17 membekali kalian observasi Rails: membaca log request (Started → Completed), log levels dengan konfigurasi tepat, structured logging via lograge untuk production, gem debug dengan breakpoints interaktif, dan troubleshooting via console.
Inti yang harus dibawa pulang:
:info.debugger (gem debug) memberi REPL; hapus sebelum commit.Di episode 18 selanjutnya kita akan membedah security best practices — SQLi, XSS, CSRF, mass assignment, dan security headers, plus praktik audit & hardening. Sampai jumpa di episode 18!