Memahami log bridge OpenTelemetry: Logs API yang masih bertahap, model log record, dan cara paling stabil mengkorelasikan log dengan traces lewat trace_id dan span_id, termasuk praktik structured logging dan injeksi konteks tracing otomatis ke log

Dari tiga pilar observability, logs adalah yang paling tua dan paling banyak dipakai — tetapi dalam ekosistem OTel, logs justru yang paling "rawan disalahpahami". Statusnya berbeda: sementara traces dan metrics sudah general availability, Logs API masih dalam tahap stabilisasi. Konsekuensinya, cara paling andal memakai logs di OTel bukan lewat API langsung, melainkan lewat log bridge — menghubungkan logger yang sudah ada (logging, stdlib) ke pipeline OTel.
Mengapa episode ini penting? Karena di dunia nyata kalian tidak akan menulis ulang seluruh logging ke API OTel. Kalian akan menyambungkan logger yang sudah ada, memastikan setiap log membawa trace_id/span_id, dan mengalirkannya ke backend yang sama dengan traces dan metrics. Itulah keterampilan yang benar-benar dipakai di produksi.
Sebelum membahas bridge, pahami bentuk log yang distandarkan OTel. Sebuah log record membawa:
ERROR, WARN, INFO, DEBUG).http.request.method, error.code).trace_id dan span_id dari konteks tracing yang sedang aktif.Inilah mengapa log OTel tidak sekadar teks: ia membawa konteks yang membuatnya bisa dikorelasikan.
Logs API (Logger, LogRecord) memang ada dan bisa dipakai:
from opentelemetry.sdk._logs import LoggerProvider
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.exporter.otlp.proto.grpc.logs_exporter import OTLPLogExporter
lp = LoggerProvider()
lp.add_log_record_processor(BatchLogRecordProcessor(OTLPLogExporter()))
logger = lp.get_logger("payment.service")
logger.error("payment.gateway.timeout", attributes={"attempt": 3})Namun perhatikan: API ini masih bergerak cepat. Untuk produksi, jalur yang disarankan adalah log bridge agar aplikasi tetap memakai logger yang familiar dan portabel.
Log bridge (atau Logs Appender) menyambungkan logger aplikasi yang sudah ada ke SDK OTel. Di Python, ini berarti mengkonfigurasi logging stdlib agar mengarahkan record ke OTelLoggingHandler:
import logging
from opentelemetry.sdk._logs import LoggerProvider
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.sdk._logs.extension.otlp import OTLPLogExporter
from opentelemetry._logs import set_logger_provider
from opentelemetry.sdk._logs.extension.logging import (
LoggingHandler, set_logging_exception_hook)
lp = LoggerProvider()
lp.add_log_record_processor(BatchLogRecordProcessor(OTLPLogExporter()))
set_logger_provider(lp)
logging.getLogger().addHandler(LoggingHandler())
logging.basicConfig(level=logging.INFO)Hasilnya: setiap logging.info(...) di aplikasi otomatis dikirim ke pipeline OTel sebagai log record — tanpa mengubah satu pun baris logging yang ada.
Inilah nilai utama logs di OTel: log yang dikeluarkan di dalam span aktif otomatis membawa trace_id dan span_id span tersebut. Ketika insiden terjadi, alur investigasinya menjadi:
trace_id yang sama → lihat pesan log persis di titik kegagalan.Untuk melihat korelasi ini berjalan, aktifkan tracing dan logging bersamaan lalu kirim request — setiap log dari dalam span akan membawa trace_id yang sama dengan trace-nya.
Tip
Jika kalian menambahkan logging di luar span (misalnya dari background thread), trace_id tidak akan terisi. Kalau korelasi log↔trace terlihat "hampir selalu kosong", cek dulu apakah log benar-benar dikeluarkan dari dalam konteks span aktif — bukan dari callback atau thread terpisah.
Log tekstual polos sulit dipakai backend dan dashboard. Praktik produksi yang dianjurkan:
ERROR benar-benar error, bukan INFO dengan teks error.user_id penuh di tiap log (PII + cardinality); gunakan identitas internal anonim.logger.info(
"order.processed",
attributes={"order.id": "ord-123", "order.currency": "IDR"},
)
# Buruk:
logger.info(f"order processed: {order_id} {user_token}")Di sisi collector (episode 0), logs sudah berjalan lewat pipeline yang sama:
service:
pipelines:
logs:
receivers: [otlp]
processors: [batch]
exporters: [otlp/jaeger, debug]Backend seperti LGTM (Loki) menerima logs via OTLP dan mengindeks trace_id sehingga filter log-by-trace bisa dilakukan langsung di UI. Kita dalami korporasi tiga sinyal secara utuh di episode 17.
trace_id; pastikan request path diinstrumentasi dulu.Pada episode 6 ini, kalian telah memahami posisi logs di OTel dan cara mengkorelasikannya dengan traces.
Inti yang harus dibawa pulang:
trace_id/span_id adalah alur investigasi SRE paling efektif.Di episode 7 selanjutnya, kita akan membahas resource & semantic conventions — identitas service (service.name, host, atribut Kubernetes) sebagai dasar pemfilteran, serta aturan penamaan span, attribute, dan metric sesuai spesifikasi OTel semantic conventions. Sampai jumpa di episode 7!