Utan en fullständig agentlogg måste tidslinjen byggas genom att korrelera flera ofullständiga källor: git (vad ändrades, av vem, i vilken ordning — inklusive reflog för det som senare skrivits över), CI/CD-loggar (vad kördes och deployades, men bara inom leverantörens retentionsfönster), API- och åtkomstloggar (vilka anrop gick ut och när) och databasens egna spår (auditlogg om en fanns i förväg, annars transaktionsloggens återställningsfönster). Första steget är alltid att frysa det som finns innan retentionsfönstren stänger det. Därefter normaliseras alla tidsstämplar till en tidszon, källorna läggs bredvid varandra på en gemensam tidslinje, och blast radius bedöms utifrån vilka rader och nedströmssystem som faktiskt låg i skrivvägen — inte utifrån vilken kod som ändrades.
Frys det som finns, innan du gör något annat
Instinkten är att börja rätta felet. Gör det om det aktivt skadar, men innan du gräver vidare: kopiera ut det som finns i loggkällorna till en plats du kontrollerar. CI-leverantörer sparar körningsloggar en begränsad tid — GitHub Actions sparar loggar och artefakter i 90 dagar som standard om inget annat är konfigurerat [1] — och molnleverantörers egna händelsehistorik har liknande gränser: AWS CloudTrails sökbara händelsehistorik täcker de senaste 90 dagarnas hanteringshändelser utan att någon aktivt satt upp en trail, men är inte permanent och saknar vissa händelsetyper [2]. Ligger incidenten inom de fönstren finns spåret kvar just nu — men om någon kör en rutinmässig städning, roterar en logggrupp eller ett nattligt jobb rensar gamla körningar innan du hunnit exportera, är det borta för gott. Exportera loggarna som filer, inte skärmdumpar av en instrumentpanel som kan ändra vy.
Samma sak gäller git. Har agenten committat och sedan blivit rebased, force-pushad eller squashad över av ett efterföljande jobb, ligger de ursprungliga commit-objekten ofta kvar lokalt i git reflog tills skräpsamlingen städar bort dem. Kör git reflog show --all och git fsck --unreachable på den maskin eller den CI-runner-cache där agenten faktiskt jobbade, innan någon kör git gc där.
Bygg tidslinjen ur fyra källor
Ingen enskild källa räcker. Varje källa svarar bara på en del av frågan "vad hände, i vilken ordning".
git log --all --reflog --date=iso-strict --format='%H %ad %an %s' ger dig varje commit inklusive de som senare försvunnit från en branch. Kolla författar- och committer-fält separat: en agent som commitar med en tjänsteanvändare syns där, men om agenten i stället pushade direkt mot plattformens API utan lokal commit-historik är det plattformens egen audit-logg (inte repots historik) som måste kontrolleras i stället.pgAudit-liknande loggning aktiverad i förväg går det att se gammalt och nytt värde, användare och tidsstämpel per ändrad rad [3]. Fanns ingen sådan loggning innan incidenten finns normalt ingen retroaktiv "vem ändrade den här raden"-historik i databasen själv — du är då hänvisad till transaktionsloggens återställningsfönster (point-in-time recovery): återställ en kopia till strax före misstänkt tidpunkt och diffa mot nuvarande tillstånd, eller till en applikationslogg som råkade skriva ut det gamla värdet innan skrivningen.CI-runnern, applikationsservern, databasen och en tredjeparts webhook-avsändare har sällan exakt synkade klockor, och loggar sällan i samma tidszon. Normalisera varje tidsstämpel till UTC innan du lägger källorna bredvid varandra, och räkna med en felmarginal på sekunder snarare än att anta millisekundexakt ordning mellan system du inte själv kontrollerar. Verkar två händelser från olika system ha skett i "omöjlig" ordning är klockskillnad den första förklaringen att utesluta, inte den sista.
Bedöm blast radius: rader, inte kodrader
Ett vanligt misstag är att bedöma skadan utifrån hur stor kodändringen var. En enda rad i ett migrationsskript kan ha berört en hel tabell; tusen rader refaktorerad kod kan ha noll produktionseffekt om deployen aldrig gick live. Fråga i stället: vilka rader, användare, köer eller nedströmssystem låg faktiskt i skrivvägen under incidentfönstret?
COUNT(*) mot villkoret som beskriver ändringen, i stället för att gissa "förmodligen bara några stycken".Provet: en gemensam tidslinje på tio minuter
Ett konkret sätt att testa om du faktiskt har en användbar tidslinje: exportera de fyra källorna ovan till separata textfiler, normalisera varje tidsstämpel till UTC, och slå ihop dem sorterat på tid i en enda fil eller kalkylark — en rad per händelse, med källa, tidsstämpel och en kort beskrivning. Provet är godkänt när du kan peka på en enskild rad i den sammanslagna listan och säga exakt vilken händelse som var den första i kedjan: det första commitet, den första deployen, det första onormala API-anropet eller den första oväntade skrivningen. Kan du inte peka på en första händelse har du fortfarande luckor, och nästa steg är att leta efter vilken av de fyra källorna som saknas eller är för kort för att täcka hela fönstret — inte att gissa dig fram till en slutsats.
Efter incidenten: vad som ska finnas nästa gång
En rekonstruktion i efterhand är alltid dyrare i tid och mer osäker i resultat än loggning som fanns på plats innan. Utifrån vad som saknades den här gången, en kort lista att gå igenom innan nästa agentkörning mot produktion:
[1] GitHub Docs, Configuring the retention period for GitHub Actions artifacts and logs — standardretention 90 dagar; konfigurerbart 1–400 dagar för privata repon, 1–90 dagar för publika repon. [2] AWS-dokumentation, Working with CloudTrail event history — 90 dagars sökbar händelsehistorik för hanteringshändelser utan aktiv trail-konfiguration. [3] CYBERTEC PostgreSQL, Row change auditing options for PostgreSQL, och PostgreSQL Wiki, Audit trigger 91plus — trigger- och tilläggsbaserad radnivåloggning. Samtliga källor lästa 17 augusti 2026. Retentionsvärden och funktioner nämns som exempel på kategorier av spår, inte som rekommendation av en enskild leverantör.