Skip to main content
BlogDevOps

OpenTelemetry Collector: Merancang Pipeline Telemetri

Panduan praktis merancang pipeline OpenTelemetry Collector, dari receiver dan processor hingga tail-based sampling dan ekspor ke banyak backend.

Matthews Wong

Software Engineer

Juli 202610 menit baca
OpenTelemetry Collector: Merancang Pipeline Telemetri

Foto oleh woodleywonderworks on flickr

Ringkasan Utama

Pipeline OpenTelemetry Collector butuh urutan processor yang jelas, bukan sekadar menyambung komponen. memory_limiter harus jalan duluan untuk melindungi proses, langkah pengurang volume seperti filter dan tail_sampling harus mendahului batch, dan memisahkan deployment agent dari gateway menjaga akurasi tail-based sampling sekaligus membuat penambahan backend baru cukup lewat perubahan konfigurasi, bukan deploy ulang.

Kebanyakan tim memulai perjalanan OpenTelemetry mereka dengan mengarahkan SDK langsung ke sebuah backend. Cara itu memang cukup untuk demo, tetapi tidak akan bertahan menghadapi lalu lintas produksi, batas biaya, atau kehadiran vendor observability kedua. Solusinya adalah menempatkan Collector di tengah dan memperlakukan telemetri sebagai pipeline tersendiri, dengan ketelitian yang sama seperti pipeline data yang mengisi sebuah gudang data.

Artikel ini membahas perancangan pipeline tersebut secara menyeluruh: bagaimana receiver, processor, dan exporter saling terhubung, mengapa urutan processor lebih penting daripada yang disadari kebanyakan tim, bagaimana tail-based sampling mempertahankan trace yang benar-benar Anda pedulikan, dan bagaimana menyalurkan aliran yang sama ke lebih dari satu backend tanpa menduplikasi instrumentasi.

Anatomi sebuah pipeline Collector

Sebuah pipeline Collector adalah jalur bernama yang dilalui oleh satu sinyal, seperti trace, metrik, atau log, melewati tiga jenis komponen yang dideklarasikan di dalam berkas konfigurasi.

  • Receiver menerima data ke dalam Collector, baik dengan mendengarkan pada sebuah port jaringan untuk protokol push seperti OTLP, maupun dengan secara aktif menarik data dari sumber sesuai jadwal.
  • Processor berada di antara receiver dan exporter, mentransformasi, memfilter, memperkaya, atau melakukan sampling pada data yang mengalir. Setiap pipeline mendapatkan instance processor-nya sendiri secara independen, meskipun dua pipeline merujuk nama processor yang sama.
  • Exporter meneruskan data yang sudah diproses ke satu atau beberapa tujuan. Jika sebuah pipeline mencantumkan lebih dari satu exporter, setiap exporter menerima salinannya sendiri melalui langkah fan-out di akhir rantai.

Data bergerak melalui pipeline hanya dalam satu arah, dari setiap receiver yang terkonfigurasi menuju processor pertama, lalu berurutan melewati setiap processor berikutnya, dan akhirnya keluar ke setiap exporter yang tercantum. Sebuah processor juga dapat memutuskan untuk membuang data sepenuhnya, dan justru begitulah sampling dan filtering diterapkan.

receivers:
  otlp:
    protocols:
      grpc:
      http:

processors:
  memory_limiter:
    check_interval: 1s
    limit_mib: 1500
  batch:
    send_batch_size: 8192
    timeout: 5s

exporters:
  otlphttp:
    endpoint: https://backend.example.com:4318

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlphttp]

Berikan nama instance pada setiap processor dan exporter, seperti batch atau otlphttp dengan sufiks garis miring, ketika sebuah sinyal membutuhkan penanganan berbeda per pipeline. Nama processor tunggal tanpa penamaan secara konsep dibagi tetapi diinstansiasi terpisah per pipeline, sehingga penamaan membuat maksudnya eksplisit di dalam berkas konfigurasi.

Mengapa urutan processor menentukan segalanya

Processor dieksekusi persis sesuai urutan yang Anda cantumkan, dan urutan itu memengaruhi baik kebenaran maupun biaya. Processor pelindung sumber daya harus berjalan sebelum apa pun yang mahal, dan apa pun yang mengurangi volume data harus berjalan sebelum processor yang melakukan batching demi efisiensi jaringan, jika tidak Anda membuat batch atas data yang justru akan Anda buang.

UrutanProcessorMengapa ditempatkan di sini
1memory_limiterMelindungi proses Collector itu sendiri dari crash kehabisan memori dengan menolak atau melepas data begitu tekanan memori melewati ambang batas yang dikonfigurasi, sebelum pemrosesan berat mana pun berjalan.
2resource / attributesMelampirkan atau memperbaiki atribut layanan, lingkungan, dan deployment lebih awal agar setiap keputusan di hilir, termasuk kebijakan sampling, dapat mengandalkan metadata yang akurat.
3filterMembuang telemetri yang sejak awal tidak perlu meninggalkan sumbernya, seperti span pemeriksaan kesehatan atau log level debug, sebelum langkah sampling dan batching yang lebih mahal menyentuhnya.
4tail_samplingMembuat keputusan simpan atau buang atas trace utuh setelah cukup span tiba untuk mengevaluasi kebijakan seperti status error atau latensi tinggi.
5batchMengelompokkan apa pun yang lolos sampling menjadi batch yang lebih besar tepat sebelum ekspor, di mana batching memberi manfaat terbesar karena tidak ada lagi di hilir yang akan menyentuh data tersebut.

Tail-based sampling: menyimpan trace yang penting

Head-based sampling memutuskan apakah menyimpan sebuah trace pada saat span pertama dibuat, sebelum siapa pun tahu apakah permintaan itu akan lambat atau gagal. Tail-based sampling menunggu hingga sebuah trace, atau cukup bagian darinya, tiba, dan baru kemudian menerapkan aturan seperti selalu simpan trace berstatus error, selalu simpan trace yang lebih lambat dari ambang latensi, dan selain itu simpan sebagian kecil persentase dari sisanya.

Komprominya adalah memori dan topologi. Processor menahan span dalam sebuah buffer hingga jendela keputusan berlalu, dan ia hanya dapat membuat keputusan yang benar jika setiap span milik satu trace tertentu mendarat pada instance Collector yang sama. Dalam armada berpenyeimbang beban, itu berarti merutekan berdasarkan pengidentifikasi trace pada lapisan yang lebih awal, bukan secara round robin.

  1. Sebuah jendela tunggu keputusan, umumnya sekitar tiga puluh detik, mengendalikan berapa lama processor mengumpulkan span untuk sebuah trace sebelum mengevaluasi kebijakan sampling-nya.
  2. Sebuah buffer dalam memori berukuran tetap, ditentukan oleh jumlah maksimum trace, menyimpan status trace antara kedatangan dan keputusan. Trace lama akan dikeluarkan begitu buffer penuh, yang dapat membuang sebuah trace sebelum sempat dievaluasi.
  3. Pola deployment berlapis adalah solusi standar untuk kebutuhan perutean: lapisan pertama Collector tanpa status menyeimbangkan beban span berdasarkan pengidentifikasi trace, dan lapisan kedua yang menjalankan tail sampling processor membuat keputusan akhir simpan atau buang per trace.

Jika Collector Anda berjalan di belakang penyeimbang beban generik yang mendistribusikan span secara round robin alih-alih berdasarkan pengidentifikasi trace, tail-based sampling akan diam-diam membuat keputusan yang salah karena span dari trace yang sama tersebar ke berbagai instance yang tidak pernah melihat gambaran utuh. Perbaiki lapisan perutean sebelum menyetel kebijakan sampling.

Deployment agent versus gateway

Ada dua tempat umum untuk menjalankan instance Collector, dan sebagian besar setup produksi menggunakan keduanya bersamaan alih-alih memilih salah satu.

  • Collector agent berjalan sebagai sidecar atau daemon set per node, dekat dengan aplikasi. Ia menangani pekerjaan lokal yang murah: menerima OTLP dari SDK, menambahkan atribut sumber daya host dan pod, serta menerapkan pembatas memori.
  • Collector gateway berjalan sebagai layanan terpisah yang di-deploy secara terpusat dan menjadi tujuan penerusan dari para agent. Ini adalah tempat yang tepat untuk apa pun yang membutuhkan pandangan global atau pemrosesan lebih berat, seperti tail-based sampling, deduplikasi, atau penyaluran ke banyak backend.
  • Connector, sebuah jenis komponen yang bertindak sebagai exporter untuk satu pipeline dan receiver untuk pipeline lain di dalam Collector yang sama, memungkinkan Anda membagi lalu lintas antar kedua lapisan tanpa keluar dari konfigurasi Collector, misalnya merutekan sebagian span ke pipeline khusus untuk backend tertentu.

Pembagian ini menjaga penggunaan sumber daya per node tetap dapat diprediksi sambil memusatkan pekerjaan yang berstatus dan rakus memori seperti tail sampling pada sejumlah kecil instance gateway berpenyeimbang beban yang dapat Anda ukur secara mandiri.

Mengirim ke backend mana pun tanpa menyentuh kode aplikasi

Karena SDK hanya berbicara OTLP ke Collector, mengganti atau menambahkan backend adalah perubahan konfigurasi, bukan deploy ulang setiap layanan yang terinstrumentasi. Tambahkan exporter kedua yang bernama dan cantumkan bersama yang pertama di dalam pipeline, dan Collector akan menyalurkan data terproses yang sama ke kedua tujuan.

exporters:
  otlphttp/tempo:
    endpoint: https://tempo.example.com:4318
  otlphttp/honeycomb:
    endpoint: https://api.honeycomb.io
    headers:
      x-honeycomb-team: ${env:HONEYCOMB_API_KEY}

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, tail_sampling, batch]
      exporters: [otlphttp/tempo, otlphttp/honeycomb]

Ini juga cara paling bersih untuk menjalankan proof of concept terhadap backend baru, seperti penyimpanan tracing open-source atau vendor berbayar, secara paralel dengan tujuan produksi Anda yang ada, tanpa risiko kehilangan data yang sudah ada jika uji coba tidak berhasil.

Karena exporter berjalan setelah sampling dan batching, menambahkan backend kedua hanya menghabiskan baris konfigurasi, bukan menggandakan volume trace yang sudah Anda bayar untuk disampling turun. Fan-out terjadi pada aliran yang sudah dikurangi.

Daftar periksa desain sebelum Anda merilis

Sebelum memperlakukan sebuah pipeline Collector sebagai siap produksi, telusuri daftar singkat ini.

  • Apakah memory_limiter adalah processor pertama di setiap pipeline, dengan batas ditetapkan di bawah plafon memori kontainer atau host?
  • Apakah segala hal yang mengurangi volume, seperti filter atau tail_sampling, berjalan sebelum batch, sehingga Anda tidak pernah membuat batch atas data yang akan Anda buang?
  • Jika tail-based sampling digunakan, apakah perutean span berdasarkan pengidentifikasi trace dijamin pada penyeimbang beban, bukan diserahkan pada kebetulan?
  • Apakah ada lapisan gateway yang menyerap pemrosesan berstatus, sehingga Collector agent pada node aplikasi tetap ringan dan mudah diukur?
FAQ

Pertanyaan Umum

Jawaban singkat untuk pertanyaan yang paling sering diajukan pembaca tentang topik ini.

Apa itu pipeline OpenTelemetry Collector?

Pipeline Collector adalah jalur bernama yang dilalui sebuah sinyal seperti trace, metrik, atau log melewati tiga jenis komponen: receiver menerima data, processor mentransformasi atau melakukan sampling, dan exporter mengirimnya ke backend. Data mengalir satu arah, dari setiap receiver melewati tiap processor secara berurutan lalu keluar ke setiap exporter. Pipeline didefinisikan per sinyal di bagian service pada berkas konfigurasi.

Mengapa urutan processor penting di Collector?

Processor berjalan persis sesuai urutan yang Anda cantumkan, sehingga urutan memengaruhi baik kebenaran maupun biaya. memory_limiter sebaiknya berjalan pertama untuk melindungi proses dari crash kehabisan memori, dan langkah pengurang volume seperti filter dan tail_sampling harus berjalan sebelum batch. Jika tidak, Anda menghabiskan CPU dan memori untuk membuat batch atas data yang akan dibuang.

Apa perbedaan head-based dan tail-based sampling?

Head-based sampling memutuskan apakah menyimpan trace saat span pertama dibuat, sebelum Anda tahu apakah permintaan lambat atau gagal. Tail-based sampling menunggu hingga trace lengkap, lalu menerapkan kebijakan seperti menyimpan semua error dan semua permintaan lambat. Tail sampling menangkap trace yang benar-benar Anda butuhkan untuk debugging, dengan biaya menahan span di memori.

Mengapa semua span sebuah trace harus mencapai Collector yang sama untuk tail sampling?

Tail sampling processor mengevaluasi kebijakan atas keseluruhan trace, jadi ia perlu melihat setiap span trace itu pada satu instance untuk memutuskan dengan benar. Jika penyeimbang beban generik menyebar span secara round robin, tiap instance hanya melihat sebagian dan membuat keputusan yang salah. Solusinya adalah setup berlapis yang merutekan berdasarkan pengidentifikasi trace ke lapisan sampling khusus.

Bagaimana cara mengirim trace yang sama ke banyak backend?

Karena SDK hanya berbicara OTLP ke Collector, Anda menambahkan exporter kedua yang bernama dan mencantumkan kedua exporter di dalam pipeline. Collector menyalurkan data yang sudah diproses sehingga setiap exporter mendapat salinannya sendiri. Ini memudahkan uji coba backend baru secara paralel dengan yang sudah ada, dan berpindah cukup dengan perubahan konfigurasi tanpa deploy ulang aplikasi.