Global och lokal felhantering
Av Jonas Mäki
Var ska fel hanteras?
Den här frågan har förmodligen många svar beroende på vem du frågar. Jag kommer att titta från utvecklarens synvinkel med operatören i åtanke.
Jag vill hantera så många av felen som möjligt lokalt så att operatören inte behöver veta att fel har uppstått. Eventuella fel som en specifik koddel inte kan hantera lokalt måste skickas till en felhanteringsprocess.
Vad är lokal felhantering?
Lokal felhantering är när en funktion eller process kan hantera ett fel direkt och helst lösa felet utan att användaren vet om att felet uppstod från första början.
Om det tar lite tid att rätta till felet måste användaren varnas på något sätt, till exempel med en lysdiod eller en upptagen markör. Detta ger en bättre förståelse för vad koden gör och det verkar inte som om den hänger sig eller fryser.
Ett exempel på ett lokalt hanterat fel kan vara att återansluta till maskinvara om kommunikationen med den externa maskinvaran misslyckades. Försök att ansluta på nytt ett visst antal gånger (jag vill att det ska vara konfigurerbart hur många gånger) innan felinformationen skickas till en global felhanterare. När en lokal process eller funktion rapporterar ett fatalt fel som den inte kan återhämta sig från ska processen gå tillbaka till ett viloläge om den startades från en annan applikation (till exempel om ditt program är en mikrotjänst) eller stängas av så elegant som möjligt om processen startas från en annan process i samma applikation.
Vad är global felhantering?
Global felhantering eller bara en felhanteringsprocess är precis vad det låter som: en process som hanterar fel. En felhanteringsprocess har något sätt att kommunicera förekomsten av ett fel med felhanteringsprocessen. Felhanteraren måste logga och eller rapportera felet. Det är också bra om det finns en sändningsfunktion för att informera applikationen om att ett visst fel har inträffat, helst med dödsnivåer.
Fel som loggas och/eller rapporteras bör åtminstone innehålla vad, när och var felet inträffade. Varför felet uppstod är upp till dig som utvecklare att ta reda på. Om felet ska loggas eller rapporteras beror på vilken typ av programvara som släpps. Generellt sett är loggning bra, men om programvaran används av många användare/stationer och systemen inte är lättillgängliga är en rapport till programvarutillverkaren att föredra. Ni har alla sett LabVIEW:s kraschrapportfönster någon gång, och det är ett bra exempel på en mycket global felhantering.
För det mesta bör de råa LabVIEW-felkoderna och fönstren inte visas direkt för slutanvändaren, eftersom denna information tenderar att vara förvirrande. Låt dem istället veta att ett fel har inträffat och öppna eventuellt felfönster som förklarar fel på användaråtgärder.
Hur ska man reagera på felhanteringssändningar?
Det är den anropande programvarans eller huvudprogrammets uppgift att bestämma vad som ska göras vid olika nivåer av fel. Vid de mest fatala/okända felen bör programmet stänga alla processer och meddela operatören att ett fatalt fel har inträffat och hänvisa till felloggen. I förekommande fall kan du också be dem att skicka rapporten till programvarutillverkaren.
Exempel på implementering av en felhanterare
Detta är en enkel men mycket effektiv felhanterare som är lätt att initiera och lätt att kommunicera fel, och loggningen kan väljas mellan temp-mappen i filer och Windows-händelsevisaren. Jag brukar göra det eftersom den här loggen bara kan raderas i sin helhet och inte delvis.
Innan vi går in på den faktiska felhanteraren har vi valt att använda OpenGDS Active Object-designmönstret med Events.
Mer information om detta finns på opengds.github.io. Klassen är inställd på att vara en singleton-klass.
Så här förbättrar du din distribuerade programvara med felhantering
Om det finns en ordentlig felhanteringsprocess kan programmet utvecklas i takt med uppgraderingar. När utvecklarna får kunskap om fel som uppstår kan buggar rättas till och lokal felhantering kan läggas till för att ta hand om de fel som ibland kan uppstå så att programvaran presterar bättre över tiden.
Funktionalitet för felhanterare
Klassen Error handler.lv har sex publika funktioner. Init och CleanUp skapar respektive förstör felhanteraren.
Med ControlProcessWindow.vi kan du öppna processfönstret för felhanteringen. Om OpenProcessOnError körs med ett sant värde visas processfönstret automatiskt. Detta används vanligtvis bara vid felsökning.
ReportError.vi kan placeras var som helst i din applikation och skickar alla fel som kommer från input-felklustret till felhanteraren.
GetErrorBroadcastEvent.vi används för att registrera en händelsestruktur för att lyssna på förekomsten av fel som rapporteras till Error-hanteraren.
HandleErrors.vi är ett exempel på applikationskod som anropar felhanteringsprocessen.
När fel rapporteras till felhanteraren och fönstret öppnas antingen automatiskt eller manuellt. Alla fel kommer att visas. Antalet förekomster och om de är varningar eller fel visas också.
Broadcasten av ErrorOccurred används för att tända en LED-lampa för att meddela användaren att ett fel har inträffat.
Felhanterare Process
I felhanteringsprocessen, som oftast genereras från den aktiva objektmallen, finns ett CMD-tillstånd som tar emot de fel som rapporteras och svarar med en sändning till en händelsekö från processen. Felet läggs också till i felkartan. Nästa steg i felhanteringen är att uppdatera listan, sedan logga felet och sedan visa felhanteringsfönstret, om det är automatiskt.
Uppdatering av fellistan med kod, antal, status och källa.
Loggning sker antingen till Windows Event Viewer eller till loggfiler. Det finns en supportklass som hanterar allt med loggfilen och allt som kommer med den.
Expansion
Jag har redan talat om att rapportera fel direkt till dig som programvarutillverkare, och detta är inte en del av denna mycket enkla felhantering. Processen skulle kunna utökas med denna logik, och den skulle också kunna utökas med felnivåer och förmodligen mycket mer. Den här koden är en bra utgångspunkt för att skapa en bra global felhantering i din applikation, men glöm inte att fel först måste hanteras lokalt om du kan.
Ladda ner koden som det hänvisas till i detta inlägg.