feat(infra): auto-commit con 86 cambios
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,36 +3,97 @@ name: docker_container_logs
|
||||
kind: function
|
||||
lang: go
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
version: "2.0.0"
|
||||
purity: impure
|
||||
signature: "func DockerContainerLogs(nameOrID string, tail int) (string, error)"
|
||||
description: "Obtiene los logs de un contenedor Docker. El parámetro tail limita a las últimas N líneas (0 devuelve todos los logs)."
|
||||
tags: [docker, container, logs, infra]
|
||||
signature: "func DockerContainerLogs(opts DockerLogsOpts) ([]DockerLogLine, error)"
|
||||
description: "Tail/grep logs de container Docker via engine API. Snapshot (N lineas) o streaming (callback por linea con context cancel). Demux frame stdout/stderr. Capability docker.container.logs del device_agent."
|
||||
tags: [docker, docker-agent, logs, streaming, infra]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
uses_types:
|
||||
- docker_logs_opts_go_infra
|
||||
- docker_log_line_go_infra
|
||||
- error_go_core
|
||||
returns:
|
||||
- docker_log_line_go_infra
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: [fmt, os/exec, strconv]
|
||||
imports:
|
||||
- context
|
||||
- encoding/binary
|
||||
- fmt
|
||||
- io
|
||||
- net
|
||||
- net/http
|
||||
- net/url
|
||||
- strings
|
||||
- time
|
||||
params:
|
||||
- name: nameOrID
|
||||
desc: "nombre o ID del contenedor Docker"
|
||||
- name: tail
|
||||
desc: "numero de ultimas lineas a devolver (0 devuelve todos los logs)"
|
||||
output: "logs del contenedor como string"
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
- name: opts
|
||||
desc: "Parametros de la peticion: container ID, tail N, since, stdout/stderr, timestamps, docker host. Ver DockerLogsOpts."
|
||||
output: "Slice de DockerLogLine con stream (stdout/stderr), timestamp RFC3339 opcional y texto de la linea."
|
||||
tested: true
|
||||
tests:
|
||||
- "snapshot stdout y stderr demuxeados"
|
||||
- "container no encontrado retorna error"
|
||||
- "timestamps parseados del prefijo Docker"
|
||||
- "tail y since se envian como query params"
|
||||
- "streaming recibe lineas via callback"
|
||||
- "ctx cancel detiene el stream"
|
||||
- "callback error cancela el stream"
|
||||
- "frame stdout decodificado correctamente"
|
||||
- "frame stderr decodificado correctamente"
|
||||
test_file_path: "functions/infra/docker_container_logs_test.go"
|
||||
file_path: "functions/infra/docker_container_logs.go"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
// Últimas 100 líneas
|
||||
logs, err := DockerContainerLogs("my-app", 100)
|
||||
// Snapshot: ultimas 50 lineas de stdout+stderr
|
||||
lines, err := DockerContainerLogs(infra.DockerLogsOpts{
|
||||
ContainerID: "registry_api",
|
||||
Tail: 50,
|
||||
Since: "10m",
|
||||
Stdout: true,
|
||||
Stderr: true,
|
||||
Timestamps: true,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(logs)
|
||||
for _, l := range lines {
|
||||
fmt.Printf("[%s] %s %s\n", l.Stream, l.Timestamp, l.Line)
|
||||
}
|
||||
|
||||
// Streaming: follow hasta cancelacion
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
err = infra.DockerContainerLogsStream(ctx, infra.DockerLogsOpts{
|
||||
ContainerID: "registry_api",
|
||||
Stdout: true,
|
||||
Stderr: true,
|
||||
}, func(line infra.DockerLogLine) error {
|
||||
fmt.Printf("[%s] %s\n", line.Stream, line.Line)
|
||||
if strings.Contains(line.Line, "FATAL") {
|
||||
return fmt.Errorf("fatal error detectado")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
```
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Cuando el device_agent necesite leer o monitorizar logs de un container Docker en tiempo real. Usar modo snapshot para health checks puntuales (N ultimas lineas). Usar streaming para tail -f reactivo con procesamiento por linea.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- Containers sin `--tty` usan el protocolo de multiplexion de 8 bytes — esta funcion lo demuxea correctamente. Containers con `--tty` mezclan stdout/stderr en un stream plano sin headers, lo que puede dar `Stream = "stdout"` para todo o parsear mal el header (byte 0 podria ser el primer caracter de texto).
|
||||
- Streaming consume una goroutine/conexion hasta que `ctx` se cancele o `cb` retorne error. El caller es responsable del ciclo de vida del contexto.
|
||||
- `Since` acepta unix timestamp en string, RFC3339 o duracion Go ("10m", "1h30m"). El daemon Docker acepta los 3 formatos directamente.
|
||||
- Sin reconexion automatica en streaming. Si el daemon reinicia o la conexion se corta, el caller recibe error y decide si reintentar.
|
||||
- `DockerHost` vacio conecta a `/var/run/docker.sock`. En sistemas donde el socket esta en otra ruta (Docker Desktop macOS, Podman), pasar la URL explicitamente.
|
||||
|
||||
## Capability growth log
|
||||
|
||||
v2.0.0 (2026-05-23) — reemplaza implementacion CLI (exec docker logs) por engine API HTTP con demux de frames. Anade DockerLogsOpts, DockerLogLine, modo streaming con callback y ctx cancel. Consumidor nordvpn_container_start actualizado.
|
||||
|
||||
Reference in New Issue
Block a user