Ön Hazırlık ve Gereksinimler
Python ile logging modülünü kullanmaya başlamak için herhangi bir harici kütüphane kurmanıza gerek yoktur; çünkü bu modül Python'ın standart kütüphanesinin bir parçasıdır. Ancak, profesyonel bir çalışma ortamı için Python 3.10 ve üzeri bir sürüm kullanmanız önerilir.
- Python 3.10+ yüklü bir geliştirme ortamı.
- Kod editörü (VS Code veya PyCharm önerilir).
- Proje dizininde log dosyalarını tutacak bir klasör yapısı.
Öncelikle, sisteminizde Python'ın yüklü olduğunu doğrulamak için terminalde python --version komutunu çalıştırabilirsiniz. Eğer yüklü değilse, resmi Python web sitesinden güncel sürümü edinmelisiniz.
Temel Logging Yapılandırması
Logging modülü beş farklı seviyeden oluşur: DEBUG, INFO, WARNING, ERROR ve CRITICAL. Bu seviyeler, log mesajlarınızın önem derecesini belirler. İlk adım olarak basit bir yapılandırma ile log mesajlarını konsola yazdıralım.
import logging
# Loglama ayarlarını yapılandırıyoruz
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s')
logging.debug("Bu bir hata ayıklama mesajıdır.")
logging.info("Uygulama başarıyla başlatıldı.")
logging.warning("Bellek kullanımı artıyor.")
logging.error("Veritabanı bağlantısı kurulamadı.")
logging.critical("Sistem kritik bir hata nedeniyle durdu.")
Burada basicConfig fonksiyonu, logların nasıl görüneceğini ve hangi seviyeden itibaren kaydedileceğini belirler. level=logging.DEBUG ayarı, tüm log seviyelerinin gösterilmesini sağlar.
Logları Dosyaya Yazdırma ve Kalıcı Hale Getirme
Uygulama kapandığında konsoldaki veriler kaybolur. Bu nedenle, hata takibini kalıcı hale getirmek için logları bir dosyaya kaydetmek gerekir. Aşağıdaki örnekte, logların bir dosyaya nasıl yönlendirileceğini görebilirsiniz.
import logging
# Logları 'uygulama.log' dosyasına kaydeder
logging.basicConfig(
filename='uygulama.log',
filemode='a', # 'a' (append) modu ile dosyanın sonuna ekler
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
level=logging.ERROR
)
def veritabani_islemi():
try:
sonuc = 1 / 0
except ZeroDivisionError:
logging.error("Sıfıra bölme hatası oluştu!", exc_info=True)
veritabani_islemi()
exc_info=True parametresi, hatanın tüm yığın izini (traceback) log dosyasına ekler. Bu, hatanın tam olarak hangi satırda ve hangi fonksiyon içinde oluştuğunu anlamak için kritiktir.
Log Seviyeleri ve Kullanım Alanları
Hata takibini verimli kılmak için doğru seviyeyi seçmek önemlidir. Yanlış seviye kullanımı, log dosyalarınızın gereksiz verilerle dolmasına veya önemli hataların gözden kaçmasına neden olabilir.
| Seviye | Kullanım Amacı |
|---|---|
| DEBUG | Geliştirme aşamasında detaylı bilgi takibi. |
| INFO | Uygulamanın normal işleyişini doğrulama. |
| WARNING | Beklenmeyen ancak sistemi durdurmayan durumlar. |
| ERROR | İşlevselliği engelleyen hatalar. |
| CRITICAL | Sistemi çökerten veya veri kaybına yol açan hatalar. |
Logger Nesneleri ile Modüler Yapı
Büyük projelerde tek bir global yapılandırma yerine, her modül için ayrı bir logger nesnesi oluşturmak daha profesyoneldir. Bu sayede hangi modülden hata geldiğini kolayca ayırt edebilirsiniz.
import logging
# Modül bazlı logger oluşturma
logger = logging.getLogger('auth_modulu')
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler('auth.log')
formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.info("Kullanıcı giriş denemesi yapıldı.")
logger.error("Hatalı şifre girişi!")
Bu yaklaşım, farklı modüllerin loglarını farklı dosyalara veya farklı seviyelerde yönetmenize olanak tanır. Örneğin, veritabanı modülünüz sadece ERROR seviyesindeki logları tutarken, kimlik doğrulama modülünüz tüm INFO loglarını tutabilir.
İleri Seviye: Log Döndürme (Rotating File Handler)
Log dosyaları zamanla devasa boyutlara ulaşabilir. RotatingFileHandler kullanarak log dosyalarınızın belirli bir boyuta ulaştığında otomatik olarak yedeklenmesini ve temizlenmesini sağlayabilirsiniz.
from logging.handlers import RotatingFileHandler
import logging
logger = logging.getLogger("sistem_log")
logger.setLevel(logging.INFO)
# 1MB boyutunda 3 adet yedek dosya tutar
handler = RotatingFileHandler('app.log', maxBytes=1000000, backupCount=3)
logger.addHandler(handler)
logger.info("Sistem dosyası döndürme yapılandırması aktif.")
Bu yöntem, sunucu disk alanınızın dolmasını engeller ve log yönetimini otomatikleştirir. Üretim ortamında çalışan uygulamalar için bu yapılandırma zorunludur.
Güvenlik Uyarısı: Log dosyalarınızın içerisine asla kullanıcı şifreleri, kredi kartı numaraları veya kişisel verileri (PII) yazdırmayın. Log dosyaları genellikle daha az güvenli ortamlarda saklanır ve bu verilerin sızması ciddi güvenlik ihlallerine yol açar.
Sıkça Sorulan Sorular
Log mesajlarını neden print() yerine logging ile yazmalıyım?
print() fonksiyonu sadece standart çıktıya yazar ve yönetilemez. logging ise hata seviyelerini, zaman damgalarını, dosya yönlendirmeyi ve log rotasyonunu destekler, bu da onu profesyonel hata takibi için vazgeçilmez kılar.
Uygulama hata takibinde en sık yapılan hata nedir?
En sık yapılan hata, log dosyalarının boyutunu yönetmemektir. Log dosyaları sürekli büyüyerek sunucunun diskini doldurabilir. Bu yüzden her zaman RotatingFileHandler kullanılmalıdır.
Üretim ortamında hangi log seviyesi kullanılmalıdır?
Genellikle üretim ortamlarında INFO veya WARNING seviyesi tercih edilir. DEBUG seviyesi, log dosyalarını gereksiz bilgilerle şişireceği için sadece hata ayıklama sırasında kullanılmalıdır.
Log mesajlarına nasıl ek bilgi (context) ekleyebilirim?
extra parametresini kullanarak log mesajlarına sözlük şeklinde ek veriler (örneğin kullanıcı ID'si) ekleyebilirsiniz. Bu, hata analizini çok daha hızlandırır.
Log dosyalarını merkezi bir yerde nasıl toplayabilirim?
Logları merkezi bir sunucuda toplamak için SocketHandler veya HTTPHandler kullanarak logları uzak bir sunucuya (ELK Stack veya Graylog gibi) gönderebilirsiniz.
Loglama Performansını Optimize Etme ve Asenkron İşlemler
Yüksek trafikli uygulamalarda, loglama işlemleri I/O (giriş/çıkış) yükü nedeniyle uygulamanın ana iş parçacığını (main thread) yavaşlatabilir. Senkron çalışan bir loglama mekanizması, özellikle dosya yazma işlemlerinde darboğaz oluşturabilir. Bu durumu aşmak için QueueHandler ve QueueListener sınıflarını kullanarak loglama işlemlerini ayrı bir iş parçacığına devredebilirsiniz.
import logging
import logging.handlers
import queue
import threading
# Log kuyruğu oluşturma
log_queue = queue.Queue(-1)
queue_handler = logging.handlers.QueueHandler(log_queue)
# Ana logger yapılandırması
logger = logging.getLogger("async_logger")
logger.addHandler(queue_handler)
logger.setLevel(logging.INFO)
# Logları işleyecek listener (ayrı thread)
file_handler = logging.FileHandler("app.log")
listener = logging.handlers.QueueListener(log_queue, file_handler)
listener.start()
try:
logger.info("Bu log asenkron olarak işleniyor.")
finally:
listener.stop()
Bu yöntem, uygulamanızın loglama süreci yüzünden beklemesini engeller ve performans kaybını minimize eder. Özellikle mikroservis mimarilerinde her servisin kendi kuyruğunu yönetmesi, sistemin genel yanıt süresini (latency) iyileştirir.
Loglama Sürecinde Güvenlik ve Hassas Veri Filtreleme
Uygulama hata takibi yaparken en sık karşılaşılan güvenlik ihlallerinden biri, log dosyalarına yanlışlıkla parola, kredi kartı bilgisi veya kişisel verilerin (KVKK kapsamında) yazılmasıdır. Bu tür verilerin loglara sızmasını engellemek için logging.Filter sınıfını kullanarak özel bir filtreleme mekanizması geliştirmelisiniz.
import logging
import re
class SensitiveDataFilter(logging.Filter):
"""Log mesajlarındaki e-posta adreslerini maskeler."""
def filter(self, record):
message = str(record.msg)
# Basit bir e-posta maskeleme regex'i
pattern = r'[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}'
record.msg = re.sub(pattern, "[MASKELENDİ]", message)
return True
logger = logging.getLogger("secure_logger")
logger.addFilter(SensitiveDataFilter())
# Kullanım örneği
logger.info("Kullanıcı girişi başarısız: test@example.com")
# Çıktı: Kullanıcı girişi başarısız: [MASKELENDİ]
Bu yaklaşım, log dosyalarınızın merkezi bir yönetim sistemine gönderilmeden önce temizlenmesini sağlar. Özellikle üretim ortamında, log dosyalarının yetkisiz kişilerce erişilebilir olması durumunda bu filtreleme katmanı kritik bir güvenlik önlemi haline gelir.
İleri Seviye İpuçları
- JSON Formatı Kullanımı: Loglarınızı ELK veya Splunk gibi sistemlere gönderiyorsanız, logları düz metin yerine JSON formatında yazdırın. Bu, verilerin ayrıştırılmasını (parsing) kolaylaştırır.
- Contextual Logging:
logging.LoggerAdapterkullanarak her log satırına otomatik olarak "request_id" veya "user_id" gibi bağlamsal bilgileri ekleyin. - Sessiz Hata Yönetimi: Loglama sisteminin kendisinin hata vermesi durumunda uygulamanın çökmemesi için
propagate = Falseayarını ve try-except bloklarını dikkatli kullanın.
Sonuç
Python ile logging modülü kullanarak uygulama hata takibi yapmak, uygulamanızın güvenilirliğini ve sürdürülebilirliğini artıran temel bir beceridir. Bu rehberde öğrendiğiniz temel yapılandırmalar, dosya yönetimi ve modüler logger kullanımı, profesyonel bir yazılım geliştirme sürecinin yapı taşlarıdır. Bir sonraki adım olarak, loglarınızı bir bulut tabanlı log yönetim sistemine (Logstash veya Datadog gibi) nasıl entegre edebileceğinizi araştırmanızı öneririm.
Sorumluluk Reddi: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Yazılımlarınızdaki güvenlik açıklarından (SQL injection, XSS vb.) geliştirici sorumludur. Loglama mekanizmalarını kurarken her zaman veri gizliliği standartlarına (KVKK/GDPR) uygun hareket edin.

Yorumlar (0)
Yorum Yaz