log me tender - the coder's...

48
Log me tender Moka Technologies mokatech.net Olivier Croisier @OlivierCroisier

Upload: trinhhanh

Post on 10-Jun-2018

213 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

Log me tender

Moka Technologiesmokatech.net

Olivier Croisier@OlivierCroisier

Page 2: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

log(me)

Olivier Croisier

● Freelance / Moka TechnologiesConseil, Développement & Formation

● Développeur Java / Web certifié

● Blog: thecodersbreakfast.net

Twitter: @OlivierCroisier

GitHub: OlivierCroisier Bordeaux

Page 3: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Plan

● De System.out à nos jours

● Des problèmes persistants

● Proposition : LogService

Page 4: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

De System.out à nos jours

Page 5: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

System.out

Log primitif

System.out.println("Hello World");

System.out

● PrintWriter

● Réassignable

Page 6: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Problème

API trop simple !

Page 7: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Log4J

Ceki Gülcü, projet Apache (2001)

Définit une API "standard"

● Impact industriel

● Inspire tous les futurs frameworks

Page 8: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Log4J

API

● Factory statique : LogManager.getLogger(id)

● log(String msg)log(String msg, Throwable ex)

Niveaux de log :

● debug, info, warn, error, fatal

Page 9: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Log4J

public class Foo {

private static final Logger LOG = LogManager.getLogger(Foo.class);

public void bar() { LOG.info("Hello world"); }

}

Page 10: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

JUL (java.util.logging)

JSR 47 (2002)

"Standardisation" de Log4J

API similaire à Log4J

Page 11: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Log4J2

Projet Apache (2012)

Réécriture totale

● Performances (Disruptor)

● Inspiré de Log4J et Logback

API similaire à Log4J

Page 12: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Problème

Trop de frameworks !

Page 13: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Trop de frameworks

"Dependency hell"

● Dépendances directes

● Dépendances transitives

● Classloaders

Solution

● … Un nouveau framework !MOAR frameworks !

Page 14: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Commons-logging

Projet Apache (2002)

Façade pour Log4J, JUL, LogKit

API similaire à Log4J

Page 15: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

SLF4J

Ceki Gülcü (Log4J) (2005)

● Le standard actuel

Façade pour Log4J, Log4J2, JUL, JCL, System.out…

API similaire à Log4J

Page 16: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

Des problèmes persistants

Page 17: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Problème #1

Concaténations dynamiques

LOG.debug("User: " + user.id);

Page 18: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Concaténation dynamique

LOG.debug("User: " + user.id);

Messages souvent dynamiques

● Concaténation de chaînes

Concaténation immédiate

● Inutile selon niveau de log effectif

Page 19: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Concaténation dynamique

Solution : concaténations "lazy"

● Placeholders

● Vérification préalable du niveau de log

LOG.debug("User: {}", user.id);

Implémentations : SLF4J, Log4J2

Page 20: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Problème #2

Évaluation immédiate des paramètres

LOG.debug("DB: {}", DB.dump());

BESTEST idea ever !

Page 21: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Évaluation des paramètres

LOG.debug("DB: {}", DB.dump());

Evaluation immédiate

● Potentiellement coûteuse : I/O, calculs

● Parfois inutile : suivant le niveau de log effectif

Page 22: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Évaluation des paramètres

Solution 1 :

● Tester préalablement le niveau de log effectif

● Pattern "standard"

if (LOG.isDebugEnabled()) {

LOG.debug("DB: " + DB.dump());

}

Page 23: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Évaluation des paramètres

Solution 1 : inconvénients

● Couplage technique avec la configuration du logger

● Non-DRY

if (LOG.isDebugEnabled()) {

LOG.info("DB: " + DB.dump());

}

Page 24: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Évaluation des paramètres

Solution 1 : inconvénients

● Fausses bonnes idées

public void logDebug(String message) {

if (LOG.isDebugEnabled()) {

LOG.debug(message);

}

}

Much SMART,

wow !

Page 25: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Évaluation des paramètres

Solution 2 :

● Évaluation "lazy" : Supplier<String> (Java 8+)

● Plus besoin de test "externe"

LOG.debug(() -> "DB: " + DB.dump());

Page 26: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Évaluation des paramètres

Solution 2 :

● Évaluation "lazy" : Supplier<String> (Java 8+)

Implémentations : JUL, Log4J2… mais pas SLF4J !

● SLF4J devient le facteur limitant

● API obsolète

Page 27: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Évaluation des paramètres

Solution 1 : ne pas utiliser SLF4J

● Difficile en pratique

Solution 2 : Améliorer SLF4J

● Rétrocompatibilité obligatoire

Solution 3 : "Façader" SLF4J

● LogService

Page 28: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Problème #3

Factory statique

private static final Logger LOG =

LogManager.getLogger(Foo.class);

Page 29: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Factory statique

private static final Logger LOG = LogManager.getLogger(Foo.class);

Référence statique

● Non configurable

● Non testable

● Non mockable

Page 30: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Factory statique

Solution : référence non-statique

Notion de "service de log"

● Injectable par IOC

● Testable (test du service de log)

● Mockable (test des services utilisateurs)

● AOP-able (performances, coupe-circuit)

Page 31: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Problème #4

Des frameworks trop bas niveau

log.debug("process "+pId+" started")

log.info("PROC_START;pid="+pId);

Page 32: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Des frameworks trop bas niveau

Non-DRY : harmonisation externe nécessaire

● Niveau de log

● Format des messages

Couplage fort

● Producteur / consommateur

● Framework de log

Page 33: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Des frameworks trop bas niveau

Solution : un service de log haut niveau

● Façade du framework technique

● Expose une API technique et métier ad hoc

● Centralise la gestion des messages (format, niveau)

public void beginProcess(int id) {

logger.info (() → "Starting process "+id);

}

Page 34: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Des frameworks trop bas niveau

Solution : un service de log haut niveau

● Possibilité de raisonner en termes d'événements

● Un événement → 1..N logs

public void restApiCalled(String url, long ms, int code) {

if (ms ≥ 10) perfLogger.info (() → url+";"+ms);

if (code != 200) alertLogger.warn(() → url+";"+code);

}

Page 35: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

LogService

Page 36: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

LogService

Design goals

● Une API restreinte et moderne

● Rétro-compatibilité et extensibilité

● Façade pour SLF4J

● Composant IOC

Page 37: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Une API restreinte et moderne

Méthode "log" fondamentale

● Couvre tous les use-cases

● Supplier résout la plupart des problèmes

interface LogService {

void log( LogLevel level, Supplier<String> msg, Throwable ex );

}

Page 38: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Rétro-compatibilité

Rétro-compatibilité via les méthodes dérivées

default void debug (Supplier<String> msg, Throwable ex) { log(LogLevel.DEBUG, msg, ex);}

default void info (Supplier<String> msg, Throwable ex) { log(LogLevel.INFO, msg, ex);}

(...)

Page 39: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Extensibilité

Possibilité d'ajouter ses propres méthodes orientées métier

void restApiCalled(String path, long ms, int code);

void userLogged(Principal user, Device device);

Page 40: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Façade pour SLF4J

public class SLF4JLogService implements LogService {

private final Logger logger;

protected SLF4JLogService(String loggerName) { this.logger = LoggerFactory.getLogger(loggerName); }

@Override public void log(LogLevel lvl, Supplier<String> msg, Throwable ex) { log(LogLevelConfig.forLogLevel(lvl), msg, ex); }

}

Page 41: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

public interface LogServiceFactory {

LogService getLogService(String loggerName);

default LogService getLogService(Class<?> loggerNameByClass) { return getLogService(loggerNameByClass.getClass()); }

}

Composant IOC

Factory toujours nécessaire pour le use-case "1 logger par classe"

● Plus simple qu'un composant de scope "prototype"

Page 42: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Composant IOC

@Componentpublic class SLF4JLogServiceFactory implements LogServiceFactory {

@Override public LogService getLogService(String loggerName) { return new SLF4JLogService(loggerName); }

}

Page 43: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Utilisation

@Serviceclass MyService {

private final LogService logService;

public MyService(LogServiceFactory factory) { this.logService = factory.getLogService(MyService.class); }

public void foo() { logService.info("Hello World"); }

}

Page 44: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

Conclusion

Page 45: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Conclusion

Un domaine en pleine évolution...

● Big Data et analyse temps réel

● Micro-services et Cloud

…mais encore mal industrialisé

● Frameworks et patterns en retard

● Peu de spécifications dans les projets

Page 46: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

#devoxxfr

Conclusion

Beaucoup reste à faire

● Sensibilisation DevOps

● Nouveaux frameworks et patterns à inventer

Voir aussi :

● ExceptionContext : trying to improve business exceptionshttp://bit.ly/2nQQqB5

Page 47: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

Question ?

Page 48: Log me tender - The Coder's Breakfastthecodersbreakfast.net/public/2017-04-10-devoxxfr-log-me-tender/...#devoxxfr log(me) Olivier Croisier Freelance / Moka Technologies Conseil, Développement

Log me tender

Moka Technologiesmokatech.net

Olivier Croisier@OlivierCroisier

Thank you !

Merci !