# Logs, métricas, terminal e arquivos

URL: https://0.0.0.0:3002/docs/aplicacoes-runtime

Acompanhar a aplicação no ar, ver o consumo, abrir um shell no container e ver ou editar o código do projeto.

Com a aplicação no ar, o detalhe dela no painel ganha quatro abas de runtime. Logs, métricas, terminal e arquivos vêm do servidor onde a app roda, ao vivo.

| Aba          | Quem vê                                  | O que faz                                                                                   |
| ------------ | ---------------------------------------- | ------------------------------------------------------------------------------------------- |
| **Logs**     | Todos do workspace (`apps:read`)         | Console ao vivo: as últimas 1000 linhas e o que chegar                                      |
| **Métricas** | Todos (`apps:read`)                      | Consumo agora e histórico de até 30 dias                                                    |
| **Terminal** | Owner, admin e developer (`apps:manage`) | Shell dentro do container                                                                   |
| **Arquivos** | Owner, admin e developer (`apps:manage`) | A pasta do projeto no servidor, ao vivo: navegar, baixar, editar, enviar, renomear e apagar |

## Logs [#logs]

* `stdout` e `stderr` da aplicação, com as cores ANSI. Linhas de `stderr` têm uma marca à esquerda.
* **Pausar** segura a tela sem perder o que chega; **Seguir** traz o atrasado. O filtro procura texto nas linhas já recebidas.
* **Erros e avisos** ficam destacados (vermelho e amarelo), reconhecidos pelo texto da linha (`error`, `fatal`, `exception`, `warn`, `deprecated`…) ou pelo campo `level` de logs em JSON (como o pino). O filtro **Todos / Avisos / Erros** mostra só um nível, com a contagem de cada um.
* O histórico é o que o servidor guarda da app (cerca de 30 MB por container, rotacionado). Depois de um deploy, o console segue o container novo.
* A conexão volta sozinha se cair.

## Métricas [#métricas]

* **Agora**, a cada 2 s: CPU (em vCPU, comparada ao tamanho da app), memória (com o limite), rede (entrada e saída por segundo), disco e número de processos.
* **Histórico**: 1 hora (pontos de 1 minuto), 24 horas (5 minutos), 7 dias (30 minutos) e 30 dias (2 horas), com média e pico de CPU e memória, a linha do limite do tamanho, rede e disco por segundo e o tamanho da pasta do projeto.
* O agente mede a cada 30 s. Intervalos sem a app rodando aparecem como buracos no gráfico.
* Pela API: `GET /v1/workspaces/{id}/apps/{appId}/metrics?range=1h|24h|7d|30d`.
* **Na lista de aplicações**, cada app no ar mostra a tendência da última hora de CPU e memória, em % do tamanho dela. Pela API: `GET /v1/workspaces/{id}/usage/apps` (12 pontos de 5 minutos por app; `null` onde não houve amostra).
* **Tempo no ar:** o detalhe da app e do banco mostra há quanto tempo estão rodando (`runningSince` na API). A contagem recomeça num deploy novo, num reinício ou quando a app volta depois de parar ou cair.

## Terminal [#terminal]

* **Abrir terminal** inicia um shell (`bash` se a imagem tiver, senão `sh`) dentro do container, com o **mesmo usuário e as mesmas restrições da aplicação**: o que a app acessa, o terminal acessa; nada além disso.
* Imagens sem shell não abrem terminal (o painel avisa).
* Até 2 terminais abertos por aplicação. A sessão fecha depois de 15 minutos sem digitar ou 4 horas no total.
* Abertura e fim ficam na **atividade** do workspace, com duração. O que é digitado e o que aparece na tela **não são gravados**.
* Só funciona pelo painel, com a sessão de uma pessoa (tokens de API não abrem terminal).

## Arquivos [#arquivos]

A aba **Arquivos** mostra a **pasta do projeto no servidor, ao vivo**: o código do último deploy e tudo o que a aplicação grava enquanto roda, como um banco SQLite, uploads ou arquivos de configuração gerados. Vale para apps por upload, do GitHub e por imagem, e funciona com a aplicação parada. A pasta só existe depois do primeiro deploy.

Dá para navegar, baixar, editar texto (até 1 MB), enviar arquivos (até 100 MB cada), criar pastas, renomear e apagar. Os arquivos abrem num editor de código (o mesmo motor do VS Code), com realce de sintaxe por linguagem e **Ctrl/Cmd+S** para salvar. Tudo é servido pelo próprio painel, sem CDN de terceiros, e cada arquivo mostra um ícone pelo tipo, quando ele é conhecido.

O que muda aqui **vale na hora, direto no servidor**:

* **Código editado só roda depois de reiniciar.** O processo que já está no ar não relê o arquivo.
* **Arquivo alterado aqui é mantido nos próximos deploys**, como o que a própria aplicação altera ([pasta do projeto](/docs/aplicacoes)). O log do deploy lista os mantidos.
* **Para voltar a seguir o código enviado,** apague o arquivo antes do próximo deploy: ele volta na sincronização.
* **Apagar um arquivo do código** só vale até o próximo deploy, que o traz de volta.
* **Mudar de vez o código de todos os deploys:** envie um .zip novo ou faça push no GitHub.

Envios, edições, renomeações, novas pastas e exclusões ficam na atividade do workspace.

### Pela API [#pela-api]

| Rota                                    | O que faz                                                                           |
| --------------------------------------- | ----------------------------------------------------------------------------------- |
| `GET .../apps/{appId}/files?path=`      | Lista uma pasta                                                                     |
| `GET .../files/content?path=`           | Baixa um arquivo                                                                    |
| `PUT .../files/content?path=`           | Envia o corpo cru (`application/octet-stream`, com `Content-Length`)                |
| `POST .../files/directories`            | Cria pasta (`{ "path": "uploads" }`)                                                |
| `POST .../files/rename`                 | Renomeia ou move (`{ "from": "a.txt", "to": "b.txt" }`); o destino não pode existir |
| `DELETE .../files?path=&recursive=true` | Apaga (pasta com conteúdo exige `recursive=true`)                                   |

Os caminhos são relativos à raiz do projeto e não aceitam `..`. A pasta `.hydro/` guarda o controle da sincronização: não aparece na lista e responde `404`.

| Erro                                           | Quando                                           |
| ---------------------------------------------- | ------------------------------------------------ |
| `404 file_not_found`                           | O caminho não existe (ou é `.hydro/`)            |
| `409 file_exists`                              | O destino de uma criação ou renomeação já existe |
| `409 directory_not_empty`                      | Pasta com conteúdo, sem `recursive=true`         |
| `413 file_too_large`                           | Arquivo maior que o limite                       |
| `409 app_not_deployed` / `409 app_not_running` | A pasta ainda não existe (sem deploy)            |
| `503 node_offline`                             | Servidor fora do ar                              |

## Como a conexão funciona [#como-a-conexão-funciona]

Logs, consumo e terminal usam um WebSocket direto com a API. O painel pede um endereço de uso único, válido por 30 segundos (`POST .../apps/{appId}/streams`), e abre a conexão nele. O endereço não carrega cookies; firewalls corporativos precisam permitir WebSocket para o endereço da API.
