使用 OpenTelemetry 檢測追蹤記錄資訊

1. 簡介

5af4a7e43b0feaab.png

上次更新時間:2021 年 3 月 5 日

應用程式的觀測能力

觀測能力與 OpenTelemetry

「觀測能力」是指用來描述系統屬性的字詞。具備觀測能力的系統可讓團隊主動偵錯。在這些情境下,觀測能力的三大要素;記錄、指標和追蹤記錄是系統取得觀測能力的基本檢測標準。

OpenTelemetry 是一組規格和 SDK,可加速檢測並匯出觀測能力所需的遙測資料 (記錄、指標和追蹤記錄)。OpenTelemetry 是根據 CNCF 編製的開放式標準和社群導向的專案。只要使用專案及其生態系統提供的程式庫,開發人員就能以不受供應商的方式,使用多個架構檢測應用程式。

分散式追蹤記錄

追蹤記錄是記錄檔、指標和追蹤記錄中的遙測資料,可指出系統中特定部分程序的延遲時間。分散式追蹤記錄 (特別是在微服務的時代) 是強大的驅動力,能找出整體分散式系統的延遲瓶頸。

分析分散式追蹤記錄時,可透過追蹤記錄的資料視覺化功能快速掌握整體系統延遲時間。在分散式追蹤記錄中,我們會處理一組呼叫,以含有多個 Spans 的 Trace 形式處理對系統進入點的單一要求。

「Span 」代表在分散式系統中完成的個別工作單元,記錄開始和停止時間。Span 通常彼此之間具有階層關係,在下圖中,所有較小的跨距都是大型 /訊息跨距的子時距,會組合成一個追蹤記錄,顯示透過系統執行工作的路徑。

adbd3ecd69d410cb.png

Google Cloud Trace 是分散式追蹤記錄後端的其中一種方案,這項服務與其他 Google Cloud 產品完美整合。

建構項目

在本程式碼研究室中,您要在名為「Shakesapp」的服務中檢測追蹤記錄資訊與 Kubernetes 叢集內運作的 Kubernetes 叢集內Shakesapp 的架構如下:

68873c018a7be7de.png

  • 用戶端將查詢字串傳送至伺服器
  • 伺服器接受從用戶端查詢、從 Google Cloud Storage 擷取所有 Shakespare 都能以文字格式運作、搜尋包含查詢的行,並傳回與用戶端相符的該行數。

您將檢測所有要求的追蹤資訊。

課程內容

  • 如何在 Python 專案中開始使用 OpenTelemetry Trace 程式庫
  • 如何使用程式庫建立 Span
  • 如何在應用程式元件之間的線路傳播 Span 內容
  • 如何將追蹤記錄資料傳送至 Google Cloud Trace
  • 如何在 Google Cloud Trace 中分析追蹤記錄

本程式碼研究室說明如何檢測微服務。為方便您理解,這個範例僅包含 3 個元件 (載入產生器、用戶端和伺服器),但您可以將本程式碼研究室所述的相同程序套用至更複雜和較大的系統。

軟硬體需求

  • 對 Python 3 的瞭解

2. 設定和需求

自修環境設定

如果您還沒有 Google 帳戶 (Gmail 或 Google Apps),請先建立帳戶。登入 Google Cloud Platform 控制台 ( console.cloud.google.com),並建立新專案。

如果您已有專案,請按一下控制台左上方的專案選取下拉式選單:

15b8b6ac4d917005.png

並點選 [新增專案]按鈕,用於建立新專案:

7136b3ee36ebaf89.png

如果您還沒有專案,系統會顯示如下的對話方塊,讓您建立第一個專案:

90977ce514204b51.png

後續的專案建立對話方塊可讓您輸入新專案的詳細資料:

6d9573e346e930b4.png

請記住,專案 ID 在所有的 Google Cloud 專案中是不重複的名稱 (已經有人使用上述名稱,目前無法為您解決問題!)。稍後在本程式碼研究室中會稱為 PROJECT_ID。

接下來,如果您尚未在 Developers Console 中啟用計費功能,您需要先在 Developers Console 中啟用計費功能,才能使用 Google Cloud 資源並啟用 Cloud Trace API

eb5325f65619ad6a.png

執行本程式碼研究室所需的費用不應超過數美元,但如果您決定使用更多資源,或讓這些資源繼續運作,費用會增加 (請參閱本文件結尾的「清理」一節)。如需 Google Cloud Trace、Google Kubernetes Engine 和 Google Artifacat Registry 的定價資訊,請參閱官方說明文件。

Google Cloud Platform 的新使用者符合 $300 美元的免費試用資格,應該可以免費使用本程式碼研究室。

Google Cloud Shell 設定

雖然 Google Cloud 和 Google Cloud Trace 可以在筆記型電腦上遠端運作,但在本程式碼研究室中,我們會使用 Google Cloud Shell,這是一種在 Cloud 中執行的指令列環境。

這種以 Debian 為基礎的虛擬機器,搭載各種您需要的開發工具。提供永久的 5 GB 主目錄,而且在 Google Cloud 中運作,大幅提高網路效能和驗證能力。換言之,本程式碼研究室只需要在 Chromebook 上運作即可。

如要透過 Cloud 控制台啟用 Cloud Shell,只要點選「啟用 Cloud Shell」圖示 gcLMt5IuEcJJNnMId-Bcz3sxCd0rZn7IzT_r95C8UZeqML68Y1efBG_B0VRp7hc7qiZTLAF-TXD7SsOadxn8uadgHhaLeASnVS3ZHK39eOlKJOgj9SJua_oeGhMxRrbOg3qigddS2A,即可佈建並連線至環境,操作只需幾分鐘的時間。

ff81d016724c4f67.png

fbe156ee6edfbb2e.png

連線至 Cloud Shell 後,您應會發現自己通過驗證,且專案已設為 PROJECT_ID

gcloud auth list

指令輸出

Credentialed accounts:
 - <myaccount>@<mydomain>.com (active)
gcloud config list project

指令輸出

[core]
project = <PROJECT_ID>

如因故未設定專案,請直接發出以下指令:

gcloud config set project <PROJECT_ID>

正在尋找 PROJECT_ID 嗎?查看您在設定步驟中使用的 ID,或在 Cloud 控制台資訊主頁查詢:

a3e716fc9e7454e9.png

根據預設,Cloud Shell 也會設定一些環境變數,方便您之後執行指令。

echo $GOOGLE_CLOUD_PROJECT

組合輸出內容

<PROJECT_ID>

最後,進行預設可用區和專案設定。

gcloud config set compute/zone us-central1-f

您可以選擇各種不同的可用區。詳情請參閱「區域與可用區

Python 設定

在本程式碼研究室中,我們使用「詩」更嚴密管理套件版本在 Cloud Shell 上執行下列指令:

curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3 -
source $HOME/.poetry/env

設定 Google Kubernetes 叢集

在本程式碼研究室中,您將在 Google Kubernetes Engine (GKE) 執行微服務叢集。本程式碼研究室的流程如下:

  1. 將基準專案下載至 Cloud Shell
  2. 將微服務建構至容器
  3. 將容器上傳至 Google Artifact Registry (GAR)
  4. 將容器部署至 GKE
  5. 修改追蹤記錄檢測服務的原始碼
  6. 前往步驟 2

啟用 Kubernetes Engine

首先,我們設定了一個 Kubernetes 叢集,讓 Shakesapp 在 GKE 上執行,因此必須啟用 GKE。前往「Kubernetes Engine」選單然後按下「啟用」按鈕

56c680e93e169731.png

您現在可以建立 Kubernetes 叢集了。

建立 Kubernetes 叢集

在 Cloud Shell 執行下列指令,建立 Kubernetes 叢集。請確認可用區值位於先前建立 Artifact Registry 存放區的區域。如果存放區區域未涵蓋可用區,請變更可用區值 us-central1-f

gcloud container clusters create otel-trace-codelab --zone us-central1-f \
--num-nodes 1 \
--machine-type e2-highcpu-4

指令輸出

Creating cluster otel-trace-codelab in us-central1-f... Cluster is being health-checked (master is healthy)...done.
Created [https://container.googleapis.com/v1/projects/psychic-order-307806/zones/us-central1-f/clusters/otel-trace-codelab].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-central1-f/otel-trace-codelab?project=psychic-order-307806
kubeconfig entry generated for otel-trace-codelab.
NAME                LOCATION       MASTER_VERSION    MASTER_IP        MACHINE_TYPE  NODE_VERSION      NUM_NODES  STATUS
otel-trace-codelab  us-central1-f  1.18.12-gke.1210  104.154.162.176  e2-medium     1.18.12-gke.1210  3          RUNNING

Artifact Registry 和 Skaffold 設定

現在,我們已準備好部署 Kubernetes 叢集,接下來,我們要針對推送和部署容器的 Container Registry 做好準備。進行這個步驟時,必須設定 GAR 和 Skaffold,

Artifact Registry 設定

前往「Artifact Registry」的選單然後按下「啟用」按鈕

f7493243bae0cdf7.png

一段時間後,您會看到 GAR 的存放區瀏覽器。按一下「建立存放區」按鈕,然後輸入存放區名稱

f97f337f5476651.png

在本程式碼研究室中,我會將新存放區命名為 trace-codelab。構件的格式為「Docker」且位置類型為「區域」選擇接近您為 Google Compute Engine 預設可用區設定的區域。以下範例選擇「us-central1-f」上方,我們選擇「us-central1 (愛荷華州)」接著按一下「建立」按鈕。

2f04143077ca56db.png

現在您會看到複製到存放區瀏覽器

7a3c1f47346bea15.png

稍後會再回來檢查登錄路徑。

Skaffold 設定

如要建構在 Kubernetes 上執行的微服務,Skaffold 是很實用的工具。這個外掛程式能使用少量指令,處理建構、推送及部署應用程式容器的工作流程。根據預設,Skaffold 會使用 Docker Registry 做為容器登錄檔,因此您需要設定 skaffold 來辨識 GAR,以將容器推送到容器。

再次開啟 Cloud Shell,並確認是否已安裝 skaffold。(Cloud Shell 預設會在環境中安裝 Skaffold。)執行下列指令並查看 Skaffold 版本。

skaffold version

指令輸出

v1.20.0

現在,您可以註冊使用 Skaffold 的預設存放區。如要取得登錄檔路徑,請前往 Artifact Registry 資訊主頁,然後按一下您在上一個步驟中設定的存放區名稱。

55173fe922f40327.png

您就會在頁面頂端看到導覽標記記錄。按一下 e157b1359c3edc06.png 圖示,將登錄路徑複製到剪貼簿。

a9b0fa44c37e0178.png

按一下「複製」按鈕後,您會在瀏覽器底部看到含有下列訊息的對話方塊:

&quot;us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab&quot;已複製

返回 Cloud Shell。使用剛剛從資訊主頁複製的值執行 skaffold config set default-repo 指令。

skaffold config set default-repo us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab

指令輸出

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

此外,您必須將登錄檔設為 Docker 設定。執行下列指令:

gcloud auth configure-docker us-central1-docker.pkg.dev --quiet

指令輸出

{
  "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

您現在可以前往下一個步驟,在 GKE 中設定 Kubernetes 容器。

摘要

在這個步驟中,您會設定程式碼研究室環境:

  • 設定 Cloud Shell
  • 已為 Container Registry 建立 Artifact Registy 存放區
  • 設定 skaffold 以使用 Container Registry
  • 建立用於執行程式碼研究室微服務的 Kubernetes 叢集

下一步

在下一個步驟中,您會建構微服務並將微服務推送至叢集

3. 建構、推送及部署微服務

下載程式碼研究室教材

在上一個步驟中,我們已設定本程式碼研究室的所有必備條件。您現在可以透過這些微服務執行整個微服務了。程式碼研究室的內容託管於 GitHub,請使用以下 Git 指令將這些內容下載至 Cloud Shell 環境。

cd ~
git clone https://github.com/GoogleCloudPlatform/opentelemetry-trace-codelab-python.git

專案的目錄結構如下:

shakesapp-python
├── LICENSE
├── manifests
│   ├── client.yaml
│   ├── loadgen.yaml
│   └── server.yaml
├── proto
│   └── shakesapp.proto
├── skaffold.yaml
└── src
    ├── client
    ├── loadgen
    └── server
  • 資訊清單:Kubernetes 資訊清單檔案
  • proto:用戶端和伺服器通訊的 Proto 定義
  • src: 每個章節的原始碼目錄
  • skaffold.yaml:skaffold 的設定檔

執行 skaffold 指令

最後,您可以開始建構完整內容,並將完整內容推送至剛剛建立的 Kubernetes 叢集。這聽起來有多個步驟,但其實 Skaffold 可以為您執行所有動作。請使用下列指令:

cd shakesapp-python
skaffold run --tail

執行指令後,您會看到 docker build 的記錄輸出,並且可以確認已成功推送至登錄檔。

指令輸出

...
---> 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

所有服務容器推送後,Kubernetes Deployment 會自動啟動。

指令輸出

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

注意:如果系統顯示「NoPush access to 指定的 image repository」這類錯誤訊息,請檢查無論 skaffold 中的預設存放區設定為何,Skaffold 指令是否正在嘗試將映像檔推送至 Docker Hub (docker.io)。在這種情況下,請嘗試新增「-default-repo」「Skaffold Run」選項如下所示。

$ skaffold 執行 –tail –default-repo=us-central1-docker.pkg.dev/[專案 ID]/[repository name]

部署完畢後,您會在每個容器中看到發送至 stdout 的實際應用程式記錄檔,如下所示:

指令輸出

[server] {"event": "starting server: 0.0.0.0:5050", "severity": "info", "timestamp": "2021-03-17T05:25:56.758575Z"}
[client] [2021-03-17 05:25:54 +0000] [1] [INFO] Starting gunicorn 20.0.4
[client] [2021-03-17 05:25:54 +0000] [1] [INFO] Listening at: http://0.0.0.0:8080 (1)
[client] [2021-03-17 05:25:54 +0000] [1] [INFO] Using worker: threads
[client] [2021-03-17 05:25:54 +0000] [7] [INFO] Booting worker with pid: 7
[client] {"event": "server address is serverservice:5050", "severity": "info", "timestamp": "2021-03-17T05:25:54.888627Z"}
[client] {"event": "request to server with query: world", "severity": "info", "timestamp": "2021-03-17T05:26:11.550923Z"}
[server] {"event": "query: world", "severity": "info", "timestamp": "2021-03-17T05:26:11.567048Z"}
[loadgen] {"event": "check connectivity: http://clientservice:8080/_healthz", "severity": "info", "timestamp": "2021-03-17T05:26:11.533605Z"}
[loadgen] {"event": "/_healthz response: ok", "severity": "info", "timestamp": "2021-03-17T05:26:11.544267Z"}
[loadgen] {"event": "confirmed connection ot clientservice", "severity": "info", "timestamp": "2021-03-17T05:26:11.544527Z"}

最後,您已準備好使用 OpenTelemetry 檢測應用程式,以對服務的分散式追蹤作業進行檢測。

摘要

在這個步驟中,您已準備好環境中的程式碼研究室教材,並確認 Skaffold 可以正常執行。

下一步

在下一個步驟中,您將修改 loadgen 服務的原始碼,以檢測追蹤記錄資訊。

4. HTTP 檢測

追蹤記錄檢測和傳播概念

在編輯原始碼之前,我們用簡單的圖表簡單說明分散式追蹤記錄的運作方式。

c8c659deaa9c9091.png

在本範例中,我們會檢測程式碼,將 Trace 和 Span 資訊匯出至 Cloud Trace,並將來自 Loadgen 服務的要求將追蹤記錄內容傳播至伺服器服務。

應用程式必須傳送追蹤記錄中繼資料 (例如追蹤記錄 ID 和時距 ID),Cloud Trace 才能將具有相同追蹤記錄 ID 的所有時距組合成單一追蹤記錄。此外,應用程式在要求下游服務時,需要傳播追蹤記錄內容 (父項時距的追蹤記錄 ID 和時距 ID 的組合),才能得知自己處理的是哪個追蹤記錄情境。

OpenTelemetry 可協助您:

  • 以便產生不重複的追蹤記錄 ID 和時距 ID
  • ,將追蹤記錄 ID 和時距 ID 匯出至後端
  • 將追蹤記錄背景資訊傳播至其他服務

檢測首距

檢測負載產生器服務

按下 Cloud Shell 右上角的 776a11bfb2122549.png 按鈕,開啟 Cloud Shell 編輯器。從左側窗格中的探索工具開啟 src/loadgen/loadgen.py,然後找出 main 函式。

src/loadgen/loadgen.py

def main():
    ...
    # start request loop to client service
    logger.info("start client request loop")
    addr = f"http://{target}"
    while True:
        logger.info("start request to client")
        call_client(addr)
        logger.info("end request to client")
        time.sleep(2.0)

main 函式中,您會看到呼叫函式 call_client 的迴圈。在目前的實作項目中,昆圖有 2 行記錄,記錄了函式呼叫的開始和結束。現在,我們可以檢測 Span 資訊,以追蹤函式呼叫的延遲時間。

首先,您需要使用不重複的追蹤記錄 ID 和時距 ID 建立 Span。OpenTelemetry 提供了實用的程式庫。加入下列幾行,將 OpenTelemetry 程式庫匯入至程式碼。

 import structlog
+from opentelemetry import propagate, trace
+from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
+from opentelemetry.sdk.trace import TracerProvider
+from opentelemetry.instrumentation.requests import RequestsInstrumentor
+from opentelemetry.sdk.trace.export import SimpleSpanProcessor
+from opentelemetry.propagators.cloud_trace_propagator import CloudTraceFormatPropagator

由於負載產生器是透過 requests 模組呼叫 HTTP 中的用戶端應用程式,因此我們會使用 requests 的擴充功能套件並啟用檢測功能。

 from opentelemetry.propagators.cloud_trace_propagator import CloudTraceFormatPropagator
+
+RequestsInstrumentor().instrument()

接著設定 Tracer 執行個體,以處理 Trace Contenxt 和匯出工具設定

     target = os.environ.get("CLIENT_ADDR", "0.0.0.0:8080")

+    exporter = CloudTraceSpanExporter()
+    trace.get_tracer_provider().add_span_processor(SimpleSpanProcessor(exporter))
+    tracer = trace.get_tracer(__name__)
+    propagate.set_global_textmap(CloudTraceFormatPropagator())
+    trace.set_tracer_provider(TracerProvider())
+
     # connectivity check to client service
     healthz = f"http://{target}/_healthz"
     logger.info(f"check connectivity: {healthz}")

請注意,由於這是用於瞭解追蹤檢測功能的程式碼研究室,因此我們將追蹤 Tracer 設定為記錄每項要求,並將要求傳送至後端。(SimpleSpanProcessor()) 不適用於實際工作環境,因此在檢測正式版應用程式時,請務必變更這個部分。

現在您可以使用 Tracer 檢測 Spans。您需要明確產生 Span,這樣就大功告成了!雖然有兩行會將事件中繼資料加入 Span,但您不需要手動產生專屬追蹤記錄 ID 和時距 ID,並將其嵌入 Span。

     logger.info("start client request loop")
     addr = f"http://{target}"
     while True:
-        logger.info("start request to client")
-        call_client(addr)
-        logger.info("end request to client")
+        with tracer.start_as_current_span("loadgen") as root_span:
+            root_span.add_event(name="request_start")
+            logger.info("start request to client")
+            call_client(addr)
+            root_span.add_event(name="request_end")
+            logger.info("end request to client")
         time.sleep(2.0)

為了讓 Docker 版本擷取所需的 OpenTelemetry 套件,請執行下列指令:

poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0"
poetry add "opentelemetry-propagator-gcp=^1.0.0rc0"
poetry add "opentelemetry-instrumentation-requests=^0.20b0"

您可以確認對應的依附元件說明是以 pyproject.toml 編寫。

檢測用戶端服務

在上一節中,我們在下方繪圖中檢測了紅色矩形包圍的部分。我們已在負載產生器服務中檢測時距資訊。與載入產生器服務類似,現在我們需要檢測用戶端服務。不同於負載產生器服務,用戶端需要從 HTTP 標頭中的載入產生器服務擷取追蹤 ID 資訊,並使用 ID 產生 Spans。

ae074d4513c9931f.png

開啟 Cloud Shell 編輯器,並新增必要模組,方法與負載產生器服務相同。

src/client/client.py

 import flask
 import grpc
 import structlog
+from opentelemetry import propagate, trace
+from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
+from opentelemetry.instrumentation.flask import FlaskInstrumentor
+from opentelemetry.sdk.trace import TracerProvider
+from opentelemetry.sdk.trace.export import SimpleSpanProcessor
+from opentelemetry.propagators.cloud_trace_propagator import \
+    CloudTraceFormatPropagator

 import shakesapp_pb2
 import shakesapp_pb2_grpc

您發現剛剛匯入的 FlaskInstrumentor 可為 Flask 應用程式啟用自動檢測功能,可代表使用者擷取 HTTP 標頭,透過單行程式碼取得 Trace Contexts。OpenTelemetry 社群提供了與其他主要程式庫類似的實用整合方式。如需更多資訊,請參閱官方說明文件

 app = flask.Flask(__name__)
+FlaskInstrumentor().instrument_app(app)

開始檢測前,您同樣必須準備 Tracer 執行個體,就像在負載產生器服務中執行一樣。

 logger.info(f"server address is {SERVER_ADDR}")

+exporter = CloudTraceSpanExporter()
+trace.get_tracer_provider().add_span_processor(SimpleSpanProcessor(exporter))
+propagate.set_global_textmap(CloudTraceFormatPropagator())
+trace.set_tracer_provider(TracerProvider())

 @app.route("/")
 def main_handler():
    ....

現在可以在處理常式中新增檢測作業。找出 main_handler(),並修改將 gRPC 要求擲回伺服器服務的部分。

@app.route("/")
def main_handler():
    q, count = random.choice(list(queries.items()))

    # get Tracer
    tracer = trace.get_tracer(__name__)

    with tracer.start_as_current_span("client") as cur_span:
        channel = grpc.insecure_channel(SERVER_ADDR)
        stub = shakesapp_pb2_grpc.ShakespeareServiceStub(channel)
        logger.info(f"request to server with query: {q}")
        cur_span.add_event("server_call_start")
        resp = stub.GetMatchCount(shakesapp_pb2.ShakespeareRequest(query=q))
        cur_span.add_event("server_call_end")
        if count != resp.match_count:
            raise UnexpectedResultError(
                f"The expected count for '{q}' was {count}, but result was {resp.match_count } obtained"
            )
        result = str(resp.match_count)
        logger.info(f"matched count for '{q}' is {result}")
    return result

與載入產生器服務類似,請使用下列指令將必要的套件新增至 pyproject.toml

poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0"
poetry add "opentelemetry-propagator-gcp=^1.0.0rc0"
poetry add "opentelemetry-instrumentation-flask=^0.20b0"

接著請嘗試透過 skaffold run 指令啟動應用程式,並查看 Cloud Trace 資訊主頁顯示的內容:

skaffold run --tail

查看一些建構、推送和部署訊息後,您將會看到 JSON 格式的應用程式記錄。前往 Cloud Trace >用於檢查您是否取得追蹤記錄資訊。由於載入產生器服務會定期向用戶端服務傳送要求,而您為所有要求啟用了追蹤記錄,因此您開始在追蹤記錄清單中看到許多圓點。

f7440360551980e.png

只要點選下方任一圖表,就能再看到類似下方的瀑布圖,說明在要求與回應程序中各部分的延遲時間。勾選「顯示事件」旁的核取方塊,即可查看刊登序列圖表中的註解。這些註解是您透過 span.add_event() 方法在程式碼中檢測的註解。

67596a4a313738.png

您可能注意到沒有看到伺服器服務中的時距,沒錯,因為我們尚未在伺服器服務中檢測 Spans,

摘要

在這個步驟中,您已檢測了負載產生器服務和用戶端服務,並確認自己可以成功在不同服務中傳播 Trace Context,並將這兩項服務的 Span 資訊匯出至 Cloud Trace。

下一步

在下一個步驟中,您將檢測用戶端服務和伺服器服務,以確認如何透過 gRPC 傳播 Trace Context。

5. gRPC 檢測

在前一個步驟中,我們已檢測了這項微服務中要求的前半部。在這個步驟中,我們會嘗試檢測用戶端服務和伺服器服務之間的 gRPC 通訊。(下圖中的綠色和紫色矩形)。

c4dec3e741c3ab4f.png

gRPC 用戶端的自動檢測

OpenTelemetry 的生態系統提供許多實用的程式庫,協助開發人員檢測應用程式。在上一個步驟中,我們針對「要求」使用自動檢測後續課程我們將逐一介紹 預先訓練的 API、AutoML 和自訂訓練在這個步驟中,由於我們嘗試透過 gRPC 傳播 Trace Context,因此會使用其程式庫。

src/client/client.py

 import flask
 import grpc
 import structlog
 from opentelemetry import propagate, trace
 from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
 from opentelemetry.instrumentation.flask import FlaskInstrumentor
+from opentelemetry.instrumentation.grpc import GrpcInstrumentorClient
 from opentelemetry.sdk.trace import TracerProvider
 from opentelemetry.sdk.trace.export import SimpleSpanProcessor
 from opentelemetry.propagators.cloud_trace_propagator import \
     CloudTraceFormatPropagator
 import shakesapp_pb2
 import shakesapp_pb2_grpc


 app = flask.Flask(__name__)
 FlaskInstrumentor().instrument_app(app)
+GrpcInstrumentorClient().instrument()

對客戶服務而言,我們需要的檢測工作小很多,我們要的目的是傳播 Trace Context,也就是透過 gRPC 導入目前 Span 的追蹤記錄 ID 和時距 ID 的組合。因此,我們呼叫 GrpcInstrumentatorClient.instrument(),讓 gRPC 用戶端能夠將追蹤 Context 嵌入至下方的 HTTP 標頭。

請務必使用 poetry add 指令在 pyproject.toml 中新增依附元件:

poetry add "opentelemetry-instrumentation-grpc=^0.20b0"

自動檢測 gRPC 伺服器

如同我們為 gRPC 用戶端的做法,我們稱之為 gRPC 伺服器的自動檢測。新增下列匯入項目,並在檔案頂端呼叫 GrpcInstrumentationServer().instrument()

注意:請務必於

GrpcInstrumentationServe() 

執行這個步驟

GrpcInstrumentationClient()

src/server/server.py

 import grpc
 import structlog
 from google.cloud import storage
 from grpc_health.v1 import health_pb2, health_pb2_grpc
+from opentelemetry import propagate, trace
+from opentelemetry.exporter.cloud_trace import CloudTraceSpanExporter
+from opentelemetry.instrumentation.grpc import GrpcInstrumentorServer
+from opentelemetry.sdk.trace import TracerProvider
+from opentelemetry.sdk.trace.export import SimpleSpanProcessor
+from opentelemetry.propagators.cloud_trace_propagator import CloudTraceFormatPropagator

 import shakesapp_pb2
 import shakesapp_pb2_grpc


 BUCKET_NAME = "dataflow-samples"
 BUCKET_PREFIX = "shakespeare/"

+# enable auto gRPC server trace instrumentation
+GrpcInstrumentorServer().instrument()
+

接下來,請新增匯出工具,將追蹤記錄資訊傳送至 Cloud Trace 後端。在 serve() 函式中加入下列程式碼。

def serve():
+    # start trace exporter
+    trace.set_tracer_provider(TracerProvider())
+    trace.get_tracer_provider().add_span_processor(
+        SimpleSpanProcessor(CloudTraceSpanExporter())
+    )
+    propagators.set_global_textmap(CloudTraceFormatPropagator())
+
+    # add gRPC services to server
     server = grpc.server(futures.ThreadPoolExecutor(max_workers=4))
     service = ShakesappService()
     shakesapp_pb2_grpc.add_ShakespeareServiceServicer_to_server(service, server)
     health_pb2_grpc.add_HealthServicer_to_server(service, server)

請務必在伺服器服務中新增新增的套件。

poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0"
poetry add "opentelemetry-instrumentation-grpc=^0.20b0"
poetry add "opentelemetry-propagator-gcp=^1.0.0rc0"
poetry add "opentelemetry-instrumentation=^0.20b0"

執行微服務並確認追蹤記錄

接著使用 skaffold 指令執行修改過的程式碼。

skaffold run --tail

您現在同樣會在 Cloud Trace 的 Trace 清單頁面中看到大量追蹤記錄。按一下其中一個追蹤記錄,您現在就會發現從載入產生器服務到伺服器服務的要求橫跨多個時段。

141cb620245b689d.png

摘要

在這個步驟中,您已完成與 OpenTelemetry 生態系統程式庫的支援,以檢測以 gRPC 為基礎的通訊。此外,您也確認在載入產生器服務中產生的追蹤記錄內容已成功傳送至伺服器服務。

6. 恭喜

您已成功透過 OpenTelemery 建立分散式追蹤記錄,並確認 Google Cloud Trace 上微服務的要求延遲時間。

對於延長的運動,您可以自行嘗試下列主題。

  • 目前的實作項目會傳送健康狀態檢查產生的所有時距。如何從 Cloud Trace 中篩除這些時距?提示請參閱這裡
  • 將事件記錄與時距建立關聯,並觀察記錄在 Google Cloud Trace 和 Google Cloud Logging 中的運作方式。提示請參閱這裡
  • 請將某些服務替換為其他語言,然後嘗試使用該語言的 OpenTelemetry 檢測服務

注意:Google Kubernetes Engine 和 Google Artifact Registry 會持續耗用資源。

清理

在這個程式碼研究室中,請停止 Kubernetes 叢集並確實刪除專案,以免在 Google Kubernetes Engine、Google Cloud Trace 和 Google Artifact Registry 中產生非預期的費用。

首先,使用下列指令刪除叢集:

skaffold delete

指令輸出

Cleaning up...
 - deployment.apps "clientservice" deleted
 - service "clientservice" deleted
 - deployment.apps "loadgen" deleted
 - deployment.apps "serverservice" deleted
 - service "serverservice" deleted

刪除叢集後,請從選單窗格中選取「IAM 與管理員」&gt;,然後按一下「SHUT DOWN」按鈕。

578ca2b72a161e9d.png

然後在對話方塊中的表單中輸入專案 ID (而非專案名稱),並確認關閉。