1. Giriş

Son Güncelleme: 2022-07-15
Uygulamanın gözlemlenebilirliği
Gözlemlenebilirlik ve OpenTelemetry
Gözlemlenebilirlik, bir sistemin özelliğini tanımlamak için kullanılan terimdir. Gözlemlenebilirlik özelliği olan bir sistem, ekiplerin sistemlerinde aktif olarak hata ayıklamasına olanak tanır. Bu bağlamda, gözlemlenebilirliğin üç temel unsuru olan günlükler, metrikler ve izler, sistemin gözlemlenebilirlik kazanması için temel enstrümantasyondur.
OpenTelemetry, gözlemlenebilirlik için gereken telemetri verilerinin (günlükler, metrikler ve izler) enstrümantasyonunu ve dışa aktarılmasını hızlandıran bir dizi spesifikasyon, kitaplık ve aracıdır. OpenTelemetry, CNCF bünyesinde açık standartlı ve topluluk odaklı bir projedir. Projenin ve ekosisteminin sağladığı kitaplıkları kullanarak geliştiriciler, uygulamalarını satıcıdan bağımsız bir şekilde ve birden fazla mimariye karşı kullanabilir.
Ayrıca, gözlemlenebilirlik için üç temel unsura ek olarak sürekli profilleme de bir diğer önemli bileşendir ve sektörde kullanıcı tabanını genişletmektedir. Cloud Profiler, bu özelliği ilk sunanlardan biridir ve uygulama çağrı yığınlarındaki performans metriklerini ayrıntılı olarak incelemek için kolay bir arayüz sağlar.
Bu codelab, serinin 1. bölümüdür ve OpenTelemetry ile Cloud Trace kullanarak mikro hizmetlerde dağıtılmış izleri enstrümante etmeyi kapsar. 2. bölümde Cloud Profiler ile sürekli profilleme ele alınacaktır.
Dağıtılmış İzleme
Günlükler, metrikler ve izler arasında iz, sistemdeki sürecin belirli bir bölümünün gecikmesini bildiren telemetridir. Özellikle mikro hizmetler çağında, dağıtılmış izleme, genel dağıtılmış sistemdeki gecikme sorunlarını bulmak için güçlü bir araçtır.
Dağıtılmış izleri analiz ederken iz verilerinin görselleştirilmesi, genel sistem gecikmelerini bir bakışta anlamanın anahtarıdır. Dağıtılmış izlemede, sisteme giriş noktasına yönelik tek bir isteği işlemek için bir dizi çağrıyı birden fazla aralık içeren bir izleme biçiminde ele alırız.
Span, dağıtılmış bir sistemde yapılan ve başlangıç ile bitiş zamanlarını kaydeden tek bir iş birimini ifade eder. Kapsamlar genellikle birbirleriyle hiyerarşik ilişkilere sahiptir. Aşağıdaki resimde, daha küçük tüm kapsamlar büyük bir /messages kapsamının alt kapsamlarıdır ve sistemdeki iş akışını gösteren tek bir İz'de birleştirilir.

Google Cloud Trace, dağıtılmış izleme arka ucu için seçeneklerden biridir ve Google Cloud'daki diğer ürünlerle iyi entegre edilmiştir.
Ne oluşturacaksınız?
Bu codelab'de, Google Kubernetes Engine kümesinde çalışan "Shakespeare uygulaması" (diğer adıyla Shakesapp) adlı hizmetlerde izleme bilgilerini kullanacaksınız. Shakesapp'in mimarisi aşağıda açıklanmıştır:

- Loadgen, HTTP'de istemciye bir sorgu dizesi gönderir.
- İstemciler, yük oluşturucudan sunucuya gRPC'de sorguyu geçirir.
- Sunucu, istemciden gelen sorguyu kabul eder, Google Cloud Storage'dan tüm Shakespeare eserlerini metin biçiminde getirir, sorguyu içeren satırları arar ve eşleşen satırın numarasını istemciye döndürür.
İzleme bilgilerini istek genelinde kullanırsınız. Ardından, sunucuya bir profil aracı aracısı yerleştirip performans sorununu inceleyeceksiniz.
Neler öğreneceksiniz?
- Go projesinde OpenTelemetry Trace kitaplıklarını kullanmaya başlama
- Kitaplıkla kapsam oluşturma
- Kapsam bağlamlarını uygulama bileşenleri arasında kablo üzerinden yayma
- İz verilerini Cloud Trace'e gönderme
- Cloud Trace'te izlemeyi analiz etme
Bu codelab'de, mikro hizmetlerinize nasıl izleme araçları ekleyeceğiniz açıklanmaktadır. Bu örneği kolay anlaşılır hale getirmek için yalnızca 3 bileşen (yük oluşturucu, istemci ve sunucu) içerir. Ancak bu codelab'de açıklanan aynı süreci daha karmaşık ve büyük sistemlere de uygulayabilirsiniz.
Gerekenler
- Go hakkında temel bilgiler
- Kubernetes hakkında temel bilgiler
2. Kurulum ve Gereksinimler
Yönlendirmesiz ortam kurulumu
Google Hesabınız (Gmail veya Google Apps) yoksa hesap oluşturmanız gerekir. Google Cloud Platform Console'da ( console.cloud.google.com) oturum açın ve yeni bir proje oluşturun.
Önceden oluşturduğunuz bir projeniz varsa konsolun sol üst kısmındaki proje seçimi açılır menüsünü tıklayın:

ve yeni bir proje oluşturmak için açılan iletişim kutusunda "YENİ PROJE" düğmesini tıklayın:

Henüz bir projeniz yoksa ilk projenizi oluşturmak için aşağıdaki gibi bir iletişim kutusu görürsünüz:

Sonraki proje oluşturma iletişim kutusunda yeni projenizin ayrıntılarını girebilirsiniz:

Tüm Google Cloud projelerinde benzersiz bir ad olan proje kimliğini unutmayın (Yukarıdaki ad zaten alınmış olduğundan sizin için çalışmayacaktır). Bu codelab'de daha sonra PROJECT_ID olarak adlandırılacaktır.
Ardından, henüz yapmadıysanız Google Cloud kaynaklarını kullanmak için Developers Console'da faturalandırmayı etkinleştirmeniz ve Cloud Trace API'yi etkinleştirmeniz gerekir.

Bu codelab'i tamamlamak size birkaç dolardan fazla maliyet getirmemelidir. Ancak daha fazla kaynak kullanmaya karar verirseniz veya kaynakları çalışır durumda bırakırsanız maliyet artabilir (bu belgenin sonundaki "temizleme" bölümüne bakın). Google Cloud Trace, Google Kubernetes Engine ve Google Artifact Registry'nin fiyatlandırması resmi dokümanlarda belirtilmiştir.
- Google Cloud'un işlem paketi fiyatlandırması | İşlem Paketi
- Fiyatlandırma | Kubernetes Engine Belgeleri
- Artifact Registry Fiyatlandırması | Artifact Registry belgeleri
Google Cloud Platform'un yeni kullanıcıları, bu codelab'i tamamen ücretsiz hale getirecek 300 ABD doları değerinde ücretsiz deneme sürümünden yararlanabilir.
Google Cloud Shell Kurulumu
Google Cloud ve Google Cloud Trace, dizüstü bilgisayarınızdan uzaktan çalıştırılabilir. Ancak bu codelab'de, bulutta çalışan bir komut satırı ortamı olan Google Cloud Shell'i kullanacağız.
Bu Debian tabanlı sanal makine, ihtiyaç duyacağınız tüm geliştirme araçlarını içerir. 5 GB boyutunda kalıcı bir ana dizin bulunur ve Google Cloud'da çalışır. Bu sayede ağ performansı ve kimlik doğrulama önemli ölçüde güçlenir. Bu nedenle, bu codelab için ihtiyacınız olan tek şey bir tarayıcıdır (Chromebook'ta da çalışır).
Cloud Shell'i Cloud Console'dan etkinleştirmek için Cloud Shell'i Etkinleştir'i
tıklamanız yeterlidir (ortamın sağlanması ve bağlantının kurulması yalnızca birkaç saniye sürer).


Cloud Shell'e bağlandıktan sonra kimliğinizin doğrulandığını ve projenin, PROJECT_ID'nize ayarlandığını görürsünüz.
gcloud auth list
Komut çıkışı
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
Komut çıkışı
[core] project = <PROJECT_ID>
Herhangi bir nedenle proje ayarlanmamışsa şu komutu verin:
gcloud config set project <PROJECT_ID>
PROJECT_ID cihazınızı mı arıyorsunuz? Kurulum adımlarında hangi kimliği kullandığınızı kontrol edin veya Cloud Console kontrol panelinde arayın:

Cloud Shell, gelecekteki komutları çalıştırırken faydalı olabilecek bazı ortam değişkenlerini de varsayılan olarak ayarlar.
echo $GOOGLE_CLOUD_PROJECT
Komut çıkışı
<PROJECT_ID>
Son olarak, varsayılan alt bölgeyi ve proje yapılandırmasını ayarlayın.
gcloud config set compute/zone us-central1-f
Çeşitli bölgeler arasından seçim yapabilirsiniz. Daha fazla bilgi için Bölgeler ve Alt Bölgeler başlıklı makaleyi inceleyin.
Dil kurulumuna gitme
Bu codelab'de tüm kaynak kodları için Go kullanılır. Cloud Shell'de aşağıdaki komutu çalıştırın ve Go sürümünün 1.17 veya daha yeni olduğunu doğrulayın.
go version
Komut çıkışı
go version go1.18.3 linux/amd64
Google Kubernetes kümesi oluşturma
Bu codelab'de, Google Kubernetes Engine'de (GKE) bir mikro hizmet kümesi çalıştıracaksınız. Bu codelab'in süreci aşağıdaki gibidir:
- Temel proje dosyasını Cloud Shell'e indirin.
- Mikro hizmetleri container'lara yerleştirme
- Google Artifact Registry'ye (GAR) kapsayıcı yükleme
- Container'ları GKE'ye dağıtma
- İzleme enstrümantasyonu için hizmetlerin kaynak kodunu değiştirme
- 2. adıma geçin.
Kubernetes Engine'i etkinleştirme
Öncelikle, Shakesapp'in GKE'de çalıştığı bir Kubernetes kümesi oluşturuyoruz. Bu nedenle GKE'yi etkinleştirmemiz gerekiyor. "Kubernetes Engine" menüsüne gidin ve ETKİNLEŞTİR düğmesine basın.

Artık Kubernetes kümesi oluşturmaya hazırsınız.
Kubernetes kümesi oluşturma
Cloud Shell'de Kubernetes kümesi oluşturmak için aşağıdaki komutu çalıştırın. Lütfen bölge değerinin, Artifact Registry deposu oluşturmak için kullanacağınız bölgenin altında olduğunu onaylayın. Depo bölgeniz bölgeyi kapsamıyorsa bölge değerini us-central1-f olarak değiştirin.
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
Komut çıkışı
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 ve skaffold kurulumu
Artık dağıtıma hazır bir Kubernetes kümemiz var. Ardından, kapsayıcıları göndermek ve dağıtmak için bir kapsayıcı kayıt defteri hazırlıyoruz. Bu adımlar için bir Artifact Registry (GAR) oluşturmamız ve bunu kullanmak üzere Skaffold'u ayarlamamız gerekir.
Artifact Registry kurulumu
"Artifact Registry" menüsüne gidin ve ETKİNLEŞTİR düğmesine basın.

Bir süre sonra GAR'ın depo tarayıcısını görürsünüz. "CREATE REPOSITORY" (DEPO OLUŞTUR) düğmesini tıklayın ve deponun adını girin.

Bu codelab'de yeni depoya trace-codelab adını veriyorum. Yapının biçimi "Docker", konum türü ise "Bölge" olmalıdır. Google Compute Engine varsayılan bölgesi için ayarladığınız bölgeye yakın bir bölge seçin. Örneğin, yukarıdaki örnekte "us-central1-f" seçildiğinden burada "us-central1 (Iowa)" seçilir. Ardından "OLUŞTUR" düğmesini tıklayın.

Artık "trace-codelab"i depo tarayıcısında görebilirsiniz.

Kayıt defteri yolunu kontrol etmek için daha sonra buraya geri döneceğiz.
Skaffold kurulumu
Skaffold, Kubernetes'te çalışan mikro hizmetler oluştururken kullanışlı bir araçtır. Küçük bir komut grubuyla uygulama kapsayıcılarını oluşturma, gönderme ve dağıtma iş akışını yönetir. Skaffold, varsayılan olarak Docker Registry'yi Container Registry olarak kullandığından, container'ları gönderirken GAR'ı tanıyacak şekilde Skaffold'u yapılandırmanız gerekir.
Cloud Shell'i tekrar açın ve Skaffold'ın yüklü olup olmadığını doğrulayın. (Cloud Shell, skaffold'u ortama varsayılan olarak yükler.) Aşağıdaki komutu çalıştırıp Skaffold sürümünü görün.
skaffold version
Komut çıkışı
v1.38.0
Artık, skaffold'un kullanacağı varsayılan veri deposunu kaydedebilirsiniz. Kayıt yolu almak için Artifact Registry kontrol paneline gidin ve önceki adımda ayarladığınız deponun adını tıklayın.

Ardından, sayfanın üst kısmında içerik haritası yollarını görürsünüz. Kayıt defteri yolunu panoya kopyalamak için
simgesini tıklayın.

Kopyala düğmesini tıkladığınızda tarayıcının alt kısmında aşağıdaki gibi bir mesaj içeren iletişim kutusu görürsünüz:
"us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab" kopyalandı
Cloud Shell'e geri dönün. skaffold config set default-repo komutunu, kontrol panelinden kopyaladığınız değerle birlikte çalıştırın.
skaffold config set default-repo us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab
Komut çıkışı
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
Ayrıca, kayıt defterini Docker yapılandırmasına göre yapılandırmanız gerekir. Aşağıdaki komutu çalıştırın:
gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
Komut çıkışı
{
"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
Artık GKE'de Kubernetes kapsayıcısı oluşturma işleminin bir sonraki adımına geçebilirsiniz.
Özet
Bu adımda codelab ortamınızı ayarlarsınız:
- Cloud Shell'i ayarlama
- Container Registry için bir Artifact Registry deposu oluşturduysanız
- Container Registry'yi kullanmak için Skaffold'u ayarlama
- Codelab mikro hizmetlerinin çalıştığı bir Kubernetes kümesi oluşturduysanız
Sıradaki
Sonraki adımda, mikro hizmetlerinizi oluşturup kümeye gönderecek ve dağıtacaksınız.
3. Mikro hizmetleri oluşturma, aktarma ve dağıtma
Codelab materyalini indirin
Önceki adımda, bu codelab için tüm ön koşulları ayarladık. Artık tüm mikro hizmetleri bunların üzerinde çalıştırmaya hazırsınız. Codelab materyali GitHub'da barındırıldığından, aşağıdaki git komutuyla Cloud Shell kabuk ortamına indirin.
cd ~ git clone https://github.com/ymotongpoo/opentelemetry-trace-codelab-go.git cd opentelemetry-trace-codelab-go
Projenin dizin yapısı aşağıdaki gibidir:
.
├── 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
- manifests: Kubernetes manifest dosyaları
- proto: İstemci ile sunucu arasındaki iletişim için proto tanımı
- src: Her hizmetin kaynak kodunun bulunduğu dizinler
- skaffold.yaml: Skaffold'un yapılandırma dosyası
Bu codelab'de, step0 klasöründe bulunan kaynak kodu güncelleyeceksiniz. Ayrıca, aşağıdaki adımlardaki yanıtlar için step[1-6] klasörlerindeki kaynak koduna da bakabilirsiniz. (1. bölümde 0. adımdan 4. adıma kadar olanlar, 2. bölümde ise 5. ve 6. adımlar ele alınır)
Skaffold komutunu çalıştırma
Son olarak, tüm içeriği oluşturmaya, aktarmaya ve yeni oluşturduğunuz Kubernetes kümesine dağıtmaya hazırsınız. Bu işlem birden fazla adım içeriyormuş gibi görünse de aslında her şeyi sizin için yapan Skaffold'dur. Bunu aşağıdaki komutla deneyelim:
cd step0 skaffold dev
Komutu çalıştırdığınız anda docker build öğesinin günlük çıkışını görür ve bunların kayıt defterine başarıyla gönderildiğini onaylayabilirsiniz.
Komut çıkışı
... ---> 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
Tüm hizmet kapsayıcıları gönderildikten sonra Kubernetes dağıtımları otomatik olarak başlar.
Komut çıkışı
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
Dağıtımdan sonra, her kapsayıcıda stdout'a gönderilen gerçek uygulama günlüklerini şu şekilde görürsünüz:
Komut çıkışı
[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
Bu noktada, sunucudan gelen tüm mesajları görmek istediğinizi unutmayın. Tamam, son olarak hizmetlerin dağıtılmış izlenmesi için uygulamanızı OpenTelemetry ile izlemeye başlamaya hazırsınız.
Hizmeti izlemeye başlamadan önce lütfen Ctrl-C ile kümenizi kapatın.
Komut çıkışı
...
[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
Özet
Bu adımda, ortamınızdaki codelab materyalini hazırladınız ve skaffold'un beklendiği gibi çalıştığını onayladınız.
Sıradaki
Bir sonraki adımda, izleme bilgilerini ölçmek için loadgen hizmetinin kaynak kodunu değiştireceksiniz.
4. HTTP için araçlar
İzleme enstrümantasyonu ve yayılımı kavramı
Kaynak kodunu düzenlemeden önce, dağıtılmış izlerin nasıl çalıştığını basit bir şemayla kısaca açıklayayım.

Bu örnekte, izleme ve kapsam bilgilerini Cloud Trace'e aktarmak ve yük oluşturma hizmetinden sunucu hizmetine yapılan istekte izleme bağlamını yaymak için kodu izleme araçlarıyla donatıyoruz.
Cloud Trace'in aynı iz kimliğine sahip tüm aralıkları tek bir izde birleştirebilmesi için uygulamaların İz Kimliği ve Aralık Kimliği gibi Trace meta verilerini göndermesi gerekir. Ayrıca, uygulamanın iz bağlamlarını (üst aralığın iz kimliği ve aralık kimliğinin kombinasyonu) aşağı akış hizmetlerine istek gönderirken yayması gerekir. Böylece, hangi iz bağlamını işlediğinin farkında olabilir.
OpenTelemetry ile yapabilecekleriniz:
- Benzersiz izleme kimliği ve kapsam kimliği oluşturmak için
- İzleme kimliğini ve kapsam kimliğini arka uca aktarmak için
- İzleme bağlamlarını diğer hizmetlere yaymak için
- izlerin analiz edilmesine yardımcı olan ek meta verileri yerleştirmek için
OpenTelemetry İzlemesindeki Bileşenler

OpenTelemetry ile uygulama izi enstrümantasyonu işlemi aşağıdaki gibidir:
- Dışa aktarıcı oluşturma
- Dışa aktarıcıyı 1'de bağlayan bir TracerProvider oluşturun ve bunu genel olarak ayarlayın.
- Yayma yöntemini ayarlamak için TextMapPropagaror'u ayarlayın.
- TracerProvider'dan Tracer'ı alma
- İzleyiciden Span oluşturma
Şu an için her bileşendeki ayrıntılı özellikleri anlamanız gerekmez. Ancak hatırlamanız gereken en önemli noktalar şunlardır:
- Buradaki dışa aktarma aracı, TracerProvider'a bağlanabilir.
- TracerProvider, izleme örnekleme ve dışa aktarma ile ilgili tüm yapılandırmaları içerir.
- Tüm izler Tracer nesnesinde paketlenir.
Bu bilgileri edindikten sonra kodlama işlemine geçebiliriz.
Instrument first span
Yük oluşturucu hizmeti
Cloud Shell'in sağ üst kısmındaki
düğmesine basarak Cloud Shell Düzenleyici'yi açın. Soldaki bölmede bulunan Gezgin'den step0/src/loadgen/main.go simgesini açın ve ana işlevi bulun.
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++
}
}
Ana işlevde, döngünün run işlevini çağırdığını görürsünüz. Mevcut uygulamada, işlev çağrısının başlangıcını ve bitişini kaydeden 2 günlük satırı bulunur. Şimdi işlev çağrısının gecikmesini izlemek için Span bilgilerini ölçelim.
Öncelikle, önceki bölümde belirtildiği gibi OpenTelemetry'nin tüm yapılandırmalarını ayarlayalım. OpenTelemetry paketlerini aşağıdaki gibi ekleyin:
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
)
Okunabilirliği artırmak için initTracer adlı bir kurulum işlevi oluşturup main işlevinde çağırırız.
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
}
OpenTelemetry'yi ayarlama prosedürünün önceki bölümde açıklandığı gibi olduğunu fark edebilirsiniz. Bu uygulamada, tüm izleme bilgilerini yapılandırılmış bir biçimde stdout'a aktaran bir stdout dışa aktarıcı kullanıyoruz.
Ardından, ana işlevden bu işlevi çağırırsınız. initTracer() numaralı telefonu arayın ve uygulamayı kapattığınızda TracerProvider.Shutdown() numaralı telefonu aradığınızdan emin olun.
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)
...
Kurulumu tamamladıktan sonra benzersiz bir izleme kimliği ve aralık kimliği içeren bir aralık oluşturmanız gerekir. OpenTelemetry bu amaçla kullanışlı bir kitaplık sunar. HTTP istemcisine yeni paketler ekleyin.
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"
)
Yük oluşturucu, runQuery işlevinde net/http ile HTTP'de istemci hizmetini çağırdığından net/http için contrib paketini kullanırız ve httptrace ile otelhttp paketinin uzantısıyla enstrümantasyonu etkinleştiririz.
Öncelikle, HTTP isteklerini izlenen istemci üzerinden çağırmak için bir paket genel değişkeni olan httpClient'ı ekleyin.
step0/src/loadgen/main.go
var httpClient = http.Client{
Transport: otelhttp.NewTransport(http.DefaultTransport)
}
Ardından, OpenTelemetry'yi ve özel HTTP istemcisinden otomatik olarak oluşturulan aralığı kullanarak özel aralık oluşturmak için runQuery işlevine enstrümantasyon ekleyin. Yapacaklarınız:
otel.Tracer()ile dünyanın dört bir yanındakiTracerProvidercihazlardan İz AlmaTracer.Start()yöntemiyle kök kapsam oluşturma- Kök kapsamı rastgele bir zamanda sonlandırın (bu örnekte
runQueryişlevinin sonu)
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)
}
Artık yük oluşturma aracında (HTTP istemci uygulaması) enstrümantasyon işlemini tamamladınız. Lütfen go.mod ve go.sum dosyalarınızı go mod komutuyla güncellediğinizden emin olun.
go mod tidy
Enstrüman müşteri hizmetleri
Önceki bölümde, aşağıdaki çizimde kırmızı dikdörtgen içine alınmış kısmı izledik. Yük oluşturucu hizmetinde span bilgilerini enstrümante ettik. Yük oluşturucu hizmetine benzer şekilde, şimdi de istemci hizmetini izlememiz gerekiyor. Yük oluşturucu hizmetinden farklı olarak, istemci hizmetinin HTTP başlığında yük oluşturucu hizmetinden yayılan İzleme Kimliği bilgilerini ayıklaması ve bu kimliği kullanarak aralıklar oluşturması gerekir.

Cloud Shell Düzenleyici'yi açın ve yük oluşturucu hizmetinde yaptığımız gibi gerekli paketleri ekleyin.
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
)
OpenTelemetry'yi tekrar kurmamız gerekiyor. loadgen'deki initTracer işlevini kopyalayıp yapıştırmanız ve istemci hizmetinin main işlevinde de çağırmanız yeterlidir.
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
}
Şimdi kapsamları izleme zamanı. Çünkü istemci hizmetinin, yük oluşturma hizmetinden gelen HTTP isteklerini kabul etmesi için işleyiciyi izlemesi gerekir. İstemci hizmetindeki HTTP sunucusu net/http ile uygulanır ve loadgen'de yaptığımız gibi otelhttp paketini kullanabilirsiniz.
İlk olarak, işleyici kaydını otelhttp işleyicisiyle değiştiririz. main işlevinde, HTTP işleyicinin http.HandleFunc() ile kaydedildiği satırları bulun.
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)
Ardından, işleyicinin içindeki gerçek aralığı ölçeriz. func (*clientService) handler() işleyicisini bulun ve trace.SpanFromContext() ile aralık enstrümantasyonu ekleyin.
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
...
Bu enstrümantasyon ile handler yönteminin başlangıcından sonuna kadar olan aralıkları elde edersiniz. Kapsamların analizini kolaylaştırmak için sorguya eşleşen sayıyı depolayan ek bir özellik ekleyin. Günlük satırının hemen öncesine aşağıdaki kodu ekleyin.
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))
...
Yukarıdaki tüm enstrümantasyonlarla, yük oluşturucu ve istemci arasındaki izleme enstrümantasyonunu tamamladınız. İşleyiş şeklini inceleyelim. Kodu tekrar Skaffold ile çalıştırın.
skaffold dev
GKE kümesinde hizmetler bir süre çalıştırıldıktan sonra aşağıdaki gibi çok sayıda günlük mesajı görürsünüz:
Komut çıkışı
[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"
...
Bu iletiler stdout dışa aktarıcı tarafından verilir. Yük oluşturma aracı tarafından oluşturulan tüm aralıkların üst öğelerinin TraceID: 00000000000000000000000000000000 olduğunu görürsünüz. Bunun nedeni, bu aralığın kök aralık (izdeki ilk aralık) olmasıdır. Ayrıca, yerleştirme özelliğinin "query" müşteri hizmetlerine iletilen sorgu dizesine sahip olduğunu da görürsünüz.
Özet
Bu adımda, HTTP üzerinden iletişim kuran yük oluşturucu hizmetini ve istemci hizmetini enstrümante ettiniz. Ayrıca, izleme bağlamını hizmetler arasında başarıyla yayabildiğinizi ve her iki hizmetten de stdout'a aralık bilgilerini dışa aktarabildiğinizi doğruladınız.
Sıradaki
Bir sonraki adımda, İzleme Bağlamı'nın gRPC üzerinden nasıl yayılacağını onaylamak için istemci hizmetini ve sunucu hizmetini izleme araçlarıyla donatacaksınız.
5. gRPC için enstrümantasyon
Önceki adımda, bu mikro hizmetlerdeki isteğin ilk yarısını izledik. Bu adımda, istemci hizmeti ile sunucu hizmeti arasındaki gRPC iletişimini izlemeye çalışırız. (Aşağıdaki resimde yeşil ve mor dikdörtgen)

gRPC istemcisi için önceden oluşturulmuş enstrümantasyon
OpenTelemetry'nin ekosistemi, geliştiricilerin uygulamaları izlemesine yardımcı olan birçok kullanışlı kitaplık sunar. Önceki adımda, net/http paketi için önceden oluşturulmuş enstrümantasyon kullandık. Bu adımda, izleme bağlamını gRPC üzerinden yaymaya çalıştığımız için kitaplığı kullanıyoruz.
Öncelikle otelgrpc adlı önceden oluşturulmuş gRPC paketini içe aktarırsınız.
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"
)
Bu kez istemci hizmeti, sunucu hizmetine karşı bir gRPC istemcisi olduğundan gRPC istemcisini izlemeniz gerekir. mustConnGRPC işlevini bulun ve istemci sunucuya her istekte bulunduğunda yeni aralıklar oluşturan gRPC araya giren işlevlerini ekleyin.
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))
}
}
Önceki bölümde OpenTelemetry'yi zaten ayarladığınız için bu adımı uygulamanız gerekmez.
gRPC sunucusu için önceden oluşturulmuş enstrümantasyon
gRPC istemcisi için yaptığımız gibi, gRPC sunucusu için önceden oluşturulmuş enstrümantasyonu çağırıyoruz. İçe aktarma bölümüne aşağıdaki gibi yeni bir paket ekleyin:
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"
)
Sunucuya ilk kez araç eklediğiniz için önce OpenTelemetry'yi kurmanız gerekir. Bu işlem, loadgen ve istemci hizmetlerinde yaptığımıza benzer.
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
...
Ardından, sunucu araya girenlerini eklemeniz gerekir. main işlevinde, grpc.NewServer() öğesinin çağrıldığı yeri bulun ve işleve araya giren işlevler ekleyin.
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)
...
Mikro hizmeti çalıştırın ve izlemeyi onaylayın
Ardından, değiştirilen kodunuzu skaffold komutuyla çalıştırın.
skaffold dev
Şimdi tekrar stdout'ta bir dizi span bilgisi görüyorsunuz.
Komut çıkışı
...
[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] }
...
Hiçbir kapsam adı yerleştirmediğinizi ve trace.Start() veya span.SpanFromContext() ile kapsamları manuel olarak oluşturduğunuzu fark ediyorsunuz. Bununla birlikte, gRPC araya girenleri bunları oluşturduğu için çok sayıda kapsam elde edersiniz.
Özet
Bu adımda, OpenTelemetry ekosistem kitaplıklarının desteğiyle gRPC tabanlı iletişimi izlediniz.
Sıradaki
Sonraki adımda, izi Cloud Trace ile görselleştirecek ve toplanan aralıkları nasıl analiz edeceğinizi öğreneceksiniz.
6. Cloud Trace ile izlemeyi görselleştirme
OpenTelemetry ile tüm sistemdeki izleri enstrümante etmiş olmanız gerekir. Şu ana kadar HTTP ve gRPC hizmetlerini nasıl izleyeceğinizi öğrendiniz. Bu metrikleri nasıl kullanacağınızı öğrenmiş olsanız da nasıl analiz edeceğinizi henüz öğrenmediniz. Bu bölümde, stdout dışa aktarıcılarını Cloud Trace dışa aktarıcılarıyla değiştirecek ve izlerinizi nasıl analiz edeceğinizi öğreneceksiniz.
Cloud Trace dışa aktarıcısını kullanma
OpenTelemetry'nin güçlü özelliklerinden biri, eklenebilir olmasıdır. Enstrümantasyonunuz tarafından toplanan tüm aralıkları görselleştirmek için yapmanız gereken tek şey stdout dışa aktarıcısını Cloud Trace dışa aktarıcısıyla değiştirmektir.
Her hizmetin main.go dosyalarını açın ve initTracer() işlevini bulun. stdout dışa aktarıcı oluşturmak için satırı silin ve bunun yerine Cloud Trace dışa aktarıcı oluşturun.
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
}
Aynı işlevi istemci ve sunucu hizmetinde de düzenlemeniz gerekir.
Mikro hizmeti çalıştırın ve izlemeyi onaylayın
Düzenlemeden sonra kümeyi her zamanki gibi skaffold komutuyla çalıştırın.
skaffold dev
Dışa aktarıcıyı Cloud Trace ile değiştirdiğiniz için artık stdout'ta yapılandırılmış günlükler biçiminde çok fazla aralık bilgisi görmüyorsunuz.
Komut çıkışı
[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
...
Şimdi tüm kapsamların Cloud Trace'e doğru şekilde gönderilip gönderilmediğini doğrulayalım. Cloud Console'a erişin ve "İzleme listesi"ne gidin. Arama kutusundan kolayca erişilebilir. Aksi takdirde, sol bölmedeki menüyü tıklayabilirsiniz. 
Ardından, gecikme grafiğinde çok sayıda mavi nokta dağıtıldığını görürsünüz. Her nokta tek bir izi temsil eder.

Bunlardan birini tıkladığınızda izleme içindeki ayrıntıları görebilirsiniz. 
Bu basit ve hızlı bakıştan bile birçok analiz elde edebilirsiniz. Örneğin, şelale grafiğinden gecikmenin nedeninin çoğunlukla shakesapp.ShakespeareService/GetMatchCount adlı aralık olduğunu görebilirsiniz. (Yukarıdaki resimde 1 numaralı bölüm) Bunu özet tablosundan doğrulayabilirsiniz. (En sağdaki sütunda her aralığın süresi gösterilir.) Ayrıca bu izleme, "arkadaş" sorgusu için yapıldı. (Yukarıdaki resimde 2 numaralı öğeye bakın)
Bu kısa analizler sayesinde, GetMatchCount yönteminde daha ayrıntılı aralıklar bilmeniz gerektiğini fark edebilirsiniz. Görselleştirme, stdout bilgilerine kıyasla daha güçlüdür. Cloud Trace ayrıntıları hakkında daha fazla bilgi edinmek için lütfen resmi belgelerimizi ziyaret edin.
Özet
Bu adımda, stdout dışa aktarıcısını Cloud Trace ile değiştirdiniz ve izleri Cloud Trace'te görselleştirdiniz. Ayrıca izleri analiz etmeye nasıl başlayacağınızı da öğrendiniz.
Sıradaki
Sonraki adımda, GetMatchCount'a bir alt aralık eklemek için sunucu hizmetinin kaynak kodunu değiştireceksiniz.
7. Daha iyi analiz için alt aralık ekleme
Önceki adımda, loadgen'den gözlemlenen gidiş dönüş süresinin nedeninin büyük ölçüde sunucu hizmetindeki GetMatchCount yönteminin içindeki işlem, yani gRPC işleyicisi olduğu belirlendi. Ancak işleyici dışında hiçbir şeyi ölçmediğimiz için şelale grafiğinden daha fazla bilgi edinemiyoruz. Bu, mikro hizmetleri izlemeye başladığımızda sıkça karşılaştığımız bir durumdur.

Bu bölümde, sunucunun Google Cloud Storage'i çağırdığı bir alt aralığı izleyeceğiz. Çünkü süreçte bazı harici ağ G/Ç'lerinin uzun sürmesi yaygın bir durumdur ve çağrının buna neden olup olmadığını belirlemek önemlidir.
Sunucuda bir alt aralık oluşturma
Sunucuda main.go simgesini açın ve readFiles işlevini bulun. Bu işlev, Shakespeare'in eserlerinin tüm metin dosyalarını getirmek için Google Cloud Storage'a istek gönderiyor. Bu işlevde, istemci hizmetinde HTTP sunucusu enstrümantasyonu için yaptığınız gibi bir alt aralık oluşturabilirsiniz.
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
...
Yeni bir aralık ekleme işlemi bu kadar. Uygulamayı çalıştırarak nasıl gittiğine bakalım.
Mikro hizmeti çalıştırın ve izlemeyi onaylayın
Düzenlemeden sonra kümeyi her zamanki gibi skaffold komutuyla çalıştırın.
skaffold dev
İz listesinden query.request adlı bir iz seçin. shakesapp.ShakespeareService/GetMatchCount altında yeni bir aralık dışında benzer bir izleme şelalesi grafiği görürsünüz. (Aşağıdaki kırmızı dikdörtgenle çevrili aralık)

Bu grafikten şu anda Google Cloud Storage'e yapılan harici çağrının büyük bir gecikmeye neden olduğu ancak gecikmenin büyük kısmının başka işlemlerden kaynaklandığı anlaşılıyor.
İzleme şelale grafiğine birkaç kez bakarak bile birçok analiz elde edebilirsiniz. Uygulamanızdaki diğer performans ayrıntılarını nasıl elde ediyorsunuz? Burada profiler devreye girer ancak şimdilik bu codelab'i sonlandıralım ve tüm profiler eğitimlerini 2. bölüme bırakalım.
Özet
Bu adımda, sunucu hizmetinde başka bir aralık oluşturup sistem gecikmesiyle ilgili daha fazla bilgi edindiniz.
8. Tebrikler
OpenTelemetry ile dağıtılmış izlemeler oluşturmayı başardınız ve Google Cloud Trace'te mikro hizmet genelindeki istek gecikmelerini onayladınız.
Daha kapsamlı alıştırmalar için aşağıdaki konuları kendi başınıza deneyebilirsiniz.
- Mevcut uygulama, durum denetimi tarafından oluşturulan tüm kapsamları gönderir. (
grpc.health.v1.Health/Check) Bu aralıkları Cloud Trace'lerden nasıl filtreleyebilirsiniz? İpucunu burada bulabilirsiniz. - Etkinlik günlüklerini aralıklarla ilişkilendirin ve Google Cloud Trace ile Google Cloud Logging'de nasıl çalıştığını görün. İpucunu burada bulabilirsiniz.
- Bir hizmeti başka dildeki bir hizmetle değiştirin ve bu dili kullanarak OpenTelemetry ile izlemeye çalışın.
Ayrıca, bu işlemden sonra profiler hakkında bilgi edinmek isterseniz lütfen 2. bölüme geçin. Bu durumda aşağıdaki temizleme bölümünü atlayabilirsiniz.
Temizleme
Bu codelab'den sonra lütfen Kubernetes kümesini durdurun ve Google Kubernetes Engine, Google Cloud Trace, Google Artifact Registry'de beklenmedik ücretler almamak için projeyi sildiğinizden emin olun.
Öncelikle kümeyi silin. Küme skaffold dev ile çalışıyorsa Ctrl-C tuşlarına basmanız yeterlidir. Kümeyi skaffold run ile çalıştırıyorsanız aşağıdaki komutu çalıştırın:
skaffold delete
Komut çıkışı
Cleaning up... - deployment.apps "clientservice" deleted - service "clientservice" deleted - deployment.apps "loadgen" deleted - deployment.apps "serverservice" deleted - service "serverservice" deleted
Küme silindikten sonra menü bölmesinde "IAM ve Yönetici" > "Ayarlar"ı seçin ve ardından "KAPAT" düğmesini tıklayın.

Ardından, iletişim kutusundaki forma proje kimliğini (proje adını değil) girin ve kapatma işlemini onaylayın.