1. Pengantar
Terakhir diperbarui: 15-07-2022
Kemampuan observasi aplikasi
Kemampuan observasi dan OpenTelemetry
Kemampuan observasi adalah istilah yang digunakan untuk menggambarkan atribut suatu sistem. Sistem dengan kemampuan observasi memungkinkan tim men-debug sistem secara aktif. Dalam konteks tersebut, tiga pilar kemampuan observasi; log, metrik, dan trace adalah instrumentasi dasar bagi sistem untuk memperoleh kemampuan observasi.
OpenTelemetry adalah sekumpulan spesifikasi, library, dan agen yang mempercepat instrumentasi dan ekspor data telemetri (log, metrik, dan trace) yang diperlukan kemampuan observasi. OpenTelemetry adalah project standar terbuka dan berbasis komunitas di bawah CNCF. Dengan memanfaatkan library yang disediakan oleh project dan ekosistemnya, developer dapat menginstrumentasikan aplikasi mereka dengan cara yang netral vendor dan terhadap beberapa arsitektur.
Selain tiga pilar kemampuan observasi, pembuatan profil berkelanjutan adalah komponen utama lain untuk kemampuan observasi dan memperluas basis pengguna di industri ini. Cloud Profiler adalah salah satu originator dan menyediakan antarmuka yang mudah untuk melihat perincian metrik performa dalam stack panggilan aplikasi.
Codelab ini adalah bagian 1 dari seri dan membahas instrumentasi trace terdistribusi di microservice dengan OpenTelemetry dan Cloud Trace. Bagian 2 akan membahas pembuatan profil berkelanjutan dengan Cloud Profiler.
Pelacakan Terdistribusi
Di antara log, metrik, dan trace, trace adalah telemetri yang memberi tahu latensi bagian tertentu dari proses dalam sistem. Khususnya di era microservice, trace terdistribusi merupakan pendorong kuat untuk mengetahui bottleneck latensi dalam sistem terdistribusi secara keseluruhan.
Saat menganalisis pelacakan terdistribusi, visualisasi data pelacakan adalah kunci untuk memahami latensi sistem secara keseluruhan secara sekilas. Dalam pelacakan terdistribusi, kami menangani serangkaian panggilan untuk memproses satu permintaan ke titik entri sistem dalam bentuk Trace yang berisi beberapa Span.
Span mewakili unit kerja individual yang dilakukan dalam sistem terdistribusi, mencatat waktu mulai dan berhenti. Span sering memiliki hubungan hierarkis satu sama lain - pada gambar di bawah ini, semua span yang lebih kecil adalah span turunan dari span /messages yang besar, dan dirangkai menjadi satu Trace yang menunjukkan jalur kerja melalui suatu sistem.
Google Cloud Trace adalah salah satu opsi untuk backend trace terdistribusi dan terintegrasi dengan baik dengan produk lain di Google Cloud.
Yang akan Anda bangun
Dalam codelab ini, Anda akan memanfaatkan informasi rekaman aktivitas di layanan yang disebut "aplikasi Shakespeare" (alias Shakesapp) yang berjalan di cluster Google Kubernetes Engine. Arsitektur Shakesapp dijelaskan di bawah ini:
- Loadgen mengirimkan string kueri ke klien di HTTP
- Klien meneruskan kueri dari loadgen ke server di gRPC
- Server menerima kueri dari klien, mengambil semua karya Shakespare dalam format teks dari Google Cloud Storage, menelusuri baris yang berisi kueri, dan menampilkan nomor baris yang cocok dengan klien
Anda akan menginstrumentasikan informasi rekaman aktivitas di seluruh permintaan. Setelah itu, Anda akan menyematkan agen profiler di server dan menyelidiki bottleneck.
Yang akan Anda pelajari
- Cara mulai menggunakan library OpenTelemetry Trace di project Go
- Cara membuat span dengan library
- Cara menyebarkan konteks span di seluruh kabel di antara komponen aplikasi
- Cara mengirim data trace ke Cloud Trace
- Cara menganalisis trace di Cloud Trace
Codelab ini menjelaskan cara melengkapi microservice. Agar mudah dipahami, contoh ini hanya berisi 3 komponen (generator beban, klien, dan server), tetapi Anda dapat menerapkan proses yang sama seperti yang dijelaskan dalam codelab ini ke sistem yang lebih kompleks dan besar.
Yang Anda butuhkan
- Pengetahuan dasar tentang Go
- Pengetahuan dasar tentang Kubernetes
2. Penyiapan dan Persyaratan
Penyiapan lingkungan mandiri
Jika belum memiliki Akun Google (Gmail atau Google Apps), Anda harus membuatnya. Login ke Google Cloud Platform console (console.cloud.google.com) dan buat project baru.
Jika Anda sudah memiliki project, klik menu pull-down pilihan project di kiri atas konsol:
dan klik tombol 'PROJECT BARU' dalam dialog yang dihasilkan untuk membuat project baru:
Jika belum memiliki project, Anda akan melihat dialog seperti ini untuk membuat project pertama:
Dialog pembuatan project berikutnya memungkinkan Anda memasukkan detail project baru:
Ingat project ID yang merupakan nama unik di semua project Google Cloud (maaf, nama di atas telah digunakan dan tidak akan berfungsi untuk Anda!) Project_ID selanjutnya akan dirujuk di codelab ini sebagai PROJECT_ID.
Selanjutnya, jika belum melakukannya, Anda harus mengaktifkan penagihan di Developers Console untuk menggunakan resource Google Cloud dan mengaktifkan Cloud Trace API.
Menjalankan melalui codelab ini tidak akan menghabiskan biaya lebih dari beberapa dolar, tetapi bisa lebih jika Anda memutuskan untuk menggunakan lebih banyak resource atau jika Anda membiarkannya berjalan (lihat bagian "pembersihan" di akhir dokumen ini). Harga Google Cloud Trace, Google Kubernetes Engine, dan Google Artifact Registry tercantum dalam dokumentasi resmi.
- Harga untuk Google Cloud Operations Suite | Operations Suite
- Harga | Dokumentasi Kubernetes Engine
- Harga Artifact Registry | Dokumentasi Artifact Registry
Pengguna baru Google Cloud Platform memenuhi syarat untuk mendapatkan uji coba gratis senilai $300, yang menjadikan codelab ini sepenuhnya gratis.
Penyiapan Google Cloud Shell
Meskipun Google Cloud dan Google Cloud Trace dapat dioperasikan secara jarak jauh dari laptop Anda, dalam codelab ini kita akan menggunakan Google Cloud Shell, yaitu lingkungan command line yang berjalan di Cloud.
Mesin virtual berbasis Debian ini memuat semua alat pengembangan yang akan Anda perlukan. Layanan ini menawarkan direktori beranda tetap sebesar 5 GB dan beroperasi di Google Cloud, sehingga sangat meningkatkan performa dan autentikasi jaringan. Ini berarti bahwa semua yang Anda perlukan untuk codelab ini adalah browser (ya, ini berfungsi di Chromebook).
Untuk mengaktifkan Cloud Shell dari Konsol Cloud, cukup klik Aktifkan Cloud Shell (hanya perlu waktu beberapa saat untuk melakukan penyediaan dan terhubung ke lingkungan).
Setelah terhubung ke Cloud Shell, Anda akan melihat bahwa Anda sudah diautentikasi dan project sudah ditetapkan ke PROJECT_ID
.
gcloud auth list
Output perintah
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
Output perintah
[core] project = <PROJECT_ID>
Jika, untuk beberapa alasan, project belum disetel, cukup jalankan perintah berikut:
gcloud config set project <PROJECT_ID>
Mencari PROJECT_ID
Anda? Periksa ID yang Anda gunakan di langkah-langkah penyiapan atau cari di dasbor Cloud Console:
Cloud Shell juga menetapkan beberapa variabel lingkungan secara default, yang mungkin berguna saat Anda menjalankan perintah di masa mendatang.
echo $GOOGLE_CLOUD_PROJECT
Output perintah
<PROJECT_ID>
Terakhir, tetapkan zona dan konfigurasi project default.
gcloud config set compute/zone us-central1-f
Anda dapat memilih berbagai zona yang berbeda. Untuk informasi selengkapnya, lihat Region & Zona.
Penyiapan bahasa Go
Dalam codelab ini, kita menggunakan Go untuk semua kode sumber. Jalankan perintah berikut di Cloud Shell dan pastikan versi Go adalah 1.17+
go version
Output perintah
go version go1.18.3 linux/amd64
Menyiapkan Cluster Google Kubernetes
Dalam codelab ini, Anda akan menjalankan cluster microservice di Google Kubernetes Engine (GKE). Proses codelab ini adalah sebagai berikut:
- Mendownload project dasar pengukuran ke Cloud Shell
- Membangun microservice ke dalam container
- Mengupload container ke Google Artifact Registry (GAR)
- Men-deploy container ke GKE
- Mengubah kode sumber layanan untuk instrumentasi rekaman aktivitas
- Lanjutkan ke langkah 2
Mengaktifkan Kubernetes Engine
Pertama, kita menyiapkan cluster Kubernetes tempat Shakesapp berjalan di GKE, jadi kita perlu mengaktifkan GKE. Buka menu "Kubernetes Engine" dan tekan tombol ENABLE.
Sekarang Anda siap untuk membuat cluster Kubernetes.
Membuat cluster Kubernetes
Di Cloud Shell, jalankan perintah berikut untuk membuat cluster Kubernetes. Konfirmasi bahwa nilai zona berada di bawah region yang akan Anda gunakan untuk pembuatan repositori Artifact Registry. Ubah nilai zona us-central1-f
jika region repositori Anda tidak mencakup zona tersebut.
gcloud container clusters create otel-trace-codelab2 \ --zone us-central1-f \ --release-channel rapid \ --preemptible \ --enable-autoscaling \ --max-nodes 8 \ --no-enable-ip-alias \ --scopes cloud-platform
Output perintah
Note: Your Pod address range (`--cluster-ipv4-cidr`) can accommodate at most 1008 node(s). Creating cluster otel-trace-codelab2 in us-central1-f... Cluster is being health-checked (master is healthy)...done. Created [https://container.googleapis.com/v1/projects/development-215403/zones/us-central1-f/clusters/otel-trace-codelab2]. To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-f/otel-trace-codelab2?project=development-215403 kubeconfig entry generated for otel-trace-codelab2. NAME: otel-trace-codelab2 LOCATION: us-central1-f MASTER_VERSION: 1.23.6-gke.1501 MASTER_IP: 104.154.76.89 MACHINE_TYPE: e2-medium NODE_VERSION: 1.23.6-gke.1501 NUM_NODES: 3 STATUS: RUNNING
Artifact Registry dan penyiapan skaffold
Sekarang cluster Kubernetes siap di-deploy. Selanjutnya, kita akan menyiapkan container registry untuk container push dan deploy. Untuk langkah-langkah ini, kita perlu menyiapkan Artifact Registry (GAR) dan skaffold untuk menggunakannya.
Penyiapan Artifact Registry
Buka menu "Artifact Registry" dan tekan tombol ENABLE.
Setelah beberapa saat, Anda akan melihat browser repositori GAR. Klik "CREATE REPOSITORY" dan masukkan nama repositori.
Dalam codelab ini, saya memberi nama repositori baru trace-codelab
. Format artefak adalah "Docker" dan jenis lokasinya adalah "Region". Pilih region yang dekat dengan region yang Anda tetapkan untuk zona default Google Compute Engine. Misalnya, contoh ini memilih "us-central1-f" di atas, jadi di sini kita pilih
"us-central1 (Iowa)". Kemudian klik tombol "CREATE" tombol.
Sekarang Anda melihat "trace-codelab" di browser repositori.
Kita akan kembali ke sini nanti untuk memeriksa jalur registry.
Penyiapan Skaffold
Skaffold adalah alat yang praktis ketika Anda membangun microservice yang berjalan di Kubernetes. Platform ini menangani alur kerja membangun, mendorong, dan men-deploy container aplikasi dengan sekumpulan kecil perintah. Skaffold secara default menggunakan Docker Registry sebagai container registry, sehingga Anda perlu mengonfigurasi skaffold untuk mengenali GAR saat mengirim container.
Buka Cloud Shell lagi dan pastikan skaffold telah diinstal. (Cloud Shell menginstal skaffold ke dalam lingkungan secara default.) Jalankan perintah berikut dan lihat versi skaffold.
skaffold version
Output perintah
v1.38.0
Sekarang, Anda dapat mendaftarkan repositori default yang akan digunakan oleh skaffold. Untuk mendapatkan jalur registry, buka dasbor Artifact Registry dan klik nama repositori yang baru saja Anda siapkan di langkah sebelumnya.
Kemudian Anda akan melihat jejak breadcrumb di bagian atas halaman. Klik ikon untuk menyalin jalur registry ke papan klip.
Saat mengklik tombol salin, Anda melihat dialog di bagian bawah browser dengan pesan seperti:
"us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab" telah disalin
Kembali ke Cloud Shell. Jalankan perintah skaffold config set default-repo
dengan nilai yang baru saja Anda salin dari dasbor.
skaffold config set default-repo us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab
Output perintah
set value default-repo to us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab for context gke_stackdriver-sandbox-3438851889_us-central1-b_stackdriver-sandbox
Selain itu, Anda perlu mengonfigurasi registry ke konfigurasi Docker. Jalankan perintah berikut:
gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
Output perintah
{ "credHelpers": { "gcr.io": "gcloud", "us.gcr.io": "gcloud", "eu.gcr.io": "gcloud", "asia.gcr.io": "gcloud", "staging-k8s.gcr.io": "gcloud", "marketplace.gcr.io": "gcloud", "us-central1-docker.pkg.dev": "gcloud" } } Adding credentials for: us-central1-docker.pkg.dev
Sekarang Anda siap melanjutkan ke langkah selanjutnya untuk menyiapkan container Kubernetes di GKE.
Ringkasan
Pada langkah ini, Anda akan menyiapkan lingkungan codelab:
- Menyiapkan Cloud Shell
- Membuat repositori Artifact Registry untuk container registry
- Menyiapkan skaffold untuk menggunakan container registry
- Membuat cluster Kubernetes tempat microservice codelab berjalan
Berikutnya
Pada langkah berikutnya, Anda akan membangun, mengirim, dan men-deploy microservice ke cluster
3. Membangun, mengirim, dan men-deploy microservice
Mendownload materi codelab
Pada langkah sebelumnya, kita telah menyiapkan semua prasyarat untuk codelab ini. Sekarang Anda siap menjalankan seluruh microservice di atasnya. Materi codelab dihosting di GitHub, jadi download materi tersebut ke lingkungan Cloud Shell dengan perintah git berikut.
cd ~ git clone https://github.com/ymotongpoo/opentelemetry-trace-codelab-go.git cd opentelemetry-trace-codelab-go
Struktur direktori project adalah sebagai berikut:
. ├── README.md ├── step0 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step1 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step2 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step3 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step4 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src ├── step5 │ ├── manifests │ ├── proto │ ├── skaffold.yaml │ └── src └── step6 ├── manifests ├── proto ├── skaffold.yaml └── src
- manifes: File manifes Kubernetes
- proto: definisi proto untuk komunikasi antara klien dan server
- direktori src: untuk kode sumber setiap layanan
- skaffold.yaml: File konfigurasi untuk skaffold
Dalam codelab ini, Anda akan memperbarui kode sumber yang berada di folder step0
. Anda juga dapat melihat kode sumber di folder step[1-6]
untuk mendapatkan jawaban dalam langkah-langkah berikut. (Bagian 1 mencakup langkah 0 hingga langkah 4, dan Bagian 2 mencakup langkah 5 dan 6)
Menjalankan perintah skaffold
Terakhir, Anda siap membangun, mengirim, dan men-deploy seluruh konten ke cluster Kubernetes yang baru saja Anda buat. Ini terdengar seperti berisi beberapa langkah, tetapi skaffold yang sebenarnya dapat melakukan semuanya untuk Anda. Mari kita coba dengan perintah berikut:
cd step0 skaffold dev
Segera setelah menjalankan perintah, Anda akan melihat output log docker build
dan dapat mengonfirmasi bahwa perintah tersebut berhasil dikirim ke registry.
Output perintah
... ---> Running in c39b3ea8692b ---> 90932a583ab6 Successfully built 90932a583ab6 Successfully tagged us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/serverservice:step1 The push refers to repository [us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/serverservice] cc8f5a05df4a: Preparing 5bf719419ee2: Preparing 2901929ad341: Preparing 88d9943798ba: Preparing b0fdf826a39a: Preparing 3c9c1e0b1647: Preparing f3427ce9393d: Preparing 14a1ca976738: Preparing f3427ce9393d: Waiting 14a1ca976738: Waiting 3c9c1e0b1647: Waiting b0fdf826a39a: Layer already exists 88d9943798ba: Layer already exists f3427ce9393d: Layer already exists 3c9c1e0b1647: Layer already exists 14a1ca976738: Layer already exists 2901929ad341: Pushed 5bf719419ee2: Pushed cc8f5a05df4a: Pushed step1: digest: sha256:8acdbe3a453001f120fb22c11c4f6d64c2451347732f4f271d746c2e4d193bbe size: 2001
Setelah semua container layanan dikirim, deployment Kubernetes akan dimulai secara otomatis.
Output perintah
sha256:b71fce0a96cea08075dc20758ae561cf78c83ff656b04d211ffa00cedb77edf8 size: 1997 Tags used in deployment: - serverservice -> us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/serverservice:step4@sha256:8acdbe3a453001f120fb22c11c4f6d64c2451347732f4f271d746c2e4d193bbe - clientservice -> us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/clientservice:step4@sha256:b71fce0a96cea08075dc20758ae561cf78c83ff656b04d211ffa00cedb77edf8 - loadgen -> us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab/loadgen:step4@sha256:eea2e5bc8463ecf886f958a86906cab896e9e2e380a0eb143deaeaca40f7888a Starting deploy... - deployment.apps/clientservice created - service/clientservice created - deployment.apps/loadgen created - deployment.apps/serverservice created - service/serverservice created
Setelah deployment, Anda akan melihat log aplikasi sebenarnya yang dimunculkan ke stdout di setiap container seperti ini:
Output perintah
[client] 2022/07/14 06:33:15 {"match_count":3040} [loadgen] 2022/07/14 06:33:15 query 'love': matched 3040 [client] 2022/07/14 06:33:15 {"match_count":3040} [loadgen] 2022/07/14 06:33:15 query 'love': matched 3040 [client] 2022/07/14 06:33:16 {"match_count":3040} [loadgen] 2022/07/14 06:33:16 query 'love': matched 3040 [client] 2022/07/14 06:33:19 {"match_count":463} [loadgen] 2022/07/14 06:33:19 query 'tear': matched 463 [loadgen] 2022/07/14 06:33:20 query 'world': matched 728 [client] 2022/07/14 06:33:20 {"match_count":728} [client] 2022/07/14 06:33:22 {"match_count":463} [loadgen] 2022/07/14 06:33:22 query 'tear': matched 463
Perlu diketahui bahwa pada tahap ini, Anda ingin melihat semua pesan dari server. Oke, akhirnya Anda siap untuk mulai melengkapi aplikasi dengan OpenTelemetry untuk pelacakan layanan yang terdistribusi.
Sebelum memulai instrumentasi layanan, matikan cluster Anda dengan Ctrl-C.
Output perintah
... [client] 2022/07/14 06:34:57 {"match_count":1} [loadgen] 2022/07/14 06:34:57 query 'what's past is prologue': matched 1 ^CCleaning up... - W0714 06:34:58.464305 28078 gcp.go:120] WARNING: the gcp auth plugin is deprecated in v1.22+, unavailable in v1.25+; use gcloud instead. - To learn more, consult https://cloud.google.com/blog/products/containers-kubernetes/kubectl-auth-changes-in-gke - deployment.apps "clientservice" deleted - service "clientservice" deleted - deployment.apps "loadgen" deleted - deployment.apps "serverservice" deleted - service "serverservice" deleted
Ringkasan
Pada langkah ini, Anda telah menyiapkan materi codelab di lingkungan Anda dan mengonfirmasi operasi skaffold seperti yang diharapkan.
Berikutnya
Pada langkah berikutnya, Anda akan memodifikasi kode sumber layanan loadgen untuk menginstrumentasikan informasi rekaman aktivitas.
4. Instrumentasi untuk HTTP
Konsep instrumentasi dan propagasi rekaman aktivitas
Sebelum mengedit kode sumber, saya akan menjelaskan secara singkat cara kerja trace terdistribusi dalam diagram sederhana.
Dalam contoh ini, kami menginstrumentasikan kode untuk mengekspor informasi Trace dan Span ke Cloud Trace dan menyebarkan konteks trace di seluruh permintaan dari layanan loadgen ke layanan server.
Aplikasi harus mengirim metadata Trace seperti ID Trace dan ID Span agar Cloud Trace dapat menyusun semua span yang memiliki ID Trace yang sama ke dalam satu trace. Selain itu, aplikasi harus menyebarkan konteks trace (kombinasi ID Trace dan ID Span dari span induk) saat meminta layanan downstream, sehingga aplikasi dapat mengetahui konteks trace mana yang ditangani.
OpenTelemetry membantu Anda:
- untuk membuat Trace ID dan ID Span unik
- untuk mengekspor ID Rekaman Aktivitas dan ID Span ke backend
- untuk menyebarkan konteks trace ke layanan lain
- untuk menyematkan metadata tambahan yang membantu menganalisis rekaman aktivitas
Komponen di OpenTelemetry Trace
Proses untuk menginstrumentasikan pelacakan aplikasi dengan OpenTelemetry adalah sebagai berikut:
- Membuat pengekspor
- Buat TracerProvider yang mengikat pengekspor di 1 dan menetapkannya secara global.
- Menetapkan TextMapPropagaror untuk menyetel metode propagasi
- Mendapatkan Tracer dari TracerProvider
- Membuat Span dari Tracer
Untuk saat ini, Anda tidak perlu memahami properti terperinci pada setiap komponen, tetapi yang paling penting untuk diingat adalah:
- pengekspor di sini dapat dicocokkan ke TracerProvider
- TracerProvider menyimpan semua konfigurasi terkait pengambilan sampel dan ekspor rekaman aktivitas
- semua rekaman aktivitas digabungkan dalam objek Tracer
Dengan pemahaman tentang ini, mari kita beralih ke pekerjaan {i>coding<i} yang sebenarnya.
Rentang pertama instrumen
Layanan generator beban instrumen
Buka Cloud Shell Editor dengan menekan tombol di kanan atas Cloud Shell. Buka
step0/src/loadgen/main.go
dari penjelajah di panel kiri dan temukan fungsi utamanya.
step0/src/loadgen/main.go
func main() { ... for range t.C { log.Printf("simulating client requests, round %d", i) if err := run(numWorkers, numConcurrency); err != nil { log.Printf("aborted round with error: %v", err) } log.Printf("simulated %d requests", numWorkers) if numRounds != 0 && i > numRounds { break } i++ } }
Pada fungsi utama, Anda akan melihat loop yang memanggil fungsi run
di dalamnya. Dalam implementasi saat ini, bagian tersebut memiliki 2 baris log yang mencatat awal dan akhir panggilan fungsi. Sekarang, mari kita pelajari informasi Span untuk melacak latensi panggilan fungsi.
Pertama, seperti yang disebutkan di bagian sebelumnya, mari kita siapkan seluruh konfigurasi untuk OpenTelemetry. Tambahkan paket OpenTelemetry sebagai berikut:
step0/src/loadgen/main.go
import ( "context" // step1. add packages "encoding/json" "fmt" "io" "log" "math/rand" "net/http" "net/url" "time" // step1. add packages "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.10.0" "go.opentelemetry.io/otel/trace" // step1. end add packages )
Agar mudah dibaca, kami membuat fungsi penyiapan yang disebut initTracer
dan memanggilnya di fungsi main
.
step0/src/loadgen/main.go
// step1. add OpenTelemetry initialization function func initTracer() (*sdktrace.TracerProvider, error) { // create a stdout exporter to show collected spans out to stdout. exporter, err := stdout.New(stdout.WithPrettyPrint()) if err != nil { return nil, err } // for the demonstration, we use AlwaysSmaple sampler to take all spans. // do not use this option in production. tp := sdktrace.NewTracerProvider( sdktrace.WithSampler(sdktrace.AlwaysSample()), sdktrace.WithBatcher(exporter), ) otel.SetTracerProvider(tp) otel.SetTextMapPropagator(propagation.TraceContext{}) return tp, nil }
Anda mungkin menyadari bahwa prosedur untuk menyiapkan OpenTelemetry dijelaskan di bagian sebelumnya. Dalam implementasi ini, kita menggunakan pengekspor stdout
yang mengekspor semua informasi rekaman aktivitas ke dalam stdout dalam format terstruktur.
Kemudian, panggil dari fungsi utama. Panggil initTracer()
dan pastikan untuk memanggil TracerProvider.Shutdown()
saat Anda menutup aplikasi.
step0/src/loadgen/main.go
func main() { // step1. setup OpenTelemetry tp, err := initTracer() if err != nil { log.Fatalf("failed to initialize TracerProvider: %v", err) } defer func() { if err := tp.Shutdown(context.Background()); err != nil { log.Fatalf("error shutting down TracerProvider: %v", err) } }() // step1. end setup log.Printf("starting worder with %d workers in %d concurrency", numWorkers, numConcurrency) log.Printf("number of rounds: %d (0 is inifinite)", numRounds) ...
Setelah menyelesaikan penyiapan, Anda harus membuat Span dengan ID Rekaman Aktivitas dan ID Span yang unik. OpenTelemetry menyediakan pustaka yang berguna untuknya. Menambahkan paket baru ekstra ke klien HTTP instrumen.
step0/src/loadgen/main.go
import ( "context" "encoding/json" "fmt" "io" "log" "math/rand" "net/http" "net/http/httptrace" // step1. add packages "net/url" "time" // step1. add packages "go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" // step1. end add packages "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.10.0" "go.opentelemetry.io/otel/trace" )
Karena generator beban memanggil layanan klien di HTTP dengan net/http
dalam fungsi runQuery
, kita menggunakan paket contrib untuk net/http
dan mengaktifkan instrumentasi dengan ekstensi paket httptrace
dan otelhttp
.
Pertama-tama, tambahkan variabel global paket httpClient untuk memanggil permintaan HTTP melalui klien berinstrumen.
step0/src/loadgen/main.go
var httpClient = http.Client{ Transport: otelhttp.NewTransport(http.DefaultTransport) }
Selanjutnya, tambahkan instrumentasi dalam fungsi runQuery
untuk membuat span kustom menggunakan OpenTelemetry dan span yang dibuat secara otomatis dari klien HTTP kustom. Yang perlu Anda lakukan adalah:
- Dapatkan Tracer dari
TracerProvider
global denganotel.Tracer()
- Membuat span root dengan metode
Tracer.Start()
- Mengakhiri span root dalam waktu arbitrer (dalam hal ini, akhir fungsi
runQuery
)
step0/src/loadgen/main.go
reqURL.RawQuery = v.Encode() // step1. replace http.Get() with custom client call // resp, err := http.Get(reqURL.String()) // step1. instrument trace ctx := context.Background() tr := otel.Tracer("loadgen") ctx, span := tr.Start(ctx, "query.request", trace.WithAttributes( semconv.TelemetrySDKLanguageGo, semconv.ServiceNameKey.String("loadgen.runQuery"), attribute.Key("query").String(s), )) defer span.End() ctx = httptrace.WithClientTrace(ctx, otelhttptrace.NewClientTrace(ctx)) req, err := http.NewRequestWithContext(ctx, "GET", reqURL.String(), nil) if err != nil { return -1, fmt.Errorf("error creating HTTP request object: %v", err) } resp, err := httpClient.Do(req) // step1. end instrumentation if err != nil { return -1, fmt.Errorf("error sending request to %v: %v", reqURL.String(), err) }
Sekarang Anda telah selesai dengan instrumentasi di loadgen (aplikasi klien HTTP). Pastikan untuk mengupdate go.mod
dan go.sum
dengan perintah go mod
.
go mod tidy
Layanan klien instrumen
Di bagian sebelumnya, kita telah melengkapi bagian yang tertutup dalam persegi panjang merah pada gambar di bawah ini. Kami menginstrumentasikan informasi span dalam layanan generator beban. Sama seperti layanan generator beban, sekarang kita perlu menginstrumentasikan layanan klien. Perbedaannya dengan layanan generator beban adalah bahwa layanan klien harus mengekstrak informasi ID Pelacakan yang disebarkan dari layanan generator beban di header HTTP dan menggunakan ID tersebut untuk membuat Span.
Buka Cloud Shell Editor dan tambahkan paket yang diperlukan seperti yang kami lakukan untuk layanan generator beban.
step0/src/client/main.go
import ( "context" "encoding/json" "fmt" "io" "log" "net/http" "net/url" "os" "time" "opentelemetry-trace-codelab-go/client/shakesapp" // step1. add new import "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/trace" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" // step1. end new import )
Sekali lagi, kita perlu
menyiapkan OpenTelemtry. Cukup salin dan tempel fungsi initTracer
dari loadgen dan panggil juga dalam fungsi main
layanan klien.
step0/src/client/main.go
// step1. add OpenTelemetry initialization function func initTracer() (*sdktrace.TracerProvider, error) { // create a stdout exporter to show collected spans out to stdout. exporter, err := stdout.New(stdout.WithPrettyPrint()) if err != nil { return nil, err } // for the demonstration, we use AlwaysSmaple sampler to take all spans. // do not use this option in production. tp := sdktrace.NewTracerProvider( sdktrace.WithSampler(sdktrace.AlwaysSample()), sdktrace.WithBatcher(exporter), ) otel.SetTracerProvider(tp) otel.SetTextMapPropagator(propagation.TraceContext{}) return tp, nil }
Sekarang saatnya untuk instrumen span. Karena layanan klien perlu menerima permintaan HTTP dari layanan loadgen, layanan tersebut perlu melengkapi pengendali. Server HTTP di layanan klien diimplementasikan dengan net/http, dan Anda dapat menggunakan paket otelhttp
seperti yang kita lakukan di loadgen.
Pertama, kita mengganti pendaftaran pengendali dengan Pengendali otelhttp
. Pada fungsi main
, temukan baris tempat pengendali HTTP didaftarkan dengan http.HandleFunc()
.
step0/src/client/main.go
// step1. change handler to intercept OpenTelemetry related headers // http.HandleFunc("/", svc.handler) otelHandler := otelhttp.NewHandler(http.HandlerFunc(svc.handler), "client.handler") http.Handle("/", otelHandler) // step1. end intercepter setting http.HandleFunc("/_genki", svc.health)
Kemudian, kita menginstrumentasikan span sebenarnya di dalam pengendali. Temukan func (*clientService) handler(), dan tambahkan instrumentasi span dengan trace.SpanFromContext()
.
step0/src/client/main.go
func (cs *clientService) handler(w http.ResponseWriter, r *http.Request) { ... ctx := r.Context() ctx, cancel := context.WithCancel(ctx) defer cancel() // step1. instrument trace span := trace.SpanFromContext(ctx) defer span.End() // step1. end instrument ...
Dengan instrumentasi ini, Anda mendapatkan span dari awal metode handler
hingga akhir. Agar span mudah dianalisis, tambahkan atribut tambahan yang menyimpan jumlah yang cocok ke kueri. Tepat sebelum baris log, tambahkan kode berikut.
func (cs *clientService) handler(w http.ResponseWriter, r *http.Request) { ... // step1. add span specific attribute span.SetAttributes(attribute.Key("matched").Int64(resp.MatchCount)) // step1. end adding attribute log.Println(string(ret)) ...
Dengan semua instrumentasi di atas, Anda telah menyelesaikan instrumentasi rekaman aktivitas antara loadgen dan klien. Mari kita pelajari cara kerjanya. Jalankan lagi kode dengan skaffold.
skaffold dev
Setelah beberapa waktu menjalankan layanan di cluster GKE, Anda akan melihat banyak pesan log seperti ini:
Output perintah
[loadgen] { [loadgen] "Name": "query.request", [loadgen] "SpanContext": { [loadgen] "TraceID": "cfa22247a542beeb55a3434392d46b89", [loadgen] "SpanID": "18b06404b10c418b", [loadgen] "TraceFlags": "01", [loadgen] "TraceState": "", [loadgen] "Remote": false [loadgen] }, [loadgen] "Parent": { [loadgen] "TraceID": "00000000000000000000000000000000", [loadgen] "SpanID": "0000000000000000", [loadgen] "TraceFlags": "00", [loadgen] "TraceState": "", [loadgen] "Remote": false [loadgen] }, [loadgen] "SpanKind": 1, [loadgen] "StartTime": "2022-07-14T13:13:36.686751087Z", [loadgen] "EndTime": "2022-07-14T13:14:31.849601964Z", [loadgen] "Attributes": [ [loadgen] { [loadgen] "Key": "telemetry.sdk.language", [loadgen] "Value": { [loadgen] "Type": "STRING", [loadgen] "Value": "go" [loadgen] } [loadgen] }, [loadgen] { [loadgen] "Key": "service.name", [loadgen] "Value": { [loadgen] "Type": "STRING", [loadgen] "Value": "loadgen.runQuery" [loadgen] } [loadgen] }, [loadgen] { [loadgen] "Key": "query", [loadgen] "Value": { [loadgen] "Type": "STRING", [loadgen] "Value": "faith" [loadgen] } [loadgen] } [loadgen] ], [loadgen] "Events": null, [loadgen] "Links": null, [loadgen] "Status": { [loadgen] "Code": "Unset", [loadgen] "Description": "" [loadgen] }, [loadgen] "DroppedAttributes": 0, [loadgen] "DroppedEvents": 0, [loadgen] "DroppedLinks": 0, [loadgen] "ChildSpanCount": 5, [loadgen] "Resource": [ [loadgen] { [loadgen] "Key": "service.name", [loadgen] "Value": { [loadgen] "Type": "STRING", [loadgen] "Value": "unknown_service:loadgen" ...
Pengekspor stdout
akan memunculkan pesan ini. Anda akan melihat bahwa induk dari semua span menurut loadgen memiliki TraceID: 00000000000000000000000000000000
, karena ini adalah span root, yaitu span pertama dalam rekaman aktivitas. Anda juga akan mendapati bahwa atribut sematan "query"
memiliki string kueri yang diteruskan ke layanan klien.
Ringkasan
Pada langkah ini, Anda telah menginstrumentasikan layanan generator beban dan layanan klien yang berkomunikasi dalam HTTP dan mengonfirmasi bahwa Anda berhasil menyebarkan Konteks Pelacakan di seluruh layanan dan mengekspor informasi Span dari kedua layanan ke stdout.
Berikutnya
Pada langkah berikutnya, Anda akan melengkapi layanan klien dan layanan server untuk mengonfirmasi cara menyebarkan Konteks Pelacakan melalui gRPC.
5. Instrumentasi untuk gRPC
Pada langkah sebelumnya, kita telah melengkapi paruh pertama permintaan di microservice ini. Pada langkah ini, kami mencoba melengkapi komunikasi gRPC antara layanan klien dan layanan server. (Persegi panjang hijau dan ungu pada gambar di bawah)
Instrumentasi pra-build untuk klien gRPC
Ekosistem OpenTelemetry menawarkan banyak library berguna yang membantu developer melengkapi aplikasi. Pada langkah sebelumnya, kita menggunakan instrumentasi pra-build untuk paket net/http
. Pada langkah ini, saat kami mencoba menyebarkan Konteks Rekaman Aktivitas melalui gRPC, kita akan menggunakan library untuknya.
Pertama, impor paket gRPC bawaan yang disebut otelgrpc
.
step0/src/client/main.go
import ( "context" "encoding/json" "fmt" "io" "log" "net/http" "net/url" "os" "time" "opentelemetry-trace-codelab-go/client/shakesapp" // step2. add prebuilt gRPC package (otelgrpc) "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/trace" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" )
Kali ini, layanan klien adalah klien gRPC terhadap layanan server, sehingga Anda perlu menginstrumentasikan klien gRPC. Temukan fungsi mustConnGRPC
dan tambahkan interseptor gRPC yang menginstrumentasikan span baru setiap kali klien membuat permintaan ke server.
step0/src/client/main.go
// Helper function for gRPC connections: Dial and create client once, reuse. func mustConnGRPC(ctx context.Context, conn **grpc.ClientConn, addr string) { var err error // step2. add gRPC interceptor interceptorOpt := otelgrpc.WithTracerProvider(otel.GetTracerProvider()) *conn, err = grpc.DialContext(ctx, addr, grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor(interceptorOpt)), grpc.WithStreamInterceptor(otelgrpc.StreamClientInterceptor(interceptorOpt)), grpc.WithTimeout(time.Second*3), ) // step2: end adding interceptor if err != nil { panic(fmt.Sprintf("Error %s grpc: failed to connect %s", err, addr)) } }
Karena sudah menyiapkan OpenTelemetry di bagian sebelumnya, Anda tidak perlu melakukannya.
Instrumentasi bawaan untuk server gRPC
Seperti yang kami lakukan untuk klien gRPC, kami menyebut instrumentasi bawaan untuk server gRPC. Tambahkan paket baru ke bagian impor seperti:
step0/src/server/main.go
import ( "context" "fmt" "io/ioutil" "log" "net" "os" "regexp" "strings" "opentelemetry-trace-codelab-go/server/shakesapp" "cloud.google.com/go/storage" // step2. add OpenTelemetry packages including otelgrpc "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "go.opentelemetry.io/otel" stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/propagation" sdktrace "go.opentelemetry.io/otel/sdk/trace" "google.golang.org/api/iterator" "google.golang.org/api/option" "google.golang.org/grpc" healthpb "google.golang.org/grpc/health/grpc_health_v1" )
Karena ini pertama kalinya Anda menggunakan server instrumentasi, Anda perlu menyiapkan OpenTelemetry terlebih dahulu, mirip dengan yang kami lakukan untuk loadgen dan layanan klien.
step0/src/server/main.go
// step2. add OpenTelemetry initialization function func initTracer() (*sdktrace.TracerProvider, error) { // create a stdout exporter to show collected spans out to stdout. exporter, err := stdout.New(stdout.WithPrettyPrint()) if err != nil { return nil, err } // for the demonstration, we use AlwaysSmaple sampler to take all spans. // do not use this option in production. tp := sdktrace.NewTracerProvider( sdktrace.WithSampler(sdktrace.AlwaysSample()), sdktrace.WithBatcher(exporter), ) otel.SetTracerProvider(tp) otel.SetTextMapPropagator(propagation.TraceContext{}) return tp, nil } func main() { ... // step2. setup OpenTelemetry tp, err := initTracer() if err != nil { log.Fatalf("failed to initialize TracerProvider: %v", err) } defer func() { if err := tp.Shutdown(context.Background()); err != nil { log.Fatalf("error shutting down TracerProvider: %v", err) } }() // step2. end setup ...
Dan selanjutnya, Anda perlu
menambahkan pencegat server. Pada fungsi main
, temukan tempat grpc.NewServer()
dipanggil dan tambahkan interseptor ke fungsi.
step0/src/server/main.go
func main() { ... svc := NewServerService() // step2: add interceptor interceptorOpt := otelgrpc.WithTracerProvider(otel.GetTracerProvider()) srv := grpc.NewServer( grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor(interceptorOpt)), grpc.StreamInterceptor(otelgrpc.StreamServerInterceptor(interceptorOpt)), ) // step2: end adding interceptor shakesapp.RegisterShakespeareServiceServer(srv, svc) ...
Menjalankan microservice dan mengonfirmasi rekaman aktivitas
Kemudian jalankan kode yang telah Anda modifikasi dengan perintah skaffold.
skaffold dev
Sekarang lagi, Anda melihat banyak informasi {i>span<i} di {i>stdout<i}.
Output perintah
... [server] { [server] "Name": "shakesapp.ShakespeareService/GetMatchCount", [server] "SpanContext": { [server] "TraceID": "89b472f213a400cf975e0a0041649667", [server] "SpanID": "96030dbad0061b3f", [server] "TraceFlags": "01", [server] "TraceState": "", [server] "Remote": false [server] }, [server] "Parent": { [server] "TraceID": "89b472f213a400cf975e0a0041649667", [server] "SpanID": "cd90cc3859b73890", [server] "TraceFlags": "01", [server] "TraceState": "", [server] "Remote": true [server] }, [server] "SpanKind": 2, [server] "StartTime": "2022-07-14T14:05:55.74822525Z", [server] "EndTime": "2022-07-14T14:06:03.449258891Z", [server] "Attributes": [ ... [server] ], [server] "Events": [ [server] { [server] "Name": "message", [server] "Attributes": [ ... [server] ], [server] "DroppedAttributeCount": 0, [server] "Time": "2022-07-14T14:05:55.748235489Z" [server] }, [server] { [server] "Name": "message", [server] "Attributes": [ ... [server] ], [server] "DroppedAttributeCount": 0, [server] "Time": "2022-07-14T14:06:03.449255889Z" [server] } [server] ], [server] "Links": null, [server] "Status": { [server] "Code": "Unset", [server] "Description": "" [server] }, [server] "DroppedAttributes": 0, [server] "DroppedEvents": 0, [server] "DroppedLinks": 0, [server] "ChildSpanCount": 0, [server] "Resource": [ [server] { ... [server] ], [server] "InstrumentationLibrary": { [server] "Name": "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc", [server] "Version": "semver:0.33.0", [server] "SchemaURL": "" [server] } [server] } ...
Anda melihat bahwa Anda belum menyematkan nama span dan membuat span secara manual dengan trace.Start()
atau span.SpanFromContext()
. Anda masih mendapatkan span dalam jumlah besar karena interseptor gRPC membuatnya.
Ringkasan
Pada langkah ini, Anda telah menginstrumentasikan komunikasi berbasis gRPC dengan dukungan dari library ekosistem OpenTelemetry.
Berikutnya
Pada langkah berikutnya, terakhir Anda akan memvisualisasikan trace dengan Cloud Trace dan mempelajari cara menganalisis span yang dikumpulkan.
6. Memvisualisasikan trace dengan Cloud Trace
Anda telah menginstrumentasikan rekaman aktivitas di seluruh sistem dengan OpenTelemetry. Sejauh ini, Anda telah mempelajari cara melengkapi layanan HTTP dan gRPC. Meskipun Anda telah mempelajari cara menginstrumentasikannya, Anda masih belum belajar bagaimana menganalisisnya. Di bagian ini, Anda akan mengganti pengekspor stdout dengan pengekspor Cloud Trace, dan mempelajari cara menganalisis trace Anda.
Menggunakan pengekspor Cloud Trace
Salah satu karakteristik kuat dari OpenTelemetry adalah kemampuannya untuk dicocokkan. Untuk memvisualisasikan semua span yang dikumpulkan oleh instrumentasi, Anda hanya perlu mengganti pengekspor stdout dengan pengekspor Cloud Trace.
Buka file main.go
dari setiap layanan, dan temukan fungsi initTracer()
. Hapus baris untuk membuat pengekspor stdout dan membuat pengekspor Cloud Trace.
step0/src/loadgen/main.go
import ( ... // step3. add OpenTelemetry for Cloud Trace package cloudtrace "github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/trace" ) // step1. add OpenTelemetry initialization function func initTracer() (*sdktrace.TracerProvider, error) { // step3. replace stdout exporter with Cloud Trace exporter // cloudtrace.New() finds the credentials to Cloud Trace automatically following the // rules defined by golang.org/x/oauth2/google.findDefaultCredentailsWithParams. // https://pkg.go.dev/golang.org/x/oauth2/google#FindDefaultCredentialsWithParams exporter, err := cloudtrace.New() // step3. end replacing exporter if err != nil { return nil, err } // for the demonstration, we use AlwaysSmaple sampler to take all spans. // do not use this option in production. tp := sdktrace.NewTracerProvider( sdktrace.WithSampler(sdktrace.AlwaysSample()), sdktrace.WithBatcher(exporter), ) otel.SetTracerProvider(tp) otel.SetTextMapPropagator(propagation.TraceContext{}) return tp, nil }
Anda juga perlu mengedit fungsi yang sama di layanan klien dan server.
Menjalankan microservice dan mengonfirmasi rekaman aktivitas
Setelah edit, cukup jalankan cluster seperti biasa dengan perintah skaffold.
skaffold dev
Kemudian, sekarang Anda tidak melihat banyak informasi span dalam format log terstruktur di stdout, karena Anda mengganti pengekspor dengan Cloud Trace.
Output perintah
[loadgen] 2022/07/14 15:01:07 simulated 20 requests [loadgen] 2022/07/14 15:01:07 simulating client requests, round 37 [loadgen] 2022/07/14 15:01:14 query 'sweet': matched 958 [client] 2022/07/14 15:01:14 {"match_count":958} [client] 2022/07/14 15:01:14 {"match_count":3040} [loadgen] 2022/07/14 15:01:14 query 'love': matched 3040 [client] 2022/07/14 15:01:15 {"match_count":349} [loadgen] 2022/07/14 15:01:15 query 'hello': matched 349 [client] 2022/07/14 15:01:15 {"match_count":484} [loadgen] 2022/07/14 15:01:15 query 'faith': matched 484 [loadgen] 2022/07/14 15:01:15 query 'insolence': matched 14 [client] 2022/07/14 15:01:15 {"match_count":14} [client] 2022/07/14 15:01:21 {"match_count":484} [loadgen] 2022/07/14 15:01:21 query 'faith': matched 484 [client] 2022/07/14 15:01:21 {"match_count":728} [loadgen] 2022/07/14 15:01:21 query 'world': matched 728 [client] 2022/07/14 15:01:22 {"match_count":484} [loadgen] 2022/07/14 15:01:22 query 'faith': matched 484 [loadgen] 2022/07/14 15:01:22 query 'hello': matched 349 [client] 2022/07/14 15:01:22 {"match_count":349} [client] 2022/07/14 15:01:23 {"match_count":1036} [loadgen] 2022/07/14 15:01:23 query 'friend': matched 1036 [loadgen] 2022/07/14 15:01:28 query 'tear': matched 463 ...
Sekarang, mari kita konfirmasi apakah semua span dikirim dengan benar ke Cloud Trace. Akses Konsol Cloud, lalu buka "Trace list". Mudah diakses dari kotak penelusuran. Jika tidak, Anda dapat mengklik menu di panel kiri.
Kemudian Anda melihat banyak bercak biru yang didistribusikan di seluruh grafik latensi. Setiap spot mewakili satu rekaman aktivitas.
Klik salah satunya dan Anda dapat melihat detailnya di dalam rekaman aktivitas.
Bahkan dari tampilan sekilas yang sederhana ini, Anda sudah mengetahui banyak wawasan. Misalnya, dari grafik waterfall, Anda dapat melihat bahwa penyebab latensi sebagian besar disebabkan oleh span yang bernama shakesapp.ShakespeareService/GetMatchCount
. (Lihat 1 pada gambar di atas) Anda dapat mengonfirmasinya dari tabel ringkasan. (Kolom paling kanan menunjukkan durasi setiap span.) Selain itu, trace ini ditujukan untuk kueri "friend". (Lihat 2 pada gambar di atas)
Dengan analisis singkat ini, Anda mungkin menyadari bahwa Anda perlu mengetahui span yang lebih terperinci di dalam metode GetMatchCount
. Dibandingkan dengan informasi {i>stdout<i}, visualisasi sangat kuat. Untuk mempelajari detail Cloud Trace lebih lanjut, buka dokumentasi resmi kami.
Ringkasan
Pada langkah ini, Anda mengganti pengekspor stdout dengan Cloud Trace satu dan memvisualisasikan trace di Cloud Trace. Anda juga telah mempelajari cara mulai menganalisis rekaman aktivitas.
Berikutnya
Pada langkah berikutnya, Anda akan memodifikasi kode sumber layanan server untuk menambahkan subspan di GetMatchCount.
7. Tambahkan sub-span untuk analisis yang lebih baik
Pada langkah sebelumnya, Anda menemukan penyebab waktu round-trip yang diamati dari loadgen sebagian besar adalah proses di dalam metode GetMatchCount, pengendali gRPC, di layanan server. Namun, karena kami belum menginstrumentasikan apa pun selain pengendali, kami tidak dapat menemukan insight lebih lanjut dari grafik waterfall. Ini adalah kasus umum saat kita mulai menginstrumentasikan microservice.
Di bagian ini, kita akan menginstrumentasikan sub-span tempat server memanggil Google Cloud Storage, karena hal ini umum terjadi ketika beberapa I/O jaringan eksternal membutuhkan waktu yang lama dalam prosesnya dan penting untuk mengidentifikasi apakah panggilan tersebut adalah penyebabnya.
Menginstrumentasikan subspan di server
Buka main.go
di server dan temukan fungsi readFiles
. Fungsi ini memanggil permintaan ke Google Cloud Storage untuk mengambil semua file teks karya Shakespeare. Dalam fungsi ini, Anda dapat membuat subspan, seperti yang Anda lakukan untuk instrumentasi server HTTP di layanan klien.
step0/src/server/main.go
func readFiles(ctx context.Context, bucketName, prefix string) ([]string, error) { type resp struct { s string err error } // step4: add an extra span span := trace.SpanFromContext(ctx) span.SetName("server.readFiles") span.SetAttributes(attribute.Key("bucketname").String(bucketName)) defer span.End() // step4: end add span ...
Itu saja untuk menambahkan span baru. Mari kita lihat cara kerjanya dengan menjalankan aplikasi.
Menjalankan microservice dan mengonfirmasi rekaman aktivitas
Setelah edit, cukup jalankan cluster seperti biasa dengan perintah skaffold.
skaffold dev
Kemudian, pilih satu rekaman aktivitas bernama query.request
dari daftar rekaman aktivitas. Anda akan melihat grafik waterfall rekaman aktivitas yang serupa, kecuali untuk span baru di bagian shakesapp.ShakespeareService/GetMatchCount
. (Rentang yang diapit kotak merah di bawah)
Yang dapat Anda ketahui dari grafik ini sekarang adalah bahwa panggilan eksternal ke Google Cloud Storage menempati sejumlah besar latensi, tetapi masih ada hal-hal lain yang membuat sebagian besar latensi tersebut.
Anda sudah mendapatkan banyak insight hanya dari beberapa tampilan dari grafik waterfall pelacakan. Bagaimana cara Anda mendapatkan detail performa lebih lanjut dalam permohonan Anda? Di sini profiler masuk, tetapi untuk saat ini, mari kita jadikan ini akhir dari codelab ini dan delegasikan semua tutorial profiler ke bagian 2.
Ringkasan
Pada langkah ini, Anda menginstrumentasikan span lain dalam layanan server dan memperoleh insight lebih lanjut tentang latensi sistem.
8. Selamat
Anda telah berhasil membuat trace terdistribusi dengan OpenTelemery dan latensi permintaan yang dikonfirmasi di seluruh microservice di Google Cloud Trace.
Untuk latihan yang diperpanjang, Anda dapat mencoba sendiri topik berikut.
- Penerapan saat ini mengirimkan semua span yang dihasilkan oleh health check. (
grpc.health.v1.Health/Check
) Bagaimana cara memfilter span tersebut dari Cloud Trace? Petunjuknya ada di sini. - Kaitkan log peristiwa dengan span dan lihat cara kerjanya di Google Cloud Trace dan Google Cloud Logging. Petunjuknya ada di sini.
- Ganti beberapa layanan dengan layanan dalam bahasa lain dan cobalah melengkapinya dengan OpenTelemetry untuk bahasa tersebut.
Selain itu, jika Anda ingin mempelajari profiler setelah ini, lanjutkan ke bagian 2. Jika demikian, Anda dapat melewati bagian pembersihan di bawah.
Pembersihan
Setelah codelab ini, hentikan cluster Kubernetes dan pastikan untuk menghapus project sehingga Anda tidak menerima tagihan yang tidak terduga di Google Kubernetes Engine, Google Cloud Trace, Google Artifact Registry.
Pertama, hapus cluster. Jika menjalankan cluster dengan skaffold dev
, Anda hanya perlu menekan Ctrl-C. Jika Anda menjalankan cluster dengan skaffold run
, jalankan perintah berikut:
skaffold delete
Output perintah
Cleaning up... - deployment.apps "clientservice" deleted - service "clientservice" deleted - deployment.apps "loadgen" deleted - deployment.apps "serverservice" deleted - service "serverservice" deleted
Setelah menghapus cluster, dari panel menu, pilih "IAM & "Admin" > "Setelan", lalu klik "MATIKAN" tombol.
Kemudian masukkan Project ID (bukan Nama Project) dalam formulir di dialog dan konfirmasi penonaktifan.