Sistem produksi modern menghasilkan jutaan baris log per hari. AI membantu menemukan jarum anomali dalam tumpukan jerami log — sebelum pengguna merasakan dampaknya.
Tanpa AI: Seorang dokter IGD harus membaca 10 juta rekam medis dalam satu jam untuk menemukan pasien yang kritis. Mustahil dilakukan secara manual.
Dengan AI: Sistem triage otomatis langsung memflag pasien yang vital sign-nya anomali — dokter hanya perlu menangani kasus yang sudah diprioritaskan. AI melakukan screening, manusia melakukan judgment.
Inilah peran AI dalam analisis log: menyaring jutaan baris log untuk menemukan pola abnormal yang menandakan masalah, sebelum sistem benar-benar down.
📋 Contoh nyata: Netflix memproses lebih dari 500 miliar event log per hari. Manual analysis tidak mungkin — mereka menggunakan Anomaly Detection berbasis ML untuk mendeteksi degradasi performa sebelum pengguna melapor.
Bayangkan 100 dokter di satu rumah sakit masing-masing menulis rekam medis dengan format berbeda — ada yang dalam Bahasa Indonesia, Inggris, ada yang menggunakan singkatan sendiri. Itulah masalah log parsing: setiap library, framework, dan developer menulis log dengan format berbeda. AI harus bisa memahami semuanya dan mengekstrak informasi yang sama.
Bayangkan 100.000 pesan keluhan customer service: "Pembayaran saya gagal jam 10:32", "Transaksi saya error jam 14:15", "Transfer saya tidak berhasil jam 09:00". Drain algorithm seperti staf yang cerdas yang mengelompokkan semua ini menjadi satu template: "Pembayaran/Transaksi/Transfer [USER_ACTION] [STATUS] jam [TIME]" — lalu bisa mendeteksi kapan template ini muncul secara anomali.
Identifikasi dan mask token yang berubah-ubah: IP address, timestamp, user ID, angka. Contoh: "user U-4421 login from 192.168.1.1" menjadi "user <ID> login from <IP>"
Drain membangun parse tree berdasarkan panjang kata dan token pertama. Log baru diarahkan ke cabang yang paling cocok, lalu dibandingkan token per token.
Jika dua log di cabang yang sama memiliki token berbeda di posisi yang sama, token itu digantikan dengan wildcard "<*>". Template menjadi semakin general seiring data baru masuk.
Setiap log dipetakan ke event template-nya. Parameter dinamis diekstrak secara terpisah. Hasilnya: structured log yang bisa dianalisis secara statistik dan ML.
| Algoritma | Kecepatan | Akurasi | Kapan Digunakan |
|---|---|---|---|
| Drain + Counting | Sangat cepat | Medium | Baseline, real-time alerting sederhana |
| Isolation Forest | Cepat | Tinggi | Metric anomaly, high-dim data, production |
| LSTM / DeepLog | Lambat (training) | Tertinggi | Complex sequential patterns, critical systems |
| Autoencoder | Medium | Tinggi | Unknown anomaly patterns, unsupervised |
| PCA-Based | Cepat | Medium | Interpretable, audit trail needed |
Elasticsearch = gudang arsip raksasa dengan index cepat — bisa mencari di antara miliaran dokumen dalam milidetik. Logstash = kurir yang mengumpulkan, memformat, dan mengantarkan dokumen ke gudang. Kibana = ruang baca interaktif di mana Anda bisa memvisualisasikan dan menganalisis apa pun yang ada di gudang. Beats = agen ringan di setiap server yang mengumpulkan log lokal untuk dikirim ke Logstash.
💡 Elastic ML Jobs adalah fitur built-in Kibana yang bisa membuat anomaly detection model secara otomatis dari time-series data di Elasticsearch — tanpa perlu kode Python sama sekali. Sangat populer di tim DevOps dan SRE.
Ops tradisional (Reactive): Seperti pemadam kebakaran — tunggu ada api, baru bertindak. Alarm berbunyi saat database down, engineer terbangun jam 3 pagi, baru investigasi.
AIOps (Predictive): Seperti sensor asap yang mendeteksi panas berlebih sebelum api muncul. AI menganalisis tren metrik (memori naik perlahan, query time meningkat gradual) dan memperingatkan engineer sebelum terjadi kegagalan, sehingga bisa dicegah di jam kerja normal.
# ================================================================
# S11409 - Sesi 11: Log Anomaly Detection Pipeline
# Dosen: Riadi Marta Dinata, S.Ti., M.Kom. | ISTN Jakarta
# pip install scikit-learn pandas numpy matplotlib
# ================================================================
import re, json
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.ensemble import IsolationForest
from sklearn.preprocessing import StandardScaler
from collections import Counter, defaultdict
from datetime import datetime, timedelta
import warnings; warnings.filterwarnings('ignore')
# ── STEP 1: GENERATE SYNTHETIC LOG DATA ──────────────────────
np.random.seed(42)
def generate_logs(n_normal=500, n_anomaly=30):
"""Generate simulated payment service logs"""
logs = []
base_time = datetime(2024, 3, 15, 8, 0, 0)
# Normal logs - gaussian distributed latency
for i in range(n_normal):
t = base_time + timedelta(seconds=i * 0.5)
latency = max(10, int(np.random.normal(120, 30))) # ~120ms normal
tx_id = f"TX-{9000 + i}"
user_id = f"U-{np.random.randint(1000, 9999)}"
amount = np.random.choice([50000, 75000, 100000, 150000, 200000])
level = "INFO" if latency < 200 else "WARN"
msg = f"Transaction {tx_id} processed for {user_id}, amount={amount}, latency={latency}ms"
logs.append({"timestamp": t, "level": level, "latency": latency,
"msg": msg, "is_anomaly": 0})
# Anomaly block - spike in errors and latency
anomaly_start = base_time + timedelta(seconds=n_normal * 0.5 + 10)
for i in range(n_anomaly):
t = anomaly_start + timedelta(seconds=i * 0.3)
latency = int(np.random.normal(800, 150)) # 800ms anomaly spike
tx_id = f"TX-{9500 + i}"
user_id = f"U-{np.random.randint(1000, 9999)}"
level = np.random.choice(["ERROR", "WARN", "ERROR"], p=[0.6, 0.2, 0.2])
if level == "ERROR":
msg = f"Transaction {tx_id} FAILED: connection timeout after {latency}ms"
else:
msg = f"Transaction {tx_id} slow warning: latency={latency}ms exceeds threshold"
logs.append({"timestamp": t, "level": level, "latency": latency,
"msg": msg, "is_anomaly": 1})
df = pd.DataFrame(logs).sort_values("timestamp").reset_index(drop=True)
return df
df = generate_logs()
print("=" * 60)
print(" LOG ANOMALY DETECTION PIPELINE")
print(" S11409 ISTN Jakarta | Sesi 11")
print("=" * 60)
print(f"\nTotal logs : {len(df)}")
print(f"Normal logs : {(df['is_anomaly']==0).sum()}")
print(f"Anomaly logs : {(df['is_anomaly']==1).sum()}")
# ── STEP 2: FEATURE ENGINEERING FROM LOGS ────────────────────
def engineer_features(df, window_size=20):
"""Extract time-window features for each log entry"""
features = []
for i in range(len(df)):
start = max(0, i - window_size)
window = df.iloc[start:i+1]
feat = {
"latency": df.iloc[i]["latency"],
"is_error": 1 if df.iloc[i]["level"] == "ERROR" else 0,
"is_warn": 1 if df.iloc[i]["level"] == "WARN" else 0,
# Window-based features
"window_error_rate": (window["level"] == "ERROR").mean(),
"window_warn_rate": (window["level"] == "WARN").mean(),
"window_mean_latency": window["latency"].mean(),
"window_max_latency": window["latency"].max(),
"window_std_latency": window["latency"].std() if len(window) > 1 else 0,
"window_p95_latency": window["latency"].quantile(0.95),
}
features.append(feat)
return pd.DataFrame(features)
print("\nEngineering features from log windows...")
X = engineer_features(df, window_size=20)
y_true = df["is_anomaly"].values
# ── STEP 3: ISOLATION FOREST ANOMALY DETECTION ───────────────
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# contamination = expected fraction of anomalies
iso_forest = IsolationForest(
n_estimators=200,
contamination=0.07, # ~7% anomali yang kita harapkan
max_samples="auto",
random_state=42,
n_jobs=-1
)
print("Training Isolation Forest...")
y_pred_raw = iso_forest.fit_predict(X_scaled)
y_pred = (y_pred_raw == -1).astype(int) # -1 = anomali, 1 = normal
anomaly_scores = -iso_forest.score_samples(X_scaled) # makin tinggi = lebih anomali
# ── STEP 4: EVALUATE ─────────────────────────────────────────
from sklearn.metrics import classification_report, confusion_matrix
print("\n--- Anomaly Detection Results ---")
print(classification_report(y_true, y_pred,
target_names=["Normal", "Anomaly"]))
tp = ((y_pred==1) & (y_true==1)).sum()
fp = ((y_pred==1) & (y_true==0)).sum()
fn = ((y_pred==0) & (y_true==1)).sum()
tn = ((y_pred==0) & (y_true==0)).sum()
print(f" True Positives (caught anomalies): {tp}")
print(f" False Positives (false alarms) : {fp}")
print(f" False Negatives (missed anomalies): {fn}")
# ── STEP 5: VISUALIZE ─────────────────────────────────────────
fig, axes = plt.subplots(2, 2, figsize=(14, 8))
fig.patch.set_facecolor('#0A0608')
fig.suptitle('Log Anomaly Detection Dashboard — S11409 ISTN',
color='white', fontsize=13, fontweight='bold', y=1.01)
# Plot 1: Latency timeline with anomalies
ax1 = axes[0, 0]; ax1.set_facecolor('#160C0E')
ax1.plot(df.index, df['latency'], color='#9B7A80', alpha=0.5, linewidth=0.8, label='Latency')
anomaly_idx = np.where(y_pred == 1)[0]
ax1.scatter(anomaly_idx, df['latency'].iloc[anomaly_idx],
color='#E8374F', s=25, zorder=5, label='Detected Anomaly')
ax1.axhline(y=200, color='#D4A017', linestyle='--', alpha=0.6, label='Threshold 200ms')
ax1.set_title('Response Latency Timeline', color='white')
ax1.tick_params(colors='#9B7A80')
ax1.legend(fontsize=8, facecolor='#160C0E', labelcolor='white')
# Plot 2: Anomaly score distribution
ax2 = axes[0, 1]; ax2.set_facecolor('#160C0E')
ax2.hist(anomaly_scores[y_true==0], bins=40, color='#22C55E', alpha=0.6, label='Normal')
ax2.hist(anomaly_scores[y_true==1], bins=20, color='#E8374F', alpha=0.7, label='Anomaly')
ax2.set_title('Anomaly Score Distribution', color='white')
ax2.tick_params(colors='#9B7A80')
ax2.legend(fontsize=9, facecolor='#160C0E', labelcolor='white')
# Plot 3: Log level distribution
ax3 = axes[1, 0]; ax3.set_facecolor('#160C0E')
level_counts = df['level'].value_counts()
colors_bar = ['#22C55E', '#F97316', '#E8374F'][:len(level_counts)]
ax3.bar(level_counts.index, level_counts.values, color=colors_bar, edgecolor='none')
ax3.set_title('Log Level Distribution', color='white')
ax3.tick_params(colors='#9B7A80')
# Plot 4: Window error rate
ax4 = axes[1, 1]; ax4.set_facecolor('#160C0E')
ax4.fill_between(range(len(X)), X['window_error_rate'],
color='#A78BFA', alpha=0.4, label='Error Rate (window)')
ax4.scatter(anomaly_idx, X['window_error_rate'].iloc[anomaly_idx],
color='#E8374F', s=20, zorder=5, label='Anomaly Points')
ax4.set_title('Window Error Rate', color='white')
ax4.tick_params(colors='#9B7A80')
ax4.legend(fontsize=8, facecolor='#160C0E', labelcolor='white')
plt.tight_layout()
plt.savefig('log_anomaly_detection.png', dpi=150,
facecolor='#0A0608', bbox_inches='tight')
print("\nVisualisasi tersimpan: log_anomaly_detection.png")
# ── STEP 6: ALERTING SIMULATION ──────────────────────────────
print("\n--- Alert Simulation (last 10 anomalies) ---")
anomaly_logs = df[y_pred == 1].tail(10)
for _, row in anomaly_logs.iterrows():
score = anomaly_scores[row.name]
severity = "CRITICAL" if score > 0.6 else "HIGH"
print(f" [{severity}] {row['timestamp'].strftime('%H:%M:%S')} "
f"| Latency={row['latency']}ms | {row['level']} "
f"| Score={score:.3f}")
print("\nDone! Jalankan dengan: python log_anomaly.py")
Berikut 4 baris log dari payment service: (1) "User U-4421 paid Rp150000 at 08:01", (2) "User U-8832 paid Rp75000 at 08:02", (3) "User U-1234 paid Rp200000 at 08:05", (4) "User U-9999 FAILED payment at 08:06". Terapkan konsep Drain: (a) Identifikasi token dinamis, (b) Tulis 2 template log yang dihasilkan, (c) Mana yang anomali dan mengapa?
Sistem e-commerce ingin mendeteksi: (a) Lonjakan tiba-tiba jumlah error dalam 1 menit, (b) Pola urutan login yang mencurigakan (login-gagal berulang lalu berhasil), (c) CPU usage yang naik gradual selama 2 jam sebelum crash. Rekomendasikan algoritma yang paling tepat untuk setiap kasus dan jelaskan alasannya.
Isolation Forest memberikan anomaly score 0.82 untuk sebuah log entry. Jelaskan: (a) Apa arti score ini secara intuitif? (b) Mengapa anomali mendapat score lebih tinggi dari data normal dalam Isolation Forest? (c) Bagaimana Anda menentukan threshold yang tepat antara normal dan anomali?
ISTN ingin membangun sistem monitoring untuk SIAKAD yang melayani 5.000 mahasiswa. Log dihasilkan dari: web server, application server, database, dan payment gateway. Desain pipeline ELK Stack yang tepat: (a) Komponen mana yang dipasang di server mana? (b) Bagaimana Logstash memproses log berbeda format? (c) Alert apa yang harus dikonfigurasi di Kibana?
Modifikasi kode di atas: (a) Tambahkan deteksi "brute force login" — jika lebih dari 5 ERROR dalam 60 detik dari satu IP yang sama, flagging sebagai anomali keamanan; (b) Implementasikan rolling window statistic dengan window 50 log; (c) Tambahkan feature "log volume per second" dan amati apakah meningkatkan akurasi deteksi.
97% log adalah noise — AI membantu menemukan 3% sinyal penting tanpa manusia membaca jutaan baris
Drain algorithm mengubah log teks bebas menjadi template terstruktur — fondasi untuk analisis statistik dan ML
Isolation Forest adalah pilihan terbaik untuk production: cepat, tidak butuh label, efektif untuk high-dimensional metrics
LSTM/DeepLog terbaik untuk sequential anomaly tapi butuh data training dan waktu komputasi lebih besar
ELK Stack adalah standar industri — Elasticsearch + Logstash + Kibana + Beats, tersedia versi open source
AIOps mengubah operasi dari reaktif ke prediktif — target utama: kurangi MTTR dan false alert >50%