> ## 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.

# Implementando observabilidad en Flowker

Flowker emite trazas, métricas y logs estructurados utilizando el estándar **OpenTelemetry**. Esta guía explica qué está disponible, cómo habilitarlo y cómo interpretar los datos en tu stack de observabilidad.

## Descripción general

***

La telemetría de Flowker se basa en tres señales:

| Señal    | Backend    | Qué cubre                                                         |
| -------- | ---------- | ----------------------------------------------------------------- |
| Trazas   | Tempo      | Spans distribuidos a través de ejecuciones y pasos de workflows   |
| Métricas | Prometheus | Tasas de solicitudes HTTP, latencia y uso de recursos del sistema |
| Logs     | Loki       | Logs JSON estructurados para cada operación                       |

Todas las señales se exportan via **OTLP (OpenTelemetry Protocol)** a un collector de tu elección.

## Configuración

***

La telemetría se controla mediante variables de entorno.

```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 `ENABLE_TELEMETRY=true` está configurado sin `OTEL_EXPORTER_OTLP_ENDPOINT`, Flowker no podrá iniciarse.
</Note>

## Trazabilidad distribuida

***

Cada solicitud HTTP y operación interna crea un **span de OpenTelemetry**. Los spans se propagan a través de toda la cadena de ejecución, por lo que una sola ejecución de workflow produce una traza conectada desde el handler HTTP hasta los pasos individuales del executor.

### Convención de nombres de spans

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

**Spans de ejecución**

| Nombre del span                                  | Descripción                                                             |
| ------------------------------------------------ | ----------------------------------------------------------------------- |
| `command.execution.execute`                      | Span raíz para la ejecución de un workflow                              |
| `command.execution.execute_executor_node`        | Span para cada nodo de executor procesado                               |
| `command.execution.execute_with_provider_config` | Span para un nodo resuelto con una configuración de provider específica |
| `command.execution.recover`                      | Span para la recuperación de ejecuciones incompletas al inicio          |

**Spans de comandos de workflow**

| Nombre del span               | Descripción                      |
| ----------------------------- | -------------------------------- |
| `command.workflow.create`     | Crear un nuevo workflow          |
| `command.workflow.update`     | Actualizar un workflow existente |
| `command.workflow.activate`   | Activar un workflow              |
| `command.workflow.deactivate` | Desactivar un workflow           |
| `command.workflow.clone`      | Clonar un workflow               |
| `command.workflow.delete`     | Eliminar un workflow             |

**Spans de configuración de executor**

| Nombre del span                             | Descripción                            |
| ------------------------------------------- | -------------------------------------- |
| `command.executor_config.create`            | Crear configuración de executor        |
| `command.executor_config.update`            | Actualizar configuración de executor   |
| `command.executor_config.activate`          | Activar configuración de executor      |
| `command.executor_config.enable`            | Habilitar configuración de executor    |
| `command.executor_config.disable`           | Deshabilitar configuración de executor |
| `command.executor_config.mark_configured`   | Marcar executor como configurado       |
| `command.executor_config.mark_tested`       | Marcar executor como probado           |
| `command.executor_config.test_connectivity` | Probar conectividad del executor       |
| `command.executor_config.delete`            | Eliminar configuración de executor     |

**Spans de configuración de provider**

| Nombre del span                             | Descripción                            |
| ------------------------------------------- | -------------------------------------- |
| `command.provider_config.create`            | Crear configuración de provider        |
| `command.provider_config.update`            | Actualizar configuración de provider   |
| `command.provider_config.enable`            | Habilitar configuración de provider    |
| `command.provider_config.disable`           | Deshabilitar configuración de provider |
| `command.provider_config.test_connectivity` | Probar conectividad del provider       |
| `command.provider_config.delete`            | Eliminar configuración de provider     |

**Spans de consulta**

| Nombre del span                        | Descripción                                                  |
| -------------------------------------- | ------------------------------------------------------------ |
| `query.execution.get`                  | Obtener ejecución por ID                                     |
| `query.execution.list`                 | Listar ejecuciones                                           |
| `query.execution.get_results`          | Obtener resultados de ejecución                              |
| `query.workflow.get`                   | Obtener workflow por ID                                      |
| `query.workflow.get_by_name`           | Obtener workflow por nombre                                  |
| `query.workflow.list`                  | Listar workflows                                             |
| `query.executor_config.get`            | Obtener configuración de executor por ID                     |
| `query.executor_config.get_by_name`    | Obtener configuración de executor por nombre                 |
| `query.executor_config.list`           | Listar configuraciones de executor                           |
| `query.executor_config.exists`         | Verificar existencia de configuración de executor            |
| `query.executor_config.exists_by_name` | Verificar existencia de configuración de executor por nombre |
| `query.provider_config.get`            | Obtener configuración de provider por ID                     |
| `query.provider_config.list`           | Listar configuraciones de provider                           |

<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 una traza completa de workflow.
</Tip>

## Métricas

***

Flowker expone métricas HTTP y del sistema automáticamente a través del SDK de OpenTelemetry. No se necesita configuración adicional más allá de habilitar la telemetría.

### Métricas HTTP (via 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 | Número de solicitudes en curso              |

Cada métrica incluye las etiquetas: `http.method`, `http.route`, `http.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 de histograma

Los histogramas de latencia utilizan los siguientes límites de bucket (en segundos):

```
0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10
```

<Note>
  Flowker no expone un endpoint de scrape de Prometheus (`/metrics`) directamente. Las métricas se exportan via OTLP a tu collector, que luego las envía a Prometheus. Configura tu collector OTLP para incluir un exportador `prometheusremotewrite`.
</Note>

## Logging estructurado

***

Flowker utiliza **logging JSON estructurado** via Zap. Cada entrada de log se enriquece con campos contextuales que pueden ser indexados y consultados en Loki.

### Referencia de campos de log

| Campo           | Descripción                                  | Ejemplo                     |
| --------------- | -------------------------------------------- | --------------------------- |
| `operation`     | Nombre del span/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 executor                   | `exec_cfg_001`              |
| `error.message` | Descripción del error cuando aplica          | `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` | Fallos de operación que requieren atención                       |

Configura la variable de entorno `LOG_LEVEL` para controlar la verbosidad.

### 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 ejecuciones incompletas:

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

Ejecución fallida:

```json theme={null}
{
  "level": "error",
  "execution.id": "exec_xyz789",
  "workflow.id": "wf_abc123",
  "execution.status": "failed",
  "error.message": "executor node missing providerConfigId",
  "message": "Workflow execution failed"
}
```

## Sondas de salud

***

Flowker expone sondas de liveness y readiness compatibles con Kubernetes para monitoreo operacional. Liveness indica si el proceso está en ejecución; readiness indica si las dependencias (notablemente la base de datos) están accesibles. Configura ambas a nivel del cluster, como parte de tus manifiestos de despliegue, para que la orquestación pueda reiniciar pods no saludables y remover 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. Los dashboards preconfigurados están disponibles a través de la instancia de Grafana administrada por Lerian.

### Paneles recomendados

**Throughput de solicitudes**

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

**Latencia P95**

* Query: `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**

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

**Ejecuciones activas (via logs)**

* Loki query: `{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>
