ABONAMENTE VIDEO REDACȚIA
RO
EN
NOU
Numărul 147
Numărul 146 Numărul 145 Numărul 144 Numărul 143 Numărul 142 Numărul 141 Numărul 140 Numărul 139 Numărul 138 Numărul 137 Numărul 136 Numărul 135 Numărul 134 Numărul 133 Numărul 132 Numărul 131 Numărul 130 Numărul 129 Numărul 128 Numărul 127 Numărul 126 Numărul 125 Numărul 124 Numărul 123 Numărul 122 Numărul 121 Numărul 120 Numărul 119 Numărul 118 Numărul 117 Numărul 116 Numărul 115 Numărul 114 Numărul 113 Numărul 112 Numărul 111 Numărul 110 Numărul 109 Numărul 108 Numărul 107 Numărul 106 Numărul 105 Numărul 104 Numărul 103 Numărul 102 Numărul 101 Numărul 100 Numărul 99 Numărul 98 Numărul 97 Numărul 96 Numărul 95 Numărul 94 Numărul 93 Numărul 92 Numărul 91 Numărul 90 Numărul 89 Numărul 88 Numărul 87 Numărul 86 Numărul 85 Numărul 84 Numărul 83 Numărul 82 Numărul 81 Numărul 80 Numărul 79 Numărul 78 Numărul 77 Numărul 76 Numărul 75 Numărul 74 Numărul 73 Numărul 72 Numărul 71 Numărul 70 Numărul 69 Numărul 68 Numărul 67 Numărul 66 Numărul 65 Numărul 64 Numărul 63 Numărul 62 Numărul 61 Numărul 60 Numărul 59 Numărul 58 Numărul 57 Numărul 56 Numărul 55 Numărul 54 Numărul 53 Numărul 52 Numărul 51 Numărul 50 Numărul 49 Numărul 48 Numărul 47 Numărul 46 Numărul 45 Numărul 44 Numărul 43 Numărul 42 Numărul 41 Numărul 40 Numărul 39 Numărul 38 Numărul 37 Numărul 36 Numărul 35 Numărul 34 Numărul 33 Numărul 32 Numărul 31 Numărul 30 Numărul 29 Numărul 28 Numărul 27 Numărul 26 Numărul 25 Numărul 24 Numărul 23 Numărul 22 Numărul 21 Numărul 20 Numărul 19 Numărul 18 Numărul 17 Numărul 16 Numărul 15 Numărul 14 Numărul 13 Numărul 12 Numărul 11 Numărul 10 Numărul 9 Numărul 8 Numărul 7 Numărul 6 Numărul 5 Numărul 4 Numărul 3 Numărul 2 Numărul 1
×
▼ LISTĂ EDIȚII ▼
Numărul 21
Abonament PDF

Bibliotecă JavaScript de logare pentru dezvoltatori

Bogdan Cornianu
Java developer
@3Pillar Global



PROGRAMARE

Cea mai folosită metodă de logging a evenimentelor pentru depanarea (debugging) codului în JavaScript este prin apelarea "console.log(mesaj)". Aceasta are ca efect afișarea mesajului în consola pentru dezvoltatori care folosesc browser-ul. Se mai pot folosi "console.warn(mesaj)" și "console.error(mesaj)" pentru înregistrarea avertismentelor, respectiv a erorilor.

Obiectul "console" este un obiect host (gazdă), ceea ce înseamnă că el este oferit de către mediul în care rulează script-ul JavaScript. Deoarece este un obiect gazdă, el nu este descris în nicio specificație. De aceea, implementările pot să difere sau în cazul Internet Explorer 7 să lipsească cu desăvârșire.

Dacă există această funcționalitate în majoritatea browser-elor, de ce ar mai fi nevoie de o bibliotecă pentru același scop? Pentru a realiza diverse funcții suplimentare cum ar fi căutarea, filtrarea și formatarea mesajelor.

Proiectul la care lucrez este o aplicație web cu partea de server scrisă în Java şi cea de client în JavaScript. Clientul pentru care am dezvoltat această soluție nu ne putea oferi log-urile de pe server într-un timp rezonabil. Pentru a putea rezolva defectele care apăreau cât mai repede, s-a implementat pe partea de server un mecanism prin care atunci când se arunca o excepție, se colectau informații despre tabelele implicate și împreună cu stack trace-ul Java erau arhivate și trimise către browser pentru a putea fi descărcate on the fly de către client. Acesta le putea trimite ulterior nouă pentru a investiga și remedia problema.

În ceaa ce privește partea de front-end, pentru investigarea unei probleme semnalată de către client,dar pe care noi n-o puteam reproduce, am apelat la conexiuni desktop la distanță, am instalat Firebug și am urmărit consola oferită de acesta.

Pentru a îmbunătăți procesul şi a face mai facilă raportarea defectelor ne-am gândit să replicăm și pe partea de client funcționalitățile mecanismului de pe server. Așa s-a născut "Logger", o bibliotecă JavaScript pentru înregistrarea evenimentelor. Ceea ce o diferențiază faţă de alte biblioteci asemănătoare este posibilitatea de salvare a evenimentelor atât în consola pentru dezvoltatori cât și în spațiul local de stocare al browser-ului (local storage) precum și posibilitatea exportului log-urilor într-un fișier text.

Câteva cuvinte despre cum se folosește librăria. Includerea librăriei este foarte simplă, realizându-se cu o singură linie:

""

Există două moduri prin care se pot înregistra evenimente:

1. Folosind Logger.log(nivel, mesaj, locație)

>Logger.log(Logger.level.Error, "mesaj de eroare", Logger.location.All);
[ERROR]> mesaj de eroare

Deoarece am folosit ca locație "All", mesajul va fi salvat și în spațiul local de stocare al browser-ului.

>localStorage;
Storage {1393948583410_ERROR: "mesaj de eroare", length: 1}

2. Folosind metode specifice pentru fiecare eveniment: Logger.error(mesaj, locație), Logger.warn(mesaj, locație), Logger.info(mesaj, locație)

>Logger.error("al doilea mesaj de eroare", Logger.location.All);
[ERROR]> al doilea mesaj de eroare 
Logger.warn("atentionare", Logger.location.All);
[WARN]> atentionare 
Logger.info("informare", Logger.location.All);
[INFO]> informare  

Fiecare eveniment este salvat în local storage sub forma de cheie și valoare. Cheia este formată din "timestamp_nivel", iar valorea conține mesajul.

>Logger.getEvents(Logger.level.All);
[ERROR]> mesaj de eroare
[ERROR]> al doilea mesaj de eroare
[WARN]> atentionare
[INFO]> informare

În continuare voi prezenta funcționalitatea care, după părerea noastră, va face programatorii mai productivi și anume exportarea tuturor mesajelor înregistrate în spațiul local de stocare al browser-ului într-un fișier text. Astfel programatorii pot avea acces mai rapid la mesajele și evenimentele petrecute în timpul rulării aplicației.

Exportul înregistrărilor în fișierul text se poate face apelând Logger.exportLog() sau setând o funcție de callback în cazul apariției unei erori în aplicație:

"Logger.onError(exportLog, suppressErrorAlerts, errorCallback)"

Dacă "exportLog" este setat pe true, atunci eroarea apărută precum și toate înregistrările prezente în spațiul de stocare al browser-ului vor fi salvate într-un fișier text. În cazul în care "suppressErrorAlerts" este setat pe true, eroarea apărută nu va mai fi afișată și în consola browser-ului. "errorCallback" reprezintă funcția ce va fi executată în cazul apariției unei erori.

Următoarea secvență de cod va afișa un mesaj de dialog în momentul în care apare o eroare de JavaScript.

Logger.onError(true, true, function(errorMsg, url, lineNumber) {

var errorMessage = errorMsg + " la linia " + 
lineNumber + " in " + url,	raspuns = "";

Logger.error(errorMessage, 
	      Logger.location.LocalStorage);

raspuns = confirm("A aparut o eroare. Doriti sa 
salvati inregistrarile intr-un fisier text?");

	if (raspuns === true) {
		Logger.exportLog();
	}
	return true;//suppress errors on console
});

Putem testa dacă acest cod funcționează prin adăugarea unui buton la al cărui eveniment onClick() vom arunca o eroare:

""

La apăsarea butonului vom primi următorul mesaj:

Apăsarea butonului "OK", în funcție de setările browser-ului va salva înregistrările într-un fișier în locația prestabilită sau va afișa un dialog de salvare cu numele fișierului format din data și ora curentă.

Dacă deschidem fișierul, vom vedea toate mesajele precum și eroarea de JavaScript.

[ERROR]> mesaj de eroare
[ERROR]> al doilea mesaj de eroare
[WARN]> atentionare
[INFO]> informare
[ERROR]> Uncaught Error: eroare. la linia 19 in http://localhost:8080/logger/main.html

Putem observa că eroarea a apărut în fișierul "main.html" la linia 19, locul în care am creat butonul la a cărui apăsare se aruncă eroarea JavaScript:

Biblioteca folosește şablonul de proiectare "Revealing Module" pentru a expune funcțiile ce pot fi apelate de către dezvoltatori.

Cea mai simplă soluție pentru a scrie datele din local storage într-un fișier era folosirea unei biblioteci JavaScript numită "FileSaver.js" ce folosește API-ul FileSystem sau furnizează o alternativă la acesta în browser-ele care nu-l suportă nativ. Am vrut să evit folosirea de biblioteci suplimentare și astfel am recurs la o soluție alternativă.

saveToDisk: function(content, filename) {
 var a = document.createElement("a"),

 blob = new Blob([content], {"type" : "
                 application/octet-stream"});
 
 a.href = window.URL.createObjectURL(blob);
 a.download = filename;
 a.click();
}

Am creat un element ancoră la a cărui atribut href am asociat un obiect URL creat dintr-un blob. Blob-ul reprezintă un obiect immutable (imuabil) ce conține date brute. Numele fișierului care este format din data și ora curentă sunt asociate atributului download,apoi se apelează funcția click() ce va avea ca efect afișarea dialogului de salvare al browser-ului.

Pentru a intercepta erorile care apar în JavaScript am creat inițial o variabilă initialWindowErrorHandler ce conține o referință la window.onerror. Inițial, window.onerror scrie toate mesajele de eroare în consolă. În funcția onError() dacă parametrul errorCallback nu este nedefinit atunci se va executa funcția primită ca parametru la fiecare eroare JavaScript.

saveToDisk: function(content, filename) {
 var a = document.createElement("a"),
 blob = new Blob([content], {"type" : 
		"application/octet-stream"});
 
 a.href = window.URL.createObjectURL(blob);
 a.download = filename;
 a.click();
}

Se poate reveni oricând la comportamentul default al lui window.onerror prin apelarea Logger. resetWindowErrorHandler().

Aceasta este versiunea inițială a Logger-ului, fără funcționalități avansate. În viitor ar putea fi îmbunătățit prin adăugarea unei limite maxime a numărului de înregistrări, posibilitatea de a șterge anumite înregistrări după tipul evenimentului, filtrarea înregistrărilor exportate după tipul acestora, realizarea unei interfețe grafice pentru vizualizarea înregistrărilor existente și posibilitatea generării de statistici pentru a determina cât de stabilă a fost aplicația pe o anumită perioadă de timp, posibilitatea de a seta numele fișierului la o valoare ce poate fi configurată.

Referințe:

Mozilla Developer Network

1. Create Object URL: https://developer.mozilla.org/en-US/docs/Web/API/URL.createObjectURL

2. Blob: https://developer.mozilla.org/en-US/docs/Web/API/Blob

3. File System API: https://developer.mozilla.org/en-US/docs/WebGuide/API/

4. Window.onerror: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers.onerror

Github

5. FileSaver.js: https://github.com/eligrey/FileSaver.js

JSFiddle

6. Save to disk example: http://jsfiddle.net/koldev/cW7W5/

7. Revealing Module Pattern: carldanley.com/js-revealing-module-pattern/

Conferință TSM

NUMĂRUL 147 - Automotive

Sponsori

  • Accenture
  • BT Code Crafters
  • Accesa
  • Bosch
  • Betfair
  • MHP
  • BoatyardX
  • .msg systems
  • P3 group
  • Ing Hubs
  • Cognizant Softvision
  • Colors in projects