Uno de los puntos importantes, en cualquier arquitectura, es la capacidad de monitorizar lo que está pasando en esta, y no sólo cuando falla 😜. De forma automática, Dapr es capaz de generar trazas entre los diferentes componentes que interactúan entre sí ya sea a través del bloque service Invocation o a través del patrón publicador suscriptor.
Siguiendo con el mismo ejemplo que he estado compartiendo contigo, de mis APIs Tour of heroes y Tour of villains, vamos a ver cómo se están registrando estas trazas y dónde.
Configuración por defecto
Si has seguido, y probado, mis últimos artículos sobre Dapr, ya habrás generado algunas trazas sin tu saberlo. Esto es así porque dapr init, el comando que lanzas cuando empiezas con Dapr en tu local, añadió una configuración por defecto para que todos los sidecars de nuestras aplicaciones ejecutándose manden las trazas que van generando a un servidor de Zipkin local, que también se inició con el mismo comando.

Generar trazas de ejemplo
Si por el contrario no has ejecutado mi versión para Dapr de Tour of heroes y Tour of villains puedes descargarte el código de ambas en mi GitHub, generar algunos registros en la base de datos que crees en Docker, y ejecutar las siguientes llamadas, en el archivo client.http de la API de los villanos:
GET http://localhost:5111/villain/batman HTTP/1.1
###
POST http://localhost:5111/villain HTTP/1.1
content-type: application/json
{
"Name": "Joker",
"hero":{
"name": "Batman",
"description": "Un multimillonario magnate empresarial y filántropo dueño de Empresas Wayne en Gotham City. Después de presenciar el asesinato de sus padres, el Dr. Thomas Wayne y Martha Wayne en un violento y fallido asalto cuando era niño, juró venganza contra los criminales, un juramento moderado por el sentido de la justicia.",
"alterEgo": "Bruce Wayne"
},
"description": "Si bien sus orígenes y rasgos han variado con el transcurso del tiempo, por lo general se le asocia con una personalidad psicópata con un humor sádico y retorcido, lo que le ha llevado a ser catalogado como la antítesis de Batman."
}
###
GET http://localhost:5111/villain/batman HTTP/1.1
###
POST http://localhost:5111/villain HTTP/1.1
content-type: application/json
{
"name": "Octopus",
"hero":{
"name": "Spiderman",
"description": "un joven huérfano neoyorquino que adquiere superpoderes después de ser mordido por una araña radiactiva, y cuya ideología como héroe se ve reflejada primordialmente en la expresión «un gran poder conlleva una gran responsabilidad».2021 Suele ser asociado con una personalidad bromista, amable, inventiva y optimista, lo que le ha llevado a ser catalogado como el «vecino amigable» de cualquiera lo cual, aunado a sus vivencias caracterizadas por los problemas cotidianos.",
"alterEgo": "Peter Parker"
},
"description": "Es un científico loco muy inteligente y algo fornido que tiene cuatro apéndices fuertes que se asemejan a los tentáculos de un pulpo, que se extienden desde la parte posterior de su cuerpo y pueden usarse para varios propósitos."
}
###
POST http://localhost:5111/villain HTTP/1.1
content-type: application/json
{
"name": "Doctor Muerte",
"hero":{
"name": "Luke Cage",
"description": "Es un exconvicto encarcelado por un crimen que no cometió, que gana los poderes de la fuerza sobrehumana y la piel irrompible después de someterse voluntariamente a un procedimiento experimental.",
"alterEgo": "Carl Lucas"
},
"description": "No solo cuenta con una armadura personal que rivaliza con las de Iron Man, albergando un variopinto y nutrido arsenal, sino que además es un hechicero de primera, estando mano a mano con el propio Doctor Extraño."
}
###
POST http://localhost:5111/villain HTTP/1.1
content-type: application/json
{
"name": "Loki",
"hero":{
"name": "Thor",
"description": "Es el dios del trueno y fuerza en la mitología nórdica y germánica. Su papel es complejo ya que tenía influencia en áreas muy diferentes, tales como el clima, las cosechas, la protección, la consagración, la justicia, las lidias, los viajes y las batallas.",
"alterEgo": "Thor"
},
"description": "El dios nórdico de las Mentiras y el Engaño. Y el hermano adoptivo de Thor según la mitología de Marvel y también su mayor rival clásico."
}
###
GET http://localhost:5111/villain/thor HTTP/1.1
Una vez hecho todo esto habrán ocurrido dos cosas: se habrán registrado los villanos en la base de datos y se habrán anunciado a la API Tour of heroes los mismos a través del patrón publicador suscriptor que ya te conté.
Por último, podemos generar más trazas con las siguientes llamadas a la API de los héroes:
### Service-to-service invocation
###
GET http://localhost:5222/api/hero/villain/spiderman HTTP/1.1
###
GET http://localhost:5222/api/hero/villain/batman HTTP/1.1
###
GET http://localhost:5222/api/hero/villain/luke%20cage HTTP/1.1
###
GET http://localhost:5222/api/hero/villain/thor HTTP/1.1
Con ellas conseguimos que se produzcan llamadas entre los servicios como vimos en este otro artículo.
¿Cómo ver las trazas?
Para ver toda la información que acabamos de generar basta con acceder a http://localhost:9411/, que es el puerto expuesto para la instancia de Zipkin, y hacer click en el botón RUN QUERY (yo lo he cambiado a los últimos 30 minutos):

Como ves, podemos revisar tanto trazas de los eventos publicados como de las llamadas entre servicios. Por otro lado, si acedemos al apartado Dependencies, y ampliamos el rango de la fecha y hora a unos 30 minutos también, comprobaremos cómo se ha hecho la relación entre las dos APIs en ambos sentidos:

Configurar otras tecnologías para las trazas distribuidas
Si bien es cierto que esta configuración es muy buen punto de arranque, quizás te gusten más otras tecnologías, como por ejemplo Jaeger. La forma de configurarlo es muy sencilla: basta con generar, en este ejemplo, un contenedor con Jaeger:
# Create Jaeger container
docker run -d --name jaeger \
-e COLLECTOR_ZIPKIN_HOST_PORT=:9412 \
-p 16686:16686 \
-p 9412:9412 \
jaegertracing/all-in-one
Y añadir esta configuración a ambos proyectos:
apiVersion: dapr.io/v1alpha1
kind: Configuration
metadata:
name: tracing
namespace: default
spec:
tracing:
samplingRate: "1"
zipkin:
endpointAddress: "http://localhost:9412/api/v2/spans"
Para que Visual Studio Code tenga en cuenta esta configuración, y no la por defecto, debemos añadir a la tarea dapr-debug, en tasks.json, la propiedad config con la ruta de este archivo:
{
//https://docs.dapr.io/developing-applications/ides/vscode/vscode-how-to-debug-multiple-dapr-apps/#daprd-parameter-table
"appId": "tour-of-heroes-api",
"appPort": 5222,
"label": "dapr-debug",
"type": "dapr",
"dependsOn": "build",
"httpPort": 3502,
"grpcPort": 50002,
"logLevel": "debug",
"args": [
"--enable-api-logging"
],
"config": "./config-dapr/jaeger-config.yaml",
"componentsPath": "./components/"
},
Si ejecutamos todas las operaciones anteriores podrás ver ahora tus trazas en Jaeger, en http://localhost:16686:

¡Saludos!