> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lerian.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Implementación de observabilidad en Flowker

> Habilita e interpreta los traces, las métricas y los logs estructurados de OpenTelemetry de Flowker en Tempo, Prometheus y Loki a través de un collector OTLP estándar.

Flowker emite traces, métricas y logs estructurados usando el estándar **OpenTelemetry**.

## Resumen

***

La telemetría de Flowker usa tres señales:

| Señal    | Backend    | Qué cubre                                                         |
| -------- | ---------- | ----------------------------------------------------------------- |
| Traces   | Tempo      | Spans distribuidos en las ejecuciones y los pasos del workflow    |
| Métricas | Prometheus | Tasas de solicitudes HTTP, latencia y uso de recursos del sistema |
| Logs     | Loki       | Logs JSON estructurados para cada operación                       |

Flowker exporta todas las señales mediante **OTLP (OpenTelemetry Protocol)** a un collector de tu elección.

## Configuración

***

Las variables de entorno controlan la telemetría.

```bash theme={null}
# Enable telemetry (required to activate OTLP export)
ENABLE_TELEMETRY=true

# OTLP collector endpoint (required when ENABLE_TELEMETRY=true)
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317

# Service identity
OTEL_RESOURCE_SERVICE_NAME=flowker
OTEL_RESOURCE_SERVICE_VERSION=1.0.0
OTEL_RESOURCE_DEPLOYMENT_ENVIRONMENT=production
OTEL_LIBRARY_NAME=flowker

# Log verbosity: debug | info | warn | error
LOG_LEVEL=info
```

<Note>
  Si defines `ENABLE_TELEMETRY=true` sin `OTEL_EXPORTER_OTLP_ENDPOINT`, Flowker no podrá iniciar.
</Note>

## Trazado distribuido

***

Cada solicitud HTTP y operación interna crea un **span de OpenTelemetry**. Los spans se propagan a lo largo de toda la cadena de ejecución. Una única ejecución de workflow genera un trace conectado, desde el handler HTTP hasta cada paso individual del ejecutor.

### Convención de nombres de spans

Los spans siguen el patrón `<layer>.<resource>.<operation>`:

**Spans de ejecución**

| Nombre del span                                  | Descripción                                                            |
| ------------------------------------------------ | ---------------------------------------------------------------------- |
| `command.execution.execute`                      | Span raíz de una ejecución de workflow                                 |
| `command.execution.execute_executor_node`        | Span de cada nodo ejecutor procesado                                   |
| `command.execution.execute_with_provider_config` | Span de un nodo resuelto con una configuración de proveedor específica |
| `command.execution.recover`                      | Span de la recuperación de una ejecución incompleta al iniciar         |

**Spans de comandos de workflow**

| Nombre del span                  | Descripción                                |
| -------------------------------- | ------------------------------------------ |
| `command.workflow.create`        | Crea un workflow nuevo                     |
| `command.workflow.update`        | Actualiza un workflow existente            |
| `command.workflow.activate`      | Activa un workflow                         |
| `command.workflow.deactivate`    | Desactiva un workflow                      |
| `command.workflow.move_to_draft` | Devuelve un workflow al estado de borrador |
| `command.workflow.clone`         | Clona un workflow                          |
| `command.workflow.delete`        | Elimina un workflow                        |

**Spans de configuración de ejecutor**

| Nombre del span                  | Descripción                             |
| -------------------------------- | --------------------------------------- |
| `command.executor_config.update` | Actualiza la configuración del ejecutor |
| `command.executor_config.delete` | Elimina la configuración del ejecutor   |

**Spans de configuración de proveedor**

| Nombre del span                   | Descripción                                |
| --------------------------------- | ------------------------------------------ |
| `command.provider_config.create`  | Crea una configuración de proveedor        |
| `command.provider_config.update`  | Actualiza una configuración de proveedor   |
| `command.provider_config.enable`  | Habilita una configuración de proveedor    |
| `command.provider_config.disable` | Deshabilita una configuración de proveedor |
| `command.provider_config.delete`  | Elimina una configuración de proveedor     |

**Spans de consultas**

| Nombre del span               | Descripción                                   |
| ----------------------------- | --------------------------------------------- |
| `query.execution.get`         | Obtiene una ejecución por ID                  |
| `query.execution.list`        | Lista ejecuciones                             |
| `query.execution.get_results` | Obtiene los resultados de una ejecución       |
| `query.workflow.get`          | Obtiene un workflow por ID                    |
| `query.workflow.list`         | Lista workflows                               |
| `query.executor_config.get`   | Obtiene una configuración de ejecutor por ID  |
| `query.executor_config.list`  | Lista configuraciones de ejecutor             |
| `query.provider_config.get`   | Obtiene una configuración de proveedor por ID |
| `query.provider_config.list`  | Lista configuraciones de proveedor            |

<Tip>
  En Grafana Tempo, busca por nombre de servicio (`flowker`) y filtra por nombre de span para aislar operaciones específicas. Usa `command.execution.execute` como punto de entrada para ver un trace completo del workflow.
</Tip>

## Métricas

***

Flowker expone métricas HTTP y del sistema de forma automática mediante el SDK de OpenTelemetry. Solo necesitas habilitar la telemetría.

### Métricas HTTP (mediante otelfiber)

Recopiladas por ruta mediante el middleware `otelfiber`:

| Métrica                       | Tipo          | Descripción                                 |
| ----------------------------- | ------------- | ------------------------------------------- |
| `http.server.duration`        | Histogram     | Duración de la solicitud en milisegundos    |
| `http.server.request.size`    | Histogram     | Tamaño del payload de la solicitud en bytes |
| `http.server.response.size`   | Histogram     | Tamaño del payload de la respuesta en bytes |
| `http.server.active_requests` | UpDownCounter | Cantidad de solicitudes en curso            |

Cada métrica lleva labels: `http.request.method`, `http.route`, `http.response.status_code`.

### Métricas del sistema

| Métrica            | Tipo  | Unidad     | Descripción                         |
| ------------------ | ----- | ---------- | ----------------------------------- |
| `system.cpu.usage` | Gauge | porcentaje | Uso de CPU del host del proceso     |
| `system.mem.usage` | Gauge | porcentaje | Uso de memoria del host del proceso |

### Buckets del histograma

Los histogramas de latencia usan los límites de bucket predeterminados del SDK de OpenTelemetry. Los valores de `http.server.duration` están en milisegundos, por lo que los límites son:

```
0, 5, 10, 25, 50, 75, 100, 250, 500, 750, 1000, 2500, 5000, 7500, 10000
```

<Note>
  Flowker no expone un endpoint de scrape de Prometheus (`/metrics`) directamente. Flowker exporta métricas mediante OTLP a tu collector, que luego las reenvía a Prometheus. Configura tu collector OTLP para incluir un exporter `prometheusremotewrite`.
</Note>

## Logging estructurado

***

Flowker usa **logging JSON estructurado** mediante Zap. Cada entrada de log lleva campos contextuales. Puedes indexar y consultar estos campos en Loki.

### Referencia de campos de log

| Campo           | Descripción                                  | Ejemplo                     |
| --------------- | -------------------------------------------- | --------------------------- |
| `operation`     | Nombre del span o de la operación            | `command.execution.execute` |
| `workflow.id`   | Identificador del workflow                   | `wf_abc123`                 |
| `execution.id`  | Identificador de la ejecución                | `exec_xyz789`               |
| `node.id`       | Identificador del nodo dentro de un workflow | `node-payment`              |
| `executor.id`   | Identificador del ejecutor                   | `exec_cfg_001`              |
| `error.message` | Descripción del error, cuando corresponde    | `database ping failed: ...` |

### Niveles de log

| Nivel   | Cuándo se usa                                                    |
| ------- | ---------------------------------------------------------------- |
| `debug` | Estado interno detallado, solo para desarrollo                   |
| `info`  | Hitos de operación normal (ejecución iniciada, recuperada, etc.) |
| `warn`  | Problemas recuperables o condiciones inesperadas pero no fatales |
| `error` | Fallas de operación que requieren atención                       |

Define la variable de entorno `LOG_LEVEL` para controlar el nivel de detalle.

### Ejemplos de entradas de log

Ejecución de workflow iniciada:

```json theme={null}
{
  "level": "info",
  "operation": "command.execution.execute",
  "workflow.id": "wf_abc123",
  "message": "Starting workflow execution"
}
```

Recuperación de una ejecución incompleta:

```json theme={null}
{
  "level": "info",
  "operation": "command.execution.recover",
  "count": 3,
  "message": "Recovering incomplete executions"
}
```

Nodo ejecutor mal configurado:

```json theme={null}
{
  "level": "error",
  "node.id": "node-payment",
  "execution.id": "exec_xyz789",
  "message": "Executor node missing providerConfigId"
}
```

## Sondas de salud

***

Flowker expone sondas de liveness y readiness compatibles con Kubernetes para el monitoreo operativo. Liveness indica si el proceso sigue en ejecución. Readiness indica si las dependencias (en particular, la base de datos) son alcanzables. Configura ambas en el nivel del clúster, como parte de tus manifiestos de despliegue. La orquestación puede entonces reiniciar los pods no saludables y quitar las instancias degradadas de los balanceadores de carga.

## Dashboards de Grafana

***

La telemetría de Flowker se integra directamente con el stack de observabilidad de Lerian. Hay dashboards preconfigurados disponibles a través de la instancia de Grafana gestionada por Lerian.

### Paneles recomendados

**Rendimiento de solicitudes**

* Consulta: `sum(rate(http_server_duration_count{service_name="flowker"}[5m])) by (http_route)`
* Muestra las solicitudes por segundo, desglosadas por ruta

**Latencia P95**

* Consulta: `histogram_quantile(0.95, sum(rate(http_server_duration_bucket{service_name="flowker"}[5m])) by (le, http_route))`
* Muestra el tiempo de respuesta del percentil 95 por ruta

**Tasa de errores**

* Consulta: `sum(rate(http_server_duration_count{service_name="flowker", http_response_status_code=~"5.."}[5m])) / sum(rate(http_server_duration_count{service_name="flowker"}[5m]))`
* Muestra la proporción de respuestas 5xx

**Ejecuciones activas (mediante logs)**

* Consulta de Loki: `{service_name="flowker"} |= "Starting workflow execution" | count_over_time([1m])`

<Note>
  Para la configuración completa del stack de observabilidad, consulta [**Plataforma → Observabilidad**](/es/platform/observability).
</Note>
