Logger-lista wymogów

Logger-lista wymogów
MasterBLB
  • Rejestracja:około 19 lat
  • Ostatnio:7 dni
  • Lokalizacja:Warszawa
  • Postów:1454
0

Heja

Z nudów postanowiłem napisać sobie logera przy użyciu qt,chciałem tylko się upewnić,że nie zapomnę o żadnym ficzerze.Zapodam najpierw co sam uważam za potrzebne:
1.Pisanie logów do okna oraz do pliku-można ustawić czy się chce tylko okno/tylko do pliku,czy tu i tu
2.Kolor tekstu w zależności od typu komunikatu,np errory na czerwono,warningi niebiesko,debugi na zielono
3.Okno z logami powinno się dać zrobić jako "above all"

O czym zapomniałem?


"Sugeruję wyobrazić sobie Słońce widziane z orbity Merkurego, a następnie dupę tej wielkości. W takiej właśnie dupie specjalista ma teksty o wspaniałej atmosferze, pracy pełnej wyzwań i tworzeniu innowacyjnych rozwiązań. Pracuje się po to, żeby zarabiać, a z resztą specjalista sobie poradzi we własnym zakresie, nawet jeśli firma mieści się w okopie na granicy obu Korei."
-somekind,
konkretny człowiek-konkretny przekaz :]
byku_guzio
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 7 lat
1

-wybór formatu pliku np. zwykły tekstowy, csv, xml
-wybór poziomu logowania z możliwością włączenia w danej chwili logowania tylko z danego poziomu tzn. funkcja logująca nie robi nic jeżeli nie jest wybrany dany poziom (coś jak logger z javy)


MasterBLB
Dzięki,na pewno te uwagi się przydadzą
MasterBLB
  • Rejestracja:około 19 lat
  • Ostatnio:7 dni
  • Lokalizacja:Warszawa
  • Postów:1454
0

Część zrobiona,loguje do okna,do .txt w postaci:
22-08-2011 13:54:01 | DEBUG | .\main.cpp | 16 | 4 | default
22-08-2011 13:54:01 | DEBUG | .\main.cpp | 18 | 4 | Always on top? true
22-08-2011 13:54:01 | DEBUG | .\main.cpp | 20 | 4 | Always on top? false
22-08-2011 13:56:14 | WARNING | .\main.cpp | 20 | 4 | Added warning log
22-08-2011 13:56:15 | ERROR | .\main.cpp | 24 | 4 | Added error log
te liczby to linia w pliku i poziom logowania (0-4)

Co do .csv,to ja nie widzę użyteczności tego,może ktoś mnie uświadomi?
A co poradzilibyście apropos .xmla?Ja osobiście myślę o takim czymś

Kopiuj
<log>
<debug>
<datetime>22-08-2011 13:54:01</datetime>
<filename>main.cpp</filename>
<fileline>16</fileline>
<loglevel>4</loglevel>
<message>some message</message>
</debug>
.....
</log>

"Sugeruję wyobrazić sobie Słońce widziane z orbity Merkurego, a następnie dupę tej wielkości. W takiej właśnie dupie specjalista ma teksty o wspaniałej atmosferze, pracy pełnej wyzwań i tworzeniu innowacyjnych rozwiązań. Pracuje się po to, żeby zarabiać, a z resztą specjalista sobie poradzi we własnym zakresie, nawet jeśli firma mieści się w okopie na granicy obu Korei."
-somekind,
konkretny człowiek-konkretny przekaz :]
RE
csv'kę łatwo zaimportować do excela, accessa
MasterBLB
Mhm...oki,czuję się przekonany,tym bardziej że zrobić takie coś nie jest rzeczą trudną.Dzięki Rev
MasterBLB
Uo....testowego .csva odworzył mi z automatu w excelu ładnie wrzucając dane do komórek.Ten ficzer faktycznie jest o wiele ciekawszy niż sądziłem z początku ;D
0
  • Autorotacja po rozmiarze lub czasie z zachowaniem wybranej liczby archiwalnych plików i ewentualną ich kompresją.
MasterBLB
Hmmm...opisz proszę dokładniej,co masz na myśli
byku_guzio
Ograniczasz rozmiar pliku/ilość wpisów w pliku, ograniczasz ilość plików. W momencie przekroczenia maksymalnej ilości wpisów(ilość wpisów na plik * max plików) usuwasz najstarszy plik
1

Sorry, że odpowiadam tu, a nie w komentarzach, ale chcę dać przykład.
Co to jest autorotacja i jak to działa. Byku_guzio już opisał po krótce w komentarzu, ja tylko uściślę.
Kiedy plik logu przekroczy określony rozmiar, lub nastąpi określona godzina, zmieniasz jego nazwę doklejając ".1", po czym tworzysz i otwierasz nowy plik. Jeśli plik o nazwie zakończonej na ".1" już istnieje, zmieniasz suffiks tego istniejącego na ".2", itd. Użytkownik może określić czy rotacja następuje po wielkości pliku (np. jeśli przekroczy 10MB), czy codziennie o określonej godzinie (np. o północy). Dodatkowo może określić ile plików z suffiksami może być utworzonych (np. 10; nadmiarowe mają być usuwane).
Przykład: rozmiar pliku "server.log" przekroczył 10MB, w katalogu są już pliki archiwalne "server.log.1" oraz "server.log.2". Zmieniasz nazwy: "server.log.2"->"server.log.3", "server.log.1"->"server.log.2", zamykasz plik logu i zmieniasz jego nazwę na "server.log.1", tworzysz nowy plik "server.log" i otwierasz go do zapisu. Jeśli plików archiwalnych jest już 10, usuwasz najpierw plik "server.log.10".
Przy wykonywaniu rotacji (zmiany nazwy "server.log" na "server.log.1") możesz skompresować plik archiwalny, ale lepiej robić to w oddzielnym wątku.

Na serwerach za to odpowiada program logrotate, więc możesz podejrzeć jak on to robi. Niestety, nie zawsze userzy mogą dodać swoje pliki logów do rotowania przez proces systemowy, więc logger który rotuje i troszczy się o archiwizację jest niesamowicie przydatny. W Pythonie jest od tego odpowiednia klasa, w C musiałem sobie sam takowy wyklepać dla loggera w GObject, bo standardowy tylko pluje do pliku i nie wnika co dalej.

MasterBLB
  • Rejestracja:około 19 lat
  • Ostatnio:7 dni
  • Lokalizacja:Warszawa
  • Postów:1454
0

Okay,skoro mówcie iż ta autorotacja jest takim użytecznym ficzerem to ją zapodam.Jedynie co do tego zmieniania nazw wszystkich plików mam zastrzeżenia,ja wolę zrobić to tak:
1.Każę logerowi logować do pliku log.txt
2.Po spełnieniu wymogów limitu log.txt jest zamykany a tworzony jest nowy plik log2.txt i teraz logi lecą do niego
3.itd,itp

Podsumujmy jeszcze tylko,wg jakich kryteriów ma się plik logu wypełniać i być zamykany
-czasowe,tj o okreśonej godzinie
-ilością wpisów(wierszy) w pliku
-rozmiarowo,czyli jak plik logu osiągnie zadany rozmiar
-jakieś jeszcze?

A,powiedzcie koledzy czy widzicie potrzebę logowania warningów,debugów i errorów do oddzielnych plików?


"Sugeruję wyobrazić sobie Słońce widziane z orbity Merkurego, a następnie dupę tej wielkości. W takiej właśnie dupie specjalista ma teksty o wspaniałej atmosferze, pracy pełnej wyzwań i tworzeniu innowacyjnych rozwiązań. Pracuje się po to, żeby zarabiać, a z resztą specjalista sobie poradzi we własnym zakresie, nawet jeśli firma mieści się w okopie na granicy obu Korei."
-somekind,
konkretny człowiek-konkretny przekaz :]
edytowany 1x, ostatnio: MasterBLB
byku_guzio
  • Rejestracja:prawie 15 lat
  • Ostatnio:około 7 lat
0

Co do tego, lepiej zmieniać nazwy wszystkich plików, im nowszy plik tym mniejszy indeks - wyżej na listach plików. Operacja taka będzie rzadko wykonywana, więc czasem czegoś takiego nie ma się co przejmować.

Z tym logowaniem do oddzielnego pliku raczej nie widzę sensu. Ale za to fajnie by było, gdyby można definiować poziomy logowania. Np. standardowo ERROR, WARRNING, INFO i do tego możliwość dodania własnego(np. OKRUTNY_ERROR) i ustawienie mu "ważności"


MasterBLB
  • Rejestracja:około 19 lat
  • Ostatnio:7 dni
  • Lokalizacja:Warszawa
  • Postów:1454
0

Na chwilę obecną są poziomy 0-4,przy czym domyślny jest 4,oraz typy debug,warning itd.Działają głównie w trybie logowania okienkowego(patrz obrazek) powodując filtrację danych z tabeli.
Niestety,takie coś w trybie konsolowym czy plikowym za bardzo sensu nie ma,stąd póki co do pliku wpada wszystko jak leci.

Hmmm...można by zrobić to tak,że loger miałby funkcję w stylu setLoggingLevel(int maxlevel) która by w trybie okienkowym nastawiała odpowiednio te guziki filtrów,a w trybie plikowym/konsolowym powodowała,że jedynie logi z przedziału <0,maxLevel> były zapisywane


"Sugeruję wyobrazić sobie Słońce widziane z orbity Merkurego, a następnie dupę tej wielkości. W takiej właśnie dupie specjalista ma teksty o wspaniałej atmosferze, pracy pełnej wyzwań i tworzeniu innowacyjnych rozwiązań. Pracuje się po to, żeby zarabiać, a z resztą specjalista sobie poradzi we własnym zakresie, nawet jeśli firma mieści się w okopie na granicy obu Korei."
-somekind,
konkretny człowiek-konkretny przekaz :]
byku_guzio
Możliwość ustawienia poziomu logowania jest wręcz konieczne
MasterBLB
Oki,zrobię tak jak piszę-w trybie graficznym wszystko+filtrowanie guzikami,a w trybie plikowym/konsolowym będzie fizyczne wycinanie nadmiarowych logów
2
MasterBLB napisał(a)

Okay,skoro mówcie iż ta autorotacja jest takim użytecznym ficzerem to ją zapodam.Jedynie co do tego zmieniania nazw wszystkich plików mam zastrzeżenia,ja wolę zrobić to tak:
1.Każę logerowi logować do pliku log.txt
2.Po spełnieniu wymogów limitu log.txt jest zamykany a tworzony jest nowy plik log2.txt i teraz logi lecą do niego
3.itd,itp

To nie jest dobry pomysł.
Po pierwsze, jako admin chcę szybko wyświetlić zawartość pliku logu, bez zastanawiania się i dociekania który indeks jest aktualnie obowiązujący.
Po drugie, różne narzędzia analizujące logi odczytują tylko jeden plik, o bazowej nazwie.
Po trzecie, jak w ten sposób chcesz załatwić sprawę przedawnionych archiwów? Przy numeracji odwrotnej są pliki od ".1" do ".maksimum". Przy Twojej numeracji po kilku miesiącach będą pliki z milionowymi liczbami w nazwie, a są usługi które działają przez lata bez restartu.

MasterBLB napisał(a)

Podsumujmy jeszcze tylko,wg jakich kryteriów ma się plik logu wypełniać i być zamykany
-czasowe,tj o okreśonej godzinie

Tak. W ten sposób można sobie rozdzielić pliki logu według dni.

MasterBLB napisał(a)

-ilością wpisów(wierszy) w pliku

To nie ma zastosowania. Rotowanie po rozmiarze robi się w celu zmniejszenia ryzyka zapchania quoty. Np. ustala się 110MB na logi - 10 plików archiwum po 10MB. Jesli ograniczasz po ilości linii, to nigdy nie wiadomo jakiej długości te linie będą. Wystarczy popatrzeć na logi serwera WWW żeby stwierdzić, że przy próbach ataku te linie mogą być baaaardzo długie.
Kolejny problem to otwarcie już istniejącego pliku logu (np. po restarcie usługi). Musiałbyś przeliczyć wszystkie linie jakie w nim są żeby odpowiednio zainicjować licznik zapisanych już linii. To może być bardzo mało wydajne przy dużych plikach.

MasterBLB napisał(a)

-rozmiarowo,czyli jak plik logu osiągnie zadany rozmiar

Nie "osiągnie". Kiedy "przekroczy". Nie będziesz przecież łamał linii w połowie żeby zmieścić się w rozmiarze pliku. Po zapisaniu każdej linii sprawdzasz czy rozmiar (sumuj długości wpisów, nie odpalaj stat() na pliku za każdym razem) przekroczył zadany i jeśli tak, wykonaj rotację.

MasterBLB napisał(a)

-jakieś jeszcze?

Nic mi już nie przychodzi do głowy.

MasterBLB napisał(a)

A,powiedzcie koledzy czy widzicie potrzebę logowania warningów,debugów i errorów do oddzielnych plików?

Ja nie widze takiej potrzeby. Od tego jest grep ;)

P.S. W razie czego mogę udostępnić moją implementację rotującego file loggera dla GObjectowego systemu rejestracji zdarzeń. Niestety, rotuje tylko po rozmiarze i nie kompresuje (nie było mi to potrzebne).

MasterBLB
E kodu nie potrzebuję,jestem na tyle obcykany w temacie programowania C++/Qt że sam dam radę(kłopot będzie dopiero przy obsłudzie wielowątkowości),za to zdecydowanie przydadzą się pomysły na ficzery,jakie porządny logger mieć powinien.Poza tym,ten program to dla mnie ćwiczenie aby pozostać w formie podczas bezrobocia.Niemniej dzięki za ofertę :)
vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
0

Zacząłbym od przejrzenia listy ficzerów istniejącego softu:
http://log4qt.sourceforge.net/

U mnie (w moim rozwiązaniu) było najważniejsze:

  • rezygnacja z poziomu logowania na rzecz maski logowania (np. ERROR + INFO)
  • nazwy plików unikalne dla każdego uruchomienia (może niezarządzalne automatycznie, ale nie o to mi chodziło)
  • możliwość podpięcia różnych wymyślnych urządzeń (np. osobnego pliku tylko dla TRACE, poza tym standard: konsola, okienko, plik). urządzenie definiuje formatowanie, obsługiwane typy komunikatów oraz miejsce przechowywania danych
  • łatwość użytkowania - singleton:
Kopiuj
MojLog::addInfo("Teraz jestem tutaj");
  • auto-odcinanie pliku po przekroczeniu progu rozmiaru (przed zapisem linii - jeśli log jest za duży to zmieniana jest jego nazwa)
edytowany 5x, ostatnio: vpiotr
0
vpiotr napisał(a)
  • auto-odcinanie pliku po przekroczeniu progu rozmiaru (przed zapisem linii - jeśli log jest za duży to zmieniana jest jego nazwa)

Ojjjj.... Takie rzeczy powinieneś robić po zapisaniu linii. Zmiana nazwy może się nie udać i/lub może spowodować awarię programu, do której jedyny ślad może się znajdować w tej jednej, opuszczonej linii logu. Złota zasada jest taka: najpierw zapisz, potem mieszaj w plikach.

Zobacz pozostały 1 komentarz
MasterBLB
No to zdziw się,bo podczas implementacji tego ficzera na desktopie zdażyła mi się parę razy taka sytuacja ;]
vpiotr
No to się dziwię, i to bardzo. Bo rename nie wymaga (zwykle) dodatkowej przestrzeni dyskowej, więc jedyną szansę jaką widzę na jego wywalenie to jak ma złe parametry wejściowe... A u Ciebie co się stało że się wywalił?
MasterBLB
Żeby to było wiadomo...ale dostaję QIODevice.errorStringa()="Unknown error" :| Podejrzewam,że coś mu się kiełbasi przy ścieżkach dostępu,jutro spróbuję przerobić na pełne i bezwzględne
vpiotr
Polecam pełne ścieżki, bo przy względnych to można ześwirować, zwłaszcza jak się jeszcze zmienia katalog aktualny, czasami odpala z IDE, a czasami z konsoli itd...
MasterBLB
Ta,to było to.Na ścieżkach względnych wszystko działało dobrze pod warunkiem,że user jako plik logu nie podał czegoś w stylu "Logs/TestLog/TestLog.txt" tylko proste "TestLog.txt"
MasterBLB
  • Rejestracja:około 19 lat
  • Ostatnio:7 dni
  • Lokalizacja:Warszawa
  • Postów:1454
0

-maska już jest,patrz załączony plik logger.png
-nazwy unikalne co uruchomienie rozważę.Jeśli będą,to powstaną ze złożenia userFileName+_+currentDate
-co do tych urządzeń,to poproszę się wypowiedzieć bardziej szczegółowo,mniej więcej tak jak zrobił to Kumashiro
-łatwość użycia jest jeszcze większa niż babranie się singletonami:

Kopiuj
#define LOGDEBUG_Full(text,loggerId,level) BLBLogger::logPrint(text,loggerId,__LINE__,__FILE__,level);
#define LOGDEBUG_Level(text,level) LOGDEBUG_Full(text,"default",level)
#define LOGDEBUG_Logger(text,loggerId) LOGDEBUG_Full(text,loggerId,MAXLEVEL)
#define LOGDEBUG(text) LOGDEBUG_Full(text,"default",MAXLEVEL)

moim priorytetem podczas tworzenia było umożliwić użytkownikom proste jak konstrukcja cepa funkcje/makra do logowania bez konieczności chrzanienia się z jakimiś log managerami i podobnymi.Oczywiście,managerem też można się bawić jak jest potrzeba,jednak w zupełności wystarczy napisać LOGDEBUG("tekst debuga") i reszta zostanie załatwiona automatycznie.
-rotacja logu po rozmiarze aktualnie w implementacji wg wytycznych Kumashiro.


"Sugeruję wyobrazić sobie Słońce widziane z orbity Merkurego, a następnie dupę tej wielkości. W takiej właśnie dupie specjalista ma teksty o wspaniałej atmosferze, pracy pełnej wyzwań i tworzeniu innowacyjnych rozwiązań. Pracuje się po to, żeby zarabiać, a z resztą specjalista sobie poradzi we własnym zakresie, nawet jeśli firma mieści się w okopie na granicy obu Korei."
-somekind,
konkretny człowiek-konkretny przekaz :]
vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
0

Makra to masakra. Robisz to w C++ czy w C?
Makra z parametrami mają inne reguły ewaluacji argumentów niż funkcje, w związku z tym są zwodnicze.
Poczytaj dlaczego "macros are evil":
http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.4

Co do urządzeń, to logger główny ma możliwość podpięcia od 1 do n urządzeń (u mnie są specyficznymi logerami).
Każde urządzenie ma to co opisałem, czyli komunikat

Kopiuj
MojLog::addInfo("Tekst") 

może iść do iluś urządzeń - w zależności od tego jakie mają maski komunikatów (INFO, WARNING, ERROR, DEBUG, TRACE).
Dzięki temu mogę logować osobno błędy a osobno resztę - wedle uznania.
Poza tym dzięki temu jedna klasa może logować zawsze w ten sam sposób, mimo że raz działa w konsoli a raz w aplikacji okienkowej.
Urządzenia podpinam na starcie aplikacji i/lub okienka logującego.

Aktualnie mam dostępne 4:

  • konsola
  • plik
  • okienko wxWidgets
  • komunikat DebugInfo (Windows - są odpowiednie aplikacje do przechwytywania tego, m.in. MS VS)

Dodatkowo przy logowaniu błędu warto zapisać unikalny kod błędu w logerze - dzięki temu będzie to sformatowane w standardowy sposób (to zamiast stosowania makra LINE, które jest słabe jeśli masz co innego uruchomione niż dostępne jako źródło, albo nie wiesz jak wyglądało źródło dla danego EXE-ca).

edytowany 2x, ostatnio: vpiotr
MasterBLB
  • Rejestracja:około 19 lat
  • Ostatnio:7 dni
  • Lokalizacja:Warszawa
  • Postów:1454
0

Ja wiem,jak działają parametry makr.Niestety,innaczej nie idzie a to z uwagi na LINE właśnie które nie mogę dać jako parametr domyślny funkcji bo wyjdą bzdury.Ponadto chcę jak najbardziej uprościć zapis użycia,nie chcę pisać kijWieCoLogger::Logger::debug(LINE,FILE,"tekst messaga") tylko po prostu LOGDEBUG("tekst messaga") a reszta ma się zrobić sama.I już.

Klasa logująca w mnie już jest 1 i loguje do okna widocznego z załącznika na poprzedniej stronie,pliku lub konsoli.Ponadto można łączyć logowanie do konsoli lub okna z plikiem.Co do masek to mam debug,warning i error,o info zapomniałem.Acha,powiedz proszę do czego używa się tej trace?Bo ja z logów nie kojarzę takiej


"Sugeruję wyobrazić sobie Słońce widziane z orbity Merkurego, a następnie dupę tej wielkości. W takiej właśnie dupie specjalista ma teksty o wspaniałej atmosferze, pracy pełnej wyzwań i tworzeniu innowacyjnych rozwiązań. Pracuje się po to, żeby zarabiać, a z resztą specjalista sobie poradzi we własnym zakresie, nawet jeśli firma mieści się w okopie na granicy obu Korei."
-somekind,
konkretny człowiek-konkretny przekaz :]
msm
Administrator
  • Rejestracja:prawie 16 lat
  • Ostatnio:4 miesiące
0

Makra to masakra. Robisz to w C++ czy w C?

Trochę głupie pytanie...

Makra z parametrami mają inne reguły ewaluacji argumentów niż funkcje, w związku z tym są zwodnicze.

Ale można je łatwo wyłączyć zmieniając opcje kompilacji. I, jak pisze MasterBLB, rozwijanie makr LINE, FILE etc.

Btw. Logger doskonały: http://nlog-project.org/ (niestety tylko dla .net)

edytowany 1x, ostatnio: msm
MasterBLB
Generanie widzę to samo do czego zmierza mój,tyle że w moim zapis będzie prostszy dzięki makrom.Za to ciekawym ficzerem NLoggera widzę jest wrzucenie do system traya i puszczanie "dymków" informacyjnych.
vpiotr
  • Rejestracja:ponad 13 lat
  • Ostatnio:prawie 3 lata
0
MasterBLB napisał(a)

Ja wiem,jak działają parametry makr.Niestety,innaczej nie idzie a to z uwagi na LINE właśnie które nie mogę dać jako parametr domyślny funkcji bo wyjdą bzdury.Ponadto chcę jak najbardziej uprościć zapis użycia,nie chcę pisać kijWieCoLogger::Logger::debug(LINE,FILE,"tekst messaga") tylko po prostu LOGDEBUG("tekst messaga") a reszta ma się zrobić sama.I już.

Tu masz rację - jeśli Ci bardzo zależy na LINE to makro będzie niezbędne. Ale to i tak zło w czystej postaci (w kontekście C++) ;)
Poza tym mój logger nie ma 3 składników wywołania - używam globalnego namespace.

MasterBLB napisał(a)

Klasa logująca w mnie już jest 1 i loguje do okna widocznego z załącznika na poprzedniej stronie,pliku lub konsoli.Ponadto można łączyć logowanie do konsoli lub okna z plikiem.Co do masek to mam debug,warning i error,o info zapomniałem.Acha,powiedz proszę do czego używa się tej trace?Bo ja z logów nie kojarzę takiej

TRACE się wiąże z urządzeniami. W pewnym momencie chciałem mieć osobną klasę komunikatów którą mogę włączyć lub wyłączyć parametrem wejściowym programu, a komunikaty te były dość liczne.
W związku z tym musiałem zrobić osobne urządzenie - które będzie bardzo szybkie i które będzie przechwytywać tylko te komunikaty - bez zwalniania aplikacji. To taki DEBUG tylko dla wersji "release".
Miałem do tego użyć OutputDebugString, ale w sumie nie pamiętam czy było wystarczająco szybkie.

Proponuję jednak pomyśleć nad OutputDebugString jeśli to Windows. Zaleta - informacje zostają po wywaleniu się aplikacji, można filtrować, stopować itd.
Jego komunikaty przechwytuje m.in.:
http://technet.microsoft.com/en-us/sysinternals/bb896647

edytowany 5x, ostatnio: vpiotr
MasterBLB
  • Rejestracja:około 19 lat
  • Ostatnio:7 dni
  • Lokalizacja:Warszawa
  • Postów:1454
0

Hmmm mam pewną zagwozdkę natury koncepcyjnej,której nie mogę wymyśleć satysfakcjonującego rozwiązania :/
Załóżmy,że nastawiłem logerowi wrzucanie wpisów do pliku Logs\log.txt i włączyłem mu autorotację.ALE w tymże folderze znajduje się też jakiś zupełnie nie powiązany z powyższym plikiem log_dupa.txt.
Teraz używając QDir::entryList(QStringList("log*.txt")....) chcę pobrać wszystkie wpisy dotyczące podanej nazwy pliku,niestety,ten log_dupa.txt też się na to log*.txt załapuje :/

Użyłem zatem listy z dokładnymi nazwami log.txt,log1.txt,log2.txt aż do log<tutaj maxLogFiles-1>.txt itd.Jest lepiej,jednak wciąż istnieje ryzyko kolizji nazw na przykład w sytuacji używania 2 różnych obiektów logerów którym niebacznie ktoś podał tą samą nazwę pliku logu.

Jak zatem rozwiązać taką sytuację?Mi przychodzi na myśl,aby logi z automatu wrzucały się do podfolderu o nazwie takiej samej,jak QString z ID logera.A mój system grawantuje,że owe IDki są unikalne.
Co wy na to?


"Sugeruję wyobrazić sobie Słońce widziane z orbity Merkurego, a następnie dupę tej wielkości. W takiej właśnie dupie specjalista ma teksty o wspaniałej atmosferze, pracy pełnej wyzwań i tworzeniu innowacyjnych rozwiązań. Pracuje się po to, żeby zarabiać, a z resztą specjalista sobie poradzi we własnym zakresie, nawet jeśli firma mieści się w okopie na granicy obu Korei."
-somekind,
konkretny człowiek-konkretny przekaz :]
vpiotr
Ja mam osobny pod-katalog pod każdą aplikację, do tego tak jak wcześniej opisałem - aktualny log nie ma fikuśnych zarostków, a jedynie te archiwalne. No i każde uruchomienie aplikacji to osobna rodzina logów (unikalne ID w nazwie) - ale to opcjonalnie.
0

Ja to robię tak (da się jeszcze podkręcić):

Kopiuj
    for ( rotsuff = logger->max_archives; rotsuff >= 1; rotsuff-- ) {
        g_snprintf(combined_old, PATH_MAX_LENGTH + 1, "%s.%d", logger->logfile, rotsuff);
        if ( !g_file_test(combined_old, G_FILE_TEST_EXISTS) )
            continue;

        if ( rotsuff == logger->max_archives ) {
            if ( g_unlink(combined_old) == -1 )
                return FALSE;
            continue;
        };

        g_snprintf(combined_new, PATH_MAX_LENGTH, "%s.%d", logger->logfile, rotsuff + 1);
        if ( g_file_test(combined_new, G_FILE_TEST_EXISTS) && (g_unlink(combined_new) == -1) )
            return FALSE;

        g_rename(combined_old, combined_new);
    };

    g_snprintf(combined_new, PATH_MAX_LENGTH, "%s.1", logger->logfile);
    g_rename(logger->logfile, combined_new);

    if ( file_logger_open(logger, &lerror) == FALSE ) {
        g_propagate_error(error, lerror);
        return FALSE;
    };

Jeśli w katalogu jest jakiś plik z innej instancji programu, o konfliktowej nazwie, to jest traktowany jako należący do aktualnej. Nie wyobrażam sobie jak dwa loggery z tej samej instancji mogłyby jednocześnie pisać do pliku o tej samej nazwie. To byłoby bez sensu.

Zobacz pozostałe 10 komentarzy
MasterBLB
Hmm,to mi w koncepcję utrafia idealnie-w moim logerze trzeba podając nazwę pliku logu podać zarazem rozszerzenie które określa typ logu (.txt,.csv itd).Zmieniając nazwę archiwalnego pliku na oldName.ext.number nie ma zatem możliwości powyżej opisanej pomyłki.Dzięki Bracie :D
KU
Tylko jeśli piszesz to jako bibliotekę wieloplatformową, to pamiętaj że w Unices rozszerzenie pliku jest tylko i wyłącznie informacją dla użytkownika i taki wymóg jest sprzeczny z tą filozofią. W Uniksach typ przechowywanych danych jest rozpoznawany po zawartości (libmagic się tym zajmuje), zatem dane CSV mogą być w pliku z rozszerzeniem ".txt", a nawet ".mp3" jeśli user sobie tak zażyczy :)
MasterBLB
Unices sobie,a u mnie kod ma nałożony taki właśnie wymóg,bo tak się orientuje w typie.Podasz mu coś innego niż .txt,.csv,*.xml to będzie komunikat o złym typie pliku logu
KU
A co jeśli ktoś będzie chciał stworzyć plik o dość typowym rozszerzeniu dla logów, czyli ".log"? Format danych wyjściowych powinineś raczej wybierać poprzez użycie odpowiedniej klasy, np. CSVWritter, TextWriter, XMLWriter czy podobne. Wtedy można wybrać dowolną nazwę pliku.
MasterBLB
Na chwilę obecną tak się nie da.Pewnie,dumałem nad tym,czy funkcji nastawiającej plik do logowania nie zrobić w stylu setLogFile(const QString &filename,LogFileType logType) gdzie ten 2 parametr to enum{Txt,Csv,Xml} ale uznałem,że skoro prostota użycia ma być moją myślą przewodnią to nie ma co kombinować.Co zaś do .log,to zawsze może podać np name.log.txt :P
MasterBLB
  • Rejestracja:około 19 lat
  • Ostatnio:7 dni
  • Lokalizacja:Warszawa
  • Postów:1454
0

Hmm kolejna sprawa koncepcyjnej natury.

Napisałem funkcję QList<Logger*> getAllLoggers().Działa świetnie,jest jednak pewne ale-jak po jej wywołaniu pojawi się nowy logger(a może),wówczas lista ta będzie zawierała nieprawdziwy stan systemu.Stąd do Was Bracia(Siostry też ;) ) pytanie-jakiego zachowania oczekujecie od takiej funkcjonalności:
1.Skoro wywołałem/-am getAllLoggers,to na liście mają być wszystkie loggery i już.Jeśli pojawi się nowy,to lista ma się zupdatować i być zawsze aktualna.
2.Lista ma zawierać tylko stan loggerów na chwilę wywołania funkcji gettera.


"Sugeruję wyobrazić sobie Słońce widziane z orbity Merkurego, a następnie dupę tej wielkości. W takiej właśnie dupie specjalista ma teksty o wspaniałej atmosferze, pracy pełnej wyzwań i tworzeniu innowacyjnych rozwiązań. Pracuje się po to, żeby zarabiać, a z resztą specjalista sobie poradzi we własnym zakresie, nawet jeśli firma mieści się w okopie na granicy obu Korei."
-somekind,
konkretny człowiek-konkretny przekaz :]
vpiotr
Chyba coś przeoczyłem, ale nie widzę gdzie opisujesz do czego ta funkcja ma służyć (oprócz tego że zwraca listę loggerów).
MasterBLB
Bo to nie jest jeszcze określone
vpiotr
Ale skoro ją implementujesz to coś zakładasz? Jakie są założenia do tej funkcji? Po co miałaby być wykorzystywana?
MasterBLB
No więc wstępne założenie było takie,aby zwracała listę wszystkich powstałych w systemie logerów.Tyle,że proste stworzenie i zwrócenie listy implikuje zagwozdkę jaką opisałem w poście.Da się to rozwiązać,ale sam nie odgadnę oczekiwań użytkowników,stąd się pytam.
vpiotr
Myślę że ta funkcja jest niepotrzebna. Bo po co mi lista wszystkich loggerów? Żeby sobie coś z nich wybrać? A jeśli tak to na jakiej podstawie? Potrzebne jakieś atrybuty i... sytuacja się rozwija. Jeśli nie ma aktualnie zapotrzebowania na taką listę to lepiej jej nie udostępniać.
MasterBLB
  • Rejestracja:około 19 lat
  • Ostatnio:7 dni
  • Lokalizacja:Warszawa
  • Postów:1454
0

"Sugeruję wyobrazić sobie Słońce widziane z orbity Merkurego, a następnie dupę tej wielkości. W takiej właśnie dupie specjalista ma teksty o wspaniałej atmosferze, pracy pełnej wyzwań i tworzeniu innowacyjnych rozwiązań. Pracuje się po to, żeby zarabiać, a z resztą specjalista sobie poradzi we własnym zakresie, nawet jeśli firma mieści się w okopie na granicy obu Korei."
-somekind,
konkretny człowiek-konkretny przekaz :]
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)