Membandingkan peran API (Tracer/Meter/Logger) dan SDK (provider, resource, exporter, batching) dalam OpenTelemetry, lalu mempraktikkan dua jalur instrumentasi: auto-instrumentation dengan agent Python, dan instrumentasi manual dengan span serta attribute di kode

Setelah di episode 2 kita memahami arsitektur — API → SDK → Exporter → OTLP → Collector — episode ini masuk ke bagian yang paling sering dihadapi developer: menginstrumentasi aplikasi. Kalian akan belajar dua jalur yang berbeda filosofinya: auto-instrumentation (tanpa mengubah kode) dan manual instrumentation (mengubah kode secara eksplisit).
Mengapa harus menguasai keduanya? Auto-instrumentation memberi cakupan cepat untuk framework HTTP/database populer, sedangkan manual instrumentation memberi kontrol untuk logika bisnis yang tidak dikenali framework. Tim yang hanya memakai satu jalur hampir selalu kehilangan sebagian konteks — kombinasi keduanya adalah praktik produksi yang sehat.
API OTel adalah interface yang kalian panggil di kode: tracer.start_span(), meter.create_counter(), logger.emit(). Aturan kuncinya: API dirancang untuk bekerja meskipun SDK belum dikonfigurasi — ia menjadi no-op. Aplikasi kalian tetap berjalan normal, hanya tanpa menghasilkan telemetry.
from opentelemetry import trace
tracer = trace.get_tracer("payment.service")
span = tracer.start_span("charge")
span.end()Kode di atas aman dieksekusi tanpa SDK apa pun — tidak ada crash, tidak ada overhead berarti. Inilah yang membuat API bisa "ditanam" sejak awal pengembangan.
SDK mewujudkan perilaku nyata: membuat TracerProvider, menempelkan Resource, membangun spans, melakukan sampling, batching, dan meneruskan ke exporter. Konfigurasi SDK dikendalikan lewat environment variable atau kode setup:
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
provider = TracerProvider(resource=Resource.create({SERVICE_NAME: "payment-service"}))
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter(endpoint="localhost:4317")))
trace.set_tracer_provider(provider)Membandingkan keduanya:
| Aspek | API | SDK |
|---|---|---|
| Peran | Kontrak, dipakai di kode | Implementasi nyata, dikonfigurasi |
| Tanpa konfigurasi | No-op, aman | Tidak aktif sampai dipasang |
| Tracer/Meter/Logger | Disediakan | Diimplementasikan |
| Provider, resource, exporter | Tidak ada | Di sini tempatnya |
| Sampling, batching | Tidak ada | Di sini tempatnya |
Note
Prinsip yang sama berlaku di semua bahasa: API JavaScript dipakai melalui @opentelemetry/api, SDK melalui @opentelemetry/sdk-node; di Go, API dipakai lewat go.opentelemetry.io/otel, SDK lewat go.opentelemetry.io/otel/sdk. Strukturnya identik — hanya package dan sintaks yang berbeda.
Auto-instrumentation memanfaatkan teknik pemrograman yang bergantung bahasa untuk menyisipkan telemetry ke library framework populer:
opentelemetry-instrument yang memakai module wrapping.-javaagent JVM agent yang memakai bytecode instrumentation.go.opentelemetry.io/contrib menawarkan middleware manual per framework (Go tanpa runtime agent, jadi berupa helper per framework).Contoh paling cepat adalah Python. Instrumentasi framework HTTP dan klien database cukup dengan satu perintah:
opentelemetry-instrument \
--service_name payment-service \
--exporter_otlp_endpoint http://localhost:4317 \
python app.pyYang terjadi di balik layar: opentelemetry-instrument memuat semua paket opentelemetry-instrumentation-* yang terinstall — Flask, requests, psycopg, dan lain-lain — dan membungkus fungsi entry-point-nya. Setiap request HTTP otomatis menjadi root span, setiap panggilan keluar menjadi child span, dan traceparent di-inject/extract secara otomatis.
pip install opentelemetry-instrumentation-flask \
opentelemetry-instrumentation-requests \
opentelemetry-instrumentation-psycopg2Auto-instrumentation brilian untuk hal yang diketahui framework — namun buta untuk logika bisnis. Ia tidak tahu maksud sebuah fungsi, tidak bisa memberi nama span yang bermakna, dan tidak menambahkan konteks bisnis seperti order.id atau customer.tier. Untuk itu kalian butuh instrumentasi manual.
Instrumentasi manual memakai API secara eksplisit untuk membungkus unit kerja dengan span:
from opentelemetry import trace
tracer = trace.get_tracer("payment.service")
def charge(order_id: str):
with tracer.start_as_current_span("payment.charge") as span:
span.set_attribute("order.id", order_id)
span.set_attribute("payment.method", "card")
result = gateway.call(order_id)
span.set_attribute("payment.amount", result.amount)
return resultKelebihan vs auto-instrumentation:
payment.charge jauh lebih informatif daripada POST /charge.order.id, payment.amount langsung melekat.Praktik terbaik adalah auto untuk lapisan transport, manual untuk lapisan bisnis:
Hasilnya: trace yang otomatis lengkap secara struktural (framework), tapi kaya konteks secara semantik (bisnis). Inilah bentuk trace yang benar-benar bisa menjawab pertanyaan incident response.
Tip
Mulailah dengan auto-instrumentation untuk cakupan cepat, lalu tambahkan manual instrumentation bertahap pada fungsi-fungsi yang paling sering menjadi penyebab insiden — payment, sync, dan job batch adalah kandidat pertama yang baik.
Cek telemetry benar-benar mengalir ke Jaeger di http://localhost:16686 (stack episode 0). Pilih service payment-service, cari trace, dan amati hierarki span: auto-instrumentation menghasilkan span HTTP + DB, manual instrumentation menambahkan span bisnis di antaranya. Kalian akan melihat langsung bagaimana dua jalur ini saling melengkapi.
Pada episode 3 ini, kalian telah memahami dua jalur instrumentasi dan perbedaan API vs SDK.
Inti yang harus dibawa pulang:
opentelemetry-instrument untuk Python, -javaagent untuk Java, module patching untuk Node.js.Di episode 4 selanjutnya, kita akan membedah traces: span, context & propagation — struktur span (nama, attributes, events, status, kind), span processor, serta W3C Trace Context (traceparent/tracestate) dan baggage untuk korelasi lintas layanan. Sampai jumpa di episode 4!