Skip to content

Entorno de desarrollo

Este documento detalla la configuración del entorno de desarrollo proporcionado por CodeDesignPlus. Su objetivo principal es simplificar y acelerar la configuración inicial, permitiendo a los desarrolladores centrarse en la lógica de negocio y reducir las tareas repetitivas.

Entorno de Desarrollo

El entorno de desarrollo de CodeDesignPlus esta disponible en el repositorio de GitHub CodeDesignPlus.Environment.Dev

Requisitos Previos

Para desarrollar microservicios con CodeDesignPlus, necesitas tener instaladas las siguientes herramientas en tu máquina:

  1. Tener instaladas las herramientas de desarrollo descritas en el artículo Herramientas de Desarrollo.
  2. Clona el repositorio de GitHub CodeDesignPlus.Environment.Dev en tu máquina local.

Docker Compose

El archivo docker-compose.yaml define un entorno de desarrollo completo utilizando contenedores Docker. Este entorno proporciona las siguientes ventajas:

  • Consistencia: Asegura que todos los desarrolladores trabajen con las mismas versiones de dependencias y servicios, evitando problemas de “funciona en mi máquina”.
  • Aislamiento: Los servicios se ejecutan en contenedores aislados, previniendo conflictos y simplificando la gestión de dependencias.
  • Rápida Configuración: Permite levantar rápidamente un entorno de desarrollo con un solo comando.
  • Simulación de Producción: El entorno se asemeja a una configuración de producción, facilitando la detección temprana de problemas.

Cómo Utilizar docker-compose.yaml

  1. Asegúrate de tener Docker y Docker Compose instalados.

  2. Navega a la carpeta resources en el proyecto.

  3. Ejecuta el siguiente comando para levantar todos los servicios:

    Terminal window
    docker-compose up -d
  4. Para detener los servicios:

    Terminal window
    docker-compose down

Vault (HashiCorp)

Vault es una herramienta para gestionar secretos, como contraseñas, tokens, claves API y certificados. Proporciona un almacenamiento seguro y un acceso controlado a estos secretos, evitando que se almacenen directamente en el código o archivos de configuración.

Vault se integra con múltiples sistemas de autenticación y motores de secretos, como base de datos, AWS, Azure y otros. Permite la rotación automática de claves y la generación de credenciales temporales para mejorar la seguridad y la gestión de secretos.

Vault
  • Key Vault: Almacena y gestiona claves y secretos sensibles.
  • Database: Almacena credenciales de bases de datos y genera credenciales temporales.
  • Transient: Almacena secretos temporales y de corta duración.
  • RabbitMQ: Almacena credenciales de RabbitMQ y genera credenciales temporales.

Convenciones de Nombres:

Muchas de las convenciones que se deben implementar en HashiCorp Vault, son con base a la configuración del microservicio, especialmente en la sección Core y Vault:

{
"Core": {
"AppName": "ms-archetype",
"Version": "v1",
"Description": "Microservice Archetype Template",
"Business": "CodeDesignPlus",
"Contact": {
"Name": "CodeDesignPlus",
"Email": "codedesignplus@outlook.com"
}
},
"Vault": {
"Enable": true,
"Address": "http://127.0.0.1:8200",
"AppName": "ms-archetype",
"Solution": "archetype",
"Token": "root",
"Mongo": {
"Enable": true,
"TemplateConnectionString": "mongodb://{0}:{1}@localhost:27017"
},
"RabbitMQ": {
"Enable": true
}
}
}

De acuerdo a la configuración anterior, es importante tener en cuenta los siguientes conceptos:

  • Solution: Nombre de la solución o proyecto como por ejemplo Jira, Trello, Management, etc. En este caso, se ha definido como archetype
  • Microservice: Nombre del microservicio o componente como por ejemplo Auth, Gateway, Users, Organization, etc. En este caso, se ha definido como ms-archetype

Ahora profundicemos en las convenciones de nombres para cada uno de los motores de secretos:

El motor de secretos Key Vault se encarga de almacenar y gestionar claves y secretos sensibles.

Vault
  1. El administrador crea un App Role con el nombre de la solución y la política de acceso para la autenticación del microservicio con ayuda de la librearía CodeDesignPlus.Net.Vault.

    Ejemplo:

    • archetype-approle
    • jira-approle
    • trello-approle
    • management-approle
    Terminal window
    vault write auth/approle/role/archetype-approle policies="full-access"
  2. El administrador habilita el motor de secretos Key Vault

    Ejemplo:

    • ms-archetype
    • ms-organization
    • ms-products
    • ms-orders
    Terminal window
    vault secrets enable -path=archetype-keyvalue kv-v2
  3. El administrador crea los secretos sensibles del microservicio con base al archivo appsettings.json.

    Ejemplo: Supongamos que el appsettings.json tiene las siguientes claves:

    {
    "Redis": {
    "Instances": {
    "Core": {
    "ConnectionString": "localhost:6379"
    }
    }
    }
    }

    El administrador almacena los siguientes secretos en el Key Vault:

    Terminal window
    vault kv put -mount=archetype-keyvalue ms-archetype Redis:Instances:Core:ConnectionString=localhost:6379
  4. Para visualizar los secretos almacenados en el Key Vault, el administrador pudede ejecutar el siguiente comando:

    Terminal window
    vault kv get -mount=archetype-keyvalue ms-archetype

    Pero tambien puede ingresar a la plataforma de Vault y visualizar los secretos almacenados en el Key Vault.

    • Ingresar a la plataforma de Vault en la URL http://localhost:8200.

      Home
    • Ingresar a la sección de Secrets y seleccionar el Key Vault del microservicio.

      Vault
    • Visualizar los secretos almacenados en el Key Vault.

      Vault

Beneficios:

  • Permite almacenar y acceder de forma segura a credenciales, claves API y otros datos sensibles.
  • Mejora la seguridad al evitar el almacenamiento de secretos en archivos de configuración o código fuente.
  • Facilita la rotación de claves y la gestión de secretos en entornos de desarrollo, pruebas y producción.

Acceso:

Para acceder a la interfaz de usuario de Vault, visita http://localhost:8200 (usando el token root para el entorno de desarrollo).

Para ingresar a la plataforma de Vault se debe ingresar el token de acceso root en el campo Token y presionar el botón Sign in.

Vault

Configuración:

El archivo docker-compose.yaml incluye un servicio de Vault sin ninguna configuración adicional. Para configurar Vault con métodos de autenticación, motores de secretos, políticas y roles, y escribir los secretos iniciales, el arquetipo de CodeDesignPlus proporciona dos scripts de configuración (Windows y Linux) que se pueden ejecutar en el entorno de desarrollo. Estos scripts se encuentran en la carpeta tools/vault del microservicio creado con el generador de CodeDesignPlus.

Configura Vault con métodos de autenticación, motores de secretos, políticas y roles, y escribe los secretos iniciales.

#!/bin/bash
# Define colors
BLUE='\033[0;34m'
NC='\033[0m' # No color
# ASCII Art for CodeDesignPlus
ascii_art=$(cat <<'EOF'
___ _ ___ _ ___ _
/ __\___ __| | ___ / \___ ___(_) __ _ _ __ / _ \ |_ _ ___
/ / / _ \ / _` |/ _ \ / /\ / _ \/ __| |/ _` | '_ \ / /_)/ | | | / __|
/ /__| (_) | (_| | __// /_// __/\__ \ | (_| | | | / ___/| | |_| \__ \
\____/\___/ \__,_|\___/___,' \___||___/_|\__, |_| |_\/ |_|\__,_|___/
|___/
EOF
)
echo "$ascii_art"
# Your Vault Address and Login
export VAULT_ADDR="http://localhost:8200"
echo "${BLUE}-Logging in to Vault...${NC}"
vault login token=root
newlines=$'\n'
# Enable AppRole
echo "$newlines"
echo "${BLUE}1. Enabling auth methods...${NC}"
if vault auth list | grep -q 'approle/'; then
echo " - The method of authentication 'approle' already exists."
else
echo " - Enabling the method of authentication 'approle'..."
vault auth enable approle
fi
# Enable Secret, database and rabbtimq
echo "$newlines"
echo "${BLUE}2. Enabling secrets engines...${NC}"
if vault secrets list | grep -q 'vault-keyvalue/'; then
echo " - The secrets engine 'kv-v2' already exists in 'vault-keyvalue/'."
else
echo " - Enabling the secrets engine 'kv-v2' in 'vault-keyvalue/'..."
vault secrets enable -path=vault-keyvalue kv-v2
fi
if vault secrets list | grep -q 'vault-database/'; then
echo " - The secrets engine 'database' already exists in 'vault-database/'."
else
echo " - Enabling the secrets engine 'database' in 'vault-database/'..."
vault secrets enable -path=vault-database database
fi
if vault secrets list | grep -q 'vault-rabbitmq/'; then
echo " - The secrets engine 'rabbitmq' already exists in 'vault-rabbitmq/'."
else
echo " - Enabling the secrets engine 'rabbitmq' in 'vault-rabbitmq/'..."
vault secrets enable -path=vault-rabbitmq rabbitmq
fi
if vault secrets list | grep -q 'vault-transit/'; then
echo " - The secrets engine 'transit' already exists in 'vault-transit/'."
else
echo " - Enabling the secrets engine 'transit' in 'vault-transit/'..."
vault secrets enable -path=vault-transit transit
fi
# Create policies
echo "$newlines"
policy_name="full-access"
if vault policy read $policy_name > /dev/null 2>&1; then
echo "${BLUE}3. The policy '$policy_name' already exists.${NC}"
else
echo "${BLUE}3. Creating policy '$policy_name'...${NC}"
vault policy write $policy_name - <<EOF
path "*" {
capabilities = ["create", "read", "update", "delete", "list"]
}
EOF
fi
# Create roles
echo "$newlines"
role_name="vault-approle"
if vault read auth/approle/role/$role_name > /dev/null 2>&1; then
echo "${BLUE}4. The AppRole '$role_name' already exists.${NC}"
else
echo "${BLUE}4. Creating AppRole '$role_name'...${NC}"
vault write auth/approle/role/$role_name policies="full-access"
fi
# Get Role ID and Secret ID, etc...
role_id=$(vault read auth/approle/role/vault-approle/role-id | grep 'role_id' | awk '{print $2}')
secret_id=$(vault write -f auth/approle/role/vault-approle/secret-id | grep 'secret_id ' | awk '{print $2}')
if [ -z "$role_id" ] || [ -z "$secret_id" ]; then
echo "Error: Not found role_id or secret_id"
exit 1
fi
echo " Role ID: $role_id"
echo " Secret ID: $secret_id"
# Login with approle
echo "$newlines"
echo "${BLUE}5. Login with approle...${NC}"
vault write auth/approle/login role_id=$role_id secret_id=$secret_id
# Write secrets, db config, rabbitmq config
echo "$newlines"
echo "${BLUE}6. Writing secrets...${NC}"
vault kv put -mount=vault-keyvalue ms-archetype \
Security:ClientId=a74cb192-598c-4757-95ae-b315793bbbca \
Security:ValidAudiences:0=a74cb192-598c-4757-95ae-b315793bbbca \
Security:ValidAudiences:1=api://a74cb192-598c-4757-95ae-b315793bbbca
vault kv get -mount=vault-keyvalue ms-archetype
# Write database configuration
echo "$newlines"
echo "${BLUE}7. Writing database configuration...${NC}"
vault write vault-database/config/db-ms-archetype \
plugin_name=mongodb-database-plugin \
allowed_roles="ms-archetype-mongo-role" \
connection_url="mongodb://{{username}}:{{password}}@mongo:27017/admin?ssl=false" \
username="admin" \
password="password"
vault write vault-database/roles/ms-archetype-mongo-role \
db_name=db-ms-archetype \
creation_statements='{ "db": "admin", "roles": [{ "role": "readWrite", "db": "db-ms-archetype" }] }' \
default_ttl="1h" \
max_ttl="24h"
vault read vault-database/creds/ms-archetype-mongo-role
# Write rabbitmq configuration
echo "$newlines"
echo "${BLUE}8. Writing rabbitmq configuration...${NC}"
sleep 12
vault write vault-rabbitmq/config/connection \
connection_uri="http://rabbitmq:15672" \
username="admin" \
password="password"
vault write vault-rabbitmq/roles/ms-archetype-rabbitmq-role \
vhosts='{"/":{"write": ".*", "read": ".*", "configure": ".*"}}'
vault read vault-rabbitmq/creds/ms-archetype-rabbitmq-role

RabbitMQ

RabbitMQ es un broker de mensajes de código abierto que implementa el protocolo AMQP (Advanced Message Queuing Protocol). Permite la comunicación asíncrona entre servicios, desacoplando las aplicaciones y facilitando la escalabilidad y resiliencia.

Se basa en el patrón de diseño Publicar/Suscribir (Publish/Subscribe) y se utiliza en arquitecturas Orientadas a Eventos (Event-Driven Architecture). Los servicios publican mensajes en un exchange, y otros servicios se suscriben a las colas para recibir mensajes de interés.

RabbitMQ

Convenciones de Nombres:

El SDK de CodeDesignPlus implementa una serie de convenciones para los exchanges, colas y rutas de RabbitMQ. Estas convenciones se basan en la configuración del microservicio, especialmente en la sección Core :

{
"Core": {
"AppName": "ms-archetype",
"Version": "v1",
"Description": "Microservice Archetype Template",
"Business": "CodeDesignPlus",
"Contact": {
"Name": "CodeDesignPlus",
"Email": "codedesignplus@outlook.com"
}
}
}
  • Exchange: [bussiness].[appname].v[number-version].[aggregate|entity].[event]
  • Queue: [bussiness].[appname].v[number-version].[aggregate|entity].[event]
  • Exchange Dlx: [bussiness].[appname].v[number-version].[aggregate|entity].[event].dlx
  • Queue Dlx: [bussiness].[appname].v[number-version].[aggregate|entity].[event].dlx

Beneficios:

  • Permite la comunicación asíncrona entre servicios, mejorando la escalabilidad y desacoplamiento.
  • Facilita la implementación de arquitecturas orientadas a eventos y patrones de diseño de mensajería.
  • Proporciona mecanismos de colas, exchanges y enrutamiento para gestionar mensajes de forma eficiente.

Acceso:

El entorno de desarrollo incluye un servicio de RabbitMQ con las siguientes credenciales y accesos:

  • UI: http://localhost:15672 (con usuario admin y contraseña password).

  • AMQP: amqp://localhost:5672 (conexión para aplicaciones).

MongoDB

MongoDB es una base de datos NoSQL orientada a documentos. Almacena datos en formato JSON-like (BSON), lo que permite una gran flexibilidad en el esquema de datos. Es ideal para aplicaciones con requisitos de datos variados y que necesitan una alta escalabilidad horizontal.

Es común en microservicios que necesitan flexibilidad de datos. Al no tener un esquema rígido como las bases de datos relacionales, permite evolucionar fácilmente los datos de cada microservicio.

MongoDB

Convenciones de Nombres:

El SDK de CodeDesignPlus implementa una serie de convenciones para el nombre de las bases de datos y las colecciones de MongoDB. Estas convenciones se basan en la configuración del microservicio, especialmente en la sección Core:

{
"Core": {
"AppName": "ms-archetype",
"Version": "v1",
"Description": "Microservice Archetype Template",
"Business": "CodeDesignPlus",
"Contact": {
"Name": "CodeDesignPlus",
"Email": "codedesignplus@outlook.com"
}
}
}
  • Base de Datos: db-[appname]
  • Colección: [aggregate|entity]

Beneficios:

  • Almacenamiento flexible de datos, ideal para aplicaciones con requisitos de datos variados.
  • Escalabilidad horizontal, permitiendo manejar grandes volúmenes de datos y tráfico.
  • Facilidad de uso y mantenimiento, con una sintaxis similar a JSON y una comunidad activa.

Acceso:

El servicio de MongoDB se encuentra disponible en mongodb://localhost:27017 (con usuario admin y contraseña password). Sin embargo, el servicio de Vault se encarga de gestionar las credenciales para los microserviciosa partir de la siguiente configuración:

Terminal window
# ...
# Write database configuration
echo "7. Writing database configuration..."
vault write archetype-database/config/db-ms-archetype \
plugin_name=mongodb-database-plugin \
allowed_roles="ms-archetype-mongo-role" \
connection_href="mongodb://{{username}}:{{password}}@mongo:27017/admin?ssl=false" \
username="admin" \
password="password"
vault write archetype-database/roles/ms-archetype-mongo-role \
db_name=db-ms-archetype \
creation_statements='{ "db": "admin", "roles": [{ "role": "readWrite", "db": "db-ms-archetype" }] }' \
default_ttl="1h" \
max_ttl="24h"
vault read archetype-database/creds/ms-archetype-mongo-role
# ...

Este script de configuración de Vault es responsable de escribir la configuración de la base de datos y los roles de acceso, y de generar credenciales temporales para acceder a la base de datos.

Redis

Redis es una base de datos en memoria de tipo clave-valor que puede usarse como cache, broker de mensajes y base de datos. Su principal fortaleza es su velocidad y baja latencia, ideal para aplicaciones que requieren respuestas rápidas y manejo de sesiones.

Se usa como cache para datos que no cambian frecuentemente o como un almacenamiento rápido de datos volátiles que se requiere que sean accedidos muy rápidamente por la aplicación.

Convenciones de Nombres:

El SDK de CodeDesignPlus implementa una serie de convenciones para los nombres de las bases de datos y las claves de Redis. Estas convenciones se basan en la configuración del microservicio, especialmente en la sección Core:

{
"Core": {
"AppName": "ms-archetype",
"Version": "v1",
"Description": "Microservice Archetype Template",
"Business": "CodeDesignPlus",
"Contact": {
"Name": "CodeDesignPlus",
"Email": "codedesignplus@outlook.com"
}
}
}
  • Key: [bussiness]:[appname]:[key]
Redis

Beneficios:

  • Cache de alto rendimiento y broker de mensajes, ideal para aplicaciones que requieren respuestas rápidas.
  • Almacenamiento en memoria, lo que permite una baja latencia y alta velocidad de acceso a los datos.
  • Persistencia de datos, permitiendo almacenar datos en disco para recuperarlos en caso de fallo.

Acceso:

  • Disponible en redis://localhost:6379 para clientes instalados en la máquina local o redis://redis:6379 para clientes en contenedores como Redis Insight aal que se puede acceder en http://localhost:5540/.

    Redis Redis

Grafana

Grafana es una plataforma de código abierto para visualización y análisis de datos. Permite crear dashboards personalizados con gráficos, tablas y paneles para monitorear métricas de la aplicación y la infraestructura. Se integra con múltiples fuentes de datos como Prometheus, Loki y otros.

Es esencial para observar la salud y el rendimiento de los microservicios. Facilita la detección temprana de problemas y la optimización de recursos.

Beneficios:

  • Permite crear dashboards para visualizar métricas de la aplicación y la infraestructura.
  • Integración con múltiples fuentes de datos como Prometheus, Loki y otros.
  • Alertas y notificaciones para detectar problemas y optimizar recursos.

Acceso:

Para acceder a Grafana, visita http://localhost:3000.

La pagina de inicio de Grafana muestra los dashboards y las fuentes de datos disponibles.

Grafana

Configuración:

El archivo docker-compose.yaml incluye configuraciones para Grafana, como fuentes de datos y dashboards predefinidos.

Configuración de las fuentes de datos para Grafana, incluyendo Prometheus y Loki.

apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
uid: prometheus
access: proxy
orgId: 1
url: http://prometheus:9090
basicAuth: false
isDefault: false
version: 1
editable: false
jsonData:
httpMethod: GET
- name: Tempo
type: tempo
access: proxy
orgId: 1
url: http://tempo:3200
basicAuth: false
isDefault: true
version: 1
editable: false
apiVersion: 1
uid: tempo
jsonData:
httpMethod: GET
serviceMap:
datasourceUid: prometheus
- name: Loki
type: loki
access: proxy
orgId: 1
url: http://loki:3100
basicAuth: false
isDefault: false
version: 1
editable: false

OpenTelemetry Collector

El OpenTelemetry Collector es un componente que recibe datos de telemetría (métricas, logs y trazas) generados por las aplicaciones y los envía a los sistemas de back-end de monitoreo. Es un componente flexible y configurable que simplifica la recolección y envío de datos de telemetría.

Beneficios:

  • Recolecta, procesa y exporta datos de telemetría (métricas, logs y trazas) hacia los diferentes backends.
  • Simplifica la configuración y recolección de datos de telemetría, reduciendo la complejidad de la instrumentación.
  • Permite la integración con múltiples sistemas de monitoreo como Prometheus, Loki y Jaeger.

Acceso:

Para enviar datos de telemetría al OpenTelemetry Collector, las aplicaciones deben configurar los puertos de recolección definidos en el archivo de configuración otel-config.yaml:

  • OTLP gRPC: localhost:4317
  • OTLP HTTP: localhost:4318

Pero el componente de OpenTelemetry Collector al no tener una interfaz gráfica. Sin embargo, se puede visualizar el estado del mismo en los paneles de grafana Grafana como processors, receivers, exporters y el estado del OTEL en el panel Collector. Estos pueden o no mostrar información dependiendo de la interacción con el OTEL.

El panel de Receivers muestra el comportamiento de los receptores de datos del OTEL.

OpenTelemetry Collector

Configuración:

El archivo docker-compose.yaml incluye configuraciones para el OpenTelemetry Collector, como el archivo de configuración otel-config.yaml.

receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
prometheus:
config: # Automatically scrape the Prometheus metrics
scrape_configs:
- job_name: otel-collector-metrics
scrape_interval: 10s
static_configs:
- targets: ['localhost:8888']
- job_name: 'loki'
scrape_interval: 10s
static_configs:
- targets: ['host.docker.internal:3100']
- job_name: 'tempo'
scrape_interval: 10s
static_configs:
- targets: ['host.docker.internal:3200']
exporters:
debug:
verbosity: detailed
loki:
endpoint: "http://host.docker.internal:3100/loki/api/v1/push"
otlp:
endpoint: host.docker.internal:5317 # Send to Tempo
tls:
insecure: true
prometheus:
endpoint: 0.0.0.0:8889 # Endpoint to scrape metrics from prometheus
service:
pipelines:
traces:
receivers: [otlp]
exporters: [otlp]
logs:
receivers: [otlp]
exporters: [loki]
metrics:
receivers: [otlp, prometheus]
exporters: [prometheus]

Loki

Loki es un sistema de agregación de logs de código abierto. Está diseñado para ser rentable y fácil de operar, lo que lo hace ideal para el monitoreo de logs en microservicios. Es especialmente efectivo en combinación con Grafana para la visualización y el análisis de logs.

Beneficios:

  • Almacenamiento de logs en texto plano y agregacion de forma simple.
  • Integración con Grafana para visualización y análisis de logs.
  • Bajo costo y fácil operación, ideal para microservicios y aplicaciones distribuidas.

Acceso:

El componente de Loki no tiene una interfaz gráfica. Sin embargo, el servicio expone un puerto para la recolección de datos en 3100 que es usado por Open Telemetry Collector para enviar los logs y por Grafana para visualizarlos.

Para visualizar los logs en Grafana, se debe configurar una fuente de datos de Loki y proceder al panel de logs en Grafana.

El panel de Explore en Grafana permite realizar consultas y visualizar logs de Loki.

Loki

Configuración:

El archivo docker-compose.yaml incluye configuraciones para Loki, como el archivo de configuración loki-config.yaml que configura el servidor con almacenamiento en filesystem y habilitación de la API.

auth_enabled: false
server:
http_listen_port: 3100
grpc_listen_port: 9096
memberlist:
bind_addr:
- 0.0.0.0
common:
instance_addr: 127.0.0.1
path_prefix: /tmp/loki
storage:
filesystem:
chunks_directory: /tmp/loki/chunks
rules_directory: /tmp/loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
query_range:
results_cache:
cache:
embedded_cache:
enabled: true
max_size_mb: 100
schema_config:
configs:
- from: 2020-10-24
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
ruler:
alertmanager_url: http://localhost:9093

Tempo

Tempo es un sistema de código abierto para el almacenamiento de trazas. Permite realizar un seguimiento de las peticiones a través de los distintos servicios de una arquitectura de microservicios, lo que facilita el diagnóstico de problemas y la optimización de la aplicación.

Es esencial para el seguimiento y la observabilidad en entornos de microservicios. Facilita la identificación de bottlenecks y errores en las solicitudes que atraviesan varios servicios.

Beneficios:

  • Almacenamiento de trazas.
  • Seguimiento de peticiones a través de los servicios.
  • Diagnóstico de problemas y optimización de la aplicación.

Acceso:

El servicio de Tempo no cuenta con una interfaz gráfica. Sin embargo, se exponen los siguientes puertos:

  • 5317: Puerto de recepción de trazas OTLP gRPC.
  • 5318: Puerto de recepción de trazas OTLP HTTP.
  • 3200: Puerto de la API de Tempo y metricas.

Para visualizar las trazas en Grafana, se debe configurar una fuente de datos de Tempo y proceder al panel de trazas en Grafana.

Tempo

Configuración:

El archivo docker-compose.yaml incluye configuraciones para Tempo, como el archivo de configuración tempo-config.yaml encargado de configurar el servidor con el backend local y el recolector de métricas.

stream_over_http_enabled: true
server:
http_listen_port: 3200
log_level: info
query_frontend:
search:
duration_slo: 5s
throughput_bytes_slo: 1.073741824e+09
trace_by_id:
duration_slo: 5s
distributor:
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318
grpc:
endpoint: 0.0.0.0:4317
ingester:
max_block_duration: 5m # cut the headblock when this much time passes. this is being set for demo purposes and should probably be left alone normally
compactor:
compaction:
block_retention: 1h # overall Tempo trace retention. set for demo purposes
metrics_generator:
registry:
external_labels:
source: tempo
cluster: docker-compose
storage:
path: /tmp/tempo/generator/wal
remote_write:
- url: http://prometheus:9090/api/v1/write
send_exemplars: true
storage:
trace:
backend: local # backend configuration to use
wal:
path: /tmp/tempo/wal # where to store the the wal locally
local:
path: /tmp/tempo/blocks
overrides:
defaults:
metrics_generator:
processors: [service-graphs, span-metrics] # enables metrics generator

Prometheus

Prometheus es un sistema de monitoreo y alertas de código abierto. Recopila métricas de las aplicaciones y los servicios y las almacena en una base de datos de series temporales. Permite realizar consultas y crear alertas basadas en estas métricas. De esta forma se puede monitorear la salud y el rendimiento de la aplicación y la infraestructura.

Beneficios:

  • Recolección y consulta de métricas para monitorear la salud y el rendimiento de la aplicación.
  • Almacenamiento de métricas en una base de datos de series temporales.
  • Creación de alertas para detectar problemas y optimizar recursos.

Acceso: A diferencia de los otros servicios, Prometheus cuenta con una interfaz gráfica que se puede acceder en http://localhost:9090.

Prometheus

En este punto, vemos que Prometheus realiza scraping de los datos de telemetría del OpenTelemetry Collector y los almacena en su base de datos de series temporales.

Para interactuar de una mejor manera con Prometheus, se puede configurar Grafana para que muestre las métricas de Prometheus en dashboards personalizados, lo que facilita la visualización y el análisis de las métricas. Los dashboards disponibles son:

  • 15983: Dashboard de métricas de OpenTelemetry Collector.
  • 17781: Dashboard de métricas de Loki.
  • 19924: ASP.NET Core metrics from OpenTelemetry
  • 19925: ASP.NET Core endpoint metrics from OpenTelemetry

El dashboard de métricas de OpenTelemetry Collector muestra información sobre los procesadores, receptores y exportadores de datos.

Prometheus

Configuración:

El archivo docker-compose.yaml incluye configuraciones para Prometheus, como el archivo de configuración prometheus-config.yaml que define las reglas de alerta, los targets y los jobs para realizar scraping del otel collector.

global:
scrape_configs:
- job_name: "otel-collector"
scrape_interval: 10s
static_configs:
- targets: ["otel-collector-contrib:8889"]

SonarQube

SonarQube es una plataforma de análisis estático de código que identifica problemas de calidad, vulnerabilidades y errores en el código fuente. Es esencial para mantener la calidad del código y prevenir problemas en producción.

Beneficios:

  • Identifica problemas de calidad, vulnerabilidades y errores en el código fuente.
  • Mejora la calidad del código y reduce los errores y vulnerabilidades.
  • Facilita la revisión del código y la detección temprana de problemas.

Cómo usar:

El arquetipo de CodeDesignPlus incluye scripts para ejecutar los análisis de SonarQube en el código fuente. Estos scripts se encuentran en la carpeta tools/sonarqube del microservicio creado con el generador de CodeDesignPlus.

  1. Navegar a http://localhost:9000 y loguearse con las credenciales admin y admin.

    SonarQube
  2. Creamos el token de acceso para el análisis de código, para eso navegamos a My Account -> Security -> Generate Tokens. Ingresamos el nombre y seleccionamos Global Analysis Token.

    SonarQube
  3. Asignamos el token a los scripts sonarqube/sonar.ps1 o sonarqube/sonar.sh en la variable token.

    Terminal window
    $token = "sqa_12f3d20d51de2b4c9639db0035d1c68dc4f2fff1"
  4. Ejecuta el script sonarqube/sonar.ps1 (Windows) o sonarqube/sonar.sh (Linux).

    #!/usr/bin/env pwsh
    #echo "Install dotnet-sonarscanner ----------------------------------------------------------------------------------------------------------------------"
    #dotnet tool install --global dotnet-sonarscanner
    Write-Host "Start Sonarscanner -------------------------------------------------------------------------------------------------------------------------------"
    $org = "codedesignplus"
    $key = "CodeDesignPlus.Net.Microservice"
    $csproj = "CodeDesignPlus.Net.Microservice.sln"
    $report = "tests/**/coverage.opencover.xml"
    $server = "http://localhost:9000"
    $token = "sqa_12f3d20d51de2b4c9639db0035d1c68dc4f2fff1"
    cd ..
    dotnet test $csproj /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
    dotnet sonarscanner begin /o:$org /k:$key /d:sonar.host.url=$server /d:sonar.coverage.exclusions="**Tests*.cs,**/tests/load/*.js" /d:sonar.cs.opencover.reportsPaths=$report /d:sonar.login=$token
    dotnet build
    dotnet sonarscanner end /d:sonar.login=$token
  5. El script ejecuta pruebas, genera reportes de cobertura, inicia un análisis de SonarQube, compila el código y finaliza el análisis.

    SonarQube

Beneficios Clave para el Desarrollador

  • Reducción del tiempo de configuración: El entorno Docker Compose reduce drásticamente el tiempo necesario para configurar un entorno de desarrollo, permitiendo que los desarrolladores empiecen a trabajar en la lógica de negocio rápidamente.
  • Mayor calidad de código: El análisis de código estático con SonarQube/SonarCloud mejora la calidad del código, reduciendo errores y vulnerabilidades.
  • Enfoque en el negocio: Al automatizar las tareas repetitivas, los desarrolladores pueden centrarse en el desarrollo de la lógica de negocio, aumentando la productividad y reduciendo la frustración.
  • Consistencia en el equipo: El uso de Docker garantiza que todos los miembros del equipo trabajen con el mismo entorno, reduciendo las diferencias entre entornos de desarrollo y producción.

Con estas herramientas, CodeDesignPlus busca ofrecer una experiencia de desarrollo más eficiente, estable y agradable, acelerando la entrega de microservicios de alta calidad.