Als ergens een systeem hapert, is de eerste reflex vaak: logs openen.
Dat begrijp ik. Logs voelen concreet. Er staat iets. Een foutmelding. Een timestamp. Een stacktrace. Een code. Iets waar je je tanden in kunt zetten.
Maar goede troubleshooting begint zelden met het zoeken naar de fout.
Goede troubleshooting begint met het kleiner maken van het probleem.
Want in complexe IT- en OT-omgevingen is bijna alles met elkaar verbonden. Een applicatie praat met een database. Die database draait op een server. Die server hangt aan een netwerk. Dat netwerk loopt via firewalls, switches, VLAN’s, DNS, certificaten, rechten, scripts, koppelingen, gebruikers, machines, processen — en soms nog een Excel-bestand waarvan niemand precies weet waarom het bestaat.
Als je dan zonder richting begint te zoeken, kun je uren bezig zijn zonder dichter bij de oorzaak te komen.
Je leest logs. Je ziet warnings. Je vindt oude fouten. Je ontdekt afwijkingen die er misschien altijd al waren. Iemand roept dat het “vast de firewall” is. Een ander zegt dat “de applicatie gisteren ook al raar deed”. Ondertussen groeit de druk, worden er steeds meer mensen bijgehaald en ontstaat er technische mist.
Iedereen kijkt ergens naar.
Maar niemand weet nog precies welk probleem wordt opgelost.
Niet: waar zit de fout? Maar: waar stopt het probleem?
Daarom begin ik liever ergens anders.
Werkt het op één werkplek niet, of op allemaal? Werkt het lokaal wel, maar vanaf buiten niet? Gaat het fout bij één gebruiker, één rol, één machine, één netwerksegment, één tijdstip, één type bestand, één productielijn, één batch, één API-call?
Wat werkte eerder? Wat is er veranderd? Wat werkt nog wel?
Die vragen lijken simpel. Soms bijna te simpel. Maar ze zijn vaak belangrijker dan de eerste technische analyse.
Een storing is gedrag binnen een context
Een systeem doet iets wat niet verwacht wordt. Maar dat betekent niet automatisch dat het systeem zelf kapot is.
Ik stond een keer bij een installatie waar een productielijn uitviel na een routinematige Windows-update. Iedereen keek naar de PLC-software. Logisch, want daar zat de foutmelding. Maar de PLC-code was niet veranderd. De omgeving wel.
De update had een driver vervangen die de communicatie met een seriële poort afhandelde. Het systeem deed precies wat het moest doen, alleen de laag eronder was onder zijn voeten weggetrokken.
Dat patroon zie ik steeds terug.
De foutmelding wijst naar de applicatie, maar de oorzaak zit in de omgeving. De code is niet veranderd, maar de driver wel. Of het SSL-certificaat is verlopen terwijl het hele team in de applicatielogica zit te zoeken. Of data wordt naar de verkeerde gateway gerouteerd na een netwerkwijziging, en de applicatie krijgt een timeout die eruitziet als een bug.
Een van de lastigste varianten: een firewall met deep packet inspection die stilletjes iets toevoegt aan een HTTP-header. De applicatie faalt, de request ziet er in de logs normaal uit, maar ergens onderweg is het pakket net iets anders dan wat de server verwacht.
Je kunt dagen in de code zitten zonder het te vinden, omdat het probleem niet in de code zĂt.
De foutmelding is dan niet de oorzaak. Het is alleen de plek waar het systeem begon te klagen.
Een thermometer veroorzaakt geen koorts. Een logregel veroorzaakt geen storing. Een alarm op een HMI is niet automatisch het probleem in de machine. Het is een signaal. En signalen moet je lezen binnen het geheel.
Zoek het contrast
Daarom zoek ik eerst naar contrast.
Dit werkt wel. Dat werkt niet. Gisteren werkte het. Vandaag niet. Deze machine reageert normaal. Die machine niet.
Dat contrast is de ingang.
Van daaruit kun je hypothesen maken. Niet als wilde gok, maar als werkbare route. Als het probleem alleen in één netwerksegment zit, hoef je niet eerst de hele applicatiecode door. Als het probleem alleen optreedt bij nieuwe records, kijk je eerder naar data, validatie of een proceswijziging. Als het probleem alleen optreedt na een bepaald tijdstip, kijk je naar batchprocessen, certificaten, scheduled tasks, resourcegebruik of externe koppelingen.
Zo wordt troubleshooting geen speurtocht door een hooiberg, maar een gecontroleerde vernauwing.
Ervaring kan ook misleiden
Dat vraagt discipline. Want het is verleidelijk om direct in de techniek te duiken. Zeker als je technisch sterk bent.
Je ziet een foutmelding en je denkt: ah, daar zit het.
Je herkent een patroon. Je hebt eerder zoiets gezien. Je wilt oplossen.
Maar soms lijkt een fout op iets wat je kent, terwijl de oorzaak ergens anders zit. Een databasefout veroorzaakt door rechten. Een netwerkfout door DNS. Een applicatiefout door verlopen certificaten. Een performanceprobleem door logging, opslag, locking of een proces dat net iets anders loopt dan vroeger.
In software zie je hetzelfde. Een service faalt omdat een downstream dependency na een update een ander response-formaat teruggeeft. Iedereen debugt de service. Niemand kijkt naar de dependency.
Of een API werkt in staging perfect, maar breekt in productie. Niet door de code, maar door een environment variable die net anders staat, een ander certificaat of een strikter netwerkbeleid.
Het systeem klaagt op de verkeerde plek.
En als je alleen kijkt waar het klaagt, graaf je op de verkeerde plek.
In OT is gedrag soms belangrijker dan documentatie
In OT-omgevingen wordt dat nog scherper.
Daar is gedrag soms belangrijker dan wat er op papier staat. Een installatie draait al jaren. Mensen weten uit ervaring wat normaal is. Een kleine vertraging kan betekenis hebben. Een afwijkend geluid, een timingverschil, een handmatige handeling of een oude bypass kan onderdeel zijn geworden van het echte systeem.
In software ken je dat ook.
Die stored procedure uit 2011 die niemand durft aan te raken. Dat try-catchblok dat er “tijdelijk” in ging en nu al drie jaar in productie draait. Die legacy service die eigenlijk al vervangen had moeten zijn, maar waar twintig andere systemen van afhangen.
Op papier hoort het misschien niet zo te werken.
In de praktijk werkt het wel zo.
Daarom vraag ik bij storingen graag aan mensen op de vloer — of het nu operators zijn of developers:
Wat is normaal gedrag?
Niet omdat zij altijd de technische oorzaak kennen. Maar omdat zij vaak sneller zien wat afwijkt. Zij kennen het ritme van het proces. Zij weten wat er gisteren anders was. Zij weten welke workaround al maanden wordt gebruikt. Zij weten welke melding wordt genegeerd omdat die “er altijd staat”.
Dat soort informatie staat zelden netjes in de documentatie. Maar het is vaak essentieel.
Diagnose, geen vergadering
Troubleshooting is daarom niet alleen techniek. Het is ook luisteren naar gedrag. Van systemen, processen en mensen.
Eerst de grens bepalen. Daarna de verandering vinden. Vervolgens de afhankelijkheden nalopen. En pas dan gericht de diepte in.
Dat voorkomt ook dat teams elkaar onnodig gaan beschuldigen.
In complexe omgevingen wijst iedereen snel naar het domein van de ander. Development kijkt naar infra. Infra kijkt naar applicatiebeheer. Beheer kijkt naar security. Security kijkt naar beleid. Operations kijkt naar “die nieuwe update”.
Maar een goede diagnose haalt de emotie eruit.
Niet: wie heeft dit veroorzaakt? Maar: onder welke omstandigheden treedt dit gedrag op?
Dat maakt het zakelijker. Rustiger. En vaak ook sneller.
Context maakt het verschil
Ik vertrouw bij troubleshooting minder op heldhaftig zoeken en meer op systematisch begrenzen.
Niet omdat logs onbelangrijk zijn. Logs zijn belangrijk. Monitoring is belangrijk. Metrics, packet captures, traces, event viewers, audit logs en dashboards kunnen enorm waardevol zijn. Maar pas als je weet waar je naar kijkt.
Zonder context is een logbestand vooral een verzameling technische kreten.
Met context wordt het bewijs.
Je begint niet met graven. Je begint met bepalen waar je moet graven. En soms is de beste eerste stap niet een commando, query of dashboard.
Maar een paar simpele vragen:
Wat werkte eerder? Wat is er veranderd? Waar stopt het probleem? Wat is nog wél stabiel?