Saat aplikasi Python-mu mulai tumbuh, menabur print() di sana-sini untuk "melihat" apa yang terjadi tidak lagi cukup. Kamu butuh cara yang lebih terstruktur untuk mencatat apa yang sedang berjalan di dalam program — baik untuk debugging, memantau aplikasi yang berjalan di production, maupun mengaudit kejadian penting. Di sinilah modul logging berperan. Pada tutorial ini, kamu akan belajar menggunakan modul logging bawaan Python secara lengkap: dari konfigurasi dasar, level log, hingga menulis log ke file dengan rotasi otomatis.

Mengapa Logging, Bukan print()?

Sekilas, print() dan logging tampak sama: keduanya menampilkan teks ke layar. Namun ada perbedaan mendasar. print() selalu mencetak ke stdout dan tidak bisa dibedakan berdasarkan tingkat kepentingan. Sementara logging punya level (DEBUG, INFO, WARNING, ERROR, CRITICAL), bisa dikirim ke banyak tujuan sekaligus (konsol, file, layanan eksternal), dan bisa dimatikan tanpa mengubah satu baris kode pun. Bayangkan kamu menyisipkan puluhan print() untuk debugging lalu harus menghapusnya satu per satu sebelum rilis — dengan logging, kamu cukup mengubah satu level konfigurasi.

Konfigurasi Dasar dengan basicConfig

Cara termudah memulai logging adalah dengan basicConfig(). Fungsi ini menyiapkan konfigurasi global sederhana yang cukup untuk kebanyakan skrip kecil.

import logging

# Konfigurasi dasar: tampilkan pesan dengan level INFO ke atas
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(levelname)s - %(message)s",
)

logging.debug("Ini pesan debug (tidak akan tampil)")
logging.info("Aplikasi berhasil dijalankan")
logging.warning("Perhatian: penggunaan memori tinggi")
logging.error("Gagal menyimpan data ke database")

Jalankan kode di atas dan kamu akan melihat tiga baris log — INFO, WARNING, dan ERROR — tetapi bukan DEBUG. Ini karena level=logging.INFO hanya menampilkan pesan dengan tingkat INFO ke atas.

Memahami Level Logging

Urutan level dari yang paling rendah ke paling tinggi adalah: DEBUG < INFO < WARNING < ERROR < CRITICAL. Semakin tinggi level yang kamu set, semakin sedikit pesan yang ditampilkan.

python
import logging

logging.basicConfig(level=logging.WARNING)

logging.debug("DEBUG: detail untuk developer")
logging.info("INFO: informasi umum")
logging.warning("WARNING: sesuatu yang patut diperhatikan")
logging.error("ERROR: terjadi masalah")
logging.critical("CRITICAL: kegagalan fatal")

Dengan level=logging.WARNING, hanya pesan WARNING ke atas yang dicetak. Aturan praktisnya: gunakan DEBUG untuk detail saat pengembangan, INFO untuk kejadian normal di production, dan ERROR/CRITICAL untuk masalah yang butuh perhatian segera.

Logger, Handler, dan Formatter

Konsep inti logging terdiri dari tiga bagian: Logger (titik masuk pesan log), Handler (tujuan pengiriman, misalnya konsol atau file), dan Formatter (penentu format teks). Dengan memisahkan ketiganya, kamu bisa mengirim log yang sama ke banyak tempat dengan format berbeda.

python
import logging

# Buat logger khusus untuk modul ini
logger = logging.getLogger("aplikasi_ku")
logger.setLevel(logging.DEBUG)

# Handler untuk menulis ke konsol
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)

# Formatter menentukan format teks log
formatter = logging.Formatter(
    "%(asctime)s | %(name)s | %(levelname)s | %(message)s",
    datefmt="%Y-%m-%d %H:%M:%S",
)
console_handler.setFormatter(formatter)

logger.addHandler(console_handler)

logger.info("Halo dari logger kustom!")

Di production, kamu pasti ingin log tersimpan permanen, bukan hanya tampil di layar. Gunakan RotatingFileHandler agar file log tidak membengkak tanpa batas.

python
import logging
from logging.handlers import RotatingFileHandler

logger = logging.getLogger("aplikasi_file")
logger.setLevel(logging.DEBUG)

# Rotasi file: maksimal 5 file, masing-masing 1 MB
file_handler = RotatingFileHandler(
    "aplikasi.log",
    maxBytes=1_000_000,   # 1 MB
    backupCount=5,
    encoding="utf-8",
)
file_handler.setFormatter(
    logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
)

logger.addHandler(file_handler)

for i in range(1000):
    logger.info(f"Baris log ke-{i}")

RotatingFileHandler secara otomatis menggulirkan file saat ukurannya melebihi maxBytes: file lama disimpan sebagai aplikasi.log.1, aplikasi.log.2, dan seterusnya, hingga backupCount file. Ini mencegah file log memenuhi seluruh disk di server production.

Hati-hati: jangan pernah menulis data sensitif seperti password, token API, atau nomor kartu kredit ke dalam log. Log sering disimpan lama dan dibaca banyak orang, sehingga bisa menjadi celah kebocoran data.

Logger Hierarchy dan getLogger

Logger bersifat hierarkis berdasarkan nama. Logger dengan nama yang sama akan mengembalikan objek yang sama, dan nama yang dipisah titik membentuk hubungan induk-anak.

python
import logging

logging.basicConfig(level=logging.DEBUG)

# getLogger dengan nama sama mengembalikan objek yang sama
a = logging.getLogger("myapp")
b = logging.getLogger("myapp")
print(a is b)  # True

# Nama dengan titik membentuk hierarki
sub = logging.getLogger("myapp.submodule")
print(sub.parent.name)  # myapp

Karena sifat hierarkis ini, konfigurasi level dan handler pada logger induk bisa diwariskan ke logger anak. Praktik terbaiknya adalah memanggil logging.getLogger(__name__) di setiap modul, sehingga kamu tahu persis dari modul mana sebuah pesan log berasal.

Logging di Aplikasi Web

Ketika membangun aplikasi web, logging menjadi alat penting untuk memantau permintaan, mendeteksi error, dan melacak aktivitas pengguna. Framework seperti Flask dan FastAPI sudah terintegrasi dengan modul logging Python. Di Flask (lihat panduan Membangun Aplikasi Web dengan Flask), kamu bisa memanggil app.logger.info() langsung. Sementara di FastAPI (baca Cara Membuat REST API dengan FastAPI), log dari uvicorn dan aplikasimu bisa dikonfigurasi lewat logging.config.dictConfig(). Dengan memahami dasar logging di tutorial ini, kamu akan jauh lebih mudah men-debug aplikasi web maupun skrip biasa.

Tips: gunakan logger bernama (via getLogger(__name__)) alih-alih memanggil logging global, hindari menulis data sensitif, dan gunakan level yang tepat — jangan menempatkan pesan biasa di level ERROR.

Kesimpulan

Logging adalah keterampilan dasar yang akan membuat hidupmu jauh lebih mudah saat men-debug kode (misalnya ketika menulis test dengan Pytest), memantau aplikasi, maupun mengaudit kejadian penting. Mulailah dari basicConfig(), lalu beralih ke logger bernama dengan handler dan formatter saat aplikasimu berkembang. Selamat mencoba!