Consells i bones pràctiques de l’logging d’aplicacions

Hem anat assumint amb el temps que aspectes com la seguretat i les proves s’han de tenir en compte durant tot el cicle de vida d’el projecte, des dels seus orígens fins a la seva finalització. Que no són requisits no funcionals desitjables o secundaris, sinó que són prioritaris com a part de l’estructura fonamental de l’aplicatiu (fa no tant eren funcionalitats o mecanismes que es dissenyaven i s’implementaven a la finalització de el projecte com un afegit, si es feien). No obstant això la traça d’aplicació, tot i haver fet mèrits, no ha rebut en molts casos la mateixa consideració ;-P.

En aquesta entrada no crec que us descobreixi res de nou als que tingueu experiència en el desenvolupament . La idea és fer un exercici de síntesi i revisió per resumir el que, al meu entendre, són les millors o les bones pràctiques de l’log d’aplicació. Per descomptat, les aportacions, observacions, matisacions i crítiques són benvingudes; us convido a que us uniu a aquest exercici.

El registre o traça d’aplicació és el processat i emmagatzematge d’informació relativa a l’execució d’una aplicació. Conté dades d’entitats, canvis d’estat i components programari involucrades en l’execució. La seva principal funcionalitat és facilitar el seguiment o anàlisi de l’execució de l’aplicació:

  • Analitzar el comportament de l’aplicació durant la fase de desenvolupament i depuració (proves de caixa blanca)
  • Analitzar els bugs o errors d’execució detectats, les causes i conseqüències
  • Servir de registre d’auditoria quan la informació continguda i la manera en què s’ha processat compleixi els criteris requerits
  • mesurar el rendiment o càrrega dels sistemes o aplicacions
  • Revertir l’estat de l’aplicatiu seguint en ordre invers al registre

Tot i que depèn de les circumstàncies en què ens trobem, el segon dels usos sol ser el més rellevant. Un bon log desenvolupat correctament en el codi i mantingut o configurat en explotació és una garantia de resposta ràpida per a anàlisi d’errors; que fins i tot podrien fer-se sense necessitat d’aturar l’aplicatiu, reconfigurar o aplicar-li cap canvi.

La traça d’aplicació sol formar-se per un conjunt d’esdeveniments que s’emmagatzemen seqüencialment, generalment en l’ordre en què succeeixen, de manera persistent o recuperable. Es poden emmagatzemar en fitxers, en BBDD, en components distribuïts a aquest efecte … Es poden habilitar mecanismes de rotació o historificació d’aquests logs, es poden utilitzar per monitors per llançar alertes, es poden integrar i fusionar per fer anàlisis més exhaustius … El que és rellevant és que la informació registrada i la forma en què es gestiona sigui útil.

Hi ha nombroses solucions i propostes programari, tant lliures com propietàries, més o menys estandarditzades, més senzilles o més completes, de mil tipus i formes . L’important és buscar aquella s’ajusta a les nostres necessitats i entorns, per oblidar-nos de la implementació de l’mecanisme per complet; i cenyir-nos als dos aspectes més importants:

  • El contingut de cada registre o esdeveniment, principal preocupació de l’desenvolupador
  • La manera en què es processa, persisteix i gestiona, principal preocupació de l’explotació de sistema o aplicatiu

el cost d’implementació de l’logging es troba al anar, mentre es desenvolupa, deixant traça en els diferents punts de el codi. Aquesta activitat s’ha de fer durant el desenvolupament, seguint patrons, criteris i procediments preestablerts. D’aquesta manera els desenvolupadors tindran criteris comuns i la traça serà coherent entre les diferents parts de el codi.

La traça i la documentació de el codi poden tenir punts en comú pel que fa a la seva filosofia, objectius i manera d’aplicació , però hi ha una diferència important entre tots dos: mentre la documentació de el codi s’endinsa en el per què es fa una mica d’aquesta manera, la traça ha de cobrir el què es fa. Per posar un exemple, en un bucle la documentació de el codi hauria d’indicar per què els límits o condicions de sortida són tals i la traça registrar durant l’execució en quin punt es va complir aquesta condició de sortida.

La informació registrada a la traça ha de ser rellevant i completa. Es poden considerar els següents aspectes a l’hora de decidir quina informació incloure:

  • Què:
    • Què esdeveniment o acció ha passat.
    • Què entitats han estat involucrades.
    • Si hi ha un canvi d’estat, quin era l’anterior? ¿Quin és el nou estat ?.
  • On:
    • En quin punt de l’codi ha passat: component, classe, fitxer de codi, mètode o bloc d’execució, línia de codi … Com més detallada sigui aquesta informació millor per localitzar el lloc de l’possible error o per on ha passat l’execució, d’una banda; però més pot afectar el logging a l’rendiment (es podria requerir informació de debug) ia la concreció de la informació de la traça, de l’altra.
  • Quan:
    • Registrant el moment temporal, bé absolut o bé relatiu a l’començament d’execució o qualsevol altre esdeveniment.
    • Generant una traça seqüencial o causal, en la qual els esdeveniments que ocorren abans en el temps o que ocasionen altres , apareguin abans.
  • En quin context:
    • Registrant estats o variables: propis de l’execució (paràmetres), de personalització o específics d’usuari, referents a la sessió o transacció en execució …
    • Indicant brins, transaccions o peticions relacionades quan estiguem en entorns concurrents.

Perquè la informació de la traça sigui més detallada en moment d’anàlisi i més manejable durant l’explotació de la mateixa, s’estableixen nivells de filtrat. De tal manera que només es mostra o emmagatzemen aquells esdeveniments amb un nivell major o igual a el de el nivell de traça establert. Les llibreries de logging permeten filtrar els esdeveniments per altres criteris com són la classe o context de l’esdeveniment, també.

Els nivells més comuns són DEBUG, INFO, WARNING i ERROR. La classificació dels diferents esdeveniments en cada nivell és part de l’exercici d’anàlisi, i s’han d’orientar a que la traça sigui llegible i útil en els diferents contextos de l’aplicatiu, des del desenvolupament fins a l’explotació.

Aquest pot ser un exemple de semàntica de nivells de logging:

  • dEBUG, per a informació de molt baix nivell només útil per al debug de l’aplicació, tant en el desenvolupament com en l’anàlisi d’incidències
    • Trucades a funcions i procediments i altres components, amb paràmetres i respostes
    • Fluxos d’execució
    • desenvolupament d’algoritmes i procediments que permetin identificar i seguir la seva execució en desenvolupament
  • INFO, informació de més alt nivell que permeti fer un seguiment de l’execució normal
    • Parades i arrencades de serveis i sistemes
    • Paràmetres crítics o rellevants de configuració
    • Començament i fi de transaccions i operacions completes
    • Canvis de estat d’operacions
  • WARN, informació de situacions, que tot i no ser d’error, si són anòmales o no previstes, tot i que l’aplicatiu té alternatives per solucionar-
    • Paràmetres no definits, i el valor es pren per defecte
    • Situacions anòmales, però que són resoltes per l’aplicatiu, deixant l’operació en un estat correcte
    • Funcionalitats no primordials o imprescindibles, que no es poden resoldre, però que deixen l’operació en un estat correcte
  • eRROR, informació de situacions que són d’error i que impedeixen l’execució correcta d’una operació o transacció, però sense afectar altres operacions o transaccions (error aïllat o contingut)
    • no s’ha pogut realitzar una operació o transacció, però no afecta altres
    • Peticions o consultes errònies (emmagatzemant els paràmetres de entrada)
    • Funcionalitats generals de l’aplicatiu, que encara afectant el funcionament general de l’APLICAT ivo, no es consideren primordials o imprescindibles
  • FATAL, informació de situacions d’error que afecten el funcionament general de l’aplicatiu (errors no aïllats o continguts en abast)
    • Paràmetres no definits o configuracions errònies
    • Manca de connexió o comunicació amb altres components
    • Errors d’execució que poden afectar operacions o transaccions independents, o que afecten el funcionament general de la aplicació

Tant el contingut i forma de cada esdeveniment de log, com la semàntica dels nivells són part de el disseny de l’aplicatiu. Aquests criteris han de definir-se i ser comunicats a l’equip de desenvolupament perquè s’apliquin de manera homogènia i coherent en tot el desenvolupament. Si aquests criteris són consensuats amb l’equip es pot treure molt profit de l’experiència dels desenvolupadors.

Altres recomanacions a tenir en compte són:

  • Registrar els esdeveniments de manera atòmica, que tota la informació referent a un esdeveniment s’emmagatzemi en un registre o línia.
  • Orientar el format de la informació mostrada a poder ser usat de manera informatitzada o automàtica amb eines específiques.
  • Pel que fa a excepcions:
    • Mostra sempre la traça completa de l’excepció amb el seu missatge i tot el stacktrace.
    • Si l’excepció és capturada, tractada i després llançada de nou (bé la mateixa o una altra) no deixar traça de l’excepció fins que es capturi i es tracti en última instància. D’aquesta manera cada excepció només es mostrarà una vegada. Si no ho fem així i vam registrar cada captura i rellançament aparacerá en la traça diverses vegades i no sabrem si és la mateixa o són diverses. (Antipatrón catch-log-throw).
    • Fer ús de la propietat d’excepció causant o interna quan capturem i relancemos l’excepció. En Java és el mètode getCause (), en .NET la propietat InnerException.
  • Fer ús de mecanismes de MDC / NDC (informació de context ) per a entorns de múltiples fils o àmbits de transacció. Aquesta informació ens pot permetre filtrar o concretar la informació de log en context de negoci específics com poden ser clients, usuaris, productes …
  • Implementar el mètode toString () de totes les classes de negoci o POJOs per facilitar la seva traceado.
  • Cal tenir en compte les diferències i zones horàries a l’hora de treballar amb logs de diverses màquines o components.
  • El logging no pot tenir efectes laterals, no pot modificar l’estat de cap paràmetre, variable o procediment. Només mostra informació. Ha de ser lleuger, el mateix logging no pot requerir de processaments llargs o costosos.
  • Les trucades a mètodes, components i components distribuïts externs, haurien de registrar després de la trucada incloent els paràmetres d’entrada i la resposta, així com classe / component i mètode, a nivell de DEBUG. I a nivell de ERROR i FATAL quan es produeix un error en l’anomenada (si fos una excepció s’ha de tracear paràmetres d’entrada i excepció)

Una salutació,

Joan Francisco Adame Lorite

Llicència de Creative Commons

Compartir:

Deixa un comentari

L'adreça electrònica no es publicarà. Els camps necessaris estan marcats amb *