1. Introdução
Última atualização:05/03/2021
Observabilidade do aplicativo
Observabilidade e OpenTelemetry
Observabilidade é o termo usado para descrever um atributo de um sistema. Um sistema com observabilidade permite que as equipes depurem ativamente o sistema. Nesse contexto, três pilares da observabilidade: registros, métricas e traces são a instrumentação fundamental para que o sistema adquira observabilidade.
O OpenTelemetry é um conjunto de especificações e SDKs que acelera a instrumentação e a exportação de dados de telemetria (registros, métricas e traces) exigidos pela observabilidade. O OpenTelemetry é um projeto de padrão aberto conduzido pela comunidade pela CNCF. Ao utilizar bibliotecas que o projeto e seu ecossistema fornecem, os desenvolvedores são capazes de instrumentar seus aplicativos de maneira neutra em termos de fornecedor e contra várias arquiteturas.
Rastreamento distribuído
Entre registros, métricas e traces, o trace é a telemetria que informa a latência de uma parte específica do processo no sistema. Especialmente na era dos microsserviços, o trace distribuído é o forte impulsionador para descobrir gargalos de latência no sistema distribuído em geral.
Ao analisar traces distribuídos, a visualização de dados de trace é a chave para entender rapidamente as latências gerais do sistema. No trace distribuído, processamos um conjunto de chamadas para processar uma única solicitação ao ponto de entrada do sistema em uma forma de Trace que contém vários períodos.
O período representa uma unidade de trabalho realizada em um sistema distribuído, registrando os horários de início e término. Os períodos geralmente têm relações hierárquicas entre si. Na imagem abaixo de todos os períodos menores, estão os períodos filhos de um período /messages grande e reunidos em um trace que mostra o caminho do trabalho em um sistema.
O Google Cloud Trace é uma das opções de back-end de trace distribuído e é bem integrado a outros produtos do Google Cloud.
O que você vai criar
Neste codelab, você vai instrumentar informações de rastreamento nos serviços chamados "Shakesapp". executado em um cluster do Kubernetes em execução no Google Kubernetes Engine. A arquitetura do Shakesapp é descrita abaixo:
- Os clientes enviam uma string de consulta para o servidor
- O servidor aceita a consulta do cliente, busca todos os trabalhos do Shakespare em formato de texto no Google Cloud Storage, pesquisa as linhas que contêm a consulta e retorna o número da linha correspondente ao cliente.
Você instrumentará as informações de rastreamento em toda a solicitação.
O que você vai aprender
- Como começar a usar as bibliotecas de trace do OpenTelemetry no projeto Python
- Como criar um período com a biblioteca
- Como propagar contextos de período entre os componentes do app
- Como enviar dados de traces para o Google Cloud Trace
- Como analisar o trace no Google Cloud Trace
Este codelab explica como instrumentar seus microsserviços. Para facilitar a compreensão, este exemplo contém apenas três componentes (gerador de carga, cliente e servidor). No entanto, é possível aplicar o mesmo processo explicado neste codelab em sistemas grandes e mais complexos.
O que é necessário
- Conhecimento sobre o Python 3
2. Configuração e requisitos
Configuração de ambiente autoguiada
Se você ainda não tem uma Conta do Google (Gmail ou Google Apps), crie uma. Faça login no Console do Google Cloud Platform ( console.cloud.google.com) e crie um novo projeto.
Se você já tiver um projeto, clique no menu suspenso de seleção no canto superior esquerdo do console:
e clique no botão "NEW PROJECT" na caixa de diálogo exibida para criar um novo projeto:
Se você ainda não tiver um projeto, uma caixa de diálogo como esta será exibida para criar seu primeiro:
A caixa de diálogo de criação de projeto subsequente permite que você insira os detalhes do novo projeto:
Lembre-se do código do projeto, um nome exclusivo em todos os projetos do Google Cloud. O nome acima já foi escolhido e não servirá para você. Faremos referência a ele mais adiante neste codelab como PROJECT_ID.
Em seguida, você precisará ativar o faturamento no Developers Console para usar os recursos do Google Cloud e ativar a API Cloud Trace, caso ainda não tenha feito isso.
A execução por meio deste codelab terá um custo baixo, mas poderá ser mais se você decidir usar mais recursos ou se deixá-los em execução. Consulte a seção "limpeza" no final deste documento. Os preços do Google Cloud Trace, do Google Kubernetes Engine e do Registro do Artifacat do Google estão indicados na documentação oficial.
- Preços de observabilidade do Google Cloud
- Preços | Documentação do Kubernetes Engine
- Preços do Artifact Registry | Documentação do Artifact Registry
Novos usuários do Google Cloud Platform estão qualificados para uma avaliação gratuita de US$ 300, o que torna este codelab totalmente gratuito.
Configuração do Google Cloud Shell
Embora o Google Cloud e o Google Cloud Trace possam ser operados remotamente do seu laptop, neste codelab vamos usar o Google Cloud Shell, um ambiente de linha de comando executado no Cloud.
O Cloud Shell é uma máquina virtual com base em Debian que contém todas as ferramentas de desenvolvimento necessárias. Ela oferece um diretório principal persistente de 5 GB, além de ser executada no Google Cloud. Isso aprimora o desempenho e a autenticação da rede. Isso significa que tudo que você precisa para este codelab é um navegador (sim, funciona em um Chromebook).
Para ativar o Cloud Shell no Console do Cloud, basta clicar em Ativar o Cloud Shell . O provisionamento e a conexão ao ambiente devem levar apenas alguns instantes.
Depois de se conectar ao Cloud Shell, você já estará autenticado e o projeto estará configurado com seu PROJECT_ID
.
gcloud auth list
Resposta ao comando
Credentialed accounts: - <myaccount>@<mydomain>.com (active)
gcloud config list project
Resposta ao comando
[core] project = <PROJECT_ID>
Se, por algum motivo, o projeto não estiver definido, basta emitir o seguinte comando:
gcloud config set project <PROJECT_ID>
Quer encontrar seu PROJECT_ID
? Veja qual ID você usou nas etapas de configuração ou procure-o no painel do Console do Cloud:
O Cloud Shell também define algumas variáveis de ambiente por padrão, o que pode ser útil ao executar comandos futuros.
echo $GOOGLE_CLOUD_PROJECT
Saída de comando
<PROJECT_ID>
Defina a zona padrão e a configuração do projeto:
gcloud config set compute/zone us-central1-f
É possível escolher uma variedade de zonas diferentes. Para mais informações, consulte Regiões e zonas.
Configuração do Python
Neste codelab, usamos "poesia" para gerenciar versões de pacotes estritamente. Execute o seguinte comando no Cloud Shell:
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python3 - source $HOME/.poetry/env
Configurar um cluster do Google Kubernetes
Neste codelab, você executará um cluster de microsserviços no Google Kubernetes Engine (GKE). O processo deste codelab é o seguinte:
- Faça o download do projeto de referência no Cloud Shell
- Crie microsserviços em contêineres
- Fazer upload de contêineres no Google Artifact Registry (GAR)
- Implantar contêineres no GKE
- Modificar o código-fonte dos serviços para instrumentação de rastreamento
- Ir para a etapa 2
Ativar o Kubernetes Engine
Primeiro, configuramos um cluster do Kubernetes em que o Shakesapp é executado no GKE, portanto, precisamos ativar o GKE. Acesse o menu "Kubernetes Engine". e pressione o botão "ATIVAR".
Agora você já pode criar um cluster do Kubernetes.
Crie o cluster do Kubernetes
No Cloud Shell, execute o comando a seguir para criar um cluster do Kubernetes. Confirme se o valor da zona está na região que você usou para criar o repositório do Artifact Registry. Altere o valor da zona us-central1-f
se a região do repositório não cobrir a zona.
gcloud container clusters create otel-trace-codelab --zone us-central1-f \ --num-nodes 1 \ --machine-type e2-highcpu-4
Resposta ao 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
Configuração do Artifact Registry e do skaffold
Agora temos um cluster do Kubernetes pronto para implantação. Em seguida, preparamos um Container Registry para enviar e implantar contêineres. Para esta etapa, precisamos configurar o GAR e o skaffold para usá-lo.
Configuração do Artifact Registry
Navegue até o menu do "Artifact Registry". e pressione o botão ATIVAR.
Depois de alguns instantes, você verá o navegador do repositório do GAR. Clique em "CRIAR REPOSITÓRIO". e insira o nome do repositório.
Neste codelab, nomeio o novo repositório como trace-codelab
. O formato do artefato é "Docker" e o tipo é "Região". Escolha a região próxima àquela que você definiu para a zona padrão do Google Compute Engine. Por exemplo, este exemplo escolhe "us-central1-f" acima, então aqui escolhemos "us-central1 (Iowa)". Em seguida, clique no botão "CRIAR" .
Agora você vai encontrar o "trace-codelab" no navegador do repositório.
Vamos voltar aqui mais tarde para verificar o caminho do registro.
Configuração do Skaffold
O Skaffold é uma ferramenta útil para a criação de microsserviços executados no Kubernetes. Ele lida com o fluxo de trabalho de criação, envio e implantação de contêineres de aplicativos com um pequeno conjunto de comandos. Por padrão, o Skaffold usa o Docker Registry como o Container Registry. Portanto, é necessário configurar o skaffold para reconhecer o GAR ao enviar contêineres para ele.
Abra o Cloud Shell novamente e confirme se o skaffold está instalado. O Cloud Shell instala o skaffold no ambiente por padrão. Execute o comando a seguir e confira a versão do skaffold.
skaffold version
Resposta ao comando
v1.20.0
Agora, você pode registrar o repositório padrão para o skaffold usar. Para encontrar o caminho do registro, acesse o painel do Artifact Registry e clique no nome do repositório que você configurou na etapa anterior.
Em seguida, você verá trilhas de navegação estrutural na parte superior da página. Clique no ícone para copiar o caminho do registro para a área de transferência.
Ao clicar no botão "Copiar", você vê a caixa de diálogo na parte inferior do navegador com a seguinte mensagem:
"us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab" foi copiado
Volte para o Cloud Shell. Execute o comando skaffold config set default-repo
com o valor que você acabou de copiar do painel.
skaffold config set default-repo us-central1-docker.pkg.dev/psychic-order-307806/trace-codelab
Resposta ao 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
Além disso, você precisa configurar o registro para o Docker. Execute este comando:
gcloud auth configure-docker us-central1-docker.pkg.dev --quiet
Resposta ao 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
Agora está tudo pronto para a próxima etapa de configuração de um contêiner do Kubernetes no GKE.
Resumo
Nesta etapa, você vai configurar seu ambiente do codelab:
- Configurar o Cloud Shell
- Criou um repositório do Artifact Registy para o Container Registry
- Configurar o skaffold para usar o Container Registry
- Criou um cluster do Kubernetes em que os microsserviços do codelab são executados
A seguir
Na próxima etapa, você vai criar, enviar e implantar seus microsserviços no cluster
3. Criar, transferir e implantar os microsserviços
Faça o download do material do codelab
Na etapa anterior, configuramos todos os pré-requisitos para este codelab. Agora está tudo pronto para executar microsserviços inteiros neles. O material do codelab está hospedado no GitHub. Faça o download dele para o ambiente do Cloud Shell com o comando git abaixo.
cd ~ git clone https://github.com/GoogleCloudPlatform/opentelemetry-trace-codelab-python.git
A estrutura de diretórios do projeto é a seguinte:
shakesapp-python ├── LICENSE ├── manifests │ ├── client.yaml │ ├── loadgen.yaml │ └── server.yaml ├── proto │ └── shakesapp.proto ├── skaffold.yaml └── src ├── client ├── loadgen └── server
- manifestos: arquivos de manifesto do Kubernetes
- proto: definição proto para a comunicação entre cliente e servidor
- src: diretórios para o código-fonte de cada serviço
- skaffold.yaml: arquivo de configuração do skaffold
Executar o comando skaffold
Por fim, você já pode criar, enviar e implantar todo o conteúdo no cluster do Kubernetes que acabou de criar. Isso parece conter várias etapas, mas o skaffold na verdade é que faz tudo por você. Vamos tentar fazer isso com o seguinte comando:
cd shakesapp-python skaffold run --tail
Assim que executar o comando, você verá a saída do registro de docker build
e poderá confirmar que eles foram enviados com sucesso para o registro.
Resposta ao 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
Após o envio de todos os contêineres de serviço, as implantações do Kubernetes são iniciadas automaticamente.
Resposta ao 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
Cuidado: se você receber o erro "Sem acesso push ao repositório de imagens especificado", verifique se o comando skaffold está tentando enviar imagens para o Docker Hub (docker.io) independentemente da sua configuração no repositório padrão no skaffold. Nesse caso, tente adicionar "–default-repo" a opção "skaffold run" como abaixo.
$ skaffold run –tail –default-repo=us-central1-docker.pkg.dev/[ID do projeto]/[nome do repositório]
Após a implantação, os registros do aplicativo serão emitidos para stdout em cada contêiner, da seguinte forma:
Resposta ao 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"}
Por fim, já pode começar a instrumentar seu aplicativo com o OpenTelemetry para o rastreamento distribuído dos serviços.
Resumo
Nesta etapa, você preparou o material do codelab no seu ambiente e confirmou as execuções do skaffold conforme o esperado.
A seguir
Na próxima etapa, você vai modificar o código-fonte do serviço loadgen para instrumentar as informações de rastreamento.
4. Instrumentação para HTTP
Conceito de instrumentação e propagação de rastreamento
Antes de editar o código-fonte, vou explicar brevemente como os traces distribuídos funcionam em um diagrama simples.
Neste exemplo, instrumentamos o código para exportar informações do Trace e do período para o Cloud Trace e propagar o contexto do trace na solicitação do serviço loadgen para o serviço de servidor.
O aplicativo precisa enviar metadados de traces, como o ID do trace e o ID do período, para que o Cloud Trace reúna todos os períodos que tenham o mesmo ID do trace em um único trace. Além disso, o aplicativo precisa propagar contextos de trace (a combinação de ID de trace e ID de período do período pai) ao solicitar serviços downstream, para que esteja ciente do contexto de trace que está processando.
O OpenTelemetry ajuda você a:
- para gerar um ID de trace e um ID de período exclusivos
- para exportar o ID do Trace e o ID do período para o back-end
- para propagar contextos de trace para outros serviços
Primeiro período da instrumentação
Serviço gerador de carga por instrumento
Pressione o botão no canto superior direito para abrir o Editor do Cloud Shell. Abra src/loadgen/loadgen.py
no explorador no painel esquerdo e encontre a função 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)
Na função main
, a repetição chama a função call_client
. Na implementação atual, o segundo tem duas linhas de registro que registram o início e o fim da chamada de função. Agora, vamos instrumentar as informações de período para rastrear a latência da chamada de função.
Primeiro, você precisa criar um período com um ID de trace e um ID de período exclusivos. O OpenTelemetry oferece uma biblioteca útil para isso. Adicione as linhas a seguir para importar as bibliotecas do OpenTelemetry para seu código.
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
Como o gerador de carga está chamando o aplicativo cliente em HTTP pelo módulo requests
, usamos o pacote de extensão para requests
e ativamos a instrumentação.
from opentelemetry.propagators.cloud_trace_propagator import CloudTraceFormatPropagator
+
+RequestsInstrumentor().instrument()
Em seguida, configure a instância do Tracer que gerencie o conteúdo do Trace e as configurações do exportador
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}")
Como este é um codelab para entender como funciona a instrumentação de rastros, configuramos o Tracer para registrar cada solicitação e enviá-la ao back-end. (SimpleSpanProcessor()
) Isso não é adequado para ambientes de produção, portanto, altere essa parte ao instrumentar seu aplicativo de produção.
Agora você pode instrumentar períodos com o Tracer. A questão aqui é que o que você precisa fazer é gerar um período explicitamente, e é isso. Embora existam duas linhas que adicionam metadados de evento ao período, não é necessário gerar manualmente o código do trace e o código do período e incorporá-los ao período.
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)
Para que o build do Docker busque os pacotes necessários do OpenTelemetry, execute o seguinte 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"
É possível confirmar se a descrição da dependência correspondente está escrita em pyproject.toml
.
Serviço de cliente de instrumentos
Na seção anterior, instrumentamos a parte envolvida no retângulo vermelho no desenho abaixo. Instrumentamos as informações de período no serviço de gerador de carga. Da mesma forma que o serviço de gerador de carga, agora precisamos instrumentar o serviço ao cliente. A diferença do serviço de gerador de carga é que o serviço cliente precisa extrair as informações do ID de trace propagado do serviço de gerador de carga no cabeçalho HTTP e usar o ID para gerar períodos.
Abra o editor do Cloud Shell e adicione os módulos necessários, como fizemos para o serviço de gerador de carga.
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
Você acabou de importar o FlaskInstrumentor
, que permite a instrumentação automática do aplicativo Flask em nome dos usuários para extrair cabeçalhos HTTP e acessar contextos de trace com uma única linha de código. A comunidade do OpenTelemetry oferece integrações úteis semelhantes com outras bibliotecas importantes. Para mais informações, consulte a documentação oficial.
app = flask.Flask(__name__)
+FlaskInstrumentor().instrument_app(app)
Antes de iniciar a instrumentação, mais uma vez, você precisa preparar a instância do Tracer de maneira semelhante ao que fizemos no serviço de gerador de carga.
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():
....
Agora está tudo pronto para adicionar instrumentação ao gerenciador. Encontre main_handler()
e modifique a parte que gera a solicitação gRPC para o serviço do servidor.
@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
Assim como o serviço de gerador de carga, adicione os pacotes necessários ao pyproject.toml
com o comando a seguir.
poetry add "opentelemetry-exporter-gcp-trace=^1.0.0rc0" poetry add "opentelemetry-propagator-gcp=^1.0.0rc0" poetry add "opentelemetry-instrumentation-flask=^0.20b0"
Em seguida, tente iniciar o aplicativo pelo comando skaffold run
e veja o que o painel do Cloud Trace mostra:
skaffold run --tail
Depois de ver algumas mensagens de criação, push e implantação, você verá os registros do aplicativo nos formatos JSON. Navegue até o Cloud Trace > Lista de traces para verificar se você recebeu as informações de rastreamento. Como o serviço do gerador de carga envia solicitações ao serviço ao cliente periodicamente e os traces foram ativados para todas as solicitações, você começa a ver muitos pontos na lista de traces.
Ao clicar em um deles, você verá um gráfico de cascata como o abaixo, que explica a latência de cada parte durante o processo de solicitação e resposta. Encontre a caixa de seleção ao lado de "Mostrar eventos". Assim, as anotações vão aparecer no gráfico de cascata. Essas anotações são aquelas que você instrumentou no código pelo método span.add_event()
.
Talvez você tenha percebido que os períodos do serviço do servidor não estão sendo exibidos. Correto. Nós não instrumentamos os períodos no serviço do servidor.
Resumo
Nesta etapa, você instrumentou o serviço de gerador de carga e o serviço do cliente, além de confirmar que é possível propagar o contexto do Trace entre os serviços e exportar as informações do período de ambos os serviços para o Cloud Trace.
A seguir
Na próxima etapa, você vai instrumentar o serviço de cliente e o serviço de servidor para confirmar como propagar o contexto de trace via gRPC.
5. Instrumentação para gRPC
Na etapa anterior, instrumentamos a primeira metade da solicitação nesses microsserviços. Nesta etapa, tentamos instrumentar a comunicação do gRPC entre o serviço do cliente e o serviço do servidor. (retângulo verde e roxo na imagem abaixo)
Instrumentação automática para o cliente gRPC
O ecossistema do OpenTelemetry oferece muitas bibliotecas úteis que ajudam os desenvolvedores a instrumentar aplicativos. Na etapa anterior, usamos a instrumentação automática para "solicitações" mais tarde neste módulo. Nesta etapa, como estamos tentando propagar o contexto do Trace pelo gRPC, usamos a biblioteca para isso.
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()
Para o atendimento ao cliente, o que precisamos fazer com a instrumentação é bem pequeno. O que queremos fazer é propagar o contexto de trace, que é a combinação do ID de trace e do ID do período do período atual via gRPC. Então, chamamos GrpcInstrumentatorClient.instrument()
para que o cliente gRPC na função do manual possa incorporar o contexto do trace ao cabeçalho HTTP abaixo.
Adicione novas dependências a pyproject.toml
com o comando poetry add
:
poetry add "opentelemetry-instrumentation-grpc=^0.20b0"
Instrumentação automática para o servidor gRPC
Assim como fizemos com o cliente gRPC, chamamos a instrumentação automática para o servidor gRPC. Adicione importações como as seguintes e chame GrpcInstrumentationServer().instrument()
na parte de cima do arquivo.
Cuidado: não se esqueça de chamar
GrpcInstrumentationServe()
nesta etapa, não
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()
+
A seguir, você vai adicionar o exportador para enviar informações de trace ao back-end do Cloud Trace. Adicione o código abaixo na função 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)
Adicione os pacotes recém-adicionados ao serviço do servidor.
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"
Executar o microsserviço e confirmar o trace
Em seguida, execute o código modificado com o comando skaffold.
skaffold run --tail
Agora, você verá vários traces na página "Lista de traces" do Cloud Trace. Clique em um dos traces para ver que ele abrange a solicitação do serviço do gerador de carga ao serviço do servidor.
Resumo
Nesta etapa, você instrumentou a comunicação baseada em gRPC com o suporte das bibliotecas do ecossistema do OpenTelemetry. Além disso, você confirmou que o contexto de trace gerado no serviço do gerador de carga foi entregue com sucesso ao serviço de servidor.
6. Parabéns
Você criou traces distribuídos com o OpenTelemery e confirmou as latências de solicitação no microsserviço no Google Cloud Trace.
Para exercícios mais longos, você pode experimentar os tópicos a seguir por conta própria.
- A implementação atual envia todos os períodos gerados pela verificação de integridade. Como filtrar esses períodos do Cloud Trace? A dica está aqui.
- Correlacione os logs de eventos com períodos e veja como isso funciona no Google Cloud Trace e no Google Cloud Logging. A dica está aqui.
- Substitua alguns serviços por um em outro idioma e tente instrumentá-los com o OpenTelemetry para esse idioma
Cuidado: o Google Kubernetes Engine e o Google Artifact Registry consomem o recurso constantemente.
Limpeza
Após este codelab, interrompa o cluster do Kubernetes e exclua o projeto para não receber cobranças inesperadas no Google Kubernetes Engine, no Google Cloud Trace e no Google Artifact Registry.
Primeiro, exclua o cluster com o seguinte comando:
skaffold delete
Resposta ao comando
Cleaning up... - deployment.apps "clientservice" deleted - service "clientservice" deleted - deployment.apps "loadgen" deleted - deployment.apps "serverservice" deleted - service "serverservice" deleted
Depois de excluir o cluster, no painel de menu, selecione "IAM e Administrador" > "Configurações" e, em seguida, clique em "DESLIGAR" .
Em seguida, insira o ID do projeto (não o nome do projeto) no formulário na caixa de diálogo e confirme o encerramento.