Series MapLesson 20 / 35
Focus mode active/Press Alt+Shift+R to toggle/Esc to exit
Deepen PracticeOrdered learning track

NGINX Observability

Observability: Access Logs, Error Logs, Metrics, and Tracing

Memahami access log, error log, structured logging, request ID, upstream timing, Prometheus exporter, OpenTelemetry, dashboard, dan alerting.

6 min read1163 words
PrevNext
Lesson 2035 lesson track20–29 Deepen Practice
#observability#access-log#error-log#metrics+3 more

Part 020 — Observability: Access Logs, Error Logs, Metrics, and Tracing

1. Tujuan Part Ini

NGINX sering menjadi layer pertama yang melihat request dan layer terakhir yang melihat response sebelum keluar ke client.

Artinya, saat production incident terjadi, NGINX bisa menjadi:

sumber kebenaran awal
atau titik buta terbesar

Jika observability NGINX buruk, banyak masalah terlihat seperti:

backend Java lambat
Kubernetes error
client network unstable
cloud load balancer bermasalah

Padahal root cause bisa berada di:

wrong location routing
timeout chain
upstream connection failure
request body terlalu besar
client disconnect
TLS handshake issue
auth subrequest timeout
Ingress annotation conflict
DNS resolver stale

Part ini membahas observability NGINX sebagai production debugging layer: access log, error log, structured logging, metrics, tracing, correlation ID, dashboard, alerting, dan cara membaca sinyal tanpa tersesat.


2. Mental Model: Four Signals at the Proxy Layer

Observability NGINX perlu menjawab empat pertanyaan:

SignalPertanyaan
TrafficBerapa request masuk, ke host/path mana, dari siapa?
ErrorsError apa, di layer mana, dan seberapa sering?
LatencyWaktu habis di client, NGINX, auth, upstream, atau response transfer?
SaturationApakah NGINX, upstream, atau connection pool kehabisan kapasitas?

Di NGINX, sinyal ini datang dari:

access log
error log
metrics endpoint
Ingress controller metrics
NGINX Plus API jika digunakan
OpenTelemetry/tracing jika tersedia
cloud load balancer metrics
Kubernetes events
application logs

Senior engineer harus bisa menggabungkan semua itu menjadi timeline request.


3. Access Log vs Error Log

Access log menjawab:

request apa yang terjadi?
status apa yang dikirim?
berapa lama?
upstream mana yang dipakai?
berapa besar body/response?
client siapa?

Error log menjawab:

apa yang gagal secara internal?
DNS resolve gagal?
connect upstream refused?
upstream timed out?
client sent invalid header?
SSL handshake gagal?
file permission salah?
config/module issue?

Access log bersifat request-centric.

Error log bersifat event/problem-centric.

Untuk debugging production, keduanya harus dibaca bersama.

Contoh:

access log: 504, upstream_response_time=30.000
error log: upstream timed out while reading response header from upstream

Interpretasi:

NGINX berhasil connect ke upstream, tetapi upstream tidak mengirim response header sebelum proxy_read_timeout.

4. Minimal Access Log Fields untuk Reverse Proxy

Default combined log sering tidak cukup untuk enterprise debugging.

Field minimum yang sebaiknya ada:

time
request_id
remote_addr / real_client_ip
xff
host
method
uri
status
request_time
upstream_addr
upstream_status
upstream_connect_time
upstream_header_time
upstream_response_time
request_length
body_bytes_sent
referer
user_agent
traceparent

Untuk Java/JAX-RS backend, field terpenting:

request_id
traceparent
host
uri
status
request_time
upstream_status
upstream_response_time
upstream_addr
xff / real client IP

Karena field-field ini membantu membedakan:

client problem
NGINX routing problem
upstream Java problem
Kubernetes Service problem
network problem

5. Example Structured Access Log

Contoh JSON-style log format:

log_format json_combined escape=json
'{'
  '"time":"$time_iso8601",'
  '"request_id":"$request_id",'
  '"remote_addr":"$remote_addr",'
  '"x_forwarded_for":"$http_x_forwarded_for",'
  '"host":"$host",'
  '"method":"$request_method",'
  '"uri":"$request_uri",'
  '"status":$status,'
  '"request_time":$request_time,'
  '"upstream_addr":"$upstream_addr",'
  '"upstream_status":"$upstream_status",'
  '"upstream_connect_time":"$upstream_connect_time",'
  '"upstream_header_time":"$upstream_header_time",'
  '"upstream_response_time":"$upstream_response_time",'
  '"request_length":$request_length,'
  '"body_bytes_sent":$body_bytes_sent,'
  '"user_agent":"$http_user_agent",'
  '"traceparent":"$http_traceparent"'
'}';

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

Catatan:

escape=json penting untuk mengurangi risiko log rusak oleh karakter khusus.

Jangan log header sensitif seperti:

Authorization
Cookie
Set-Cookie
X-Api-Key
raw JWT
client certificate full PEM

6. Request ID and Correlation ID

Tanpa request ID, debugging distributed system menjadi forensik manual.

Request ID harus konsisten dari edge ke backend:

client/load balancer -> NGINX -> Java/JAX-RS -> downstream services -> logs/traces

Pattern umum:

map $http_x_request_id $req_id {
    default $http_x_request_id;
    ""      $request_id;
}

proxy_set_header X-Request-ID $req_id;

Pertimbangan:

jika client mengirim X-Request-ID, apakah dipercaya?
apakah harus generate ulang di edge?
apakah format dibatasi?
apakah request ID boleh mengandung PII?
apakah semua service log field yang sama?

Untuk external client, sering lebih aman membuat edge-generated request ID dan menyimpan client request ID sebagai field terpisah.


7. Trace Context Propagation

Modern distributed tracing biasanya memakai W3C trace context:

traceparent
tracestate

NGINX dapat meneruskan header tersebut:

proxy_set_header traceparent $http_traceparent;
proxy_set_header tracestate  $http_tracestate;

Tetapi meneruskan header saja tidak sama dengan membuat span NGINX.

Ada tiga level capability:

1. NGINX hanya meneruskan trace headers.
2. NGINX/Ingress membuat telemetry via module/exporter tertentu.
3. NGINX Plus/NGINX Ingress Controller/Gateway Fabric menggunakan OpenTelemetry integration jika tersedia.

Internal verification wajib karena kemampuan tracing berbeda antara:

NGINX Open Source standalone
NGINX Plus
community ingress-nginx
F5 NGINX Ingress Controller
NGINX Gateway Fabric
cloud API gateway/service mesh

8. Understanding NGINX Timing Fields

Timing field penting:

FieldMakna
$request_timetotal waktu request dari NGINX membaca byte pertama sampai log ditulis
$upstream_connect_timewaktu connect ke upstream
$upstream_header_timewaktu sampai response header upstream diterima
$upstream_response_timewaktu menerima response dari upstream

Interpretasi sederhana:

request_time tinggi, upstream_response_time rendah
-> client lambat membaca response, request body lambat, buffering, atau NGINX/client side issue

upstream_connect_time tinggi
-> network, service endpoint, pod readiness, SYN backlog, security group, DNS/service routing

upstream_header_time tinggi
-> Java service lambat mulai response, DB/external call/thread pool

upstream_response_time tinggi
-> upstream lambat menyelesaikan response, streaming/download/large payload

Untuk retry upstream, field upstream bisa berisi beberapa nilai.

Contoh konseptual:

upstream_addr="10.1.1.10:8080, 10.1.1.11:8080"
upstream_status="502, 200"
upstream_response_time="0.003, 0.120"

Artinya request mencoba upstream pertama, gagal, lalu sukses di upstream kedua.


9. Status Codes That Matter at NGINX Layer

Beberapa status code punya makna proxy-specific:

StatusMakna umum
400request malformed, header invalid, bad host/header/path
401authentication required/failed
403forbidden by policy, allowlist, authz, file/path rule
404route tidak match, wrong location, backend not found
408client timeout saat mengirim request
413body terlalu besar
414URI terlalu panjang
429rate limit/throttling
499client menutup koneksi sebelum response selesai
500internal NGINX/app error tergantung source
502bad gateway, upstream invalid/refused/reset/protocol issue
503service unavailable, upstream unavailable, overload, maintenance
504gateway timeout, upstream tidak merespons tepat waktu

Status code harus dikorelasikan dengan:

upstream_status
error log
request_time
upstream_response_time
route/host/path
client IP/user-agent
Kubernetes events
application logs

10. Why 499 Deserves Special Attention

499 adalah sinyal penting di NGINX.

Maknanya:

client menutup koneksi sebelum NGINX selesai mengirim response

Penyebab umum:

browser/user membatalkan request
mobile network putus
client timeout lebih pendek dari server timeout
load balancer idle timeout
API client retry sebelum request selesai
backend terlalu lambat
large response lambat dikirim

499 sering tidak muncul di application log sebagai error eksplisit.

Jika 499 meningkat, jangan langsung menyalahkan client. Cek:

apakah upstream latency naik?
apakah timeout client lebih pendek dari proxy/backend?
apakah response besar?
apakah network egress lambat?
apakah deploy baru memperlambat endpoint?
apakah SSE/WebSocket/long polling salah dikonfigurasi?

11. Error Log Levels

NGINX error log memiliki level seperti:

debug
info
notice
warn
error
crit
alert
emerg

Di production, level umum biasanya warn atau error, kecuali sedang investigasi.

Contoh:

error_log /var/log/nginx/error.log warn;

Debug log sangat detail dan bisa mahal.

Gunakan debug log dengan batasan:

time-boxed
scope terbatas
environment terbatas
sampling jika memungkinkan
pastikan tidak bocor data sensitif

Untuk Kubernetes, cek apakah error log dikirim ke stdout/stderr dan dikumpulkan oleh log pipeline.


12. Metrics: What NGINX Should Expose

Metrics yang berguna:

request rate
status code count
latency histogram/summary
active connections
accepted/handled connections
reading/writing/waiting connections
upstream errors
upstream latency
reload count
controller sync errors
config rejected count
TLS handshake errors jika tersedia
rate limit rejection count

NGINX Open Source dapat expose basic status via stub_status jika module tersedia.

Contoh:

location /nginx_status {
    stub_status;
    allow 127.0.0.1;
    allow 10.0.0.0/8;
    deny all;
}

Namun stub_status basic dan bukan full request-level observability.

Untuk Kubernetes, biasanya metrics masuk melalui:

NGINX Ingress Controller metrics endpoint
Prometheus scrape
ServiceMonitor
Grafana dashboard
cloud monitoring integration

13. Prometheus and Ingress Controller Metrics

Dalam Kubernetes, observability NGINX sering bergantung pada controller.

Hal yang perlu dicek:

apakah metrics endpoint aktif?
port metrics berapa?
apakah ServiceMonitor dibuat?
apakah namespace Prometheus dapat scrape?
apakah label selector cocok?
apakah endpoint diamankan?
apakah dashboard membedakan controller metrics dan data-plane metrics?

Metrics ingress yang berguna:

requests by ingress/host/path/status
latency by ingress/service
config reload/reconciliation errors
controller workqueue issue
SSL certificate expiration jika tersedia
upstream/service endpoint availability

Risiko:

label host/path/ingress terlalu high-cardinality
metrics tidak konsisten antar controller
histogram bucket tidak sesuai latency SLO
metrics endpoint publik tanpa proteksi

14. NGINX Plus and Advanced Metrics

Jika environment menggunakan NGINX Plus, observability bisa lebih kaya.

Kemungkinan capability:

NGINX Plus API
upstream zone metrics
active health check state
per-upstream server stats
dashboard
Prometheus integration module
OpenTelemetry module

Tetapi jangan mengasumsikan NGINX Plus.

Internal verification:

apakah image/license NGINX Plus digunakan?
apakah API/dashboard diaktifkan?
apakah endpoint metrics diamankan?
apakah upstream zone dikonfigurasi?
apakah active health check tersedia?

Jika menggunakan NGINX Open Source, beberapa metrics advanced harus diperoleh dari log, exporter, ingress controller, atau platform observability.


15. OpenTelemetry and Tracing Integration

Tracing di NGINX harus dipahami dengan hati-hati.

Kemungkinan mode:

header propagation only
OpenTelemetry module di NGINX Plus
OpenTelemetry di F5 NGINX Ingress Controller
tracing dari API gateway/cloud/service mesh
application-only tracing di Java service

Jika hanya Java service yang membuat span, maka NGINX tidak terlihat sebagai span tersendiri.

Efeknya:

latency antara client dan backend bisa hilang dari trace
502/503/504 dari proxy bisa tidak muncul di trace aplikasi
client disconnect 499 bisa tidak muncul di trace aplikasi

Tracing ideal:

edge span
proxy/upstream span
application span
downstream service span
DB/external call span

Tetapi implementasi ideal harus dibandingkan dengan kemampuan platform aktual.


16. Dashboard Design

Dashboard NGINX yang baik tidak hanya menampilkan CPU dan request count.

Minimal dashboard:

request rate by host/service
status code distribution
4xx by reason/path
5xx by upstream/service
499 trend
502/503/504 trend
p50/p95/p99 request_time
p50/p95/p99 upstream_response_time
upstream_connect_time trend
rate limit rejection
body size / 413
active connections
NGINX pod CPU/memory
reload/config error
TLS certificate expiry if available

Untuk senior debugging, dashboard harus memungkinkan drill-down:

host -> ingress -> path -> service -> pod -> status -> latency

Bukan hanya cluster-wide aggregate.


17. Alerting Strategy

Alert harus actionable.

Contoh alert buruk:

NGINX 5xx > 0

Contoh alert lebih baik:

5xx rate for public-api host > 2% for 5 minutes
504 count for quote-service ingress above baseline
p99 upstream_response_time exceeds SLO for 10 minutes
499 rate doubles while upstream latency also rises
Ingress controller config reload failures > 0
TLS cert expires in less than 14 days
Prometheus scrape for ingress controller failing

Alert harus punya:

owner
severity
runbook
dashboard link
expected first diagnostic step
escalation path

Tanpa runbook, alert hanya noise.


18. Log Sampling and Cardinality Risk

High traffic systems bisa menghasilkan log sangat besar.

Sampling bisa dibutuhkan, tetapi hati-hati.

Jangan sampling buta untuk:

5xx
429
499 spike
security denial
auth failure
large body rejection
TLS/auth incident

High-cardinality risk pada metrics:

full URI dengan ID unik
query string
user ID
tenant ID berjumlah besar
request ID
raw user agent
IP address

Gunakan route template jika tersedia:

/api/quotes/{quoteId}

Bukan:

/api/quotes/123456789?customer=...

Untuk log, full URI sering berguna. Untuk metrics label, full URI bisa merusak Prometheus/cardinality.


19. Sensitive Data and Log Redaction

NGINX berada di edge sehingga bisa melihat data sensitif.

Jangan log:

Authorization header
Cookie
Set-Cookie
API key
raw JWT
password
client secret
full request body
PII di query string jika bisa dihindari
client certificate full content

Masalah umum:

GET endpoint membawa PII di query string
access log menyimpan request_uri penuh
log dikirim ke third-party observability
retention log terlalu panjang
engineer terlalu banyak punya akses log production

Untuk compliance, verifikasi:

log field apa yang dikumpulkan
siapa yang bisa membaca log
berapa lama retention
apakah redaction terjadi sebelum ingest
apakah log bisa digunakan sebagai audit evidence

20. Java/JAX-RS Observability Alignment

NGINX dan Java service harus memakai identitas observability yang sama.

Minimal alignment:

X-Request-ID sama
traceparent diteruskan
client IP semantics jelas
host dan path public vs internal bisa dipetakan
status code backend vs status code NGINX dibedakan

Di Java/JAX-RS log, pastikan ada:

request_id
trace_id
method
route template
status
latency
user/tenant hash jika aman
exception class
upstream dependency timing

Jika NGINX log menunjukkan:

status=504
upstream_status="-"

Kemungkinan request tidak mencapai backend.

Jika menunjukkan:

status=504
upstream_status="200"

Perlu interpretasi hati-hati, bisa ada retry/multiple upstream atau logging sequence yang harus dibaca dengan konteks.

Selalu korelasikan dengan application log berdasarkan request ID/trace ID.


21. Kubernetes Observability

Untuk NGINX di Kubernetes, debugging memerlukan beberapa sumber:

Ingress resource
Ingress Controller pod logs
Controller metrics
Generated NGINX config jika bisa diakses
Kubernetes Service
EndpointSlice
Pod readiness
Events
ConfigMap
Secret/TLS Secret
Cloud load balancer metrics

Command investigasi umum:

kubectl get ingress -A
kubectl describe ingress <name> -n <namespace>
kubectl get svc -n <namespace>
kubectl get endpointslice -n <namespace>
kubectl logs deploy/<nginx-ingress-controller> -n <namespace>
kubectl describe pod <pod> -n <namespace>

Sinyal penting:

Ingress accepted/rejected
annotation invalid
service has no endpoints
pod not ready
TLS secret missing
config reload failed
controller cannot update status

22. Cloud Load Balancer Observability

NGINX bukan satu-satunya edge.

Di AWS/EKS, cek:

ALB/NLB metrics
target group health
TargetResponseTime
HTTPCode_ELB_5XX
HTTPCode_Target_5XX
security group drops
NLB TCP reset metrics jika tersedia
CloudWatch logs jika aktif

Di Azure/AKS, cek:

Application Gateway metrics/logs
Azure Load Balancer health
Front Door/WAF logs
NSG flow logs jika tersedia
Azure Monitor
backend pool health

On-prem/hybrid:

enterprise LB logs
firewall logs
DNS resolver logs
proxy chain logs
certificate appliance logs

Jangan berhenti di NGINX jika request bahkan belum mencapainya.


23. Debugging Patterns by Symptom

High 502

Cek:

error log: connection refused/reset/no live upstream
upstream_connect_time
Service endpoints
Pod readiness
backend protocol mismatch HTTP/HTTPS/gRPC
upstream TLS verification

High 503

Cek:

no endpoints
maintenance/overload
upstream marked unavailable
Ingress default backend
rate/connection exhaustion
controller config issue

High 504

Cek:

proxy_read_timeout
upstream_header_time
Java thread pool/DB latency
external dependency
load balancer idle timeout
retry chain

High 499

Cek:

client timeout
upstream latency
large response
mobile/partner network
LB idle timeout
user cancellation

High 413

Cek:

client_max_body_size
Ingress body size annotation
multipart endpoint
upload path
API contract

24. Observability for Security Events

Security-relevant events:

401/403 spike
429 spike
blocked IP/path
invalid host header
large header/body rejection
mTLS verification failure
TLS handshake error
suspicious user agent
path traversal attempt
request smuggling indicators
WAF block if used

Do not mix all security events into generic 4xx.

Security dashboard should separate:

auth failure
authorization denial
rate limit
WAF/security block
malformed request
client behavior error

This helps avoid two mistakes:

ignoring attack traffic as normal 4xx
escalating normal client validation errors as security incidents

25. Observability PR Review Checklist

Gunakan checklist ini saat review perubahan NGINX/Ingress:

Apakah request ID dipertahankan atau dibuat?
Apakah traceparent/tracestate diteruskan?
Apakah access log punya upstream timing?
Apakah log format JSON valid?
Apakah Authorization/Cookie/API key tidak dilog?
Apakah status 499/502/503/504 terlihat di dashboard?
Apakah metrics endpoint aktif dan diamankan?
Apakah ServiceMonitor/Prometheus scrape ada?
Apakah label metrics tidak high-cardinality?
Apakah alert punya runbook?
Apakah route baru punya observability sebelum production?
Apakah auth/rate limit/security denial punya sinyal terpisah?
Apakah rollback/config reload failure terlihat?

26. Internal Verification Checklist

Untuk konteks CSG/team, verifikasi:

Log format NGINX/Ingress yang digunakan.
Apakah access log aktif di semua environment.
Apakah error log level production sesuai.
Apakah logs dikirim ke platform observability pusat.
Apakah request ID dibuat di cloud LB, NGINX, API gateway, atau aplikasi.
Header correlation apa yang distandardkan.
Apakah traceparent diteruskan sampai Java/JAX-RS service.
Apakah NGINX menghasilkan spans atau hanya meneruskan headers.
Apakah Prometheus scrape aktif untuk ingress controller.
Apakah dashboard membedakan host/ingress/service/status.
Apakah 499 dipantau.
Apakah 502/503/504 punya alert dan runbook.
Apakah TLS/cert expiry dimonitor.
Apakah log redaction sudah memenuhi compliance.
Apakah PII muncul di query string/access log.
Apakah incident notes sebelumnya menunjukkan observability gap.

27. Anti-Patterns

Menggunakan default access log untuk production API kompleks.
Tidak mencatat upstream_response_time.
Tidak punya request ID end-to-end.
Menganggap trace aplikasi cukup untuk proxy failure.
Melog Authorization/Cookie/JWT penuh.
Memakai full URI sebagai metrics label.
Tidak memantau 499.
Menggabungkan semua 4xx sebagai client error biasa.
Mengabaikan error log saat debugging access log.
Metrics endpoint terbuka publik.
Alert tanpa runbook.
Tidak memisahkan NGINX 5xx dari backend 5xx.
Tidak menyimpan enough context untuk incident RCA.

28. Practical Senior Engineer Heuristics

If it is not in logs or metrics, it did not happen operationally.
Access log tells what happened; error log often tells why.
request_time without upstream timing is incomplete.
499 is a customer experience signal, not just client noise.
502/503/504 are different failure classes; do not lump them together.
A trace without edge visibility can miss proxy failures.
Metrics labels should be stable; logs can carry richer detail.
Every production route should be debuggable before it is launched.
Redaction is part of observability design, not an afterthought.
Dashboards should follow the request path: edge -> ingress -> service -> pod -> app.

29. Ringkasan

Observability NGINX adalah kemampuan untuk menjawab:

request masuk dari mana
masuk ke host/path mana
status apa yang keluar
upstream mana yang dipilih
berapa lama connect/header/response
apakah client disconnect
apakah NGINX atau backend yang menghasilkan error
apakah config/ingress/controller sehat
apakah sinyal ini bisa dikorelasikan dengan Java/JAX-RS logs

Target pemahaman senior engineer:

mendesain structured access log
membaca error log dengan konteks
memahami request_time vs upstream timing
membedakan 499/502/503/504
menyambungkan request ID dan trace context
menghindari log leakage
membuat dashboard dan alert yang actionable
menggunakan observability untuk mempercepat RCA

NGINX observability yang baik tidak hanya membuat sistem terlihat. Ia membuat failure dapat dijelaskan, diprioritaskan, dan diperbaiki tanpa debat spekulatif antar tim.


30. Referensi Resmi untuk Diverifikasi

NGINX log module:
https://nginx.org/en/docs/http/ngx_http_log_module.html

NGINX upstream variables:
https://nginx.org/en/docs/http/ngx_http_upstream_module.html

NGINX stub status module:
https://nginx.org/en/docs/http/ngx_http_stub_status_module.html

F5 NGINX Ingress Controller Prometheus metrics:
https://docs.nginx.com/nginx-ingress-controller/logging-and-monitoring/prometheus/

F5 NGINX OpenTelemetry module:
https://docs.nginx.com/nginx/admin-guide/dynamic-modules/opentelemetry/

F5 NGINX Ingress Controller OpenTelemetry:
https://docs.nginx.com/nginx-ingress-controller/logging-and-monitoring/opentelemetry/
Lesson Recap

You just completed lesson 20 in deepen practice. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.

Continue The Track

Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.