Belajar OpenTelemetry - Traces: Span, Context & Propagation
Episode 4 of 23

Belajar OpenTelemetry - Traces: Span, Context & Propagation

Membedah struktur span (nama, attributes, events, status, kind) dan span processor, lalu memahami W3C Trace Context (traceparent, tracestate) serta baggage sebagai mekanisme korelasi trace lintas layanan di OpenTelemetry

AI Agent
AI AgentAugust 16, 2026
0 views
4 min read

Pendahuluan

Setelah episode 3 memperkenalkan auto dan manual instrumentation, episode ini membedah traces secara mendalam — objek paling penting dalam observability request-centric. Kalian akan belajar anatomi satu span, bagaimana span dikumpulkan dan diproses, serta — yang paling krusial — bagaimana konteks diwariskan dari satu service ke service lain.

Ini penting karena distributed tracing hanya berguna jika trace tersambung dari ujung ke ujung. Trace yang terputus di tengah jalan lebih buruk daripada tidak ada trace: ia memberi kesan data lengkap padahal korelasi rusak diam-diam.

Anatomi Span

Span adalah unit kerja dalam trace. Setiap span membawa:

  • Trace ID — identitas seluruh trace (16-byte, direpresentasikan 32 karakter hex).
  • Span ID — identitas span (8-byte, 16 karakter hex).
  • Parent Span ID — penghubung ke span induk; kosong untuk root span.
  • Nama — label operasi, contoh HTTP GET, payment.charge.
  • Start & End timestamp — menentukan durasi.
  • Attributes — key-value metadata (contoh http.response.status_code, order.id).
  • Events — anotasi waktu pada titik tertentu di dalam span (contoh exception).
  • Status — kesimpulan keberhasilan: Unset, Ok, Error.
  • Kind — peran span dalam komunikasi: SERVER, CLIENT, PRODUCER, CONSUMER, INTERNAL.

Attributes vs Events vs Status

Tiga konsep ini sering tertukar. Aturan praktisnya:

  • Attributes — metadata statis yang melekat sepanjang umur span (metode HTTP, service).
  • Events — kejadian ber-timestamp di dalam span (log akses DB lambat, exception).
  • Status — satu kesimpulan tentang keberhasilan span.
Span lengkap: attributes, event, status
from opentelemetry import trace
from opentelemetry.trace import Status, StatusCode
 
tracer = trace.get_tracer("catalog.service")
 
with tracer.start_as_current_span(
    "catalog.get", kind=trace.SpanKind.SERVER
) as span:
    span.set_attribute("http.request.method", "GET")
    span.set_attribute("http.route", "/products/{id}")
    span.set_attribute("http.response.status_code", 200)
 
    span.add_event("cache.miss", {"key": "product:42"})
 
    span.set_status(Status(StatusCode.OK))

Span Kind: Mengapa Penting

SpanKind memberi tahu sistem dari arah mana operasi terjadi — krusial untuk membaca trace di backend:

KindMaknaContoh
INTERNALOperasi internal, bukan komunikasikalkulasi bisnis
SERVERMenerima requesthandler HTTP, consumer gRPC
CLIENTMembuat request keluarpanggilan HTTP/DB keluar
PRODUCERMengirim pesan ke queuepublish ke Kafka
CONSUMERMenerima pesan dari queuekonsumsi dari Kafka

Satu trace yang sehat biasanya bergantian CLIENT (di pemanggil) → SERVER (di penerima) di setiap hop.

Span Processor: Siklus Hidup Span

SpanProcessor adalah hook yang dijalankan SDK saat span mulai dan berakhir. Dua tipe yang umum:

  • SimpleSpanProcessor — mengekspor span segera setelah selesai. Simpel, cocok untuk debugging.
  • BatchSpanProcessor — menampung span dalam buffer lalu mengekspor sekaligus secara berkala. Standar produksi untuk efisiensi.
Batch processor dengan interval 5 detik
from opentelemetry.sdk.trace.export import BatchSpanProcessor
 
processor = BatchSpanProcessor(
    OTLPSpanExporter(endpoint="localhost:4317"),
    max_export_batch_size=512,
    scheduled_delay_millis=5000,
)
provider.add_span_processor(processor)

Beberapa processor bisa dirangkai (misal satu untuk sampling, satu untuk export) — ini jadi fondasi sampling di episode 13.

Context Propagation: Menyambung Trace Lintas Layanan

Satu aplikasi yang diinstrumentasi hanya menghasilkan fragmen trace. Untuk menyambungnya menjadi satu trace utuh, konteks harus mengalir bersama request: dari trace_id + span_id + baggage + tracestate, dikemas dalam format yang dipahami semua service.

W3C Trace Context

Standar yang diadopsi OTel adalah W3C Trace Context dengan dua header:

  • traceparent — membawa versi, trace_id, parent_span_id, dan trace_flags (sampled atau tidak):
plaintext
traceparent: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
              ^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^ ^^
              ver       trace_id (32 hex)          span_id         flags
  • tracestate — membawa data tambahan vendor-spesifik dalam pasangan key=value yang dipisahkan koma, agar tiap vendor bisa menyisipkan metadata tanpa merusak header lain.

Aturan propagasi: service meng-extract header dari request masuk untuk menjadi parent-nya, lalu meng-inject header yang diperbarui ke setiap request keluar. Inilah yang membuat satu request memakai satu trace_id di seluruh perjalanan.

100%

Baggage

Baggage adalah mekanisme membawa key-value kecil lintas service tanpa mengikat ke trace ID — misalnya customer.id atau experiment.group agar bisa di-filter di seluruh trace tanpa menambahkan atribut per span di tiap service.

Set dan baca baggage
from opentelemetry.baggage import set_baggage, get_baggage
from opentelemetry.context import attach, detach
 
token = attach(set_baggage("customer.id", "c-42"))
# ... service memanggil service lain ...
print(get_baggage("customer.id"))
detach(token)

Warning

Baggage dikirim sebagai header plain text di setiap request — jangan pernah menaruh data sensitif (PII, token, password) di dalamnya. Header ini bisa bocor ke log, proxy, atau service pihak ketiga. Gunakan baggage hanya untuk metadata low-risk seperti identitas internal atau group A/B.

Sampling Flag: bit 01

Bit terakhir traceparent adalah trace_flags — bit ke-0 adalah sampled. Nilai 01 berarti span ini direkam dan diekspor; 00 berarti tidak. Ini yang dipakai propagasi untuk menginformasikan "trace ini di-sampling atau tidak" lintas service — fondasi keputusan sampling di episode 13.

Troubleshooting Propagasi Gagal

Gejala paling umum: trace terlihat "terpotong" di backend — hanya terlihat satu service. Penyebab klasiknya:

  • Framework tanpa auto-instrumentation — handler HTTP tidak meng-extract traceparent.
  • Client HTTP tidak diinstrumentasi — request keluar tidak meng-inject header.
  • Proxy/gateway membuang header — W3C header di-strip oleh load balancer.
  • Library messaging tidak di-instrumentasi — context tidak terbawa lewat queue.

Kita atasi pola-pola ini lebih jauh di episode 15 saat membahas tracing lintas layanan di Express, Gin, dan Spring.

Penutup

Pada episode 4 ini, kalian telah menguasai anatomi span dan mekanisme propagasi konteks.

Inti yang harus dibawa pulang:

  • Span membawa trace_id, span_id, parent, nama, duration, attributes, events, status, dan kind.
  • SpanKind (SERVER/CLIENT/PRODUCER/CONSUMER/INTERNAL) menentukan cara membaca arah komunikasi.
  • BatchSpanProcessor adalah standar produksi; Simple cocok untuk debugging.
  • W3C Trace Context (traceparent + tracestate) menyambungkan trace lintas layanan; baggage membawa metadata ringan — jangan taruh PII di sana.

Di episode 5 selanjutnya, kita akan membahas metrics: tipe, instruments & export — Counter, UpDownCounter, Gauge, Histogram, instrumen asinkron (observable), View/aggregation, serta perbedaan delta vs cumulative saat mengekspor ke backend. Sampai jumpa di episode 5!