1. Introduzione
Ultimo aggiornamento: 2021-03-05
Osservabilità dell'applicazione
Osservabilità e OpenTelemetry
Osservabilità è il termine utilizzato per descrivere un attributo di un sistema. Un sistema con osservabilità consente ai team di eseguire attivamente il debug del proprio sistema. In questo contesto, esistono tre pilastri dell'osservabilità: log, metriche e tracce sono la strumentazione fondamentale che il sistema utilizza per acquisire l'osservabilità.
OpenTelemetry è un insieme di specifiche e SDK che accelera la strumentazione e l'esportazione dei dati di telemetria (log, metriche e tracce) richiesti dall'osservabilità. OpenTelemetry è uno standard aperto e un progetto guidato dalla community all'interno del CNCF. Utilizzando le librerie fornite dal progetto e dal suo ecosistema, gli sviluppatori sono in grado di instrumentare le loro applicazioni in modo indipendente dal fornitore e su più architetture.
Traccia distribuita
Tra log, metriche e tracce, la traccia è la telemetria che indica la latenza di una parte specifica del processo nel sistema. In particolare nell'era dei microservizi, le tracce distribuite sono il fattore chiave per individuare i colli di bottiglia della latenza nell'intero sistema distribuito.
Quando si analizzano le tracce distribuite, la visualizzazione dei dati di traccia è fondamentale per comprendere a colpo d'occhio le latenze complessive del sistema. Nella traccia distribuita, gestiamo un insieme di chiamate per elaborare una singola richiesta al punto di ingresso del sistema sotto forma di traccia contenente più intervalli.
L'intervallo rappresenta una singola unità di lavoro svolto in un sistema distribuito, che registra i tempi di inizio e di fine. Gli intervalli hanno spesso relazioni gerarchiche tra loro. Nella figura seguente, tutti gli intervalli più piccoli sono intervalli figlio di un grande intervallo /messages e sono assemblati in un'unica traccia che mostra il percorso di lavoro attraverso un sistema.
Google Cloud Trace è una delle opzioni per il backend di traccia distribuita ed è ben integrato con altri prodotti di Google Cloud.
Cosa creerai
In questo codelab, accederai alle informazioni di traccia dello strumento nei servizi chiamati "Shakesapp" in esecuzione su un cluster Kubernetes in esecuzione su Google Kubernetes Engine. L'architettura di Shakesapp è descritta di seguito:
- I client inviano una stringa di query al server
- Il server accetta la query dal client, recupera tutte le opere di Shakespare in formato testo da Google Cloud Storage, cerca le righe che contengono la query e restituisce il numero della riga corrispondente al client.
Potrai instrumentare le informazioni di traccia nella richiesta.
Cosa imparerai a fare
- Come iniziare a utilizzare le librerie di Trace OpenTelemetry nel progetto Python
- Come creare un intervallo con la libreria
- Come propagare i contesti di intervallo lungo il cavo tra i componenti dell'app
- Come inviare dati di traccia a Google Cloud Trace
- Come analizzare la traccia su Google Cloud Trace
Questo codelab spiega come instrumentare i tuoi microservizi. Per essere più comprensibile, questo esempio contiene solo tre componenti (generatore di carico, client e server), ma puoi applicare la stessa procedura spiegata in questo codelab a sistemi più complessi e di grandi dimensioni.
Che cosa ti serve
- Conoscenza di Python 3
2. Configurazione e requisiti
Configurazione dell'ambiente da seguire in modo autonomo
Se non disponi già di un account Google (Gmail o Google Apps), devi crearne uno. Accedi alla console della piattaforma Google Cloud ( console.cloud.google.com) e crea un nuovo progetto.
Se hai già un progetto, fai clic sul menu a discesa per la selezione del progetto in alto a sinistra nella console:
e fai clic su "NUOVO PROGETTO" nella finestra di dialogo risultante per creare un nuovo progetto:
Se non hai ancora un progetto, dovresti visualizzare una finestra di dialogo come questa per crearne uno:
La finestra di dialogo di creazione del progetto successiva ti consente di inserire i dettagli del nuovo progetto:
Ricorda l'ID progetto, che è un nome univoco tra tutti i progetti Google Cloud (il nome precedente è già in uso e non funzionerà per te). Verrà indicato più avanti in questo codelab come PROJECT_ID.
Successivamente, se non l'hai ancora fatto, dovrai abilitare la fatturazione in Developers Console per utilizzare le risorse Google Cloud e abilitare l'API Cloud Trace.
L'esecuzione di questo codelab non dovrebbe costare più di qualche euro, ma potrebbe essere più costoso se decidi di utilizzare più risorse o se le lasci in esecuzione (consulta la sezione relativa alla pulizia alla fine di questo documento). I prezzi di Google Cloud Trace, Google Kubernetes Engine e Google Artifacat Registry sono riportati nella documentazione ufficiale.
- Prezzi per Google Cloud Observability
- Prezzi | Documentazione di Kubernetes Engine
- Prezzi di Artifact Registry | documentazione di Artifact Registry
I nuovi utenti della piattaforma Google Cloud hanno diritto a una prova senza costi di 300$, che dovrebbe rendere questo codelab completamente senza costi.
Configurazione di Google Cloud Shell
Mentre Google Cloud e Google Cloud Trace possono essere gestiti da remoto dal tuo laptop, in questo codelab utilizzeremo Google Cloud Shell, un ambiente a riga di comando in esecuzione nel cloud.
Questa macchina virtuale basata su Debian viene caricata con tutti gli strumenti di sviluppo necessari. Offre una home directory permanente da 5 GB e viene eseguita in Google Cloud, migliorando notevolmente le prestazioni di rete e l'autenticazione. Ciò significa che per questo codelab è sufficiente un browser (sì, funziona su Chromebook).
Per attivare Cloud Shell dalla console Cloud, fai clic su Attiva Cloud Shell (il provisioning e la connessione all'ambiente dovrebbero richiedere solo pochi minuti).
Dopo la connessione a Cloud Shell, dovresti vedere che hai già eseguito l'autenticazione e che il progetto è già impostato su PROJECT_ID
.
gcloud auth list
Output comando
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
Output comando
[core] project = <PROJECT_ID>
Se, per qualche motivo, il progetto non è impostato, invia semplicemente il seguente comando:
gcloud config set project <PROJECT_ID>
Stai cercando il tuo PROJECT_ID
? Controlla l'ID utilizzato nei passaggi di configurazione o cercalo nella dashboard della console Cloud:
Cloud Shell imposta anche alcune variabili di ambiente per impostazione predefinita, cosa che può essere utile quando eseguirai comandi futuri.
echo $GOOGLE_CLOUD_PROJECT
Output Comand
<PROJECT_ID>
Infine, imposta la zona e la configurazione del progetto predefinite.
gcloud config set compute/zone us-central1-f
Puoi scegliere zone diverse. Per ulteriori informazioni, consulta Regioni e Zone.
Configurazione Python
In questo codelab utilizziamo la "poesia" per gestire rigorosamente le versioni dei pacchetti. Esegui questo comando su Cloud Shell:
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3 - source $HOME/.poetry/env
Configura un cluster Google Kubernetes
In questo codelab, eseguirai un cluster di microservizi su Google Kubernetes Engine (GKE). Il processo di questo codelab è il seguente:
- Scarica il progetto di base in Cloud Shell
- Creazione di microservizi in container
- Caricare container in Google Artifact Registry (GAR)
- esegui il deployment dei container in GKE
- Modifica il codice sorgente dei servizi per la strumentazione di traccia
- Vai al passaggio 2
Abilita Kubernetes Engine
Per prima cosa, abbiamo configurato un cluster Kubernetes in cui Shakesapp viene eseguito su GKE, quindi dobbiamo abilitare GKE. Vai al menu "Kubernetes Engine". e premi il pulsante ABILITA.
Ora è tutto pronto per creare un cluster Kubernetes.
Crea un cluster Kubernetes
Su Cloud Shell, esegui questo comando per creare un cluster Kubernetes. Verifica che il valore della zona si trovi al di sotto della regione che hai utilizzato per la creazione del repository Artifact Registry. Modifica il valore della zona us-central1-f
se la regione del repository non copre la zona.
gcloud container clusters create otel-trace-codelab --zone us-central1-f \ --num-nodes 1 \ --machine-type e2-highcpu-4
Output comando
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
Configurazione di Artifact Registry e skaffold
Ora il cluster Kubernetes è pronto per il deployment. Ora ci prepariamo per creare un Container Registry per il push e il deployment dei container. Per questo passaggio, dobbiamo configurare GAR e skaffold per utilizzarli.
Configurazione di Artifact Registry
Vai al menu di "Artifact Registry". e premi il pulsante ABILITA.
Dopo qualche istante, vedrai il browser del repository di GAR. Fai clic su "CREA REPOSITORY" e inserisci il nome del repository.
In questo codelab, assegno il nome trace-codelab
al nuovo repository. Il formato dell'artefatto è "Docker" mentre il tipo di località è "Region". Scegli la regione vicina a quella impostata per la zona predefinita di Google Compute Engine. Ad esempio, per questo esempio è stato scelto "us-central1-f" in alto, quindi qui scegliamo "us-central1 (Iowa)". Poi fai clic sul pulsante "CREA" .
Ora vedi "trace-codelab" sul browser del repository.
Torneremo qui più tardi per controllare il percorso del registro.
Configurazione di Skaffold
Skaffold è uno strumento utile quando lavori alla creazione di microservizi in esecuzione su Kubernetes. Gestisce il flusso di lavoro di creazione, push e deployment di container di applicazioni con un piccolo set di comandi. Per impostazione predefinita, Skaffold utilizza Docker Registry come Container Registry, quindi devi configurare skaffold in modo che riconosca GAR al momento del push dei container.
Apri di nuovo Cloud Shell e verifica che skaffold sia installato. Cloud Shell installa skaffold nell'ambiente per impostazione predefinita. Esegui questo comando e visualizza la versione di skaffold.
skaffold version
Output comando
v1.20.0
Ora puoi registrare il repository predefinito per l'utilizzo di skaffold. Per ottenere il percorso del registro, vai alla dashboard di Artifact Registry e fai clic sul nome del repository che hai appena configurato nel passaggio precedente.
Nella parte superiore della pagina verranno visualizzate le tracce dei breadcrumb. Fai clic sull'icona per copiare il percorso del Registro di sistema negli appunti.
Facendo clic sul pulsante Copia, viene visualizzata la finestra di dialogo nella parte inferiore del browser con un messaggio simile al seguente:
"us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab" è stato copiato
Torna a Cloud Shell. Esegui il comando skaffold config set default-repo
con il valore che hai appena copiato dalla dashboard.
skaffold config set default-repo us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab
Output comando
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
Inoltre, devi configurare il registro in base alla configurazione Docker. Esegui questo comando:
gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
Output comando
{ "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
Ora puoi iniziare il passaggio successivo per configurare un container Kubernetes su GKE.
Riepilogo
In questo passaggio devi configurare il tuo ambiente codelab:
- Configura Cloud Shell
- Repository Artifact Registy creato per Container Registry
- Configurare skaffold per utilizzare Container Registry
- Creazione di un cluster Kubernetes in cui vengono eseguiti i microservizi del codelab
A seguire
Nel passaggio successivo, creerai, eseguirai il push e il deployment dei microservizi nel cluster
3. Crea ed esegui il push e il deployment dei microservizi
Scarica il materiale del codelab
Nel passaggio precedente, abbiamo configurato tutti i prerequisiti per questo codelab. Ora è tutto pronto per eseguire interi microservizi sopra i microservizi. Il materiale del codelab è ospitato su GitHub, quindi scaricalo nell'ambiente Cloud Shell con il seguente comando git.
cd ~ git clone https://github.com/GoogleCloudPlatform/opentelemetry-trace-codelab-python.git
La struttura di directory del progetto è la seguente:
shakesapp-python ├── LICENSE ├── manifests │ ├── client.yaml │ ├── loadgen.yaml │ └── server.yaml ├── proto │ └── shakesapp.proto ├── skaffold.yaml └── src ├── client ├── loadgen └── server
- manifest: i file manifest di Kubernetes
- proto: definizione proto per la comunicazione tra client e server
- src: directory per il codice sorgente di ogni Searvices
- skaffold.yaml: file di configurazione per skaffold
Esegui comando skaffold
Infine, sei pronto per creare, eseguire il push e il deployment di interi contenuti nel cluster Kubernetes che hai appena creato. Sembra che contenga più passaggi, ma quello effettivo è skaffold che fa tutto per te. Proviamo con questo comando:
cd shakesapp-python skaffold run --tail
Non appena esegui il comando, viene visualizzato l'output di log di docker build
e puoi confermare che il push è stato eseguito correttamente al registro.
Output comando
... ---> 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
Dopo il push di tutti i container di servizio, i deployment di Kubernetes vengono avviati automaticamente.
Output comando
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
Attenzione: se visualizzi un messaggio di errore simile a "Nessun accesso push al repository di immagini specificato", verifica se il comando skaffold sta tentando di eseguire il push delle immagini in Docker Hub (docker.io) a prescindere dalla configurazione sul repository predefinito in skaffold. In questo caso, prova ad aggiungere "–default-repo" con "skaffold run" come mostrato di seguito.
$ skaffold run –tail –default-repo=us-central1-docker.pkg.dev/[ID progetto]/[nome repository]
Dopo il deployment, vedrai i log effettivi dell'applicazione emessi nello stdout in ogni container, in questo modo:
Output comando
[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"}
Infine, puoi iniziare a dotare la tua applicazione di OpenTelemetry per il tracciamento distribuito dei servizi.
Riepilogo
In questo passaggio, hai preparato il materiale del codelab nel tuo ambiente e hai confermato che skaffold funziona come previsto.
A seguire
Nel passaggio successivo modificherai il codice sorgente del servizio loadgen per instrumentare le informazioni di traccia.
4. Strumentazione per HTTP
Concetto di strumentazione e propagazione delle tracce
Prima di modificare il codice sorgente, vediamo brevemente come funzionano le tracce distribuite in un semplice diagramma.
In questo esempio, instruiamo il codice per esportare le informazioni di tracciamento e intervallo in Cloud Trace e propagare il contesto della traccia attraverso la richiesta dal servizio loadgen al servizio server.
L'applicazione deve inviare metadati di traccia come ID traccia e ID intervallo per consentire a Cloud Trace di assemblare tutti gli intervalli con lo stesso ID traccia in un'unica traccia. Inoltre l'applicazione deve propagare i contesti di traccia (la combinazione di ID traccia e ID intervallo dell'intervallo padre) per richiedere i servizi downstream, in modo che possa essere a conoscenza del contesto di traccia che gestisce.
OpenTelemetry ti aiuta a:
- per generare un ID traccia e un ID intervallo univoci
- per esportare l'ID traccia e l'ID intervallo nel backend
- per propagare i contesti delle tracce ad altri servizi
Primo intervallo dello strumento
Servizio generatore di carico per strumentazione
Apri l'editor di Cloud Shell premendo il pulsante in alto a destra in Cloud Shell. Apri
src/loadgen/loadgen.py
da Explorer nel riquadro a sinistra e trova la funzione 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)
Nella funzione main
, puoi vedere il loop che chiama la funzione call_client
al suo interno. Nell'implementazione attuale, la sezione ha 2 righe di log che registrano l'inizio e la fine della chiamata di funzione. Ora strumentiamo le informazioni sull'intervallo per tracciare la latenza della chiamata di funzione.
Per prima cosa, devi creare un intervallo con un ID traccia e un ID intervallo univoci. OpenTelemetry offre una pratica libreria. Aggiungi le seguenti righe per importare le librerie OpenTelemetry nel tuo codice.
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
Poiché il generatore di carico chiama l'applicazione client in HTTP tramite il modulo requests
, utilizziamo il pacchetto di estensione per requests
e abilitiamo la strumentazione.
from opentelemetry.propagators.cloud_trace_propagator import CloudTraceFormatPropagator
+
+RequestsInstrumentor().instrument()
Quindi configura un'istanza Tracer che gestisce le impostazioni di Trace Contenxt ed esportatore
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}")
Tieni presente che, poiché si tratta di un codelab per capire come funziona la strumentazione di traccia, configuriamo il Tracer in modo da registrare ogni singola richiesta e inviarla al backend. (SimpleSpanProcessor()
) Questa funzionalità non è adatta agli ambienti di produzione, quindi assicurati di modificare questa parte quando instruisci l'applicazione di produzione.
Ora puoi usare intervalli di strumenti con il Tracer. Il punto è che quello che devi fare è generare un intervallo in modo esplicito e questo è tutto. Sebbene esistano due righe che aggiungono metadati di evento a un intervallo, non è necessario generare manualmente l'ID traccia e l'ID intervallo univoci e incorporarli nell'intervallo.
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)
Per consentire alla build Docker di recuperare i pacchetti OpenTelemetry richiesti, esegui questo comando:
poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0" poetry add "opentelemetry-propagator-gcp=^1.0.0rc0" poetry add "opentelemetry-instrumentation-requests=^0.20b0"
Puoi confermare che la descrizione della dipendenza corrispondente è scritta in pyproject.toml
.
Servizio clienti degli strumenti
Nella sezione precedente, abbiamo instrumentato la parte racchiusa nel rettangolo rosso nel disegno seguente. Abbiamo instrumentato le informazioni sugli intervalli nel servizio del generatore di carico. Analogamente al servizio generatore di carico, ora dobbiamo instrumentare il servizio client. La differenza dal servizio di generatore di carico è che il servizio client deve estrarre le informazioni sull'ID traccia propagate dal servizio generatore di carico nell'intestazione HTTP e utilizzare l'ID per generare intervalli.
Apri l'editor di Cloud Shell e aggiungi i moduli richiesti come abbiamo fatto per il servizio del generatore di carico.
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
Noti che hai appena importato FlaskInstrumentor
, che consente la strumentazione automatica per l'applicazione Flask per conto degli utenti di estrarre intestazioni HTTP e ottenere contesti di traccia con una singola riga di codice. La community OpenTelemetry offre integrazioni utili simili con altre librerie principali. Per saperne di più, puoi consultare la documentazione ufficiale.
app = flask.Flask(__name__)
+FlaskInstrumentor().instrument_app(app)
Prima di avviare la strumentazione, devi preparare l'istanza Tracer in modo simile a quanto abbiamo fatto per il servizio del generatore di carico.
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():
....
Ora è pronto per aggiungere la strumentazione nel gestore. Trova main_handler()
e modifica la parte che invia la richiesta gRPC al servizio server.
@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
Analogamente al servizio generatore di carico, aggiungi i pacchetti richiesti a pyproject.toml
con il comando seguente.
poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0" poetry add "opentelemetry-propagator-gcp=^1.0.0rc0" poetry add "opentelemetry-instrumentation-flask=^0.20b0"
Quindi prova ad avviare l'applicazione tramite il comando skaffold run
e guarda cosa viene visualizzato nella dashboard di Cloud Trace:
skaffold run --tail
Dopo aver visto alcuni messaggi di build, push e deployment, vedrai i log delle applicazioni in formato JSON. Vai a Cloud Trace > Elenco di tracce per verificare se ottieni le informazioni di traccia. Poiché il servizio generatore di carico invia periodicamente richieste al servizio client e hai abilitato le tracce per tutte le richieste, inizierai a vedere molti punti nell'elenco delle tracce.
Facendo clic su una di queste, vedrai un grafico a cascata come di seguito che spiega la latenza di ogni parte durante il processo di richiesta e risposta. Individua la casella di controllo accanto a "Mostra eventi" per visualizzare le annotazioni all'interno del grafico a cascata. Queste annotazioni sono quelle che hai instrumentato nel codice con il metodo span.add_event()
.
Potresti notare che non vedi gli intervalli dal servizio server. La risposta è corretta, perché non abbiamo instrumentato gli intervalli nel servizio server.
Riepilogo
In questo passaggio, hai attrezzato il servizio generatore di carico e il servizio client e hai confermato di poter propagare correttamente il contesto di traccia tra i servizi ed esportare le informazioni sull'intervallo da entrambi i servizi in Cloud Trace.
A seguire
Nel passaggio successivo, instrumenterai il servizio client e il servizio server per confermare come propagare il contesto di traccia tramite gRPC.
5. Strumentazione per gRPC
Nel passaggio precedente, abbiamo instrumentato la prima metà della richiesta in questo microservizio. In questo passaggio, cercheremo di instrumentare la comunicazione gRPC tra il servizio client e il servizio server. (Rettangolo verde e viola nella foto sotto)
Strumentazione automatica per client gRPC
L'ecosistema di OpenTelemetry offre molte librerie utili che aiutano gli sviluppatori a instrumentare le applicazioni. Nel passaggio precedente, abbiamo utilizzato la strumentazione automatica per le "richieste" in maggior dettaglio più avanti in questo modulo. In questo passaggio, poiché stiamo tentando di propagare il contesto della traccia tramite gRPC, utilizziamo la libreria apposito.
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()
Per l'assistenza clienti, ciò che dobbiamo fare per la strumentazione è piuttosto piccolo. Quello che vogliamo fare è propagare il contesto di traccia, ovvero la combinazione di ID traccia e ID intervallo dell'intervallo attuale tramite gRPC. Quindi chiamiamo GrpcInstrumentatorClient.instrument()
in modo che il client gRPC nella funzione hander possa incorporare il contesto traccia nell'intestazione HTTP sottostante.
Assicurati di aggiungere nuove dipendenze a pyproject.toml
con il comando poetry add
:
poetry add "opentelemetry-instrumentation-grpc=^0.20b0"
Strumentazione automatica per server gRPC
Come per il client gRPC, chiamiamo la strumentazione automatica per il server gRPC. Aggiungi importazioni come le seguenti e chiama GrpcInstrumentationServer().instrument()
all'inizio del file.
Attenzione: assicurati di chiamare
GrpcInstrumentationServe()
in questo passaggio, non
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()
+
Successivamente, aggiungerai l'utilità di esportazione per inviare le informazioni di traccia al backend Cloud Trace. Aggiungi il seguente codice nella funzione 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)
Accertati di aggiungere al servizio server i pacchetti appena aggiunti.
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"
Esegui il microservizio e conferma la traccia
Quindi esegui il codice modificato con il comando skaffold.
skaffold run --tail
Anche in questo caso, puoi vedere una serie di tracce nella pagina dell'elenco di Trace di Cloud Trace. Fai clic su una delle tracce per scoprire che si estende alla richiesta, dal servizio del generatore di carico al servizio del server.
Riepilogo
In questo passaggio, hai instrumentato la comunicazione basata su gRPC con il supporto delle librerie dell'ecosistema OpenTelemetry. Hai inoltre confermato che il contesto traccia generato nel servizio del generatore di carico sia stato consegnato correttamente al servizio server.
6. Complimenti
Hai creato tracce distribuite con OpenTelemery e hai confermato le latenze delle richieste nel microservizio su Google Cloud Trace.
Per esercizi estesi, puoi provare autonomamente i seguenti argomenti.
- L'implementazione attuale invia tutti gli intervalli generati dal controllo di integrità. Come si filtrano questi intervalli da Cloud Traces? Il suggerimento è qui.
- Correla i log eventi con gli intervalli e osserva come funziona su Google Cloud Trace e Google Cloud Logging. Il suggerimento è qui.
- Sostituisci qualche servizio con quello di un'altra lingua e prova a usarli con OpenTelemetry per quella lingua
Attenzione: Google Kubernetes Engine e Google Artifact Registry consumano costantemente la risorsa.
Pulizia
Dopo questo codelab, arresta il cluster Kubernetes e assicurati di eliminare il progetto in modo da non ricevere addebiti imprevisti su Google Kubernetes Engine, Google Cloud Trace e Google Artifact Registry.
Innanzitutto, elimina il cluster con il comando seguente:
skaffold delete
Output comando
Cleaning up... - deployment.apps "clientservice" deleted - service "clientservice" deleted - deployment.apps "loadgen" deleted - deployment.apps "serverservice" deleted - service "serverservice" deleted
Dopo aver eliminato il cluster, nel riquadro di menu seleziona "IAM e Amministratore" > "Impostazioni", quindi fai clic su "SPEGNI" .
Quindi inserisci l'ID progetto (non il nome del progetto) nel modulo della finestra di dialogo e conferma l'arresto.