Registro
ghchronicle escribe su registro en la salida de error, y el bloque log fija el nivel, el formato y un fichero rotativo opcional.
log: level: info # debug, info, warn, error format: text # text o json file: /var/log/ghchronicle/ghchronicle.log max_bytes: 67108864 keep: 5Las claves
Sección titulada «Las claves»| Clave | Por omisión | Significado |
|---|---|---|
level | info | debug, info, warn o error; cualquier otro valor se comporta como info |
format | text | text para una persona, json para un agente de envío; cualquier otro valor es text |
file | ninguno | Un fichero rotatorio además de la salida de error |
max_ | 67108864 | Rota a los 64 MiB. Un valor no positivo cae al valor por defecto |
keep | 5 | Cuántos ficheros rotados conservar. Un valor no positivo cae al valor por defecto |
Los dos, nunca en lugar de
Sección titulada «Los dos, nunca en lugar de»Un file configurado no sustituye a la salida de error, se escribe además de
ella. Bajo systemd el journal es donde mira todo el mundo primero, y un fichero
de log que ocupara en silencio el lugar del journal sería una trampa:
journalctl -u ghchronicle se quedaría mudo y la conclusión obvia sería que el
servicio se ha parado.
La rotación es por tamaño con sufijos numerados, así que la retención es un recuento y no una fecha y dos rotaciones en el mismo segundo no pueden chocar. El contador de tamaño se lee del fichero al arrancar, así que un reinicio no lo pone a cero dejando que el fichero crezca sin límite.
Qué dice el log un día bueno
Sección titulada «Qué dice el log un día bueno»Tomado del servicio del autor el 2026-09-27, un arranque y las líneas de sus pasadas:
level=INFO msg="ghchronicle running" tick=15m0s tick_from="shortest cadence"level=INFO msg="cache file read" file=/var/lib/ghchronicle/state-cache.bin written=2026-09-27T15:27:41+02:00 answers=1170 runs=672 refusals=100 page_sizes=54 age=1slevel=INFO msg="repositories discovered" count=37 archived_aside=17level=INFO msg="slow families due together take turns" starting=planning waiting=settings,trafficlevel=INFO msg=written sink=influxdb family=repo points=934 unchanged=1955level=INFO msg="nothing moved since the window, repositories left unread" family=commits repos=34level=INFO msg=written sink=influxdb family=commits points=17 unchanged=0level=INFO msg="rate budget" bucket=core remaining=4477 limit=5000level=INFO msg="points already written and not sent again" sink=influxdb skipped=54511level=INFO msg="sweep finished"Las dos primeras salen una vez, cuando arranca el proceso: el tic al que
despierta el bucle, y lo que devolvió la caché que hay junto al fichero de
estado. La lista de
repositorios se rehace una vez por hora, y archived_aside cuenta los
archivados apartados,
que siguen recibiendo sus dos filas. En written, points es lo que llegó al
almacén y unchanged lo que el registro de escrituras dejó fuera porque el
almacén ya lo tiene; ver qué cuenta la línea de
escritura. Una
familia de seis horas o más a la que le toca detrás de otra aparece en
waiting, ver las familias lentas se
turnan,
y commits, issues e issueevents dicen cuántos repositorios dejaron sin
leer porque nada se movió en ellos, ver preguntar primero qué se
movió.
Una familia que aún no toca sencillamente no aparece. Eso es normal, y es lo
primero que hay que mirar cuando parece faltar una medida: con una cadencia de
doce horas, medio día de logs puede legítimamente no mencionar nunca stats.
Las dos líneas que merecen alerta
Sección titulada «Las dos líneas que merecen alerta»rate limit reserve reached significa que se saltó una familia para
proteger el presupuesto.
level=WARN msg="rate limit reserve reached, family skipped" family=artifactsUna vez está bien. En cada pasada significa que las cadencias son demasiado rápidas para el número de repositorios.
family failed everywhere, not marking it as run significa que fallaron
todos los repositorios en una familia.
level=WARN msg="family failed everywhere, not marking it as run" family=securityLa familia no se marca como hecha a propósito, así que se reintenta en la siguiente cadencia en vez de darse por completa. Esa es la línea que separa “una función está apagada en un repositorio” de “el token ha perdido un permiso”.
Depuración
Sección titulada «Depuración»log: level: debugDebug añade estas líneas, y ninguna más:
loaded the written-points ledger, con cuántos puntos volvió el libro de escrituras, cuando arranca el servicio;no cache file yet, the first pass of each family pays in full, en el primer arranque con fichero de estado;not every store keeps a write ledger, cuando las ejecuciones que recuerda el fichero de caché se vuelven a listar porque un almacén no lleva registro o la ejecución termina con su pasada;no targets.user, account-wide families skipped;sink dropped old entries, con cuántas entradas dejó fuera un destino por ser más antiguas que su horizonte, la única forma de ver que un envío se recortó en lugar de rechazarse;card-only sweep, the state file is left as it was;cache file saved, con cuántas respuestas y ejecuciones guarda y cuánto tardó;migration not neededymigration applied before, en cada arranque, por cada cambio que un almacén nunca necesitó o que ya tiene aplicado;migration noted: nothing is changedymigration frozen, en cada arranque después del primero, que dice cada una enINFO;set-aside copy forgotten, cuando le llega su hora a una copia que apartó una migración y el fichero de estado deja de nombrarla:the store purges it itselfpara una que InfluxDB 3 purga con su propio calendario, ythe store keeps it for good, and -migrate asks the store for itpara una que guarda para siempre.
No hay registro por petición: el cliente de internal/ghapi no lleva
registrador, así que qué endpoint se llamó y qué respuesta volvió 304 no se ven
en ningún nivel. Eso incluye su único reintento: una petición REST respondida
con 500, 502, 503 o 504 se repite dos segundos después, en silencio, y también
la descarga del log de un job desde el almacenamiento, así que un
collector failed que nombra uno de esos cuatro ya ha fallado dos veces.
No confundir con el colector de logs de jobs
Sección titulada «No confundir con el colector de logs de jobs»log es el diario de la propia herramienta. every.families.joblogs es un colector:
recoge las últimas cuarenta líneas de cada job fallido de GitHub Actions y las
convierte en puntos. Son ajustes sin relación, y el segundo pertenece a un
almacén de logs y no a una base de datos de métricas. Ver
Loki.