Broker Log: Mengonfigurasi dan Menganalisis Log Server Apache Kafka #

Dalam mengoperasikan Apache Kafka di skala produksi, kita sering kali dihadapkan pada situasi misterius di mana kinerja kluster tiba-tiba menurun atau salah satu broker terputus dari koordinasi kluster. Untuk melakukan diagnosis masalah (troubleshooting), instrumen pertama yang harus kita periksa adalah log operasional server broker (Broker Log). Berbeda dengan log data (log segments) yang menampung payload pesan asli dari produser, log server berisi pesan diagnostik dari mesin internal Kafka (seperti status replikasi, siklus hidup konsumen, otorisasi ACL, dan metadata pengawas).

Banyak tim DevOps pemula yang mencampuradukkan kedua istilah log ini atau membiarkan konfigurasi log server default berjalan di produksi. Akibatnya, disk server mereka cepat penuh oleh file log server raksasa yang tidak berotasi, atau sebaliknya, mereka kehilangan informasi berharga karena level logging disetel terlalu tinggi (WARN atau ERROR saja).

Dalam panduan ini, kita akan membedah perbedaan log data vs log server, menyusun konfigurasi log4j.properties yang optimal untuk produksi, mempelajari teknik mengubah level logging secara dinamis tanpa restart broker (Dynamic Log Level Tuning), serta mendekode pesan log server untuk memecahkan masalah produksi yang umum terjadi.

Membedakan Log Data vs Log Server #

Sebelum melangkah lebih jauh, sangat penting bagi kita untuk memisahkan kedua konsep log berikut karena kegagalan memahami perbedaan ini sering kali berujung pada kesalahan konfigurasi disk:

+---------------------------------------------------------------------------------+
|                         PERBEAAN UTAMA DUA JENIS LOG                            |
|                                                                                 |
|  1. LOG DATA (Data Log Segments)                                                |
|     * Jalur Properti: log.dirs=/var/lib/kafka/data                              |
|     * Isi: Payload biner pesan asli dari produser (.log, .index, .timeindex)    |
|     * Pengaturan: log.retention.hours, log.retention.bytes                      |
|                                                                                 |
|  2. LOG SERVER (Server Operation Log)                                           |
|     * Konfigurasi: /etc/kafka/log4j.properties                                  |
|     * Isi: Teks logs diagnostik JVM Java/Scala (ReplicaManager, Controller, ZK) |
|     * Pengaturan: FileSize, MaxBackupIndex, DailyRollingFileAppender            |
+---------------------------------------------------------------------------------+

Log server ditulis oleh framework Log4j yang dibungkus oleh Java Virtual Machine (JVM). Log inilah yang akan menjadi fokus pembahasan kita untuk memantau kesehatan operasional broker.


Arsitektur Alur Logger Internal Kafka Broker #

Kafka membagi aktivitas pencatatannya ke dalam beberapa kategori logger khusus agar kita dapat memisahkan file output berdasarkan fungsinya.

Berikut adalah diagram alur logger internal Kafka menuju berkas log fisiknya:

flowchart TD
    subgraph Subsystems ["Subsistem Broker Kafka"]
        ReplicaMgr["Replica Manager (ISR)"]
        Controller["Controller Manager (KRaft/ZK)"]
        GroupCoord["Group Coordinator (Rebalance)"]
        RequestLog["Network Request Processor"]
    end

    subgraph Log4jLoggers ["Log4j Logger Categories"]
        StateLogger["state.change.logger"]
        ContrLogger["kafka.controller"]
        CoordLogger["kafka.coordinator"]
        ReqLogger["kafka.request.logger"]
    end

    subgraph PhysicalFiles ["Berkas Log Fisik (Disk)"]
        StateFile["/var/log/kafka/state-change.log"]
        ServerFile["/var/log/kafka/server.log"]
        RequestFile["/var/log/kafka/kafka-request.log"]
    end

    ReplicaMgr --> StateLogger
    Controller --> ContrLogger
    GroupCoord --> CoordLogger
    RequestLog --> ReqLogger

    StateLogger --> StateFile
    ContrLogger --> ServerFile
    CoordLogger --> ServerFile
    ReqLogger --> RequestFile

Pemecahan kategori ini sangat membantu kita ketika ingin menaikkan tingkat kedetailan log untuk satu modul tertentu tanpa membanjiri modul lainnya dengan pesan yang tidak perlu.


Konfigurasi Produksi: log4j.properties yang Aman #

Secara default, Kafka menulis seluruh log ke dalam satu file tunggal yang berputar setiap hari tanpa batas kapasitas. Di produksi, kita harus membatasi ukuran file maksimal menggunakan RollingFileAppender dengan setelan MaxFileSize dan MaxBackupIndex untuk mencegah disk penuh akibat kebocoran log.

Berikut adalah konfigurasi /etc/kafka/log4j.properties produksi yang telah dioptimalkan:

# ==============================================================================
# log4j.properties - KONFIGURASI PRODUKSI LOG SERVER KAFKA
# ==============================================================================

# 1. Definisikan Level Root Logger dan Appender Utama
log4j.rootLogger=INFO, kafkaAppender

# 2. Konfigurasi Appender Utama (server.log)
log4j.appender.kafkaAppender=org.apache.log4j.RollingFileAppender
log4j.appender.kafkaAppender.File=/var/log/kafka/server.log
# Batasi ukuran per file maksimal 100 MB
log4j.appender.kafkaAppender.MaxFileSize=100MB
# Simpan maksimal 10 file backup (total kapasitas maks 1 GB)
log4j.appender.kafkaAppender.MaxBackupIndex=10
log4j.appender.kafkaAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.kafkaAppender.layout.ConversionPattern=[%d] %p %m (%c)%n

# 3. Konfigurasi Appender Khusus Transisi Status (state-change.log)
log4j.logger.state.change.logger=INFO, stateChangeAppender
log4j.additivity.state.change.logger=false

log4j.appender.stateChangeAppender=org.apache.log4j.RollingFileAppender
log4j.appender.stateChangeAppender.File=/var/log/kafka/state-change.log
log4j.appender.stateChangeAppender.MaxFileSize=100MB
log4j.appender.stateChangeAppender.MaxBackupIndex=5
log4j.appender.stateChangeAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.stateChangeAppender.layout.ConversionPattern=[%d] %p %m (%c)%n

# 4. Konfigurasi Appender Khusus Controller (controller.log)
log4j.logger.kafka.controller=INFO, controllerAppender
log4j.additivity.kafka.controller=false

log4j.appender.controllerAppender=org.apache.log4j.RollingFileAppender
log4j.appender.controllerAppender.File=/var/log/kafka/controller.log
log4j.appender.controllerAppender.MaxFileSize=50MB
log4j.appender.controllerAppender.MaxBackupIndex=5
log4j.appender.controllerAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.controllerAppender.layout.ConversionPattern=[%d] %p %m (%c)%n

# 5. Batasi Verbosity Pustaka Pihak Ketiga (Zookeeper / Netty / Reflections)
log4j.logger.org.apache.zookeeper=WARN
log4j.logger.org.I0Itec.zkclient=WARN
log4j.logger.org.reflections=WARN

# 6. Logger Khusus untuk Keamanan (ACL & Otorisasi)
log4j.logger.kafka.authorizer.logger=INFO, authorizerAppender
log4j.additivity.kafka.authorizer.logger=false

log4j.appender.authorizerAppender=org.apache.log4j.RollingFileAppender
log4j.appender.authorizerAppender.File=/var/log/kafka/kafka-authorizer.log
log4j.appender.authorizerAppender.MaxFileSize=50MB
log4j.appender.authorizerAppender.MaxBackupIndex=5
log4j.appender.authorizerAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.authorizerAppender.layout.ConversionPattern=[%d] %p %m (%c)%n

Integrasi dengan Logrotate Sistem #

Untuk memastikan file log yang telah dirotasi dikompresi dengan aman untuk menghemat ruang disk, kita dapat membuat konfigurasi /etc/logrotate.d/kafka seperti berikut:

/var/log/kafka/*.log {
    daily
    rotate 7
    copytruncate
    compress
    delaycompress
    missingok
    notifempty
}

Metode copytruncate sangat penting karena Kafka memegang deskriptor file log secara terus-menerus. Dengan menggunakan copytruncate, sistem operasi menyalin konten log aktif ke file baru dan mengosongkan file aktif saat ini tanpa memutuskan tautan proses JVM yang sedang menulis log.


Dynamic Log Level Tuning via CLI dan Code #

Ketika kluster mengalami kegagalan otorisasi atau masalah replikasi yang sangat kompleks, level logging INFO sering kali kurang memberikan detail error. Namun, kita tidak boleh merestart broker hanya untuk mengubah level log menjadi DEBUG karena restart akan memicu failover partisi, migrasi kepemimpinan, dan memperparah degradasi performa kluster secara keseluruhan.

Apache Kafka menyediakan API dinamis untuk merubah level logging logger tertentu secara langsung (on-the-fly).

Metode 1: Menggunakan CLI kafka-configs.sh #

Kita dapat memodifikasi level logging secara dinamis menggunakan CLI bawaan Kafka. Perubahan ini dikomunikasikan melalui protokol Kafka AdminClient langsung ke broker tujuan dan diterapkan secara instan tanpa restart JVM.

  1. Memeriksa Level Logger Saat Ini: Untuk melihat daftar logger aktif beserta levelnya pada broker dengan ID 1:

    kafka-configs.sh --bootstrap-server localhost:9093 \
      --command-config /etc/kafka/client.properties \
      --describe \
      --entity-type broker-loggers \
      --entity-name 1
    
  2. Mengubah Level Logger secara Dinamis: Jika kita ingin memantau detail request otorisasi ACL untuk melacak kegagalan otentikasi klien, ubah level kafka.authorizer.logger menjadi DEBUG:

    kafka-configs.sh --bootstrap-server localhost:9093 \
      --command-config /etc/kafka/client.properties \
      --alter \
      --entity-type broker-loggers \
      --entity-name 1 \
      --add-config kafka.authorizer.logger=DEBUG
    
  3. Mengembalikan ke Level Semula: Setelah proses troubleshooting selesai, kita harus segera mengembalikannya ke level INFO agar tidak membebani performa I/O disk broker:

    kafka-configs.sh --bootstrap-server localhost:9093 \
      --command-config /etc/kafka/client.properties \
      --alter \
      --entity-type broker-loggers \
      --entity-name 1 \
      --add-config kafka.authorizer.logger=INFO
    

Metode 2: Mengubah Level Logger Secara Programmatic (Java AdminClient) #

Bagi kita yang bertindak sebagai tim SRE (Site Reliability Engineering) yang ingin membangun alat otomasi penalaan log (automatic log tuning tool), kita dapat memicu pengubahan logger level menggunakan Java AdminClient API secara terprogram:

package com.mycompany.kafka.admin;

import org.apache.kafka.clients.admin.AdminClient;
import org.apache.kafka.clients.admin.AlterConfigsResult;
import org.apache.kafka.common.config.ConfigResource;
import org.apache.kafka.clients.admin.ConfigEntry;
import org.apache.kafka.clients.admin.AlterConfigOp;

import java.util.*;

public class DynamicLoggerTuner {

    private final AdminClient adminClient;

    public DynamicLoggerTuner(Properties properties) {
        this.adminClient = AdminClient.create(properties);
    }

    /**
     * Mengubah level logger broker secara dinamis tanpa restart.
     *
     * @param brokerId   ID dari broker Kafka yang ditargetkan
     * @param loggerName Nama logger (misalnya "kafka.authorizer.logger")
     * @param level      Tingkat log baru (misalnya "DEBUG", "INFO", "WARN")
     */
    public void setBrokerLoggerLevel(int brokerId, String loggerName, String level) throws Exception {
        // 1. Definisikan tipe sumber daya sebagai BROKER_LOGGER
        ConfigResource resource = new ConfigResource(
                ConfigResource.Type.BROKER_LOGGER, 
                String.valueOf(brokerId)
        );

        // 2. Buat entri konfigurasi level logger baru
        ConfigEntry loggerConfig = new ConfigEntry(loggerName, level);
        
        // 3. Setel operasi pengubahan (SET)
        AlterConfigOp op = new AlterConfigOp(loggerConfig, AlterConfigOp.OpType.SET);
        
        Map<ConfigResource, Collection<AlterConfigOp>> configs = new HashMap<>();
        configs.put(resource, Collections.singletonList(op));

        // 4. Kirim request perubahan ke Broker secara asinkron
        AlterConfigsResult result = adminClient.incrementalAlterConfigs(configs);
        
        // Tunggu hingga konfirmasi jabat tangan sukses ke broker
        result.all().get(); 
        
        System.out.println("Berhasil merubah logger [" + loggerName + "] pada broker [" + brokerId + "] menjadi " + level);
    }

    public void close() {
        if (adminClient != null) {
            adminClient.close();
        }
    }
}

Pendekatan programmatic ini sangat aman jika kita pasangkan dengan sistem alert otomatis. Sebagai contoh, ketika tingkat kegagalan otorisasi melampaui batas tertentu, sistem dapat otomatis menaikkan level log authorizer ke DEBUG selama 15 menit, lalu menurunkannya kembali setelah mengumpulkan sampel log yang cukup.


Menganalisis Log Server untuk Troubleshooting Masalah Produksi #

Ketika kluster mengalami kegagalan operasional, kita harus mampu mengidentifikasi akar masalah secara cepat dengan mencocokkan pola pesan kesalahan yang muncul di file log. Berikut adalah pembahasan mendalam mengenai lima skenario kegagalan produksi yang paling sering terjadi, lengkap dengan analisis struktur log aslinya.

1. Masalah Replikasi: Shrinking ISR #

Skenario ini terjadi saat replikasi antar broker mengalami hambatan fisik, memaksa leader partisi mengeluarkan replika lambat dari kelompok ISR.

Contoh Pesan Log:

[2026-06-08 14:22:15,102] INFO [ReplicaManager broker=1] Shrinking ISR for partition payment.orders-0 to 1,2 (kafka.server.ReplicaManager)

Analisis Masalah:

  1. Identifikasi Awal: Partisi payment.orders-0 kehilangan salah satu replika aktifnya. Daftar ISR sebelumnya (misalnya berisi broker 1, 2, dan 3) menyusut menjadi hanya dihuni oleh broker 1 dan 2. Broker dengan ID 3 telah dinyatakan keluar dari ISR.
  2. Akar Penyebab: Broker 3 kemungkinan mengalami salah satu dari masalah berikut:
    • Jeda Garbage Collection yang sangat lama (stop-the-world pause) sehingga broker 3 gagal mengirimkan sinyal detak jantung (heartbeat) ke controller dalam kurun waktu replica.lag.time.max.ms.
    • Kemacetan I/O disk pada partisi log data broker 3, menyebabkan thread replikasi (ReplicaFetcherThread) tertinggal jauh di belakang Log End Offset (LEO) milik leader.
    • Masalah jaringan lokal (network packet loss) antara broker 1 dan broker 3.
  3. Langkah Mitigasi:
    • Periksa log garbage collection di broker 3. Jika durasi pause GC melebihi 5-10 detik, lakukan optimasi G1GC.
    • Periksa latensi I/O disk dengan utilitas iostat untuk memantau apakah ada antrean tulis disk yang tinggi.

2. Masalah Konsumen: Rebalance Loop dan Session Timeouts #

Skenario ini sering dikeluhkan oleh pengembang ketika aplikasi konsumen mereka tampak berhenti memproses data dan terus-menerus melakukan proses penyeimbangan ulang (rebalance).

Contoh Pesan Log:

[2026-06-08 14:25:30,415] INFO [GroupCoordinator 1]: Preparing rebalance for group payment-processor in state PreparingRebalance with member client-1-8c4d21e8 (reason: Peer re-joined group) (kafka.coordinator.group.GroupCoordinator)
[2026-06-08 14:25:45,910] INFO [GroupCoordinator 1]: Member client-1-8c4d21e8 in group payment-processor has failed, removing from group (reason: join-group timeout) (kafka.coordinator.group.GroupCoordinator)

Analisis Masalah:

  1. Pemicu Awal: Group Coordinator pada Broker 1 mendeteksi bahwa salah satu anggota grup konsumen (client-1-8c4d21e8) keluar atau terlambat merespons, memicu transisi ke fase PreparingRebalance.
  2. Akar Penyebab:
    • Properti max.poll.interval.ms pada sisi klien disetel terlalu rendah dibandingkan dengan waktu pemrosesan satu batch data. Jika konsumen memerlukan waktu 60 detik untuk memproses data dari satu panggilan poll(), tetapi max.poll.interval.ms disetel hanya 30 detik, konsumen akan dianggap mati oleh coordinator.
    • Konsumen mengalami error di luar dugaan (out of memory) atau terhenti karena jeda GC lokal yang lama.
  3. Langkah Mitigasi:
    • Tingkatkan nilai max.poll.interval.ms pada konfigurasi klien agar memberikan toleransi waktu pemrosesan yang lebih panjang.
    • Alternatifnya, turunkan nilai max.poll.records untuk membatasi jumlah data yang ditarik dalam sekali poll sehingga pemrosesan selesai lebih cepat.
    • Pindahkan logika pemrosesan yang berat ke dalam thread pool terpisah (worker threads) dan gunakan thread utama konsumen hanya untuk melakukan poll dan commit offset.

3. Masalah Log Compaction: Cleaner Starved atau Thread Crash #

Skenario ini terjadi ketika proses pembersihan log kotor (log compaction) pada topik dengan kebijakan retensi compact mengalami kegagalan.

Contoh Pesan Log:

[2026-06-08 14:28:10,005] WARN [LogCleaner 1]: Cleaner 1 is starved on log directory /var/lib/kafka/data/tenant-a.logs-0 (kafka.log.LogCleaner)
[2026-06-08 14:28:15,310] ERROR [LogCleaner 1]: Error due to local offset map overflow (kafka.log.LogCleaner)

Analisis Masalah:

  1. Pemicu Awal: Thread LogCleaner memperingatkan bahwa pembersihan log pada direktori tenant-a.logs-0 tertahan (starved) dan tidak dapat memproses pemadatan data.
  2. Akar Penyebab:
    • Jumlah kunci unik (unique keys) pada partisi tersebut melebihi kapasitas memori dari peta offset pencatat (SkimpyOffsetMap). Alokasi memori deduplikasi default (log.cleaner.dedupe.buffer.size yang bernilai 128 MB) tidak cukup untuk menampung seluruh representasi hash kunci pesan.
    • Ketika buffer penuh sebelum seluruh segmen log terpetakan, proses pembersihan akan macet atau thread LogCleaner akan mengalami crash dengan pesan ERROR.
  3. Langkah Mitigasi:
    • Tingkatkan kapasitas memori deduplikasi cleaner di berkas server.properties:
      log.cleaner.dedupe.buffer.size=536870912 # Naikkan menjadi 512 MB
      
    • Tambahkan jumlah thread pembersih log dengan menyetel log.cleaner.threads=2 atau lebih untuk mempercepat proses pemadatan paralel.

4. Masalah KRaft Metadata: Recovery Latency dan Socket Depletion #

Untuk kluster modern yang menggunakan mode KRaft (tanpa ZooKeeper), melacak koordinasi metadata sangat bergantung pada log controller KRaft.

Contoh Pesan Log:

[2026-06-08 14:31:02,110] INFO [MetadataLoader] Metadata loader has processed up to offset 1045230 in 150 ms (org.apache.kafka.image.loader.MetadataLoader)
[2026-06-08 14:31:05,420] WARN [RaftManager] Raft leader 1 failed to heartbeat to voter 2 within the timeout of 3000 ms (org.apache.kafka.raft.KafkaRaftClient)

Analisis Masalah:

  1. Pemicu Awal: Controller KRaft mendeteksi keterlambatan pemrosesan metadata atau kegagalan detak jantung antara voter quorum KRaft.
  2. Akar Penyebab:
    • Aliran perubahan metadata terlalu masif (misalnya akibat pembuatan ribuan partisi topik secara dinamis dalam waktu singkat), sehingga loader metadata mengalami antrean pemrosesan (recovery latency).
    • Node controller kekurangan alokasi thread atau mengalami kehabisan socket koneksi (file descriptor depletion) akibat membludaknya jumlah koneksi dari klien eksternal.
  3. Langkah Mitigasi:
    • Pisahkan node KRaft controller secara fisik dari node data broker. Jangan gabungkan peran broker dan controller di server yang sama untuk kluster skala besar.
    • Pastikan parameter OS ulimit -n disetel minimal 100.000 untuk mencegah error Too many open files pada socket internal quorum KRaft.

5. Masalah Keamanan: ACL Authorization Failures #

Kita harus memantau log keamanan secara ketat untuk mendeteksi upaya akses tidak sah oleh klien ilegal atau kesalahan konfigurasi kredensial aplikasi.

Contoh Pesan Log:

[2026-06-08 14:35:10,218] INFO Principal = User:CN=payment-app,O=MyCorp is Denied Operation = Write for Resource = Topic:payment.orders (kafka.authorizer.logger)

Analisis Masalah:

  1. Pemicu Awal: Pengguna dengan sertifikat SSL User:CN=payment-app,O=MyCorp ditolak (Denied) saat mencoba melakukan operasi Write ke topik payment.orders.
  2. Akar Penyebab:
    • Klien menggunakan nama pengguna yang benar, tetapi kebijakan ACL (Access Control List) di Kafka belum diperbarui untuk mengizinkan operasi penulisan pada topik tersebut.
    • Terjadi kesalahan penulisan nama topik di sisi kode aplikasi klien (misalnya salah menulis nama topik menjadi payment.orders padahal seharusnya payment-orders-v2).
  3. Langkah Mitigasi:
    • Jalankan perintah CLI berikut untuk memverifikasi daftar ACL topik target:
      kafka-acls.sh --bootstrap-server localhost:9093 \
        --command-config /etc/kafka/client.properties \
        --list \
        --topic payment.orders
      
    • Berikan izin akses tulis yang sah jika identitas klien terbukti valid:
      kafka-acls.sh --bootstrap-server localhost:9093 \
        --command-config /etc/kafka/client.properties \
        --add \
        --allow-principal User:CN=payment-app,O=MyCorp \
        --operation Write \
        --topic payment.orders
      

Kepatuhan Operasional dan Checklist Audit Log Server #

Untuk menjamin keandalan sistem pemantauan kita, lakukan audit rutin terhadap log server Kafka menggunakan checklist kepatuhan produksi berikut:

No Item Kepatuhan Audit Log Server Metode Verifikasi Status
1 Rotasi Log Aktif Verifikasi bahwa seluruh appender di log4j.properties bertipe RollingFileAppender dan membatasi ukuran maksimal file. [ ]
2 Batas Ukuran Log Terpenuhi Pastikan parameter MaxFileSize disetel maksimal 100MB dan MaxBackupIndex disetel maksimal 10 untuk mengontrol konsumsi ruang disk. [ ]
3 Pemisahan File Log Khusus Pastikan log controller, log state-changes, dan log otorisasi diarahkan ke file log fisiknya masing-masing agar tidak mengotori server.log. [ ]
4 Pembersihan Log via Cron Konfigurasikan daemon logrotate sistem untuk mengompresi file log backup yang sudah tua dan menghapusnya setelah batas waktu retensi. [ ]
5 Keamanan Akses File Log Hak akses file log server di /var/log/kafka/ hanya boleh dibuka untuk user sistem kafka (chmod 640). [ ]
6 Level Log Default Aman Pastikan default root logger disetel pada level INFO untuk mencegah penurunan performa akibat penulisan log berlebih di level DEBUG/TRACE. [ ]

Ringkasan #

  • Pisahkan Konsep Log — Selalu pisahkan pemahaman antara log data segment (yang menampung payload pesan terkompresi dari klien) dengan log server Log4j (yang menampung pesan diagnostik JVM).
  • Batasi Ukuran File — Jangan biarkan log server tumbuh tanpa batas di disk broker. Gunakan RollingFileAppender dengan batas kapasitas maksimal untuk mengamankan sisa ruang disk broker.
  • Tuning Log Dinamis — Manfaatkan perintah kafka-configs.sh atau Java AdminClient untuk menaikkan level log ke DEBUG saat melakukan troubleshooting tanpa perlu merestart JVM broker.
  • Dekode Secara Akurat — Pelajari pesan log kunci seperti Shrinking ISR, Preparing rebalance, dan Cleaner starved untuk mempercepat deteksi akar masalah saat terjadi insiden di produksi.

← Sebelumnya: Broker Health   Berikutnya: Client Log →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact