Files
fn_registry/functions/infra/push_loki_stream.md
T

4.0 KiB

name, kind, lang, domain, version, purity, signature, description, tags, uses_functions, uses_types, returns, returns_optional, error_type, imports, params, output, tested, tests, test_file_path, file_path
name kind lang domain version purity signature description tags uses_functions uses_types returns returns_optional error_type imports params output tested tests test_file_path file_path
push_loki_stream function go infra 1.0.0 impure func PushLokiStream(endpoint string, user string, pass string, labels map[string]string, timestampsNs []int64, lines []string) error Envia lineas de log a un servidor Grafana Loki via su push API. Construye el cuerpo JSON {"streams":[{"stream":{labels},"values":[["<ts_ns>","<line>"],...]}]} y lo POSTea al endpoint. Soporta Basic Auth opcional, valida que timestamps y lineas tengan igual longitud, es no-op si no hay lineas, y exige status 2xx. Solo stdlib, TLS verificado.
loki
grafana
logs
push
metrics
http
json
stdlib
infra
fleet-metrics
false error_go_core
bytes
encoding/json
fmt
io
net/http
strconv
time
name desc
endpoint URL completa del push API de Loki (ej https://logs-xxxx.organic-machine.com/loki/api/v1/push)
name desc
user usuario para Basic Auth; si es cadena vacia no se envia Authorization
name desc
pass password para Basic Auth; solo se usa cuando user != ''
name desc
labels labels del stream Loki (ej {instance:lucas, job:journald, unit:ssh.service}); van tal cual en el campo stream
name desc
timestampsNs timestamps en nanosegundos desde epoch, uno por linea; debe tener la misma longitud que lines
name desc
lines lineas de log a enviar, alineadas posicionalmente con timestampsNs; si esta vacio la funcion es no-op
error si la peticion falla, las longitudes no coinciden o el status no es 2xx; nil en exito (incluido el no-op de 0 lineas) true
JSON enviado tiene estructura streams/stream/values correcta
longitudes desiguales dan error antes del POST
len lines cero es no-op sin peticion
Basic Auth presente cuando user no vacio
status 500 produce error
functions/infra/push_loki_stream_test.go functions/infra/push_loki_stream.go

Ejemplo

labels := map[string]string{
    "instance": "lucas",
    "job":      "journald",
    "unit":     "ssh.service",
}
nowNs := time.Now().UnixNano()
ts := []int64{nowNs, nowNs + 1}
lines := []string{
    "Accepted publickey for lucas from 10.0.0.2",
    "session opened for user lucas",
}

err := PushLokiStream(
    "https://logs-abcd.organic-machine.com/loki/api/v1/push",
    "tenant1",   // user para Basic Auth (vacio = sin auth)
    "s3cr3t",    // pass
    labels,
    ts,
    lines,
)
if err != nil {
    return err
}

Cuando usarla

Cuando necesites enviar lineas de log a Grafana Loki desde un agente o servicio Go (ej. reenviar journald, eventos de una app, o lineas de un tailer) sin arrastrar el cliente oficial de Loki. Util para alimentar dashboards de la flota (fleet-metrics) con logs etiquetados por instancia/job/unit. Pasa los logs ya batcheados: un solo stream por llamada con sus labels.

Gotchas

  • timestampsNs y lines deben tener exactamente la misma longitud; si no, retorna error ANTES de hacer la peticion (no envia nada).
  • len(lines)==0 es un no-op deliberado: retorna nil sin tocar la red. Comprueba el caso vacio en el caller si necesitas distinguir "no habia logs" de "envio ok".
  • Loki exige timestamps en NANOSEGUNDOS. Pasar segundos o milisegundos hace que las lineas caigan fuera de la ventana de retencion y Loki las rechace silenciosamente.
  • Dentro de un mismo stream las entradas deberian ir en orden creciente de timestamp; Loki puede rechazar entradas fuera de orden segun su config.
  • Exito = status 2xx (Loki normalmente devuelve 204 No Content). Un 4xx/5xx produce error con el codigo + primeros 200 bytes del cuerpo de respuesta para diagnostico.
  • TLS verificado (sin InsecureSkipVerify) y http.Client con timeout de 10s fijo. Para endpoints con certificado interno hace falta CA confiable en el sistema.
  • Secretos (user/pass): nunca hardcodear — resolver desde pass/vault en el caller.