Wątek przeniesiony 2016-05-20 11:08 z C# i .NET przez ŁF.

Zapis Logów do pliku

0

Ktoś mnie poprosił żebym mu napisał rozbudowaną funkcję zapisu logów do pliku łatwą do edytowania. czy łatwa to nie wiem

Ostrzegam zrobiłem w 2 godzinki właśnie skończyłem i jeszcze nie przetestowałem. Ale powinno działać. Może komuś się jeszcze przyda.
A ja mam pytanie z innej beki

Moduł - za co jest odpowiedzialny takie sprostowanie ;)

FatalError() - jakbyście wy go rozbudowali.

Oraz jaki jest inny sposób a na pewno jest ;) by do logów przesłać w łatwy sposób namespaca klasę oraz funkcję w której został wywołany zapis do logów ?

PS. Klasa tworzy sama pliku z aktualna data

namespace FS_Loger
{
    /*************************************************************************************************************
         ##########################################################################################################
         ############                             Łukasz Komur C# Developer                            ############
         ############                                    Fight Solution                                ############
         ############                                    [email protected]                                 ############
         ##########################################################################################################
         ##########################################################################################################
                Informacje o klasie FS_Logerr
     
     * Co należy zobić przed zaczeciem używania klasy
     * 1. uzupełnić
     * FolderPatchLogsMain - podać nazwę głownego katalogu
     * FolderPatchLogsLower - podać nazwę pod katalogu
     * 2. AddFileName() - odać do słownika moduły oraz nazwy pliku
     * 3. AddFileName() - odpalić wraz z wywłaniem pierwszego uruchomienia programu
     * 
     * Kozystamy podczas używania programu tylko z funkcji Logs() poprzez wywołąnie
     * FS_Logerr.Write.Logs(Status,Class,Void,modul,msg,Exception = null) 
     * 
     * W przypadku przesłania Exception wywoła się wykonaie zapisu opszerniejszych ifnormacji w funkcji FatalError()
     * 
     * Każdy inny status przyjmuej inną formę zapisu i jest zapisywany w pliku przeznaczonym dla swojego modułu 
     * Mozna wrzucić pare modułów do jednego pliki generujac ten sam value dla paru key a w logach mozna odroznic jaki to jest modul
     * 
     * Statusy - w przypadku pojawienia sie Exception sa zapisywane dodatkowe informacje o nim
     * Trace   - w przypadku pojawienia sie log zostaje wyszczegulniony spacjami i znacznikiem dodatkowo Log + FatalError jak zajedzie koniecznosc 
     * Info    - jw. tylko bez wyszczegolnienia mozna zrobic po swojemu
     * Warn    - jw. tylko bez wyszczegolnienia mozna zrobic po swojemu
     * Error   - jw. tylko bez wyszczegolnienia mozna zrobic po swojemu
     * Fatal   - w przypadku pojawienia sie tego statusu informacje o nim sa zapisywane w pliku modulu wraz z infomracja o excetionie dodatkowo Log + FatalError jak zajedzie koniecznosc
     * Log     - w przypadku pojawienia sie tego statusu informacje o nim sa zapisywane tylko w Log + FatalError jak zajedzie koniecznosc
     * 
     * W przypadku nieudanego zapisu logu jest funkcja wspomagajaca zapis WriteError
         ##########################################################################################################
         ##########################################################################################################
     ************************************************************************************************************/

    public sealed class FS_Logerr
    {
        /* Instancja klasy tylko do odczytu */
        private readonly static FS_Logerr instance = new FS_Logerr();

        private string FolderPatchLogsLower = "\\"; // Odpowiada za nazwe podfoldera dla logów
        private string FolderPatchLogsMain = "\\";  // Odpowiada za głowny folder z logami


        /// <summary>
        /// Funkcja zwracjąaca string z lokalizacja sciezki do FolderPatchLogsMain
        /// </summary>
        /// <returns>string user\desktop\FolderPatchLogsMain</returns>
        private string GetFolderPatchLogsMain()
        {
            return Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + FolderPatchLogsMain; 
        }

        /// <summary>
        /// Funkcja zwracajaca stringa do lokalizacji sciezki FolderPatchLogsLower
        /// </summary>
        /// <returns>string user\desktop\FolderPatchLogsMain\FolderPatchLogsLower</returns>
        private string GetFolderPatchLogsLower()
        {
            return GetFolderPatchLogsMain() + FolderPatchLogsMain;
        }

        /// <summary>
        /// Funkcja Zwracajaca pelna sciezke do bierzacego pliki z rozroznieniem folderow za pomoca statusu oraz modulu
        /// </summary>
        /// <param name="status">Log - głowny folder, reszta podfolder</param>
        /// <param name="modul">oroznia pliki</param>
        /// <returns></returns>
        private string GetFilePatchLogs(string status ,string modul)
        {
            switch(status)
            {
                case "Log": // zwraca sciezke do pliku w FolderPatchLogsMain za pomoca statusu
                    return Path.Combine(GetFolderPatchLogsMain(), GetFullNameFileByStatus(status));

                case "FatalError": // zwracane ścieżki do pliku w lokalizacji FolderPatchLogsLower za pomoca statusu
                    return Path.Combine(GetFolderPatchLogsLower(), GetFullNameFileByStatus(status));

                case "WriteError": // zwracane ścieżki do pliku w lokalizacji FolderPatchLogsLower za pomoca statusu
                    return Path.Combine(GetFolderPatchLogsLower(), GetFullNameFileByStatus(status));

                default: // zwracane ścieżki do pliku w lokalizacji FolderPatchLogsLower za pomoca modulu
                    return Path.Combine(GetFolderPatchLogsLower(), GetFullNameFileBymodul(modul));
            }
        }

        private Dictionary<string, string> NameFile = new Dictionary<string, string>(); // key - modul || value NameFile

        /// <summary>
        /// Funkcja zwracajaca pelna nazwe pliki, rozpoznaje za pomoca modul
        /// </summary>
        /// <param name="modul"></param>
        /// <returns></returns>
        private string GetFullNameFileBymodul(string modul)
        {   
            string nameFile = NameFile[modul];                                                      // Tylko to nalezy zmienić jeżeli chcemy stworzyć nowy plik z logami
            return String.Format("{0}_{1}", DateTime.Now.ToString("yyyy-MM-dd"), nameFile);   // Tworzy pełną nazwę pliki poprzez dodanie przed nazwa pliku dzisiejszej daty
        }

        private string GetFullNameFileByStatus(string status)
        {
            string nameFile = NameFile[status];                                                      // Tylko to nalezy zmienić jeżeli chcemy stworzyć nowy plik z logami
            return String.Format("{0}_{1}", DateTime.Now.ToString("yyyy-MM-dd"), nameFile);   // Tworzy pełną nazwę pliki poprzez dodanie przed nazwa pliku dzisiejszej daty
        }
         
         //   return Path.Combine(patch, fullNameFile); 


        /// <summary>
        /// Tworzenie instancji
        /// </summary>
        public static FS_Logerr Write
        {
            get
            {
                return instance;
            }
        }

        /// <summary>
        /// Funkcja niezbedna do zainicjowania podczas pierwszego uruchomienia programu dodaje nazwy plików dla odpowiedniego modulu
        /// </summary>
        public void AddFileName()
        {
            NameFile.Clear(); //Czyszczenie Słownika by uniknąć zdublowania się danych
            /* Klucze wykożystywane w inny sposób */
            NameFile["Log"] = "MainLogsFile.txt";                // Klucza ("Log") - nie można zmieniać odpowiada za głowny plik z logami
            NameFile["FatalError"] = "FatalLosFile.txt";         // Klucza nie nalezy zmieniac - odpowiada za specjany zapis exception jak wystapia
            NameFile["WriteError"] = "WriteRrrorLogsFile.txt";   // Kluka nie nalezy zmieniac - odpowiada za zapis plików których zapis się nie udał z przeciażenia
            
            /* klcze dobierane za pomocą modulu */
            //NameFile["MojModul"] = "MojModul.txt";    // Odpowiada za pliki z modulu
            /*Wystarczy dodać tylko tutaj */
        }

        /// <summary>
        /// Głowna funkcja odpowiadająca za zapis otrzymywanych logów w odpowiedni sposób.
        /// </summary>
        /// <param name="Status">Trace, Info, Warn, Error, Fatal, Log</param>
        /// <param name="Class">Z jakiej klasy wywołane</param>
        /// <param name="Void">Z jakiej funkcji wywołane</param>
        /// <param name="modul">Za jaki moduł odpowiada</param>
        /// <param name="msg">wiadomość</param>
        /// <param name="exc">Exception = null</param>
        public void Logs(string Status, string Class, string Void, string modul, string msg, Exception exc = null )
        {
            switch (Status)
            {
                case "Trace": // Odpowiada za śledzenie informacji
                    Log(Status, Class, Void, modul); // Zapisuje Informacje co sie wydazyło i gdzie ("Przydaje się w śledzeniu miejsca wysypania programu")
                    if (exc != null) { FatalError(Status,modul,exc); } // gdy dla danego statusu wystapi excepcion zostaje on zapisany 
                    Trace(Status, Class, Void, modul, msg); // wywołanie funkcji zapisu logu dla modułu
                    break;

                case "Info":   // Odpowiada za zapis informacji istotnych
                    Log(Status, Class, Void, modul); // Zapisuje Informacje co sie wydazyło i gdzie ("Przydaje się w śledzeniu miejsca wysypania programu")
                    if (exc != null) { FatalError(Status,modul,exc); } // gdy dla danego statusu wystapi excepcion zostaje on zapisany
                    Info(Status, Class, Void, modul, msg); // wywołanie funkcji zapisu logu dla modułu
                    break;

                case "Warn":   // Odpowiada za Zapis informacji które mogłą mieć wpływ na jakoś świadczenia usługi
                    Log(Status, Class, Void, modul); // Zapisuje Informacje co sie wydazyło i gdzie ("Przydaje się w śledzeniu miejsca wysypania programu")
                    if (exc != null) { FatalError(Status,modul,exc); } // gdy dla danego statusu wystapi excepcion zostaje on zapisany
                    Warn(Status, Class, Void, modul, msg); // wywołanie funkcji zapisu logu dla modułu
                    break;

                case "Error":  // Odpowiada Za Zapis informacji które uniemożliwają pracę
                    Log(Status, Class, Void, modul); // Zapisuje Informacje co sie wydazyło i gdzie ("Przydaje się w śledzeniu miejsca wysypania programu")
                    if (exc != null) { FatalError(Status,modul,exc); } // gdy dla danego statusu wystapi excepcion zostaje on zapisany
                    Error(Status, Class, Void, modul, msg); // wywołanie funkcji zapisu logu dla modułu
                    break;

                case "Fatal": // Odpowiada za zapis Excepion w pliku modułu
                    Log(Status, Class, Void, modul); // Zapisuje Informacje co sie wydazyło i gdzie ("Przydaje się w śledzeniu miejsca wysypania programu")
                    if (exc != null) { FatalError(Status,modul,exc); } // gdy dla danego statusu wystapi excepcion zostaje on zapisany
                    Fatal(Status, Class, Void, modul, msg, exc); // wywołanie funkcji zapisu logu dla modułu
                    break;

                case "Log": // W przypadku log msg trafia tutaj, w przypadku innego wyboru trafiaja tutaj podstawowe informacje wywołania
                    Log(Status, Class, Void, modul); // Zapisuje Informacje co sie wydazyło i gdzie ("Przydaje się w śledzeniu miejsca wysypania programu")
                    break;

                default: // to samo co log
                    Log(Status,Class,Void,modul); // Zapisuje Informacje co sie wydazyło i gdzie ("Przydaje się w śledzeniu miejsca wysypania programu")
                    if (exc != null) { FatalError(Status,modul,exc); } // gdy dla danego statusu wystapi excepcion zostaje on zapisany
                    break;
            }
        }

        /// <summary>
        /// Funkcja zapisu logu ułatwiajaca odnalezienie poprzez odseparowanie i wiadomość po statusie
        /// </summary>
        private void Trace(string Status, string Class, string Void, string modul, string msg)
        {
            try
            {
                StreamWriter write = File.AppendText(GetFilePatchLogs("", modul)); // funkcja zapisu log dla odpowieniego modułu
                write.WriteLine(" \r\n");
                write.WriteLine(DateTime.Now.ToString("HH:mm:ss tt") + "--> {0} Wiadomość : ({1}) Modul {2} Class {3} Void {4}",Status,msg,modul,Class,Void);
                write.Close();                                                     // Zamkniecie Procesu zapisywania
            }
            catch (Exception ex)
            {
                WriteError(Status, Void, ex, msg); // Awaryjny zapis do pliku
            }
        }

        private void Info(string Status, string Class, string Void, string modul, string msg)
        {
            try
            {
                StreamWriter write = File.AppendText(GetFilePatchLogs("", modul)); // funkcja zapisu log dla odpowieniego modułu
                write.WriteLine(DateTime.Now.ToString("HH:mm:ss tt") + "Status {0}  Modul {2} Class {3} Void {4} Wiadomość : ({1})", Status, msg, modul, Class, Void);
                write.Close();                                                     // Zamkniecie Procesu zapisywania
            }
            catch (Exception ex)
            {
                WriteError(Status, Void, ex, msg); // Awaryjny zapis do pliku
            }
        }

        private void Warn(string Status, string Class, string Void, string modul, string msg)
        {
            try
            {
                StreamWriter write = File.AppendText(GetFilePatchLogs("", modul)); // funkcja zapisu log dla odpowieniego modułu
                write.WriteLine(DateTime.Now.ToString("HH:mm:ss tt") + "Status {0}  Modul {2} Class {3} Void {4} Wiadomość : ({1})", Status, msg, modul, Class, Void);
                write.Close();                                                     // Zamkniecie Procesu zapisywania
            }
            catch (Exception ex)
            {
                WriteError(Status, Void, ex, msg); // Awaryjny zapis do pliku
            }
        }

        private void Error(string Status, string Class, string Void, string modul, string msg)
        {
            try
            {
                StreamWriter write = File.AppendText(GetFilePatchLogs("", modul)); // funkcja zapisu log dla odpowieniego modułu
                write.WriteLine(DateTime.Now.ToString("HH:mm:ss tt") + "#### {0} Wiadomość : ({1}) Modul {2} Class {3} Void {4}", Status, msg, modul, Class, Void);
                write.Close();                                                     // Zamkniecie Procesu zapisywania
            }
            catch (Exception ex)
            {
                WriteError(Status, Void, ex, msg); // Awaryjny zapis do pliku
            }
        }

        /// <summary>
        /// Bardziej rozbudowany zapis logu
        /// </summary>
        private void Fatal(string Status, string Class, string Void, string modul, string msg, Exception exc) 
        {
            try
            {
                StreamWriter write = File.AppendText(GetFilePatchLogs("", modul)); // funkcja zapisu log dla odpowieniego modułu
                write.WriteLine(DateTime.Now.ToString("HH:mm:ss tt") + "!!! ==> Critical Error {0} Class {1} Void {2} Modul {3} Wiadomosc {4} Exc Message {5}",Status,Class, Void,modul,msg,exc.Message);
                write.Close();                                                     // Zamkniecie Procesu zapisywania
            }
            catch (Exception ex)
            {
                WriteError(Status, Void, ex, msg); // Awaryjny zapis do pliku
            }
        }

        /// <summary>
        /// Funkcja zapisujaca iformacje co sie w programie wydazylo
        /// </summary>
        private void Log(string Status, string Class, string Void, string modul)
        {
            try 
            {
                StreamWriter write = File.AppendText(GetFilePatchLogs("Log", "")); // funkcja zapisu log jest wykozystywana do zapisywania wszystkich statusów dla tego odwołanie się do sciezki nie powino odbywać się po statusie otrzymanym w parametrze
                write.WriteLine(DateTime.Now.ToString("HH:mm:ss tt") + "Status : {0} Klasa wywołania : {1} Funkcja : {2} Moduł {3}",Status,Class,Void,modul);  
                write.Close();                                                     // Zamkniecie Procesu zapisywania
            }
            catch(Exception ex)
            {
                WriteError(Status, Void, ex, ""); // Awaryjny zapis do pliku
            }
        }

        /// <summary>
        /// Funkcja odpowiadajaca za pełny zapis wystapienia problemu wywoływana dla każdego modułu który posiada exception
        /// </summary>
        /// <param name="Status"></param>
        /// <param name="modul"></param>
        /// <param name="ex"></param>
        private void FatalError(string Status, string modul,Exception ex)
        {
            
            try
            {
                StreamWriter write = File.AppendText(GetFilePatchLogs("FatalError", "")); // wywołanie działa podbnie jak Log oraz WriteError
                write.WriteLine(DateTime.Now.ToString("HH:mm:ss tt") + " Wykryto Błąd dla modułu {0} o statusie {1} Exception Message -{2}- Exception TargetSite -{3}- Exception Source {4} Exception -{5}-", modul, Status, ex.Message, ex.TargetSite , ex.Source , ex.ToString());
                write.Close();
            }
            catch(Exception exc)
            {
                WriteError(Status,"", exc, "Nie udał się zapis Fatal Error"); // Awaryjny zapis do pliku
            }
        }

        /// <summary>
        /// Funkcja pomocniczja do uchwycenia niezapisanych logow
        /// </summary>
        private void WriteError(string Status, string Void, Exception ex, string msg ="")
        {
            try
            {
                StreamWriter write = File.AppendText(GetFilePatchLogs("WriteError", "")); // Wystarczy że zdefinujemy w tym przypadku tylko status do pobrania sciezki
                write.WriteLine(DateTime.Now.ToString("HH:mm:ss tt") + " Wystąpił problem z zapisem LOGU o Statusie : {0} dla Funkcji : {1} z Wiadomościa : [{2}] Exception.Message {3}",Status,Void,msg,ex.Message);  // Zapis pełnego logu
                write.Close();                                                           // Zamkniecie Procesu zapisywania
            }
            catch
            {
                // podwójny zapis w przypadku przeciążenia dysku może tylko nam go uszkodzić
                //MessageBox.Show("Wiadomość"); // tutaj możecie zrobić obsługę co ma się stać jeśi znowu wybije 
            }
        }

        
    }
}
 
0

GetFolderPatchLogsLower ma mały błąd xd wywołuje GetFolderPatchLogsMain + powinno być tutaj folder Lowe a on wywołuje znowu Main xd. Sorry Darek musisz to poprawić u siebie sam.

0

WTF? NLoga użyj i się nie spuszczaj dalej nad logami?

3

public static FS_Logerr Write
{
get
{
return instance;
}
}
Od zwracania instancji jest getter Instance, a nie jakieś Write.
Getterów nie nazywa się czasownikami.

private string GetFullNameFileBymodul(string modul) { string nameFile = NameFile[modul];
GetFullNameFileBymodul - camel case.
NameFile[modul]; - a co jak nie ma tego w słowniku?

public void Logs(string Status, string Class, string Void, string modul, string msg, Exception exc = null )
Nazwy argumentów z małej litery.
Status powinno być enumem.
Class powinno być typu Type, a najlepiej nie powinno być argumentem, a powinno być pobierane z odpowiedniej ramki stosu.
'void', modul - wtf?
Logs - co to za nazwa? Powinien być czasownik w formie rozkazującej, czyli Log.
Nie pomagasz przy zapisie z formatem, tj. składnia taka jak w string.Format byłaby znacznym udogodnieniem.

// podwójny zapis w przypadku przeciążenia dysku może tylko nam go uszkodzić - cooooo? Nie ma czegoś takiego jak przeciążenie dysku, chyba że na niego nadepniesz albo spadnie na ziemię. Po prostu dłużej trzeba poczekać na zapis i ewentualnie może nastąpić timeout, ale to w operacjach asynchronicznych, z których nie korzystasz. A żeby dysk uszkodziła długa kolejka do zapisu to po prostu bzdura.

write.WriteLine(DateTime.Now.ToString("HHss tt") + "#### {0} Wiadomość : ({1}) Modul {2} Class {3} Void {4}", Status, msg, modul, Class, Void);
write.WriteLine(DateTime.Now.ToString("HHss tt") + "!!! ==> Critical Error {0} Class {1} Void {2} Modul {3} Wiadomosc {4} Exc Message {5}",Status,Class, Void,modul,msg,exc.Message);
To w końcu po polsku, czy po angielsku?
Ustal JEDEN konkretny format, a nie raz strzałki jakieś, raz dwukropki, raz nawiasy, przecież przebicie się przez takie logi doprowadzi do płaczu, a jeśli chciałbyś je parsować jakimś narzędziem, to zestarzejesz o 10 lat się w jedną noc.

GetFolderPatchLogsMain - patch to co innego niż path.
FS_Logerr - bardzo zła nazwa klasy.
Module a nie modul, jak już usiłujesz po angielsku nazywać zmienne.

Ogólne uwagi:
Duplikujesz kod. I to bardzo.
Logger nie jest thread-safe.
Nie logujesz stack trace'a wyjątku, co jest bardzo grubym brakiem.
Zobacz jak działa prawdziwy logger (np. nlog czy log4net), jak się go konfiguruje, jak się zachowuje jeśli konfiguracja jest nieprawidłowa albo dane do zalogowania są nieprawidłowe, zobacz jak się używa metod do logowania, jakie parametry przyjmują, zobacz jak wygląda format pliku z logami. Potem porządnie zastanów się nad architekturą swojego rozwiązania, co chcesz osiągnąć i jak to chcesz osiągnąć i napisz loggera od początku, bez łamania DRY, z przyjaznym interfejsem, bez singletona, z dobrze ponazywanymi metodami/klasami/argumentami/zmiennymi.

0

Jak poleci wyjątek przy zapisie, to nie zamykasz strumienia. To bardzo złe podejście, zapoznaj się z finally albo lepiej using w kontekście IDisposable.

1 użytkowników online, w tym zalogowanych: 0, gości: 1