Format Log Kustom

Format Log Kustom #

Format log default Nginx sudah cukup untuk kebutuhan dasar, tapi seiring aplikasi berkembang, kamu akan butuh informasi lebih di log — response time backend, status cache, request ID, atau bahkan field dari header aplikasi. Nginx memudahkan ini dengan log_format yang bisa menggunakan variabel apapun.

Menambahkan Field Performa #

Format yang paling sering dikustomisasi menambahkan data timing untuk analisis performa:

http {
    log_format performance '$remote_addr [$time_local] '
                           '"$request" $status '
                           '$body_bytes_sent '
                           '$request_time '           # Total waktu dari terima request hingga kirim response
                           '$upstream_response_time ' # Waktu backend memproses
                           '$upstream_cache_status';  # HIT/MISS/BYPASS

    access_log /var/log/nginx/access.log performance;
}

Dengan format ini, kamu bisa langsung melihat apakah request lambat karena backend lambat ($upstream_response_time tinggi) atau karena masalah network ke klien (selisih $request_time dan $upstream_response_time besar).


Format JSON untuk Log Aggregator #

Jika menggunakan sistem log terpusat (ELK Stack, Grafana Loki, Datadog, Splunk), format JSON jauh lebih mudah diparsing daripada format teks:

http {
    log_format json_combined escape=json
    '{'
        '"timestamp":"$time_iso8601",'
        '"remote_addr":"$remote_addr",'
        '"request_method":"$request_method",'
        '"request_uri":"$uri",'
        '"query_string":"$args",'
        '"status":$status,'
        '"bytes_sent":$body_bytes_sent,'
        '"request_time":$request_time,'
        '"upstream_addr":"$upstream_addr",'
        '"upstream_status":"$upstream_status",'
        '"upstream_response_time":"$upstream_response_time",'
        '"upstream_cache_status":"$upstream_cache_status",'
        '"http_referer":"$http_referer",'
        '"http_user_agent":"$http_user_agent",'
        '"http_x_forwarded_for":"$http_x_forwarded_for",'
        '"ssl_protocol":"$ssl_protocol",'
        '"ssl_cipher":"$ssl_cipher"'
    '}';

    access_log /var/log/nginx/access.json json_combined;
}

Parameter escape=json penting — ia memastikan karakter khusus dalam nilai variabel (seperti tanda kutip atau backslash) di-escape dengan benar sehingga JSON selalu valid.


Menambahkan Request ID untuk Tracing #

Dalam arsitektur microservice, melacak satu request yang melewati banyak service membutuhkan request ID yang unik. Nginx bisa membuat dan mencatatnya:

http {
    # Gunakan kombinasi IP dan timestamp sebagai request ID sederhana
    # Untuk ID yang benar-benar unik, gunakan modul ngx_http_unique_id
    map $time_msec $request_id_header {
        default $request_id;
    }

    log_format trace '$remote_addr [$time_local] '
                     '"$request" $status '
                     'reqid=$request_id '      # Variabel bawaan Nginx 1.11.0+
                     'rt=$request_time';

    server {
        # Sertakan request ID di response header agar klien bisa melapor
        add_header X-Request-ID $request_id always;

        # Teruskan ke backend agar backend bisa mencatat di log mereka
        proxy_set_header X-Request-ID $request_id;

        access_log /var/log/nginx/access.log trace;
    }
}

$request_id tersedia sejak Nginx 1.11.0 — berupa string hex 16 byte yang di-generate acak untuk setiap request.


Conditional Logging: Log Hanya Request Tertentu #

Kadang kamu tidak ingin log semua request — misalnya abaikan health check, atau hanya log error:

http {
    # Buat variabel: 0 = jangan log, 1 = log
    map $status $loggable {
        ~^[23]  0;   # Jangan log 2xx dan 3xx
        default 1;   # Log semua error (4xx, 5xx)
    }

    # Syntax: access_log path format if=variabel
    access_log /var/log/nginx/errors.log combined if=$loggable;
}

Contoh lain — log hanya request yang lambat:

http {
    map $request_time $slow_request {
        default         0;
        ~^[1-9]         1;   # Request yang butuh >= 1 detik
    }

    access_log /var/log/nginx/slow.log performance if=$slow_request;
    access_log /var/log/nginx/access.log combined;  # Log semua ke file utama
}

Dengan pola ini kamu bisa punya dua file log: satu untuk semua request, satu khusus untuk request lambat yang perlu diinvestigasi.


Menyertakan Header dari Aplikasi #

Backend sering mengirim header khusus yang berguna untuk debugging. Kamu bisa mencatatnya di log:

http {
    log_format app_debug '$remote_addr [$time_local] '
                         '"$request" $status '
                         '$upstream_http_x_request_id '     # Header X-Request-ID dari backend
                         '$upstream_http_x_powered_by '     # Header X-Powered-By dari backend
                         '"$upstream_http_x_debug_info"';   # Header debug kustom dari backend

    # Pola: $upstream_http_NAMA_HEADER
    # Gunakan huruf kecil dan ganti tanda hubung dengan underscore
}

Ringkasan #

  • Tambahkan $request_time dan $upstream_response_time ke format log untuk membedakan lambat di backend vs lambat di jaringan.
  • Gunakan escape=json dan format JSON untuk integrasi dengan ELK, Loki, atau Datadog — tidak perlu konfigurasi parser tambahan.
  • $request_id (Nginx ≥ 1.11.0) memberikan ID unik per request yang bisa diteruskan ke backend untuk distributed tracing.
  • Conditional logging dengan if= memungkinkan log selektif — misalnya hanya log error atau hanya request yang lambat.
  • Akses header dari backend di log menggunakan $upstream_http_NAMA — berguna untuk mencatat request ID yang di-generate backend.

← Sebelumnya: Error Log   Berikutnya: Rotasi Log →

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