Syslog sub Windows – Microsoft Log Parser

Multa lume, presupun ca lucreaza in Windows si deployaza pe linux, si asta de multe ori poate sa insemne ca aplicatia pe care o dezvolti trebuie sa poata sa aiba un comportament similar cand ruleaza in local, sub windows, sau cand ruleaza probabil pe o distributie de linux.

Legat de acest comportament deci, azi as dori sa tratez loggingul, si mai exact syslogul. Syslogul este o maniera convenienta de a observa si trace-a o aplicatie.

Sub windows, syslog inseamna de obicei event log/application, adica ceva de genul.
eventlog1

Naspa. Ca sa vezi pe ansamblu ce se intampla te uiti in ferestrica aia de cacat.

eventlog2

Ceea ce cautam eu este ceva de genul:

linux

Am cautat un pic pe net, sunt o groaza de softuri de cacao care cica sunt event loguri mai smechere, dar in final sunt mult prea complicate si mai ales greu de utilizat.
Pana cand am dat peste Microsoft Log Parser (2.2). Tot de la Microcrap a venit pana la urma solutia. Asta e un soft misto care permita sa faci in linie de comanda query-uri intr-un limbaj quasi-sql asupra variatelor loguri din windows, inclusiv ce ma interesa pe mine, logul de evenimente.
Sau, cum zic ei “Log parser is a powerful, versatile tool that provides universal query access to text-based data such as log files, XML files and CSV files, as well as key data sources on the Windows® operating system such as the Event Log, the Registry, the file system, and Active Directory®.”

Ca urmare, se downloadeaza de aici.

Apoi poti sa faci de ex :

PS C:\Program Files\Log Parser 2.2> .\logparser.exe “SELECT top 10 TimeGenerated, EventID,Strings FROM Application order by TimeGenerated Desc”

logparser

Mai multe detalii despre utilizare aici. Exact.

Unde pula mea e MODELUL ?

model view controller pula

Deci in pula mea, eram ieri la servici, pe la pranz, si ma ia  A-C, sefa mea cu ea la etajul 1 (nu sa-i dau o muie cum poate va gandeati) ci pentru o “reuniune”. Reuniunea de fata insemna de fapt ca am intrat in biroul unuia si ne-am asezat pe niste scaune, el urmand sa ne prezinte, si apoi sa ne predea un maret backoffice de moderare. Backofficeul asta, teoretic, ar trebui sa ma scuteasca pe mine de sarcina de a scrie unul noul pentru proiectul la care lucrez, asa ca putea fi util, daca era adaptabil.

Ok, individul intoarce monitorul si ne arata cum se logheaza el, cu vede niste inregistrari, si le “modereaza”. Adica alege daca sunt spam sau nu, evident. Aplicatia are un aer invechit si arata destul de naspa, dar, ni se precizeaza, a fost utilizata intensiv de echipele care fac moderarea, deci sunt deja obisnuite cu modul de utilizare. In plus, si aici devin brusc interesat, este scrisa foarte curat, obiectual, si poate fi extinsa/adaptata usor pentru a obtine ce avem nevoie.
“Perfect”, imi zic, hai sa vedem codul ala. Reunionistul deschide pspad (intotdeaua mi s-au parut dubiosi programatorii care folosesc pspad, intre noi fie vorba), si imi arata structura de clase. “E arhitectura MVC”, ma asigura el triumfator.  Asa cum aveam deja sentimentul, mvc la el inseamna ca are un fisier, index.php, in care foloseste un switch pentru a selecta codul care se va executa. Exact asa si era …
Restul codului era intr-un folder separat de “clase”, si inca unul de “functii”. Ok, zic eu, arata-mi “clasele” tale.

Clasele erau de fapt bucati de cod care se executau pentru fiecare pagina a siteului, si care tratau tot fluxul, de la intrare pana la template-ul smarty. As face aici o paranteza, legat de smarty. Smarty este un cacat inutil, utilizat de fraieri ca sa dea impresia ca sunt mari programatori si separa “codul” de “view”. De fapt obti acelasi rezultat daca scri un template in php (php este in esenta pulii lui un limbaj de template-uri!) si ii pasezi argumentele intr-un array. La fel de usor ajungi sa bagi business logic in template si in smarty si in php. Si aici inchid paranteza.
Asadar, fiecare pagina avea codul ei,100 % procedural, jalnic inchis intre o declaratie de clasa si paranteza de inchidere corespunzatoare.
Dar asta nu e tot, continua programatorul. Exista si un (simulacru) de sistem de mostenire, pe un nivel: toate clasele mostenesc o clasa de baza pentru a mosteni niste functii comune (si destul de dubioase) de autentificare si acces la baza de date. Pentru ca, da, nici macar o abstractizare BD calumea nu a fost implementata, pentru ca, imi explica el usor jenat, nu a reusit sa gestioneze problema cele 2 servere BD (unul pentru citit, frontul si altul master, pentru scris). “Deci ai facut o treaba de cacat” imi zic eu in gand, apoi zambesc protocolar, pentru ca urma sa-l mai intalnesc pe individ la cafea.

Si acum partea didactica pentru toti pularaii care au deschis un editor si au inceput sa “programeze” in PHP, in principal pentru ca ca are  bariera de intrare foarte joasa.
In cuvinte simple, model view controller este un pattern care ar trebui in principiu sa izoleze logica aplicatiei, cum s-ar zice Business Model-ul, de interfata, de afisare. Asta inseamna ce … de exemplu daca ai de implementat afisarea listei de sefi carora trebuie sa le sugi pula ca sa ajungi un sef mai mic, in modelul aplicatiei incarci lista, din baza de date sa zicem, o prelucrezi, aplici reguli specifice (sa zicem ca ai o filtrare, numai sefi cu acelasi etaj cu tine sa va intalniti la aceeasi toaleta), dupa care pasezi aceste informatii, intr-un format neutru, afisarii. Si cine paseaza datele si face legatura intre model si afisare (view) ? Controllerul.
Aici este momentul in care fraierul cade in plasa … o regula foarte ignorata este TC-FM (thin controller – fat model), adica controllerul trebuie sa faca STRICT doar interfata intre cele 2, sa nu contina business logic. Dar, este mult mai usor sa bagi la greu cod in asa zisa ta “clasa” care devine un fat controller curand singleton curand o mare laba.
In poza de sus, in partea acoperita de pula, scrie “encapsulates application logic” si “exposes functionality”. Adica … adica ofera un acces selectiv la sistemul care e modelat. Deci fara query-uri in controller, desi pare mai usor. Izolarea scopului, asta e esential.
Muirea continua cu viewul: intr-o aplicatie web nivelul view este de fapt o combinatie intre codul server side care prepara afisarea, codul client side care o modifica/afiseaza (html + javascript care manipuleaza html) + browserul web, exact cois… Daca vrei sa fi ortodox nu faci query-uri in template-uri php sau altceva, nu prelucreazi informatie in view si nimic altceva. Doar afisezi, faci un for chestii de genu asta.
Mult mai ingrijorator este persistenta acestei abordari, daca pot macar sa-i zic asa, in framework-uri cu pretentii. Un trist exemplu este Zend Framework care nu ofera absolut nici un suport pentru partea de model, parca incearca sa fie o continuare a “traditiei” scriptkiddies legata atat de des de PHP.
Ca sa revin la intrebarea initiala: “unde pula mea e modelul?”

P.S.

Dupa amiaza m-am intalnit la o tigara cu Mikael, din celula de securitate, care mi- a zis ca cunoaste backoffice-ul respectiv, ca e “un truc de merde” dpdv securitate,  si tradus mai pe scurt, ca “isi baga pula, el nu aproba utilizarea lui in aplicatie”.

JsLint in Eclipse

JsLint (http://www.jslint.com) este un validator de sintaxa si “bune practici”, evident pentru Javascript. Utilitate relativ indoielnica, dar devine util de exemplu cand ai probleme de cross browser.

In acest context, am incercat sa creez un “external tool” in eclipse cu jslint ca sa-l pot rula usor pe orice fisier. Problema e ca jslint e scris in … javascript – deci aveam nevoie de un interpretor de javascript care merge pe windows in linia de comanda.
Un scurt search pe g, ar fi cateva optiuni:

– rhino (http://www.mozilla.org/rhino/) Rhino e teoretic un motor care ar putea face asa ceva, dar e scris in java deci trebuie sa chem interpetorul java care sa cheme rhino care sa intepreteze jslint … prea complicat. In plus, sincer, nu am reusit sa fac sa mearga combinatia, deci pula.

– jslib (http://code.google.com/p/jslibs/) Jslib e o librarie destul de misto … aparent. Dar nu ruleaza jslint, da erori .. deci pula si asta.

Usor enervat, mai gasisem ceva in care era utilizat motorul jscript din windows dar era outdated, eram gata sa renunt cand am descoperit. Javascript Lint : http://www.JavaScriptLint.com , care e practic o versiune compilata, cu interfata in linie de comanda pentru jslint-ul original.
Are si un fisier de configuratie care e destul de flexibil … deci merge.
Pentru a utiliza asta in eclipse, am creat un nou external tool, care arata cam asa:

external tool
external tool

Cu chestia asta am rezolvat problema, rezultatul evaluarii apare in consola.

Despre MySQL si soundex

Deci MySQL … Sincer sa fiu, in disputele religioase MySQL vs PostgreSQL, sunt de obicei de partea Postgres, dar fortat de imprejurari in general trebuie sa utilizez MySQL (impotriva bunului meu simt, of course). Anyway, pana acum nu am avut motive chiar asa serioasa sa ma irite MySQL. Pana acum.

De curand intr-un proiect care-l “repar”, aveam o pagina care lista niste aeroporturi in functie de inputul utilizatorului. De exemplu daca introduceai “paris”, respectiva pagina iti lista cele cateva aeroporturi din paris si inca vreo 7 – 8 din lume care erau “asemanatoare” ca nume.

Problema e ca rezultatele erau foarte aiurea in unele cazuri, si nu intelegeam de ce. O scurta privire in codul primitiv si prostesc care domneste in acest proiect mi-a dezvaluit modul destul de simplu in care se facea operatiunea:

in baza de date o tabela stoca o lista de aeroporturi care avea in nume si orasul (utilizatorul urma sa caute dupa oras), si folosind functia SOUNDEX, lista toate inregistrarile alea carui SOUNDEX era identic cu cel al stringului cautat. Destul de normal .. aparent.

SELECT ID,Code,City, Airport, Country FROM airports WHERE Soundex(City) = SOUNDEX(\”$deptArpt\”)

Problema e ca “baietii de la mysql” au hotarat ca nu are sens sa urmeze algoritmul de soundex din manual, ei sunt mai destepti si algoritmul lor nu se opreste dupa 3 numere identificate, ci merge pana la sfarsit. Ideea pare ok, pana iti dai seama ca in felul asta “new york airport” si “new york” au scoruri diferite, which really sux. De aici veneau problemele – soundex este destul de inutil in forma lui initiala.
O posibila rezolvare ar fi sa pastrez doar primele 3 numere si sa le ignor pe restul, ceea ce am si facut. Insa inainte am calculat toate soundex-urile intr-un camp suplimentar  (soundscore) pentru a usura load-ul in timpul functionarii.
O alta problema a fost “similitudinea”. Un SGBD inteligent ca Postgres are o functie care se cheama similarity si care iti returneaza un scor care il poti folosi pentru a regla cate rezultate primesti. MySQL … normal ca nu are asa ceva. Eu aveam nevoie si de acest comportament, asa ca am scos prima litera din rezultatul soundex (care arata ceva de genul P345, unde P e prima litera a stringului), si am facut o comparatie a diferentei intre scorul initial si scorul stringului cautat.
Adica ceva cam asa:

select ID,Code,City, Airport, Country from airports where ABS(CAST(substring(soundex(\”$deptArpt\”), 2) as SIGNED) – soundscore) < 5 AND substring(soundex(\”$deptArpt\”), 1, 1) = soundletter

Ultima comparatie este necesara pentru ca prima litera este esentiala in acest tip de cautare.
Bun asta cam imi rezolva problema, pot stoca rezultatele in soundscore pentru ca lista de aeroporturi este statica. Oricum … MySQL … pula mea …varza.

Drupal 5.0 si sections

Pentru un proiect care l-am avut, am vrut sa utilizam modulul sections pentru a avea teme diferite pentru admin si site. Nimic anormal pana acum, doar ca modulul sections nu vroia sa mearga, in mod misterios …

Asa ca a trebuit sa hacuiesc un pic:
Pe drupal.org am mai intalnit oameni cu aceeasi problema, care insa se zicea ca se rezolva prin modificarea weight a modului la -10, care deja era inclusa in versiunea curenta, si tot nu mergea. Pana la urma am ajuns in system.module la urmatorul cod:

if (arg(0) == 'admin') {
global $custom_theme;
$custom_theme = variable_get('admin_theme', '0');
drupal_add_css(drupal_get_path('module', 'system') .'/admin.css', 'module');
}

Care in mod evident suprascria ce facuse modulul de sections, care baga tema in $custom_theme.

Asa ca am facut un mic hack:

if (arg(0) == 'admin') {
global $custom_theme;
if(empty($custom_theme)) {
$custom_theme = variable_get('admin_theme', '0');
}
drupal_add_css(drupal_get_path('module', 'system') .'/admin.css', 'module');
}

Si gata, acu merge … desi solutia nu este foarte ortodoxa.