# Lee los logs de un Workload
Continúa desde [Despliega un Workload desde una imagen pública](/es/guides/containers-deploy). Usa el ayudante `api` de esa guía, además de `PROJECT_ID` y `SERVICE_ID`. Qué se guarda y durante cuánto tiempo está en [Logs y métricas](/es/units/logs-and-metrics).

```bash
export LOGS="$ZAROZ_API/projects/$PROJECT_ID/service-instances/$SERVICE_ID/units/logs"
```

:::note{title="Estado de la API"}
Las rutas de unidades las usa la consola y están marcadas como solo consola en la referencia de la API. Aceptan tu token de sesión o un token de acceso personal.
:::

## Las líneas más nuevas

Sin parámetros obtienes las 500 líneas más nuevas de todas las unidades juntas. Dentro de la página, las líneas llegan de la más antigua a la más nueva.

```bash
curl -s "$LOGS?limit=100" -H "Authorization: Bearer $ZAROZ_TOKEN" | jq -r '.lines[] | "\(.at) u\(.unit_ordinal) \(.text)"'
```

```ts
const base = `/projects/${projectId}/service-instances/${serviceId}/units/logs`;
const page = await api("GET", `${base}?limit=100`);
for (const l of page.lines) console.log(l.at, `u${l.unit_ordinal}`, l.text);
console.log(page.coverage);
```

```python
base = f"/projects/{project_id}/service-instances/{service_id}/units/logs"
page = api("GET", base, limit=100)
for l in page["lines"]:
    print(l["at"], f"u{l['unit_ordinal']}", l["text"])
print(page["coverage"])
```

## Retroceder

`next_cursor` indica dónde continuar en la dirección en que lees. Devuélvelo exactamente como lo recibiste. Es `null` cuando se agotan los 30 días de retención.

```ts
let cursor: string | null = null;
for (let i = 0; i < 5; i++) {
  const q = new URLSearchParams({ limit: "500", ...(cursor ? { cursor } : {}) });
  const p = await api("GET", `${base}?${q}`);
  for (const l of p.lines) console.log(l.at, l.text);
  cursor = p.next_cursor;
  if (!cursor) break;
}
```

```python
cursor = None
for _ in range(5):
    p = api("GET", base, limit=500, **({"cursor": cursor} if cursor else {}))
    for l in p["lines"]:
        print(l["at"], l["text"])
    cursor = p["next_cursor"]
    if not cursor:
        break
```

```bash
curl -s "$LOGS?limit=500&cursor=$NEXT_CURSOR" -H "Authorization: Bearer $ZAROZ_TOKEN"
```

## Filtrar

- `search=error`: subcadena sin distinguir mayúsculas, de hasta 200 caracteres, no una expresión regular.
- `unit_id=<uuid>`: una unidad, viva o ya retirada. Los ids están en `GET .../units`.
- `container=<nombre>`: el nombre de un contenedor.
- `from` y `to`: instantes RFC 3339, recortados a los últimos 30 días.

```bash
curl -s "$LOGS?search=timeout&from=2026-10-13T00:00:00Z" -H "Authorization: Bearer $ZAROZ_TOKEN"
```

## Seguir en directo

Lee hacia delante desde el `follow_cursor` de tu última página, y espera `poll_after_ms` entre consultas en lugar de fijar un intervalo.

```bash
curl -s "$LOGS?direction=forward&cursor=$FOLLOW_CURSOR" -H "Authorization: Bearer $ZAROZ_TOKEN"
```

```ts
let follow: string | null = (await api("GET", `${base}?limit=20`)).follow_cursor;
for (;;) {
  const q = new URLSearchParams({ direction: "forward", ...(follow ? { cursor: follow } : {}) });
  const p = await api("GET", `${base}?${q}`);
  for (const l of p.lines) console.log(l.at, `u${l.unit_ordinal}`, l.text);
  follow = p.follow_cursor ?? follow;
  await new Promise((r) => setTimeout(r, p.poll_after_ms));
}
```

```python
import time
follow = api("GET", base, limit=20)["follow_cursor"]
while True:
    p = api("GET", base, direction="forward", **({"cursor": follow} if follow else {}))
    for l in p["lines"]:
        print(l["at"], f"u{l['unit_ordinal']}", l["text"])
    follow = p["follow_cursor"] or follow
    time.sleep(p["poll_after_ms"] / 1000)
```

Una línea tiene el mismo `id` allí donde se lea, así que si reinicias un seguidor puedes descartar las líneas que ya imprimiste.

## Marcas

`markers` contiene hechos del ciclo de vida entre las líneas: un pod arrancado, sustituido o perdido, y `container_restarted` con un `reason` como `OOMKilled` o `Error`. Cuando un contenedor escribe más de 500 líneas por segundo, el resto va a un archivo y una marca `overflow` dice cuántas y cuándo; no se pierde nada, y la ruta de descarga las devuelve en orden.

## Descargar

`GET .../units/logs/download` devuelve un archivo con el desbordamiento archivado ya mezclado, para cuando necesitas todas las líneas.
