A telemetria története egyidős a szoftverfejlesztéssel. Már az Apollo-programban használt Saturn V rakéták is rendelkeztek telemetiával. De mi is az a telemetria?
A telemetria nagy távolságú adattovábbítást, távoli méréseket és vezérlést lehetővé tévő, jellemzően vezeték nélküli kommunikációs rendszer. A görög téle= ‘távoli, messzire’, és metreó= ‘mér’ szavakból ered.
A definícióból adódóan a telemetria nem csak informatikai rendszerek esetén alkalmazható. Informatikában a telemetria a futtató rendszerről gyűjt adatokat. Ez modern világunkban az adatkezelésre vonatkozó törvények és a konstans megfigyeléstől félés idejében mondhatni szitokszónak számít bizonyos körökben.
Ennek az oka abban keresendő, hogy telemetria segítségével minden begyűjthető a számítógépről, beleértve akár a böngészési előzményeket, telepített programok listáját és még sorolhatnám. Azonban a legtöbb esetben, ha észszerű felhasználásról beszélünk, akkor a telemetria korlátozódik a releváns információk begyűjtésere.
Releváns információ lehet például egy gép esetén a processzor típusa (támogatott utasításkészletek, magok száma, cache, stb…), a rendszermemória mennyisége és sebessége, videokártya típusa. Összegezve tehát a telemetriai rendszerek a legtöbb esetben olyan adatokat gyűjtenek a futtató gépről, amelyek közvetlenül vagy közvetett módon befolyásolhatják a program futásának sebességét és a felhasználói élményt.
Ezen adatok a legtöbb esetben anonim módon tárolódnak, mivel a fejlesztőknek nem lényeges a felhasználó személye, csak a "vas" adatai, hogy jobban optimalizálni tudják a programot és helyesen határozzák meg a minimális rendszerkövetelményeket. Persze ettől eltérni lehet, de a GDPR1, vagyis az Általános adatvédelmi rendelet értelmében, ha adatkezelés valósul meg valamilyen formában valahol, akkor arról a felhasználót tájékoztatni kell. Ennek a tájékoztatásnak ki kell térnie a tárolt adatokra, illetve arra is, hogy mire használja az adatkezelő ezeket.
A törvény további előírása, hogy az adatkezelésből a felhasználónak bármikor lehetősége legyen kihátrálni. Ez a programunkban azt jelenti, hogy biztosítanunk kell annak a módját, hogy ha a felhasználó nem szeretne diagnosztikai adatokat küldeni fejlesztőknek, akkor bármikor ebből ki tudjon hátrálni.
Egy másik hatékony módszer a hibák felderítésére a logolás. Ez lényegében szöveges információk írása egy fájlba vagy adatbázisba arról, hogy éppen mit is csinál a programunk. Ilyen log üzeneteket nekünk kell a programunkba írni.
Kérédés, hogy mit logoljunk? Ennek a megállapítása nagymértékben függ a feladat komplexitásától és a szoftver felépítésétől, illetve a környezettől. Például mindentől függetlenül a kivételek keletkezését érdemes naplózni, illetve a hozzájuk kapcsolódó információkat is. De ugyanígy értelme lehet naplózni a programunk belső állapotváltozásának eseményeit is.
De azzal is tisztában kell lennünk, hogy a beszédes naplófájlok segítik a programozók munkáját, de ugyanígy segítik a gonosz szándékú felhasználókat is. Például egy web alkalmazás esetén kifejezetten káros bárminemű részletes hiba információ megjelenítése (kivétel típusa, keletkezésének helye és körülményei) a felhasználónak, mert abból célzottan készíthet DDoS2 támadásra vagy az adatbázis támadására alkalmas kódot.
A telemetria és logolás kéz a kézben jár asztali és mobilalkalmazásoknál, mivel egy napló sem ér semmit, ha az nem jut el a fejlesztőkhöz a megfelelő módon. A naplóhoz hozzáférés biztosítása csak a fejlesztők számára viszonylag egyszerű egy webes alkalmazás esetén, mivel ott mi kontrolláljuk, hogy ki mihez fér hozzá. Ugyanez igaz a telemetriai adatokra is.
Mobil és asztali alkalmazások esetén támadási felület általában az átvitel. Ha nem titkosítottan, biztonságos módon visszük át az adatokat, akkor az illetéktelenek is megszerezhetik.
Ennyi bevezetőből látszik szerintem, hogy a telemetria és biztonságos naplózás kérdése nem egyszerű feladat. Kivitelezhetjük magunk is, de rengeteg apróságra kell ügyelnünk, amik mind visszaüthetnek valamilyen módon. Éppen ezért a legtöbb alkalmazás valamilyen külső komponenst használ erre a célra egyedi megoldások helyett.
Ezekből N+1 van eltérő tudással, eltérő felhasználói körnek, ezért mindenre kitérni észszerűtlen és lehetetlen is. Éppen ezért a könyv ezen szakaszában két népszerű könyvtárat mutatok be, ami megkönnyíti az életünket.
Sentry
A Sentry egy hiba monitorozó rendszer, ami kifejezetten hasznos, ha asztali vagy mobil alkalmazást fejlesztünk. Tételezzük fel, hogy kiadunk egy alkalmazást, ez eljut a felhasználóhoz. A programban nem kezelünk le egy kivételt, aminek hatására összeomlik az alkalmazás. Ha volt eszünk, akkor legalább egy általános kivételkezelőt beleépítettünk és nem csak a rendszer összeomlott a program dialógusát/üzenetét látja a felhasználó.
Bármelyik is legyen a szituáció, a tapasztalat azt mutatja, hogy a felhasználók nagyon kis százaléka fog használható hibajelentést készíteni a hiba reprodukálásához szükséges információkkal. Nagyobb valószínűséggel fognak egy csillagos, vagy negatív értékelést adni az alkalmazásunkra.
Itt jön képbe a Sentry. A programunkban az utolsó, általános kivételkezelőben kell elhelyezni egy speciális kódot, ami a https://sentry.io/ oldalon található fiókunkba naplózza a kivétel részleteit és minden fontos információt, ami a hiba megtalálásában segítségünkre lehet.
A Sentry használata egyszerű, használata két részből áll. Először regisztrálnunk kell egy fiókot a sentry.io oldalon, majd a programunkba be kell építeni egy kódrészletet. A kódrészlet beépítéséhez a Sentry NuGet csomagra lesz szükségünk.
Ezt követően egy konzol alkalmazás esetén a legegyszerűbb módon így tudjuk használni:
using System;
using Sentry;
namespace SentryTest
{
class Program
{
static void Main(string[] args)
{
using (SentrySdk.Init(o =>
{
// projekt konfigurálása, hogy hova is naplózunk.
o.Dsn = "https://examplePublicKey@o0.ingest.sentry.io/0";
}))
{
try
{
//Alkalmazás kódja
}
catch (Exception ex)
{
//kivétel naplózása
SentrySdk.CaptureException(ex);
}
}
}
}
}
A kötelező konfigurálás után a SentrySdk.CaptureException(); metódust bármelyik beágyazott kivételkezelő blokkban alkalmazhatjuk, ha akarjuk. Lényegében ez a metódus végzi el a hiba adatok felöltését.
Ennek kapcsán megjegyzem, hogy a Sentry használata egy bizonyos projekt méret felett fizetős. Erről a https://sentry.io/pricing/ oldalon tájékozódhatunk, míg a keretrendszer lehetőségeiről és használatáról a https://docs.sentry.io/platforms/dotnet/ oldalon találunk több információt.
Serilog
.NET-hez jónéhány naplózó keretrendszer létezik. A népszerűbbek közé tartozik az NLog, log4net és a Serilog. Ezek közül jelen pillanatban a Serilog a lengépszerűbb. Használat szempontjából a naplózó keretrendszerek többsége ugyanúgy használható: konfigurálni kell, hogy hova naplózzon, majd egy objektumon vagy absztrakciós interfészen keresztül metódusok segítségével tudunk írni a naplóba. A metódusok az üzenet súlyosságát, kategóriáját határozzák meg. A konfiguráció alapján bizonyos kategóriák naplózását akár le is tilthatjuk. Például egy Release konfigurációban futó alkalmazás esetén felesleges alapértelmezetten Debug üzeneteket kiírni.
A Serilog moduláris felépítésű, ami a kimenetek típusában mutatkozik meg. Ezeket a Serilog Sink-nek nevezi. Egy naplózó objektumhoz több Sink is tartozhat, vagyis megcsinálhatjuk azt, hogy nem csak a konzolra, hanem egy fájlba is logolunk párhuzamosan.
A Serilog használatát az alábbi példaprogram mutatja be. Használatához a Serilog, Serilog.Sinks.Console és Serilog.Sinks.File NuGet csomagokat telepítenünk kell.
using System;
using Serilog;
namespace SerilogExample
{
class Program
{
static void Main()
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.WriteTo.File("logs/myapp.txt", rollingInterval: RollingInterval.Day)
.CreateLogger();
Log.Information("Hello, world!");
int a = 10, b = 0;
try
{
Log.Debug("Dividing {A} by {B}", a, b);
Console.WriteLine(a / b);
}
catch (Exception ex)
{
Log.Error(ex, "Something went wrong");
}
finally
{
Log.CloseAndFlush();
}
}
}
}
A program kimenete:
[17:12:37 INF] Hello, world!
[17:12:37 DBG] Dividing 10 by 0
[17:12:37 ERR] Something went wrong
System.DivideByZeroException: Attempted to divide by zero.
at SerilogExample.Program.Main() in e:\csharpkonyv\Peldak\Serilog\Program.cs:line 22
A Log statikus osztályon keresztül tudunk naplózni. Használata előtt egy Builder segítségével konfigurálni kell. Amit mindenképpen be kell állítani, az a minimum naplózási szint és hogy hova történjen a logolás. Jelen esetben konzolt és egy fájlt adtunk meg.
A naplófájloknál ügyelni kell a naplók rendszeres forgatására. Nem egészséges, ha egyetlen egy fájlba naplózunk, mert egy 20 millió soros szöveges fájl megnyitása bármilyen szerkesztőnek feladja a leckét, arról nem is beszélve, hogy egy ilyen nagy fájlban a hibát megtalálni olyan, mint ha tűt keresnénk a szénakazalban. A kódban a rollingInterval: RollingInterval.Day beállítás napi Log fájlokat fog létrehozni.
A naplózási szintek egymásra épülnek. A legalacsonyabb szintű a Debug. Ezek az információk a fejlesztés közbeni hibakeresést szolgálják. Efölötti szint az Information. Ezek általános információk, amit nem baj, ha a felhasználó is lát.
Ezt követik a Warning és Error szintek. Ha a minimum naplózási szintet Warning-ra állítjuk, akkor az Information és Debug üzenetek nem fognak kiíródni.
Ez elég alpaszintű használata a Serilognak. Természetesen ennél bőven többet tud a keretrendszer. Használatáról a https://github.com/serilog/serilog/wiki/ oldalon lehet tájékozódni.
Microsoft.Extensions.Logging
A Microsoft is rendelkezik saját naplózó keretrendszerrel. Ez az ASP.NET alkalmazásokhoz lett fejlesztve. Ez egy interfészen leválasztott megvalósítást használ, ami azt jelenti, hogy a naplózás és a dependency injection kéz a kézben jár. Egyébként ez a valós alkalmazások többségére igaz.
A Microsoft.Extensions.Logging használatára külön nem térnék most itt ki, mivel akkor bele kellene magunkat ásni az ASP.NET dependency injection keretrendszerébe és annak használatába is.
Erről a naplózó keretrendszerről azt érdemes tudni, hogy szintén moduláris felépítésű és akár Serilog-ot is használhatunk a háttérben.
-
https://eur-lex.europa.eu/legal-content/HU/TXT/HTML/?uri=CELEX:32016R0679↩
-
"A szolgáltatásmegtagadással járó támadás (Denial of Service vagy DoS), más néven túlterheléses támadás, illetve az elosztott szolgáltatásmegtagadással járó támadás (Distributed Denial of Service, DDoS) informatikai szolgáltatás teljes vagy részleges megbénítása, helyes működési módjától való eltérítése." – https://hu.wikipedia.org/wiki/Szolg%C3%A1ltat%C3%A1smegtagad%C3%A1ssal_j%C3%A1r%C3%B3_t%C3%A1mad%C3%A1s↩