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

# SDK Python: logs e status ao vivo

> Acompanhe ao vivo os logs, o status e os eventos de uma aplicação com client.apps.realtime() no SDK Python, síncrono ou assíncrono, com reconexão automática.

`client.apps.realtime(app_id)` abre um stream ao vivo dos logs, do status e dos eventos de sistema de uma aplicação. Com o `SquareCloud` ele é um **iterador** consumido com `for`; com o `AsyncSquareCloud` ele é um **iterador assíncrono** consumido com `async for`. Use-o em um bloco `with` / `async with` para que sair do bloco feche a conexão.

Os exemplos usam o `client` de [Criando o cliente](/pt-br/sdks/py/client#criando-o-cliente). `app_id` é o id de uma das suas aplicações: [`client.account.me()`](/pt-br/sdks/py/client#conta) lista todas.

<Tabs>
  <Tab title="Síncrono">
    ```python theme={"system"}
    with client.apps.realtime(app_id) as stream:
        for event in stream:
            if event["event"] == "logs":
                print(event["stream"], event["line"])  # "stdout" | "stderr"
            elif event["event"] == "status":
                print(event["status"].get("cpu"), event["status"].get("ram"))  # always the full, merged state
            else:
                print(event["event"], event["data"])  # "system" or "error"
    ```
  </Tab>

  <Tab title="Assíncrono">
    ```python theme={"system"}
    async with client.apps.realtime(app_id) as stream:  # no await: realtime() is not a coroutine
        async for event in stream:
            if event["event"] == "logs":
                print(event["stream"], event["line"])  # "stdout" | "stderr"
            elif event["event"] == "status":
                print(event["status"].get("cpu"), event["status"].get("ram"))  # always the full, merged state
            else:
                print(event["event"], event["data"])  # "system" or "error"
    ```
  </Tab>
</Tabs>

Com o `AsyncSquareCloud`, `apps.realtime(app_id)` retorna um `AsyncRealtime` diretamente: **não** use `await` nele. Uma thread de leitura em segundo plano entrega os eventos ao seu event loop, então nenhuma thread do executor fica ocupada enquanto você espera.

## Eventos

Todo evento é um dict com `event`, `data` (o texto bruto do frame) e `id` (`None` quando o frame não tem um).

| `event` | Campos extras | Descrição |
| - | - | - |
| `logs` | `stream`, `line` | Uma linha de log. O primeiro caractere de `data` indica o stream (`\u0001` stdout, `\u0002` stderr); o SDK o remove em `line` e define `stream` como `"stdout"` ou `"stderr"` |
| `status` | `status` | Métricas do container ao vivo. O primeiro frame é completo e os seguintes trazem apenas o que mudou: o SDK os mescla, então `status` é sempre o estado completo |
| `system` | | Eventos de conexão como `REALTIME_CONNECTING \| <id>`, `REALTIME_TIMEOUT` ou `REALTIME_DISCONNECTED` |
| `error` | | Um código de erro como `CONTAINER_NOT_FOUND` |
| `message` | | Um frame sem nome de `event` |

### O objeto `status`

| Campo | Descrição |
| - | - |
| `cpu` | Uso de CPU (%) |
| `cpuLimit` | Número de núcleos de CPU alocados |
| `ram` | `[usedMB, limitMB]` |
| `status` | Estado do container, por exemplo `running` |
| `netIO` | Totais de rede `{ i, o }`, com `new` para o intervalo mais recente |
| `bIO` | Totais de disco `{ i, o }` |
| `uptime` | Unix ms do início do container |

## Encerrando o stream

O loop termina sozinho quando:

* o servidor fecha a conexão de forma limpa (cada conexão dura até **10 minutos**);
* o servidor envia `REALTIME_DISCONNECTED`;
* você sai do loop com `break` (e então deixa o bloco `with`, que fecha a conexão);
* você chama `stream.close()`, a partir de qualquer thread, mesmo enquanto o loop espera por dados ou por uma reconexão (o loop simplesmente termina, sem lançar erro).

`close()` é síncrono tanto em `Realtime` quanto em `AsyncRealtime`. Para continuar acompanhando além de 10 minutos, abra um novo stream quando o loop terminar.

```python theme={"system"}
import threading

stream = client.apps.realtime(app_id)
threading.Timer(60, stream.close).start()  # stop after one minute

for event in stream:
    print(event["event"], event["data"])
```

## Reconexão

Uma conexão perdida, ou o servidor delegando a reconexão ao cliente (`REALTIME_RECONNECT`), reabre o stream sozinho:

* até **3 vezes seguidas**; qualquer evento `logs` ou `status` zera a contagem;
* cada reabertura ocorre pelo menos **5,5 s** após a abertura anterior, para respeitar o ritmo da API de uma abertura a cada 5 segundos por aplicação.

Após 3 reconexões falhas, o loop lança um `SquareCloudAPIError` com `NETWORK_ERROR`. Cada abertura é um `GET`, então um erro de rede durante a abertura também é [tentado novamente](/pt-br/sdks/py/errors#novas-tentativas) até `max_retries` vezes; uma abertura que ainda falhe lança o erro.

## Limites e erros

* **5** conexões simultâneas por conta e **30** por aplicação, somando todos os usuários. Ultrapassar resulta em 429 `REALTIME_MAX_CONNECTIONS` ou `REALTIME_MAX_CONNECTIONS_APP`.
* O status HTTP é verificado antes do streaming, então esses erros (e o 404 para uma aplicação desconhecida) são lançados na primeira iteração.
* O timeout cobre apenas a abertura, até os headers da resposta chegarem. O stream em si não tem timeout: uma conexão meio aberta (um notebook saindo do modo de suspensão) espera até você chamar `close()`.

## Próximos passos

<CardGroup cols={3}>
  <Card title="Snapshots" icon="clock-rotate-left" href="/pt-br/sdks/py/snapshots">
    Faça backup e restaure aplicações e bancos de dados.
  </Card>

  <Card title="Referência da API de tempo real" icon="code" href="/pt-br/api-reference/endpoint/apps/realtime">
    O endpoint REST por trás deste stream.
  </Card>

  <Card title="Logs pela CLI" icon="terminal" href="/pt-br/cli-reference/logs">
    O mesmo stream pelo terminal.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.