Grafikus C# – Windows Forms tanfolyam › 13.7 lecke

Windows Forms · 13.7 lecke · naplózás

Diagnosztika és naplózás

A hibakeresőt (13.2–13.3 lecke) te használod, a saját gépeden. De a hibák a felhasználó gépén jelentkeznek, amikor te nem látod: „nálam nem megy a mentés”, „tegnap lefagyott”. Ilyenkor nincs töréspont: csak az marad, amit a program előre feljegyzett. A napló a program fekete doboza (mint a repülőgépé): megmutatja, mi történt a hiba előtt. Ebben a leckében megtanulod, mit és milyen szinten naplózz, hogyan írsz saját, szálbiztos naplózót napi fájllal és méretkorláttal, hogyan használod a Debug és Trace osztályt és a Debug.Assertet, hogyan méred a teljesítményt Stopwatch-csal, és mire kell vigyáznod (személyes adatok a naplóban).

  • kb. 100 perc
  • közepes–haladó szint
  • naplózás
Diák C# programozást gyakorol egy tanulósarokban

A lecke végére

  • megmagyarázod, mire jó a napló, és mit érdemes (és mit nem) naplózni;
  • használod a naplószinteket (Debug, Information, Warning, Error, Critical);
  • szálbiztos, hibatűrő naplózót írsz (napi fájl, méretkorlát, nem dob kivételt);
  • használod a Debug.WriteLine, Trace és Debug.Assert eszközöket, valamint a [Conditional] attribútumot;
  • teljesítményt naplózol Stopwatch-csal;
  • a naplót interface mögé teszed, és naplónézőt építesz.

Mielőtt elkezded

Ehhez a leckéhez a 13.4 lecke (kivételkezelés, globális kezelő), a 12.8 lecke (interface és függőség átadása) és a 11.7 lecke (szálbiztosság) szükséges.

13.6 Fájl- és adatbázis-kivételek →

Mit, milyen szinten, mit ne?

SzintMire való?Példa
Debug (nyomkövetés)Részletes fejlesztői információ: változók, lépések. Alapból kikapcsolva.Debug: n = 5, osszeg = 15
InformationA program normál működésének fontos eseményei.A program elindult (1.4.2), Mentés kész: 250 sor
WarningSzokatlan, de kezelt helyzet.A fájl hiányzott, üres lista betöltve, Újrapróbálás (2/4)
ErrorEgy művelet nem sikerült, de a program fut tovább.A mentés nem sikerült: lemez megtelt
CriticalA program nem tud tovább működni.Kezeletlen kivétel: ...

Mit naplózz?

  • Indulás és leállás (verzió, gép, .NET).
  • A fontos műveleteket (mentés, betöltés, törlés, import) eredménnyel.
  • Minden kivételt teljes ex.ToString() szöveggel (stack trace, inner).
  • A döntési pontokat: melyik ágon ment el a program (tartalék betöltve).
  • A teljesítményt (mennyi ideig tartott a betöltés).

Mit ne naplózz?

  • Jelszavakat, tokeneket, titkos kulcsokat.
  • Személyes adatot (név, e-mail, telefonszám, cím): jogi kockázat (GDPR) és biztonsági.
  • Bankkártya- és egészségügyi adatot.
  • Teljes dokumentumtartalmat (csak a méretét/azonosítóját).
  • Ciklusonként ezer sort (elárasztja a naplót, és lassít).
A szint a szűrőA napló szintje (minimális szint) határozza meg, mi kerül a fájlba. Fejlesztéskor Debug, éles használatnál Information vagy Warning: a részletes sorok nem árasztják el a fájlt, de szükség esetén bekapcsolhatók.
Egy sor, egy eseményEgy naplósor tartalmazza: időbélyeg, szint, szál, üzenet. Kereshető, rendezhető, olvasható. A kivétel többsoros szöveg: a sor elejére tedd az üzenetet.
Személyes adatA név, e-mail, telefonszám személyes adat. Ha mégis kell az azonosítás, naplózz azonosítót (pl. Felhasznalo #4821), vagy rövidített/maszkolt alakot (an***@pelda.hu). A naplót a felhasználó elküldheti segítségkérésnél: nem szabad érzékeny adatot tartalmaznia.
A napló maga is hibaforrásA naplózás nem dobhat kivételt (a hibakezelő hibája a legrosszabb), nem lassíthatja a programot észrevehetően, és nem tölthet meg lemezt (méretkorlát, forgatás).

Jósolj!

A program a mentés minden sorát Debug szinten naplózza, és a minimális szint Debug marad az éles gépen. Egy 50 000 soros fájl mentésekor mi történik a naplóval és a sebességgel?

Jóslat ellenőrzése

50 000 naplósor keletkezik (több megabájt), és a mentés érezhetően lassul (minden sorért fájlművelet). Ezért a részletes naplót éles gépen kikapcsolják (szint: Information), és a ciklusokban nem naplózunk soronként, hanem összegzünk (Mentés kész: 50 000 sor, 320 ms).

Saját naplózó osztály

Naplo.cs (using System.IO; using System.Text; using System.Threading;)C#
public enum NaploSzint { Debug = 0, Information = 1, Warning = 2, Error = 3, Critical = 4 }

// a szerződés: a program többi része ezt ismeri (12.8 lecke: interface és függőség átadása)
public interface INaplo
{
void Ir(NaploSzint szint, string uzenet, Exception ex = null);
}

public class FajlNaplo : INaplo
{
private readonly object zar = new object(); // több szál is írhat: a zár egyszerre egyet enged
private readonly string mappa;
private readonly long maxMeret;

public NaploSzint MinSzint { get; set; }

public FajlNaplo(string mappa, NaploSzint minSzint = NaploSzint.Information, long maxMeret = 1024 * 1024)
{
this.mappa = mappa; this.MinSzint = minSzint; this.maxMeret = maxMeret;
}

public void Ir(NaploSzint szint, string uzenet, Exception ex = null)
{
if (szint < MinSzint) { return; } // a szint a szűrő

try // a naplózás SOHA nem dobhat kivételt
{
string sor = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")
+ " [" + szint.ToString().ToUpper().PadRight(11) + "] (szál " + Environment.CurrentManagedThreadId + ") " + uzenet
+ (ex != null ? Environment.NewLine + ex : "");

lock (zar)
{
Directory.CreateDirectory(mappa);

string fajl = Path.Combine(mappa, "naplo-" + DateTime.Now.ToString("yyyyMMdd") + ".log"); // napi fájl

Forgat(fajl);
File.AppendAllText(fajl, sor + Environment.NewLine, new UTF8Encoding(false));
}
}
catch { /* a naplózó hibája ne okozzon újabb hibát; legfeljebb Debug.WriteLine */ }
}

// FORGATÁS: ha a fájl túl nagy, átnevezzük, és újat kezdünk (régi napló: .1.log)
private void Forgat(string fajl)
{
if (!File.Exists(fajl) || new FileInfo(fajl).Length < maxMeret) { return; }

string regi = Path.ChangeExtension(fajl, ".1.log");

if (File.Exists(regi)) { File.Delete(regi); }

File.Move(fajl, regi);
}
}

// kényelmi bővítők: naplo.Info("..."), naplo.Hiba("...", ex)
public static class NaploBovitok
{
public static void Info(this INaplo n, string uzenet) { n.Ir(NaploSzint.Information, uzenet); }
public static void Figyelmeztet(this INaplo n, string uzenet) { n.Ir(NaploSzint.Warning, uzenet); }
public static void Hiba(this INaplo n, string uzenet, Exception ex = null) { n.Ir(NaploSzint.Error, uzenet, ex); }
}
naplo-20260115.logkimenet
2026-01-15 09:02:11.304 [INFORMATION] (szál 1) A program elindult (verzió 1.4.2, .NET 8.0.1)
2026-01-15 09:02:11.420 [INFORMATION] (szál 1) Betöltés kész: 250 jegyzet, 38 ms
2026-01-15 09:14:52.017 [WARNING ] (szál 1) Mentés: a fájl zárolva, újrapróbálás (2/4)
2026-01-15 09:14:52.911 [ERROR ] (szál 6) A mentés nem sikerült: lemez megtelt
System.IO.IOException: There is not enough space on the disk.
at System.IO.File.WriteAllText(...)
at Jegyzetek.FajlTarolo.Ment(...) in FajlTarolo.cs:line 42
Interface mögöttA program INaplo-t kap (konstruktorban), nem a konkrét fájlnaplót: így tesztben MemoriaNaplo (egy lista) vagy NincsNaplo (semmit sem csinál) adható át (12.8 lecke). A szolgáltatások naplóznak, a Form is, de mindegyik ugyanazt a példányt kapja.
lockTöbb szál (11. fejezet: háttérmunka, időzítő) egyszerre írhat. A lock biztosítja, hogy a sorok ne keveredjenek, és a fájl ne legyen egyszerre kétszer megnyitva.
Napi fájl és forgatásA napi fájlnév (naplo-20260115.log) segít keresni, a méretkorlát (maxMeret) és a régi fájl átnevezése megakadályozza, hogy a napló végtelenül nőjön. Hosszú távra a régi naplókat törlik (pl. 30 napnál régebbi).
A catch üres, de indokoltA naplózó belsejében a catch { } az egyetlen elfogadható elnyelés (13.4 lecke): a naplózás hibája nem szakíthatja meg a programot, és nem naplózhatja újra önmagát (végtelen ciklus).

Jósolj!

A FajlNaplo.Ir belsejében nincs try–catch, és a naplómappa csak olvasható. Mi történik, ha a program elindulásakor az első Info sort írja?

Jóslat ellenőrzése

Egy UnauthorizedAccessException keletkezik a naplózásból, és a program indulás előtt összeomlik egy mellékes dolog (a napló) miatt. A naplózó soha nem lehet a hibaforrás: ezért védett a teljes metódus.

Debug, Trace, Assert, Conditional

Kod.cs (using System.Diagnostics;)C#
// DEBUG: csak a Debug fordításban él; a Release változatból a fordító kiveszi (nulla költség)
Debug.WriteLine("n = " + n);
Debug.WriteLineIf(n > 1000, "Szokatlanul nagy n: " + n);

// ASSERT: feltétel, amelynek MINDIG igaznak kell lennie (programozói hiba esetén megáll a futás)
Debug.Assert(lista != null, "A lista nem lehet null ezen a ponton.");
Debug.Assert(osszeg >= 0, "Az összeg nem lehet negatív: " + osszeg);

// TRACE: Debug és Release fordításban is él; figyelők (listener) fogadják
Trace.Listeners.Add(new TextWriterTraceListener("trace.log"));
Trace.AutoFlush = true;
Trace.WriteLine("Ez Release fordításban is naplózódik.");

// CONDITIONAL: a metódushívás csak DEBUG fordításban kerül a kódba
[Conditional("DEBUG")]
private static void Allapot(string uzenet) { Debug.WriteLine("ÁLLAPOT: " + uzenet); }

// fordítási feltétel
#if DEBUG
btnTesztAdat.Visible = true; // a tesztgomb csak fejlesztéskor látszik
#endif
Debug vs. TraceA Debug.* hívások a Release fordításból teljesen eltűnnek (fejlesztői segédlet). A Trace.* megmarad (éles diagnosztika). A kimenet a Listeners gyűjteményen át megy (Output ablak, fájl, eseménynapló).
Debug.AssertAz Assert a programozói feltevéseket ellenőrzi („itt a lista sosem null”). Ha megsérül, a Debug fordításban párbeszédablak jelzi a hibát. A felhasználói hibát (rossz bevitel) nem Assert-tel, hanem kivétellel/ellenőrzéssel kezeld (13.5 lecke): az Assert Release-ben nem fut.
[Conditional]A [Conditional("DEBUG")] attribútumú metódus hívása Release-ben ki sem fordul (a paraméterek sem értékelődnek ki): ideális fejlesztői naplózáshoz. A #if DEBUG kódrészleteket zár ki.
Mikor mit?Fejlesztői nyomkövetés: Debug.WriteLine. Éles diagnosztika és hibák: a saját INaplo (vagy Trace). Állítások: Debug.Assert. A kettő nem helyettesíti egymást.

Jósolj!

Egy ellenőrzést Debug.Assert(kor >= 0) formában írsz meg a felhasználói bevitel védelmére, és a programot Release módban adod ki. Mi történik negatív életkorral?

Jóslat ellenőrzése

Semmi: a Debug.Assert Release-ben nem fut le, a negatív érték átmegy az ellenőrzésen. A felhasználói bevitelt valódi ellenőrzéssel (if, kivétel) védd; az Assert csak a programozói feltevések fejlesztés közbeni ellenőrzésére való.

Teljesítmény napló és a napló olvasása

Form1.cs (using System.Diagnostics; using System.Reflection;)C#
// INDULÁSKOR: környezet-információ a naplóba (hibabejelentésnél aranyat ér)
private void IndulasiAdatok()
{
naplo.Info("A program elindult. Verzió: " + Assembly.GetExecutingAssembly().GetName().Version
+ "; OS: " + Environment.OSVersion
+ "; .NET: " + Environment.Version
+ "; kultúra: " + System.Globalization.CultureInfo.CurrentCulture.Name
+ "; 64 bites: " + Environment.Is64BitProcess);
}

// TELJESÍTMÉNY: a művelet idejét naplózzuk
private void Betolt()
{
Stopwatch sw = Stopwatch.StartNew();

var adatok = tarolo.Betolt();

sw.Stop();
naplo.Info("Betöltés kész: " + adatok.Count + " elem, " + sw.ElapsedMilliseconds + " ms");

if (sw.ElapsedMilliseconds > 1000) { naplo.Figyelmeztet("A betöltés szokatlanul lassú: " + sw.ElapsedMilliseconds + " ms"); }
}

// A NAPLÓFÁJL OLVASÁSA közben a program írja: megosztott olvasás kell (FileShare.ReadWrite)
using (FileStream fs = new FileStream(ut, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (StreamReader r = new StreamReader(fs, Encoding.UTF8)) { string szoveg = r.ReadToEnd(); }

Hogyan olvass naplót?

  1. Keresd meg az első hibát ([ERROR], [CRITICAL]), nem a legutolsót: a későbbiek gyakran következmények.
  2. Nézd az előzményeket: mit csinált a program a hiba előtt (a sorok időrendben)?
  3. Olvasd el a stack trace-t: a legfelső saját kódsor a hiba helye.
  4. Keresd a mintát: mindig ugyanabban a műveletben, ugyanabban az időben, ugyanazzal a bemenettel?
  5. Reprodukáld a hibát a napló alapján, és a debuggerrel (13.2 lecke).

Szokások

  • Üzenet = esemény + adat: „Mentés nem sikerült: lemez megtelt (C:, 18 KB szabad)”, nem „hiba”.
  • Ne naplózz kétszer: ha elkapod és továbbdobod (throw;), csak egy helyen naplózz (a végén).
  • Legyen UI-felület: a Napló megnyitása menü és a hibaablak a naplófájl helyét megadja.
  • Kezeld a méretet: forgatás, törlés N nap után.
  • Tesztelj naplóval: az automatikus tesztben a MemoriaNaplo ellenőrizhető (naplózott-e a hibát?).

Jósolj!

A programod a catch blokkban naplózza a hibát, majd throw; segítségével továbbdobja, a hívó pedig szintén naplózza. Hány sor lesz a naplóban ugyanarról a hibáról?

Jóslat ellenőrzése

Két (vagy több) sor ugyanarról a hibáról: zajt keltenek, és az olvasó azt hiheti, két külön hiba történt. Egy elv: ott naplózz, ahol a kivételt véglegesen kezeled (megjeleníted, vagy a globális kezelőben), ne minden szinten.

📷 Képernyőkép helye

Mit tegyél ide: a naplónéző ablak a szűrt hibasorokkal, mellette a nyers naplófájl.Javasolt fájlnév: winforms-13-7-naplonezo.webp · Alt szöveg: A naplónéző program

Hibakeresés: te vagy a hibadetektív

Mi a baj, és hogyan javítod?

Gondold végig az okot, és csak utána nyisd le a megoldást.

1. A napló nem keletkezik

A program fut, de nincs naplófájl.

Ok és javítás

A naplózó catch blokkja elnyeli a hibát: valószínűleg nincs írási jog a mappában (a program mappája: Program Files). Használd az %AppData% vagy %LocalAppData% mappát; fejlesztéskor a catchben Debug.WriteLine(ex).

2. A naplósorok összekeverednek

Két szál sorai beleolvadnak egymásba a fájlban.

Ok és javítás

Nincs lock az írás körül. A lock (zar) az egész írást (mappa létrehozás, forgatás, hozzáfűzés) védje.

3. A napló a lemezt tölti

Hónapok alatt gigabájtos fájl keletkezett.

Ok és javítás

Nincs méretkorlát és tisztítás. Forgatás (maxMeret), napi fájl, és N napnál régebbi naplók törlése.

4. A jelszó a naplóban

naplo.Info("Bejelentkezés: " + felhasznalo + ", jelszó: " + jelszo);
Hiba és javítás

Jelszót, tokent és személyes adatot soha ne naplózz. Naplózd az eseményt (Bejelentkezés sikeres: #4821).

5. A naplófájl nem olvasható futás közben

A naplónéző IOException-t kap a megnyitáskor.

Ok és javítás

A fájl írás alatt áll. Nyisd meg FileShare.ReadWrite paraméterrel (a File.ReadAllText nem megosztott).

6. Az Assert nem véd éles gépen

Debug.Assert(fajl != null);
Feldolgoz(fajl); // Release-ben NullReferenceException
Hiba és javítás

Az Assert Release-ben nem fut. A kötelező ellenőrzés valódi: if (fajl == null) throw new ArgumentNullException("fajl");.

Mini projekt: naplózó és naplónéző

Építs naplózó rendszert egy példaprogramhoz, és naplónézőt, amely szűrni és keresni tud:

  1. Naplózó: NaploSzint, INaplo, FajlNaplo (napi fájl, forgatás 200 KB-nál, lock, védett catch), MemoriaNaplo (teszthez), kényelmi bővítők.
  2. Példaprogram: egy kis kalkulátor vagy jegyzetkezelő, amely indításkor környezeti adatot naplóz (verzió, OS, .NET, kultúra), a műveleteket Information szinten, a szokatlan eseteket Warning, a hibákat Error szinten (ex.ToString()-gal); a globális hibakezelő (13.4 lecke) Critical.
  3. Teljesítmény: a betöltés és mentés ideje (Stopwatch), Warning, ha lassabb 500 ms-nál.
  4. Szint beállítása: menü: Naplózás: Debug / Information / Warning, a MinSzint futás közben módosul (és a napló maga is jegyzi: Naplószint váltva).
  5. NaploNezo ablak: megnyitja a mai naplófájlt FileShare.ReadWrite paraméterrel; ListView oszlopokkal (Idő, Szint, Szál, Üzenet); a sorok szintje szerinti jelölés (szöveg is, nem csak szín); szűrők: szint (ComboBox), keresés (TextBox), Csak a mai; Frissítés gomb (és 2 mp-es automatikus frissítés Timerrel, a kijelölés megtartásával).
  6. Kivételek többsoros kezelése: a naplónéző a [-vel nem kezdődő sorokat (stack trace) a megelőző naplósorhoz fűzi, és a részletek a kijelölt sor alatti szövegmezőben látszanak.
  7. Adatvédelem: a példaprogram bemeneteiből a név és e-mail nem kerül a naplóba (csak azonosító és hossz); a leírásban sorold fel, mit nem naplózol és miért.
  8. Tesztek: MemoriaNaplo segítségével: a szolgáltatás hibánál Error sort naplóz; a minimális szint kiszűri a Debug sorokat; a naplózó nem dob kivételt, ha a mappa nem írható.
  9. Teszteld: két szál egyszerre naplóz (nem keverednek a sorok), forgatás (200 KB), futás közben megnyitott naplónéző, a napló tisztítása (30 napnál régebbi fájlok törlése induláskor).
Megoldás megnyitása (próbáld ki előbb önállóan!)
MemoriaNaplo, NaploNezo, tisztítás (using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.RegularExpressions;)C#
public class MemoriaNaplo : INaplo
{
public readonly List<string> Sorok = new List<string>();
public NaploSzint MinSzint = NaploSzint.Debug;

public void Ir(NaploSzint szint, string uzenet, Exception ex = null)
{
if (szint < MinSzint) { return; }

lock (Sorok) { Sorok.Add(szint + ": " + uzenet + (ex != null ? " | " + ex.GetType().Name : "")); }
}
}

public static class NaploTisztitas
{
public static int RegiTorles(string mappa, int napok)
{
int db = 0;

if (!Directory.Exists(mappa)) { return 0; }

foreach (string f in Directory.GetFiles(mappa, "naplo-*.log"))
{
try { if (File.GetLastWriteTime(f) < DateTime.Now.AddDays(-napok)) { File.Delete(f); db++; } }
catch (IOException) { }
catch (UnauthorizedAccessException) { }
}

return db;
}
}

public class NaploSor { public string Ido, Szint, Szal, Uzenet; public StringBuilder Reszlet = new StringBuilder(); }

public static class NaploElemzo
{
private static readonly Regex minta = new Regex(@"^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}) \[(\w+)\s*\] \(szál (\d+)\) (.*)$");

public static List<NaploSor> Beolvas(string ut)
{
List<NaploSor> lista = new List<NaploSor>();

using (FileStream fs = new FileStream(ut, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (StreamReader r = new StreamReader(fs, Encoding.UTF8))
{
string sor;

while ((sor = r.ReadLine()) != null)
{
Match m = minta.Match(sor);

if (m.Success) { lista.Add(new NaploSor { Ido = m.Groups[1].Value, Szint = m.Groups[2].Value, Szal = m.Groups[3].Value, Uzenet = m.Groups[4].Value }); }
else if (lista.Count > 0) { lista[lista.Count - 1].Reszlet.AppendLine(sor); } // a stack trace az előző sorhoz tartozik
}
}

return lista;
}
}

// ---- NaploNezo.cs (Form) ----
private List<NaploSor> osszes = new List<NaploSor>();

private void Frissit()
{
string ut = Path.Combine(mappa, "naplo-" + DateTime.Now.ToString("yyyyMMdd") + ".log");

if (!File.Exists(ut)) { tsslUzenet.Text = "Nincs mai naplófájl."; return; }

try { osszes = NaploElemzo.Beolvas(ut); }
catch (IOException ex) { tsslUzenet.Text = "A napló nem olvasható: " + ex.Message; return; }

Szur();
}

private void Szur()
{
string szint = cmbSzint.SelectedItem == null ? "Mind" : cmbSzint.SelectedItem.ToString();
string keres = txtKeres.Text.Trim();

lv.BeginUpdate();
lv.Items.Clear();

foreach (NaploSor s in osszes.Where(x => (szint == "Mind" || x.Szint.Equals(szint, StringComparison.OrdinalIgnoreCase)) && (keres.Length == 0 || x.Uzenet.IndexOf(keres, StringComparison.CurrentCultureIgnoreCase) >= 0)))
{
ListViewItem it = new ListViewItem(new string[] { s.Ido, s.Szint, s.Szal, s.Uzenet }) { Tag = s };

if (s.Szint.StartsWith("ERROR") || s.Szint.StartsWith("CRITICAL")) { it.ForeColor = Color.Firebrick; } // a szint a szöveges oszlopban is látszik

lv.Items.Add(it);
}

lv.EndUpdate();
tsslUzenet.Text = lv.Items.Count + " / " + osszes.Count + " sor";
}

private void lv_SelectedIndexChanged(object sender, EventArgs e)
{
txtReszlet.Text = lv.SelectedItems.Count == 0 ? "" : ((NaploSor)lv.SelectedItems[0].Tag).Reszlet.ToString();
}
📷 Képernyőkép helye

Mit tegyél ide: a kész naplózó rendszer és naplónéző.Javasolt fájlnév: winforms-13-7-kesz.webp · Alt szöveg: A kész naplózó és naplónéző

Három önálló gyakorlófeladat

Egyszerre csak egyet csinálj: tervezd meg, írd meg, futtasd, ellenőrizd, és csak utána nyisd ki a megoldást.

1. Naplózó teszt

Írj tesztet a MemoriaNaplo segítségével: a Mentes hibájánál naplózódik-e Error?

Egy lehetséges megoldás

A szolgáltatásnak INaplo-t adsz (MemoriaNaplo), egy hibás tárolóval (kivételt dob) hívod a mentést, majd ellenőrzöd: naplo.Sorok.Any(s => s.StartsWith("Error")).

2. Egy kérés, egy azonosító

Hogyan kapcsolod össze egy művelet naplósorait (összetartozó sorok keresése)?

Egy lehetséges megoldás

Minden művelet kap egy rövid azonosítót (Guid.NewGuid().ToString("N").Substring(0, 6)), amelyet az összes naplósor tartalmaz ([a3f9c1] Mentés indul). Így a naplóban az azonosítóra szűrve a teljes menet látszik.

3. Eseménynapló

Hogyan írnál a Windows eseménynaplóba?

Egy lehetséges megoldás

A System.Diagnostics.EventLog osztállyal (EventLog.WriteEntry(forras, uzenet, EventLogEntryType.Error)); a forrás létrehozása rendszergazdai jogot igényel egyszer, telepítéskor, ezért asztali programban a fájl-napló egyszerűbb.

Gyakorlótár: 6 további feladat

Három szinten gyakorolhatsz: alap, közepes és kihívás. Csak a próbálkozás után nyisd le a megoldást.

Alap szint

1. Melyik szint?

Szint: (a) a program elindult; (b) a fájl hiányzott, üres lista betöltve; (c) a mentés nem sikerült.

Megoldás megnyitása

(a) Information; (b) Warning; (c) Error.

2. Mit ne?

Sorolj fel három dolgot, amit nem naplózol.

Megoldás megnyitása

Jelszó, személyes adat (név, e-mail, telefonszám), bankkártyaszám, teljes dokumentum; ciklusonként ezer sor.

Közepes szint

3. Debug vagy Trace?

Mi a különbség?

Megoldás megnyitása

A Debug csak Debug fordításban él (Release-ből eltűnik); a Trace mindkettőben.

4. Assert

Védhet-e az Assert a felhasználói hibás bevitel ellen?

Megoldás megnyitása

Nem: Release-ben nem fut. A bevitelt valódi ellenőrzéssel (kivétel, if) kell védeni.

Kihívás szint

5. Naplózó kivétele

Mit tegyen a naplózó, ha a naplófájl nem írható?

Megoldás megnyitása

Ne dobjon kivételt; nyelje el (a program ne álljon le a napló miatt), esetleg Debug.WriteLine-nal jelezze, és próbálkozzon másik hellyel (%TEMP%).

6. Naplózás és sebesség

Hogyan gyorsítanád a naplózást sok szál mellett?

Megoldás megnyitása

A sorokat egy ConcurrentQueue-ba tennéd (a hívó nem vár), és egy háttérszál írná ki adagonként (11.7 lecke): nincs lemezvárakozás a hívó szálon; leálláskor a sort ki kell üríteni (flush).

Gyors önellenőrzés

Válaszolj fejben, és csak utána nyisd le a választ.

1. Mire jó a napló?

A felhasználó gépén keletkezett hibák nyomkövetésére, amikor nincs debugger.

2. Melyek a naplószintek?

Debug, Information, Warning, Error, Critical.

3. Miért lock a naplózóban?

Több szál egyszerre írhat: a lock megakadályozza a sorok keveredését.

4. Dobhat-e kivételt a naplózó?

Nem: a naplózás hibája nem szakíthatja meg a programot.

5. Mit jelent a forgatás?

A túl nagy naplófájlt átnevezi, és újat kezd (és a régieket törli).

6. Mi a [Conditional("DEBUG")]?

A metódushívás csak Debug fordításban kerül a kódba.

7. Naplózhatod-e a jelszót?

Soha: sem jelszót, sem személyes adatot.

Mit tudsz már?

  • Tudod, mit és milyen szinten naplózz, és mit nem.
  • Szálbiztos, hibatűrő naplózót írsz forgatással.
  • A Debug, Trace, Assert és [Conditional] eszközöket helyesen használod.
  • Teljesítményt naplózol, naplót olvasol és szűrsz.

Következő lecke: Manuális tesztelés és tesztesetek

A program módszeres kipróbálása: tesztesetek írása, tesztterv, hibajelentés és regressziós tesztelés.