Tutorial Logging Loguru Python: Penyiapan Tanpa Konfigurasi
Pelajari Loguru, kerangka kerja logging paling mudah di Python. Kuasai rotasi file, logging terstruktur, penanganan pengecualian, dan sink kustom tanpa konfigurasi.
Sepanjang karier coding, Anda terbiasa melakukan debug dengan pernyataan print(). Mungkin Anda pernah mencoba modul logging bawaan Python sekali dua kali, tetapi kembali ke print karena lebih sederhana.
Sebenarnya ada cara yang lebih baik dan sama mudahnya digunakan.
Pernyataan print tidak dapat disimpan ke file atau diaktifkan/dinonaktifkan dengan mudah. Logging bawaan Python bisa melakukan itu, tetapi membutuhkan kode penyiapan yang lebih panjang daripada program Anda sendiri.
Loguru mengambil pendekatan berbeda: logging harus semudah printing, namun jauh lebih bermanfaat. Anda mendapatkan warna di terminal, stempel waktu otomatis, dan kemampuan menyimpan semuanya ke file tanpa menulis satu baris konfigurasi pun.
Dalam tutorial ini, saya akan menunjukkan contoh praktis yang membuat logging terasa alami alih-alih membebani. Anda akan melihat fitur-fitur yang mungkin belum Anda ketahui, menggunakan pola kode yang benar-benar mempermudah debug.
Jika Anda baru dalam debugging Python atau ingin memperkuat keterampilan dasar,membangun fundamental Python yang solid membantu Anda memahami kapan dan mengapa logging diperlukan.
Dengan modul logging biasa, Anda harus menyiapkan handler, formatter, dan mengonfigurasi semuanya sebelum melihat satu pesan log pun.
Untuk perbandingan lebih mendalam tentang pendekatan logging bawaan Python, lihattutorial logging komprehensif yang membahas metode tradisional.
Dengan Loguru, Anda cukup mengimpor dan mulai melakukan logging:
from loguru import logger
# Instead of print("Processing user data...")
logger.info("Processing user data...")# Instead of print(f"Found {count} records")
logger.info("Found {} records", count)Didukung oleh
Output muncul di terminal Anda dengan warna, stempel waktu, dan level log secara otomatis. Tanpa perlu penyiapan.
Misalnya Anda membangun web scraper sederhana. Berikut perubahan cara Anda melakukan debug:
import requests
from loguru import logger
defscrape_website(url):
logger.info("Starting scrape for {}", url)
response = requests.get(url)
logger.debug("Response status: {}", response.status_code)if response.status_code ==200:
logger.success("Successfully scraped {} characters",len(response.text))return response.text
else:
logger.error("Failed to scrape {}: status {}", url, response.status_code)returnNoneDidukung oleh
Perhatikan level log yang berbeda (info, debug, success, error) dan format gaya kurung kurawal. Semuanya langsung bekerja tanpa file konfigurasi atau kode penyiapan.
Logging ke File dan Rotasi yang Sederhana
Saat Anda melakukan debug dengan output konsol, semuanya hilang begitu Anda menutup terminal. Anda tidak bisa menelusuri apa yang terjadi satu jam lalu, dan jika skrip Anda crash semalaman, tidak ada jejak apa yang salah. Anda juga tidak mudah membagikan output debug kepada rekan saat meminta bantuan.
Logging ke file menyelesaikan ini dengan menyimpan semuanya secara permanen.
Logging tradisional membuat Anda menulis kode konfigurasi untuk menyiapkan file handler. Anda perlu menentukan path file, membuat direktori, dan menangani perizinan. Dengan Loguru, menambahkan logging ke file benar-benar cukup satu baris:
from loguru import logger
# Add file logging alongside console output
logger.add("app.log")
logger.info("This appears in both console and file")
logger.error("So does this error message")Didukung oleh
Sekarang semuanya disimpan ke app.log sambil tetap tampil di terminal Anda.
Namun file log akan membesar seiring waktu. Aplikasi web yang berjalan berhari-hari bisa menghasilkan gigabyte log yang akhirnya memenuhi disk. Rotasi file menyelesaikan ini dengan otomatis membuat file log baru saat kondisi tertentu terpenuhi. File lama diubah namanya dengan stempel waktu, dan file baru dimulai:
# When app.log reaches 10 MB, it becomes app_2024-07-15_14-30-25.log# and a new empty app.log starts
logger.add("app.log", rotation="10 MB")# Or start a new file every day at midnight
logger.add("app.log", rotation="00:00")Didukung oleh
Stempel waktu bawaan berfungsi, namun sering kali dalam UTC atau sulit dibaca. Loguru memungkinkan Anda menyesuaikan format datetime sesuai kebutuhan:
# Custom timestamp format that's easier to read
logger.add("app.log",format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}",
rotation="1 day")Didukung oleh
Untuk sistem produksi, Anda butuh kontrol lebih atas file lama. Logging produksi memerlukan penerapan praktik terbaik Python agar log Anda mudah dirawat dan aman. Tanpa pengelolaan, file log menumpuk dan menghabiskan penyimpanan:
# Keep only the last 10 rotated files, compress the rest
logger.add("production.log",
rotation="50 MB",# New file every 50MB
retention=10,# Keep only 10 old files
compression="zip")# Compress rotated filesDidukung oleh
Mari lihat ini dalam skenario realistis. Anda membangun pipeline data yang memproses banyak file CSV setiap malam, membersihkan dan memvalidasi data pelanggan sebelum memuatnya ke database. Anda perlu melacak file mana yang berhasil diproses dan menangkap masalah kualitas data:
import pandas as pd
from loguru import logger
# Production-ready file logging setup
logger.add("data_processing_{time:YYYY-MM-DD}.log",
rotation="00:00",# New file daily
retention="1 week",# Keep 1 week of logsformat="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}")defprocess_csv_files(file_list):
logger.info("Starting batch processing of {} files",len(file_list))for filename in file_list:try:
df = pd.read_csv(filename)
logger.info("Loaded {} with {} rows", filename,len(df))# Your processing logic here
processed_df = df.dropna()
logger.success("Processed {} - kept {} rows", filename,len(processed_df))except Exception as e:
logger.error("Failed to process {}: {}", filename,str(e))
logger.info("Batch processing complete")Didukung oleh
Log Anda disimpan dengan stempel waktu yang mudah dibaca, file berotasi otomatis, dan log lama dibersihkan sendiri. Anda dapat meninjau apa yang terjadi beberapa hari kemudian atau mengirim file log ke rekan saat troubleshooting.
Logging Terstruktur untuk Aplikasi Modern
Saat menjalankan aplikasi web, log Anda cepat menjadi campuran informasi yang berantakan. Aksi pengguna, kueri basis data, panggilan API, dan error tercampur menjadi dinding teks. Anda tidak mudah memfilter pengguna tertentu, melacak permintaan individual, atau mem-parsing log secara otomatis untuk sistem pemantauan.
Aplikasi berbasis data sangat diuntungkan dari logging terstruktur. Jika Anda bekerja dengan pipeline data atau analitik, mengembangkan keterampilan analis data membantu Anda memahami informasi apa yang perlu ditangkap dalam log.
Logging berbasis string tradisional memperburuk ini. Setiap pesan log hanyalah teks, jadi mengekstrak data bermakna membutuhkan pola regex yang kompleks atau pencarian manual.
Logging terstruktur mengubah ini dengan memperlakukan entri log sebagai objek data, bukan sekadar teks. Setiap entri log menjadi catatan terstruktur dengan bidang yang dapat dicari, sehingga mudah ditanya dan dianalisis secara terprogram.
Logging terstruktur JSON dengan serialize=True
Loguru membuat logging terstruktur menjadi sederhana dengan opsi serialize=True:
Parameter serialize=True memberi tahu Loguru untuk menghasilkan JSON alih-alih teks biasa. Alih-alih kalimat yang mudah dibaca, file log Anda kini berisi data terstruktur:
{"text":"User login","record":{"time":"2024-07-15T14:30:25","level":{"name":"INFO"},"extra":{"user_id":123,"ip_address":"192.168.1.1"}}}Didukung oleh
Format ini bekerja sempurna dengan alat analisis log yang dapat mencari dan memfilter data JSON secara otomatis.
Pengikatan konteks
Namun aplikasi web membutuhkan lebih dari sekadar data terstruktur. Anda butuh konteks yang menghubungkan entri log terkait. Saat memproses permintaan pengguna, Anda ingin semua log terkait berbagi informasi umum seperti user ID atau session ID.
Pengikatan konteks menyelesaikan ini dengan melampirkan informasi persisten ke logger Anda menggunakan logger.bind():
from loguru import logger
defprocess_user_order(user_id, order_data):# Create a logger with attached context
order_logger = logger.bind(user_id=user_id, order_id=order_data['id'])
order_logger.info("Starting order processing")
order_logger.debug("Validating payment method", method=order_data['payment'])
order_logger.info("Order processing complete", total=order_data['total'])Didukung oleh
Kini setiap log dari order_logger otomatis menyertakan user_id dan order_id, sehingga mudah melacak semua log terkait pesanan tertentu.
Banyak sink untuk output berbeda
Aplikasi modern juga membutuhkan output log berbeda untuk tujuan berbeda. Anda mungkin ingin log konsol yang mudah dibaca saat pengembangan, tetapi log JSON untuk pemantauan produksi. Di Loguru, setiap tujuan output disebut “sink” — anggap sebagai tempat aliran pesan log.
Loguru memungkinkan Anda menambahkan banyak sink dengan format dan aturan berbeda:
from loguru import logger
import sys
# Remove the default console output
logger.remove()# Sink 1: Human-readable console for development
logger.add(sys.stdout,
level="DEBUG",format="<green>{time:HH:mm:ss}</green> | {level} | {message}")# Sink 2: JSON file for production monitoring
logger.add("app.log",
serialize=True,
level="INFO")# Sink 3: Error-only file for alerts
logger.add("errors.log",
level="ERROR")Didukung oleh
Panggilan logger.remove() menghapus output konsol bawaan Loguru agar Anda bisa menyiapkan sendiri. Setiap logger.add() membuat sink baru dengan aturannya sendiri tentang apa yang dicatat dan bagaimana formatnya.
Kini pernyataan log yang sama menghasilkan output berbeda:
logger.debug("Processing started")# Only appears in console
logger.info("User data loaded")# Appears in console and app.log
logger.error("Database connection failed")# Appears in all three placesDidukung oleh
Contoh lengkap Loguru: sistem pendaftaran pengguna
Mari lihat contoh yang lebih sederhana namun realistis menggunakan Loguru — sistem pendaftaran pengguna dasar:
from loguru import logger
import sys
# Set up multiple outputs
logger.remove()
logger.add(sys.stdout, level="INFO",format="{time:HH:mm:ss} | {message}")
logger.add("user_registration.log", serialize=True, level="INFO")
logger.add("errors.log", level="ERROR")defregister_user(email, password):# Create logger with user context
user_logger = logger.bind(email=email)
user_logger.info("Starting user registration")# Validate emailif"@"notin email:
user_logger.error("Invalid email format")returnFalse# Check if user exists
user_logger.debug("Checking if user already exists")# Simulate password hashing
user_logger.debug("Hashing password")# Save to database
user_logger.info("Saving user to database")
user_logger.success("User registration completed")returnTrue# Usage
register_user("[email protected]","secure123")Didukung oleh
Penyiapan ini memberi Anda output konsol yang mudah dibaca saat pengembangan, log JSON terstruktur untuk pemantauan otomatis, dan log error terpisah untuk peringatan. Metode bind() memastikan semua log untuk setiap pendaftaran pengguna menyertakan alamat email, sehingga debug jauh lebih mudah.
Penanganan Pengecualian Loguru
Saat kode Anda crash, biasanya Anda mendapatkan stack trace dasar yang memberi tahu di mana error terjadi, tetapi tidak banyak tentang alasannya. Anda kehilangan nilai variabel saat crash, sehingga sulit memahami apa yang salah. Penanganan pengecualian tradisional juga mengharuskan Anda membungkus semuanya dalam blok try-catch dan mencatat setiap pengecualian secara manual.
Ini menjadi sangat menyakitkan saat debug masalah produksi. Pengguna melaporkan error, tetapi Anda tidak dapat mereproduksinya karena tidak memiliki konteks yang ada saat error terjadi.
Loguru menyelesaikan ini dengan penangkapan pengecualian otomatis dan traceback yang disempurnakan yang menunjukkan tepat apa yang terjadi di kode Anda saat sesuatu berjalan salah.
Penangkapan pengecualian otomatis dengan @logger.catch
Dekorator @logger.catch secara otomatis menangkap pengecualian apa pun yang terjadi di suatu fungsi dan mencatatnya dengan konteks lengkap. Dekorator seperti @logger.catch adalahkonsep Python tingkat menengah yang dapat mengubah cara Anda menangani error di seluruh codebase:
from loguru import logger
@logger.catchdefdivide_numbers(a, b):
result = a / b
return result
# This automatically logs the exception with full traceback
result = divide_numbers(10,0)Didukung oleh
Alih-alih program Anda crash dengan pesan error dasar, Loguru menangkap pengecualian dan mencatatnya dengan informasi terperinci, sementara program Anda terus berjalan. Dekorator ini berfungsi pada fungsi apa pun — metode kelas, fungsi async, atau fungsi biasa.
Traceback yang disempurnakan dengan inspeksi variabel
Namun Loguru melangkah lebih jauh dengan traceback yang disempurnakan yang menampilkan nilai variabel di setiap level call stack. Fitur ini disebut “diagnose” dan ibarat debugger yang tertanam di log Anda:
from loguru import logger
# Enable enhanced tracebacks
logger.add("debug.log", diagnose=True)@logger.catchdefprocess_user_data(users):for user in users:
age = user['age']if age >0:
years_to_retirement =65- age
print(f"User {user['name']} has {years_to_retirement} years to retirement")# When this crashes, you'll see the exact values of 'users', 'user', and 'age'
users_data =[{"name":"Alice","age":30},{"name":"Bob","age":"invalid"},# This will cause an error]
process_user_data(users_data)Didukung oleh
Dengan diagnose=True, saat fungsi crash karena mencoba mengurangkan string dari angka, Loguru menunjukkan tepat apa yang ada di setiap variabel:
TypeError: unsupported operand type(s) for -: 'int' and 'str'
Variables values:
users = [{"name": "Alice", "age": 30}, {"name": "Bob", "age": "invalid"}]
user = {"name": "Bob", "age": "invalid"}
age = "invalid"Didukung oleh
Tingkat detail ini membuat debug jauh lebih cepat karena Anda dapat melihat persis data apa yang menyebabkan masalah.
Penanganan pengecualian yang peka terhadap lingkungan
Namun, traceback yang disempurnakan dapat mengekspos informasi sensitif seperti kata sandi atau API key di log produksi. Loguru memungkinkan Anda mengontrol perilaku ini untuk lingkungan yang berbeda:
from loguru import logger
import os
# Development: Full diagnostic informationif os.getenv("ENVIRONMENT")=="development":
logger.add("app.log", diagnose=True, level="DEBUG")else:# Production: Basic logging without variable inspection
logger.add("app.log", diagnose=False, level="INFO")@logger.catchdefauthenticate_user(username, password, api_key):# In development, you'll see all variable values if this crashes# In production, sensitive data stays hiddenifnot username ornot password:raise ValueError("Missing credentials")Didukung oleh
Evaluasi malas untuk kinerja
Fitur kuat lainnya adalah evaluasi malas (lazy evaluation), yang meningkatkan kinerja saat mencatat operasi mahal. Terkadang Anda ingin mencatat informasi kompleks, tetapi hanya jika benar-benar terjadi error:
from loguru import logger
@logger.catchdefprocess_large_dataset(data):try:# Some complex processing that might fail
result = complex_calculation(data)return result
except Exception as e:# This expensive operation only runs if there's an error
logger.error("Processing failed with data: {data}",
data=lambda: expensive_data_summary(data))raisedefexpensive_data_summary(data):# This function takes time to run, summarizing huge datasetsreturn{"row_count":len(data),"columns":list(data.keys()),"memory_usage": data.memory_usage()}Didukung oleh
Sintaks lambda: membuat fungsi yang hanya dipanggil ketika Loguru benar-benar menulis pesan log. Jika tidak ada error, expensive_data_summary() tidak pernah dijalankan, menghemat waktu pemrosesan.
Strategi berbeda untuk jenis error berbeda
Anda juga dapat menggunakan strategi penanganan pengecualian yang berbeda untuk berbagai jenis error:
from loguru import logger
# Configure multiple outputs for different error severities
logger.add("warnings.log", level="WARNING",filter=lambda record: record["level"].name =="WARNING")
logger.add("critical_errors.log", level="ERROR")@logger.catch(level="ERROR")defcritical_database_operation(query):# Database errors get logged as ERROR level
execute_database_query(query)@logger.catch(level="WARNING", reraise=False)defoptional_feature(user_id):# Non-critical features log as WARNING and continue execution
send_optional_notification(user_id)defprocess_user_request(user_id, query):# Critical operation - if this fails, the whole request fails
critical_database_operation(query)# Optional operation - if this fails, request continues
optional_feature(user_id)Didukung oleh
Parameter reraise=False memberi tahu Loguru untuk mencatat pengecualian tetapi tidak melemparkannya kembali, sehingga program Anda dapat terus berjalan. Ini berguna untuk fitur opsional yang tidak boleh merusak alur kerja utama Anda.
Contoh lengkap: pemrosesan file dengan penanganan error
Mari lihat contoh lengkap dengan sistem pemrosesan file yang menangani berbagai jenis error secara elegan:
from loguru import logger
import os
# Set up environment-aware loggingif os.getenv("DEBUG"):
logger.add("file_processor.log", diagnose=True, level="DEBUG")else:
logger.add("file_processor.log", diagnose=False, level="INFO")@logger.catch(reraise=False)defvalidate_file_format(filename):ifnot filename.endswith(('.csv','.json','.xml')):raise ValueError(f"Unsupported file format: {filename}")@logger.catchdefload_file_data(filename):
logger.info("Loading file: {}", filename)# Expensive operation only logged on errors
logger.debug("File stats: {stats}",
stats=lambda:{"size": os.path.getsize(filename),"modified": os.path.getmtime(filename)})withopen(filename,'r')as f:return f.read()defprocess_files(file_list):
results =[]for filename in file_list:# Validation errors are logged but don't stop processing
validate_file_format(filename)try:# Loading errors are logged and do stop processing this file
data = load_file_data(filename)
results.append(data)
logger.success("Successfully processed {}", filename)except Exception:
logger.error("Skipping file {} due to loading error", filename)continuereturn resultsDidukung oleh
Penyiapan ini memberi Anda penangkapan pengecualian otomatis, konteks error yang detail saat dibutuhkan, dan strategi penanganan berbeda untuk berbagai tipe error. Log Anda menjadi jauh lebih berguna untuk debug, sementara kode Anda tetap bersih dan mudah dibaca.
Konfigurasi dan Kustomisasi Loguru Lanjutan
Seiring aplikasi Anda berkembang, Anda akan menemukan skenario di mana default Loguru kurang pas. Mungkin Anda butuh level log khusus untuk metrik bisnis, ingin menyaring data sensitif dari log, atau perlu mengirim peringatan ke Slack saat terjadi error.
Kabar baiknya, Loguru dibangun untuk dikustomisasi tanpa kehilangan kesederhanaannya. Anda dapat memperluasnya dengan cara yang dalam sistem logging tradisional butuh konfigurasi kompleks, sembari menjaga kode tetap bersih dan mudah dibaca.
Mari lihat kustomisasi paling berguna yang menyelesaikan masalah nyata yang akan Anda hadapi di aplikasi produksi.
Level dan warna log kustom
Loguru hadir dengan level standar seperti INFO, DEBUG, dan ERROR. Namun terkadang Anda butuh sesuatu yang spesifik untuk aplikasi Anda. Mungkin Anda ingin level khusus untuk metrik kinerja atau peristiwa bisnis.
Membuat level log kustom itu mudah:
from loguru import logger
# Add a custom level for business metrics
logger.level("METRIC", no=38, color="<yellow>", icon="📊")# Add a custom level for security events
logger.level("SECURITY", no=45, color="<red><bold>", icon="🔒")# Now you can use these levels
logger.log("METRIC","Order completed in {} seconds",2.5)
logger.log("SECURITY","Failed login attempt from IP: {}","192.168.1.100")Didukung oleh
Parameter no menetapkan prioritas level (angka lebih tinggi = prioritas lebih tinggi). Level standar: DEBUG=10, INFO=20, WARNING=30, ERROR=40, CRITICAL=50.
Mari lihat ini dalam skenario pelatihan machine learning:
from loguru import logger
# Set up custom levels for ML tracking
logger.level("EPOCH", no=35, color="<cyan><bold>")
logger.level("CHECKPOINT", no=38, color="<green><bold>")# Configure output
logger.remove()
logger.add("training_{time:YYYY-MM-DD}.log", level="INFO")deftrain_model(model, data_loader, epochs=10):
logger.info("Starting training with {} epochs", epochs)for epoch inrange(epochs):# Log epoch progress with custom level
logger.log("EPOCH","Epoch {}/{} started", epoch +1, epochs)# Training logic here
loss =0.523-(epoch *0.05)# Simulated improving loss
accuracy =0.72+(epoch *0.03)# Simulated improving accuracy
logger.info("Loss: {:.4f}, Accuracy: {:.2%}", loss, accuracy)# Save checkpoint every 5 epochsif(epoch +1)%5==0:
logger.log("CHECKPOINT","Model saved at epoch {}", epoch +1)
logger.success("Training completed!")Didukung oleh
Mencegat dan memodifikasi pesan log
Terkadang Anda perlu memodifikasi pesan log sebelum ditulis. Kasus umum termasuk menghapus data sensitif, menambahkan ID permintaan, atau memformat ulang pesan untuk alat tertentu.
Loguru memungkinkan Anda mencegat pesan menggunakan parameter filter:
from loguru import logger
import re
defhide_sensitive_data(record):# Hide credit card numbers
record["message"]= re.sub(r'\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b','XXXX-XXXX-XXXX-XXXX',
record["message"])# Hide email addresses
record["message"]= re.sub(r'\b[\w.-]+@[\w.-]+\.\w+\b','***@***.***',
record["message"])# Continue processing the logreturnTrue# Add the filter to your logger
logger.add("secure.log",filter=hide_sensitive_data)# Test it
logger.info("User paid with card 4532-1234-5678-9012")
logger.info("Contact email: [email protected]")Didukung oleh
Anda juga dapat menggunakan filter untuk menambahkan informasi kontekstual:
from loguru import logger
import threading
defadd_thread_info(record):# Add thread name to every log message
record["extra"]["thread_name"]= threading.current_thread().name
returnTruedefadd_environment_info(record):# Add environment to production logs
record["extra"]["env"]="production"
record["extra"]["region"]="us-west-2"returnTrue# Apply multiple filters
logger.add("app.log",filter=lambda record: add_thread_info(record)and add_environment_info(record),format="{time} | {extra[env]} | {extra[thread_name]} | {message}")Didukung oleh
Sink kustom untuk layanan eksternal
Sink adalah tempat aliran log Anda. Meskipun file dan konsol umum digunakan, sering kali Anda perlu mengirim log ke layanan eksternal seperti Slack, email, atau sistem pemantauan.
Berikut cara membuat sink kustom yang mengirim error ke Slack:
from loguru import logger
import requests
defsend_to_slack(message):"""Custom sink that sends messages to Slack"""# Parse the log record
record = message.record
# Only send errors and aboveif record["level"].no <40:# ERROR level is 40return# Format message for Slack
slack_message ={"text":f"🚨 {record['level'].name}: {record['message']}","attachments":[{"color":"danger","fields":[{"title":"Time","value":str(record["time"]),"short":True},{"title":"Function","value": record["function"],"short":True},{"title":"File","value":f"{record['file'].name}:{record['line']}","short":False}]}]}# Send to Slack webhook
webhook_url ="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
requests.post(webhook_url, json=slack_message)# Add the custom sink
logger.add(send_to_slack, level="ERROR")# Test it
logger.error("Database connection lost!")Didukung oleh
Berikut contoh praktis lainnya — sink kustom yang mengumpulkan metrik kinerja sepanjang jalannya aplikasi dan menyimpannya untuk analisis:
from loguru import logger
from collections import defaultdict
import json
classMetricsCollector:def__init__(self):
self.metrics = defaultdict(list)def__call__(self, message):"""This method is called for every log message"""
record = message.record
# Only process METRIC level logsif record["level"].name !="METRIC":return# Extract metric data from the 'extra' fields
extra = record["extra"]if"metric_name"in extra and"value"in extra:
self.metrics[extra["metric_name"]].append({"value": extra["value"],"timestamp": record["time"].timestamp()})defsave_metrics(self):"""Save all collected metrics to a JSON file"""withopen("metrics.json","w")as f:
json.dump(dict(self.metrics), f, indent=2)# Create the collector and add it as a sink
collector = MetricsCollector()
logger.add(collector)# Create the METRIC level
logger.level("METRIC", no=38)# Now when you log metrics, they're automatically collected# The bind() method attaches extra data to the log entry
logger.bind(metric_name="response_time", value=0.234).log("METRIC","API response")
logger.bind(metric_name="response_time", value=0.189).log("METRIC","API response")
logger.bind(metric_name="active_users", value=1523).log("METRIC","User count")# Later, save all metrics to file
collector.save_metrics()# The metrics.json file will contain:# {# "response_time": [# {"value": 0.234, "timestamp": 1627...},# {"value": 0.189, "timestamp": 1627...}# ],# "active_users": [# {"value": 1523, "timestamp": 1627...}# ]# }Didukung oleh
Keindahan pendekatan ini adalah kode aplikasi Anda tetap bersih — Anda cukup mencatat metrik seperti biasa, dan sink kolektor menangani penyimpanan secara otomatis. Anda dapat dengan mudah menggantinya dengan sink yang mengirim metrik ke Prometheus, DataDog, atau layanan pemantauan lainnya.
Kustomisasi ini memberi Anda fleksibilitas untuk menyesuaikan Loguru dengan kebutuhan spesifik sambil menjaga kesederhanaan yang menjadikannya unggul. Baik Anda membangun skrip kecil atau aplikasi besar, Anda dapat memperluas Loguru untuk menangani kebutuhan logging unik tanpa file konfigurasi kompleks atau boilerplate.
Kesimpulan
Loguru membuat logging di Python sesederhana yang seharusnya. Tidak ada lagi file konfigurasi, tidak ada lagi penyiapan handler, tidak ada lagi boilerplate. Cukup impor dan mulai logging dengan warna, stempel waktu, dan rotasi file otomatis.
Anda telah melihat bagaimana Loguru menangani titik sakit umum: menyimpan log ke file, merotasinya secara otomatis, menangkap pengecualian dengan konteks lengkap, dan mengirim log ke layanan eksternal. Fitur logging terstruktur membuatnya siap produksi, sementara level dan sink kustom memungkinkan Anda menyesuaikannya untuk kasus apa pun.
Gunakan Loguru saat:
Anda lelah melakukan debug dengan print
Anda membutuhkan logging cepat di skrip atau notebook
Anda membangun aplikasi web yang membutuhkan log terstruktur
Anda menginginkan pelacakan pengecualian yang lebih baik tanpa penyiapan kompleks
Mulailah dari hal kecil. Ganti satu pernyataan print dengan logger.info(). Anda tidak akan kembali lagi.
Loguru FAQs
Bagaimana Loguru dibandingkan dengan pustaka logging Python lainnya?⌄
Loguru menonjol karena tidak memerlukan konfigurasi — Anda bisa langsung logging dengan from loguru import logger. Berbeda dengan modul logging bawaan Python yang membutuhkan handler, formatter, dan penyiapan kompleks, Loguru menyediakan warna, stempel waktu, dan rotasi file secara bawaan. Loguru juga menawarkan traceback yang disempurnakan dengan inspeksi variabel yang tidak disediakan pustaka lain.
Apa keunggulan utama menggunakan Loguru dibanding modul logging bawaan Python?⌄
Loguru menghilangkan kompleksitas konfigurasi, menyediakan rotasi dan retensi file otomatis, menawarkan logging JSON terstruktur dengan serialize=True, menyertakan traceback pengecualian yang disempurnakan dengan nilai variabel, dan mendukung sink kustom untuk layanan eksternal. Anda mendapatkan fitur logging siap produksi tanpa menulis kode penyiapan.
Apakah Loguru dapat menangani aplikasi multi-thread secara efisien?⌄
Ya, Loguru thread-safe secara bawaan dan menangani aplikasi multi-thread dengan baik. Anda dapat menambahkan informasi thread ke log menggunakan filter, dan metode logger.bind() berfungsi lintas thread untuk menjaga konteks. Performa Loguru dioptimalkan untuk logging konkuren tanpa memblokir thread.
Bagaimana cara kerja rotasi dan retensi log otomatis Loguru?⌄
Loguru menawarkan rotasi fleksibel berdasarkan ukuran file (rotation="10 MB"), interval waktu (rotation="00:00" untuk harian), atau kondisi kustom. Retensi secara otomatis menghapus file lama (retention=10 menyimpan 10 file), dan kompresi menghemat ruang (compression="zip"). Semuanya terjadi otomatis tanpa pengelolaan file manual.
Apa contoh praktis penggunaan fitur sink kustom Loguru?⌄
Sink kustom memungkinkan Anda mengirim log ke layanan eksternal seperti Slack untuk peringatan error, mengumpulkan metrik untuk sistem pemantauan, atau memformat log untuk alat tertentu. Anda dapat membuat sink yang memfilter berdasarkan level log, menambahkan informasi kontekstual, atau mengintegrasikan dengan layanan seperti DataDog, Prometheus, atau notifikasi email untuk error kritis.
Saya adalah kreator konten data science dengan pengalaman lebih dari 2 tahun dan salah satu dengan jumlah pengikut terbesar di Medium. Saya suka menulis artikel mendalam tentang AI dan ML dengan sedikit gaya sarkastik—karena harus ada sesuatu untuk membuatnya tidak terlalu membosankan. Saya telah menghasilkan lebih dari 130 artikel dan satu kursus di DataCamp, dengan satu lagi sedang dalam proses. Konten saya telah dilihat oleh lebih dari 5 juta pasang mata, dan 20 ribu di antaranya menjadi pengikut di Medium dan LinkedIn.
Temukan alasan mengapa Anda sebaiknya (tidak) menggunakan spaghetti plot untuk menyampaikan ketidakpastian jalur prediksi badai serta dampaknya terhadap interpretasi.
Kuasai pertanyaan wawancara basis data, dari konsep SQL dasar hingga skenario desain sistem tingkat lanjut. Panduan mendalam ini mencakup semua yang Anda perlukan untuk sukses di wawancara DBMS dan meraih peran berikutnya.
Kembangkan keterampilan data Anda, pelajari cara mengolah dan memvisualisasikan data, serta terapkan analisis canggih untuk mengambil keputusan berbasis data.
Pelajari Python untuk pengembangan perangkat lunak, mulai dari menulis fungsi hingga mendefinisikan kelas. Dapatkan keterampilan yang diperlukan untuk memulai karir Anda sebagai pengembang!
Sepanjang karier coding, Anda terbiasa melakukan debug dengan pernyataan
print(). Mungkin Anda pernah mencoba modul logging bawaan Python sekali dua kali, tetapi kembali ke print karena lebih sederhana.Sebenarnya ada cara yang lebih baik dan sama mudahnya digunakan.
Pernyataan print tidak dapat disimpan ke file atau diaktifkan/dinonaktifkan dengan mudah. Logging bawaan Python bisa melakukan itu, tetapi membutuhkan kode penyiapan yang lebih panjang daripada program Anda sendiri.
Loguru mengambil pendekatan berbeda: logging harus semudah printing, namun jauh lebih bermanfaat. Anda mendapatkan warna di terminal, stempel waktu otomatis, dan kemampuan menyimpan semuanya ke file tanpa menulis satu baris konfigurasi pun.
Dalam tutorial ini, saya akan menunjukkan contoh praktis yang membuat logging terasa alami alih-alih membebani. Anda akan melihat fitur-fitur yang mungkin belum Anda ketahui, menggunakan pola kode yang benar-benar mempermudah debug.
Jika Anda baru dalam debugging Python atau ingin memperkuat keterampilan dasar, membangun fundamental Python yang solid membantu Anda memahami kapan dan mengapa logging diperlukan.
Mulai Dengan Loguru: Keajaiban Tanpa Konfigurasi
Menginstal Loguru hanya butuh satu perintah:
Dengan modul
loggingbiasa, Anda harus menyiapkan handler, formatter, dan mengonfigurasi semuanya sebelum melihat satu pesan log pun.Untuk perbandingan lebih mendalam tentang pendekatan logging bawaan Python, lihat tutorial logging komprehensif yang membahas metode tradisional.
Dengan Loguru, Anda cukup mengimpor dan mulai melakukan logging:
Output muncul di terminal Anda dengan warna, stempel waktu, dan level log secara otomatis. Tanpa perlu penyiapan.
Misalnya Anda membangun web scraper sederhana. Berikut perubahan cara Anda melakukan debug:
Perhatikan level log yang berbeda (
info,debug,success,error) dan format gaya kurung kurawal. Semuanya langsung bekerja tanpa file konfigurasi atau kode penyiapan.Logging ke File dan Rotasi yang Sederhana
Saat Anda melakukan debug dengan output konsol, semuanya hilang begitu Anda menutup terminal. Anda tidak bisa menelusuri apa yang terjadi satu jam lalu, dan jika skrip Anda crash semalaman, tidak ada jejak apa yang salah. Anda juga tidak mudah membagikan output debug kepada rekan saat meminta bantuan.
Logging ke file menyelesaikan ini dengan menyimpan semuanya secara permanen.
Logging tradisional membuat Anda menulis kode konfigurasi untuk menyiapkan file handler. Anda perlu menentukan path file, membuat direktori, dan menangani perizinan. Dengan Loguru, menambahkan logging ke file benar-benar cukup satu baris:
Sekarang semuanya disimpan ke
app.logsambil tetap tampil di terminal Anda.Namun file log akan membesar seiring waktu. Aplikasi web yang berjalan berhari-hari bisa menghasilkan gigabyte log yang akhirnya memenuhi disk. Rotasi file menyelesaikan ini dengan otomatis membuat file log baru saat kondisi tertentu terpenuhi. File lama diubah namanya dengan stempel waktu, dan file baru dimulai:
Stempel waktu bawaan berfungsi, namun sering kali dalam UTC atau sulit dibaca. Loguru memungkinkan Anda menyesuaikan format datetime sesuai kebutuhan:
Untuk sistem produksi, Anda butuh kontrol lebih atas file lama. Logging produksi memerlukan penerapan praktik terbaik Python agar log Anda mudah dirawat dan aman. Tanpa pengelolaan, file log menumpuk dan menghabiskan penyimpanan:
Mari lihat ini dalam skenario realistis. Anda membangun pipeline data yang memproses banyak file CSV setiap malam, membersihkan dan memvalidasi data pelanggan sebelum memuatnya ke database. Anda perlu melacak file mana yang berhasil diproses dan menangkap masalah kualitas data:
Log Anda disimpan dengan stempel waktu yang mudah dibaca, file berotasi otomatis, dan log lama dibersihkan sendiri. Anda dapat meninjau apa yang terjadi beberapa hari kemudian atau mengirim file log ke rekan saat troubleshooting.
Logging Terstruktur untuk Aplikasi Modern
Saat menjalankan aplikasi web, log Anda cepat menjadi campuran informasi yang berantakan. Aksi pengguna, kueri basis data, panggilan API, dan error tercampur menjadi dinding teks. Anda tidak mudah memfilter pengguna tertentu, melacak permintaan individual, atau mem-parsing log secara otomatis untuk sistem pemantauan.
Aplikasi berbasis data sangat diuntungkan dari logging terstruktur. Jika Anda bekerja dengan pipeline data atau analitik, mengembangkan keterampilan analis data membantu Anda memahami informasi apa yang perlu ditangkap dalam log.
Logging berbasis string tradisional memperburuk ini. Setiap pesan log hanyalah teks, jadi mengekstrak data bermakna membutuhkan pola regex yang kompleks atau pencarian manual.
Logging terstruktur mengubah ini dengan memperlakukan entri log sebagai objek data, bukan sekadar teks. Setiap entri log menjadi catatan terstruktur dengan bidang yang dapat dicari, sehingga mudah ditanya dan dianalisis secara terprogram.
Logging terstruktur JSON dengan serialize=True
Loguru membuat logging terstruktur menjadi sederhana dengan opsi
serialize=True:Parameter
serialize=Truememberi tahu Loguru untuk menghasilkan JSON alih-alih teks biasa. Alih-alih kalimat yang mudah dibaca, file log Anda kini berisi data terstruktur:Format ini bekerja sempurna dengan alat analisis log yang dapat mencari dan memfilter data JSON secara otomatis.
Pengikatan konteks
Namun aplikasi web membutuhkan lebih dari sekadar data terstruktur. Anda butuh konteks yang menghubungkan entri log terkait. Saat memproses permintaan pengguna, Anda ingin semua log terkait berbagi informasi umum seperti user ID atau session ID.
Pengikatan konteks menyelesaikan ini dengan melampirkan informasi persisten ke logger Anda menggunakan
logger.bind():Kini setiap log dari
order_loggerotomatis menyertakanuser_iddanorder_id, sehingga mudah melacak semua log terkait pesanan tertentu.Banyak sink untuk output berbeda
Aplikasi modern juga membutuhkan output log berbeda untuk tujuan berbeda. Anda mungkin ingin log konsol yang mudah dibaca saat pengembangan, tetapi log JSON untuk pemantauan produksi. Di Loguru, setiap tujuan output disebut “sink” — anggap sebagai tempat aliran pesan log.
Loguru memungkinkan Anda menambahkan banyak sink dengan format dan aturan berbeda:
Panggilan
logger.remove()menghapus output konsol bawaan Loguru agar Anda bisa menyiapkan sendiri. Setiaplogger.add()membuat sink baru dengan aturannya sendiri tentang apa yang dicatat dan bagaimana formatnya.Kini pernyataan log yang sama menghasilkan output berbeda:
Contoh lengkap Loguru: sistem pendaftaran pengguna
Mari lihat contoh yang lebih sederhana namun realistis menggunakan Loguru — sistem pendaftaran pengguna dasar:
Penyiapan ini memberi Anda output konsol yang mudah dibaca saat pengembangan, log JSON terstruktur untuk pemantauan otomatis, dan log error terpisah untuk peringatan. Metode
bind()memastikan semua log untuk setiap pendaftaran pengguna menyertakan alamat email, sehingga debug jauh lebih mudah.Penanganan Pengecualian Loguru
Saat kode Anda crash, biasanya Anda mendapatkan stack trace dasar yang memberi tahu di mana error terjadi, tetapi tidak banyak tentang alasannya. Anda kehilangan nilai variabel saat crash, sehingga sulit memahami apa yang salah. Penanganan pengecualian tradisional juga mengharuskan Anda membungkus semuanya dalam blok try-catch dan mencatat setiap pengecualian secara manual.
Ini menjadi sangat menyakitkan saat debug masalah produksi. Pengguna melaporkan error, tetapi Anda tidak dapat mereproduksinya karena tidak memiliki konteks yang ada saat error terjadi.
Loguru menyelesaikan ini dengan penangkapan pengecualian otomatis dan traceback yang disempurnakan yang menunjukkan tepat apa yang terjadi di kode Anda saat sesuatu berjalan salah.
Penangkapan pengecualian otomatis dengan @logger.catch
Dekorator
@logger.catchsecara otomatis menangkap pengecualian apa pun yang terjadi di suatu fungsi dan mencatatnya dengan konteks lengkap. Dekorator seperti@logger.catchadalah konsep Python tingkat menengah yang dapat mengubah cara Anda menangani error di seluruh codebase:Alih-alih program Anda crash dengan pesan error dasar, Loguru menangkap pengecualian dan mencatatnya dengan informasi terperinci, sementara program Anda terus berjalan. Dekorator ini berfungsi pada fungsi apa pun — metode kelas, fungsi async, atau fungsi biasa.
Traceback yang disempurnakan dengan inspeksi variabel
Namun Loguru melangkah lebih jauh dengan traceback yang disempurnakan yang menampilkan nilai variabel di setiap level call stack. Fitur ini disebut “diagnose” dan ibarat debugger yang tertanam di log Anda:
Dengan
diagnose=True, saat fungsi crash karena mencoba mengurangkan string dari angka, Loguru menunjukkan tepat apa yang ada di setiap variabel:Tingkat detail ini membuat debug jauh lebih cepat karena Anda dapat melihat persis data apa yang menyebabkan masalah.
Penanganan pengecualian yang peka terhadap lingkungan
Namun, traceback yang disempurnakan dapat mengekspos informasi sensitif seperti kata sandi atau API key di log produksi. Loguru memungkinkan Anda mengontrol perilaku ini untuk lingkungan yang berbeda:
Evaluasi malas untuk kinerja
Fitur kuat lainnya adalah evaluasi malas (lazy evaluation), yang meningkatkan kinerja saat mencatat operasi mahal. Terkadang Anda ingin mencatat informasi kompleks, tetapi hanya jika benar-benar terjadi error:
Sintaks
lambda:membuat fungsi yang hanya dipanggil ketika Loguru benar-benar menulis pesan log. Jika tidak ada error,expensive_data_summary()tidak pernah dijalankan, menghemat waktu pemrosesan.Strategi berbeda untuk jenis error berbeda
Anda juga dapat menggunakan strategi penanganan pengecualian yang berbeda untuk berbagai jenis error:
Parameter
reraise=Falsememberi tahu Loguru untuk mencatat pengecualian tetapi tidak melemparkannya kembali, sehingga program Anda dapat terus berjalan. Ini berguna untuk fitur opsional yang tidak boleh merusak alur kerja utama Anda.Contoh lengkap: pemrosesan file dengan penanganan error
Mari lihat contoh lengkap dengan sistem pemrosesan file yang menangani berbagai jenis error secara elegan:
Penyiapan ini memberi Anda penangkapan pengecualian otomatis, konteks error yang detail saat dibutuhkan, dan strategi penanganan berbeda untuk berbagai tipe error. Log Anda menjadi jauh lebih berguna untuk debug, sementara kode Anda tetap bersih dan mudah dibaca.
Konfigurasi dan Kustomisasi Loguru Lanjutan
Seiring aplikasi Anda berkembang, Anda akan menemukan skenario di mana default Loguru kurang pas. Mungkin Anda butuh level log khusus untuk metrik bisnis, ingin menyaring data sensitif dari log, atau perlu mengirim peringatan ke Slack saat terjadi error.
Kabar baiknya, Loguru dibangun untuk dikustomisasi tanpa kehilangan kesederhanaannya. Anda dapat memperluasnya dengan cara yang dalam sistem logging tradisional butuh konfigurasi kompleks, sembari menjaga kode tetap bersih dan mudah dibaca.
Mari lihat kustomisasi paling berguna yang menyelesaikan masalah nyata yang akan Anda hadapi di aplikasi produksi.
Level dan warna log kustom
Loguru hadir dengan level standar seperti INFO, DEBUG, dan ERROR. Namun terkadang Anda butuh sesuatu yang spesifik untuk aplikasi Anda. Mungkin Anda ingin level khusus untuk metrik kinerja atau peristiwa bisnis.
Membuat level log kustom itu mudah:
Parameter
nomenetapkan prioritas level (angka lebih tinggi = prioritas lebih tinggi). Level standar: DEBUG=10, INFO=20, WARNING=30, ERROR=40, CRITICAL=50.Mari lihat ini dalam skenario pelatihan machine learning:
Mencegat dan memodifikasi pesan log
Terkadang Anda perlu memodifikasi pesan log sebelum ditulis. Kasus umum termasuk menghapus data sensitif, menambahkan ID permintaan, atau memformat ulang pesan untuk alat tertentu.
Loguru memungkinkan Anda mencegat pesan menggunakan parameter
filter:Anda juga dapat menggunakan filter untuk menambahkan informasi kontekstual:
Sink kustom untuk layanan eksternal
Sink adalah tempat aliran log Anda. Meskipun file dan konsol umum digunakan, sering kali Anda perlu mengirim log ke layanan eksternal seperti Slack, email, atau sistem pemantauan.
Berikut cara membuat sink kustom yang mengirim error ke Slack:
Berikut contoh praktis lainnya — sink kustom yang mengumpulkan metrik kinerja sepanjang jalannya aplikasi dan menyimpannya untuk analisis:
Keindahan pendekatan ini adalah kode aplikasi Anda tetap bersih — Anda cukup mencatat metrik seperti biasa, dan sink kolektor menangani penyimpanan secara otomatis. Anda dapat dengan mudah menggantinya dengan sink yang mengirim metrik ke Prometheus, DataDog, atau layanan pemantauan lainnya.
Kustomisasi ini memberi Anda fleksibilitas untuk menyesuaikan Loguru dengan kebutuhan spesifik sambil menjaga kesederhanaan yang menjadikannya unggul. Baik Anda membangun skrip kecil atau aplikasi besar, Anda dapat memperluas Loguru untuk menangani kebutuhan logging unik tanpa file konfigurasi kompleks atau boilerplate.
Kesimpulan
Loguru membuat logging di Python sesederhana yang seharusnya. Tidak ada lagi file konfigurasi, tidak ada lagi penyiapan handler, tidak ada lagi boilerplate. Cukup impor dan mulai logging dengan warna, stempel waktu, dan rotasi file otomatis.
Anda telah melihat bagaimana Loguru menangani titik sakit umum: menyimpan log ke file, merotasinya secara otomatis, menangkap pengecualian dengan konteks lengkap, dan mengirim log ke layanan eksternal. Fitur logging terstruktur membuatnya siap produksi, sementara level dan sink kustom memungkinkan Anda menyesuaikannya untuk kasus apa pun.
Gunakan Loguru saat:
Untuk pembelajaran lebih dalam, jelajahi dokumentasi resmi bersama tutorial logging ini untuk cakupan komprehensif strategi logging Python.
Mulailah dari hal kecil. Ganti satu pernyataan print dengan
logger.info(). Anda tidak akan kembali lagi.