viernes, 27 de julio de 2012

Obtener información del entorno de una aplicación web en Java

Java
Hace un tiempo comenté algunas ventajas que obtenemos al tener un sistema de logging en una aplicación y una combinación de librerías que podríamos utilizar para este propósito [1]. Una vez que tenemos un sistema de logging en una aplicación podemos sacarle mucho provecho, como obtener alguna información básica del entorno de ejecución.

La razón de obtener la mayor información del entorno de ejecución es más para el entorno de pruebas o producción que para el entorno en el que desarrollamos, ya que estos primeros pueden llevar alguna configuración especial que no solemos revisar o están fuera de nuestro control aunque en los últimos también puede ser interesante si las hay varias personas que colaboran con posiblemente diferentes sistemas operativos instalados y configuraciones. Tener a nuestra disposición esta información nos puede permitir darnos cuenta de la causa de algun comportamiento extraño. Algún ejemplo de información que nos puede ser de utilidad es la hora del sistema, si trabajamos con fechas la zona horaria en la que está configurado o la codificación de caracteres por defecto.

Vamos a verlo en el caso de una aplicación web. En las aplicaciones web Java tenemos a nuestra disposición dos interfaces que podemos implementar y ser notificados cuando ocurran ciertos eventos en la aplicación como son cuando se inicia, cuando se va a terminar, cuando se crea una sesión y cuando se destruye una sesión. Ahora que estamos interesandos en obtener información del sistema vamos a ver unos ejemplos de clases ServletContextListener y HttpSessionListener que podríamos utilizar para obtener información.

Mediante la interfaz ServletContextListener y sus métodos contextInitialized y contextDestroyed podremos obtener una referencia a un objeto ServletContext y podremos acceder a los métodos que proporciona para por ejemplo conocer los parámetros de inicialización de la aplicación si esta la parametrizamos de esta manera. En el siguiente ejemplo se saca al log la siguiente información: unas trazas de cabecera para saber donde empieza en la salida del log cada inicio de la aplicación, el nombre de contexto de la aplicación, las propiedades del sistema (incluyendo la zona horaria y la codificación de caracteres por defecto), la información del servidor sobre el que se ejecuta la aplicación y la versión de la Java Servlet API, los nodos del arbol JNDI y un enumerado que identificará el servidor de aplicaciones sobre el que se ejecuta la aplicación.

package es.com.blogspot.elblogdepicodev.misc;

import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NameClassPair;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import es.com.blogspot.elblogdepicodev.Entorno.Servidor;

/**
 * Clase que recibe los eventos de inicio y fin de la aplicación web.
 */
public class ContextListener implements ServletContextListener {

 private static Logger logger;

 public static ServletContext SERVLET_CONTEXT;

 @Override
 public void contextInitialized(ServletContextEvent sce) {
  SERVLET_CONTEXT = sce.getServletContext();

  // Configurar el entorno
  try {
   Utilidades.setupEntorno();
  } catch (Exception e) {
   e.printStackTrace();
  }

  logger = LoggerFactory.getLogger(ContextListener.class);

  logger.info("");
  logger.info("--- -.-. . -. ... ..- .-. .- -.. --- -.-. . -. ... ..- .-. .- -.. --- -.-. . -. ... ..- .-. .- -.. ---");
  logger.info("--- -.-. . -. ... ..- .-. .- -.. --- -.-. . -. ... ..- .-. .- -.. --- -.-. . -. ... ..- .-. .- -.. ---");
  logger.info("--- -.-. . -. ... ..- .-. .- -.. --- -.-. . -. ... ..- .-. .- -.. --- -.-. . -. ... ..- .-. .- -.. ---");

  {
   try {
    logger.info("Iniciando aplicación web [" + sce.getServletContext().getServletContextName() + "]...");
    logger.info("Propiedades del sistema:");

    SecurityManager sm = System.getSecurityManager();
    Enumeration e = System.getProperties().keys();
    while (e.hasMoreElements()) {
     String key = (String) e.nextElement();
     try {
      if (sm != null) {
       sm.checkPropertyAccess(key);
      }
      logger.info(key + ": " + System.getProperties().get(key));
     } catch (SecurityException se) {
      logger.info(key + ": [No hay permisos]");
     }
    }
   } catch (Exception e) {
    logger.warn(e.getMessage(), e);
   }
  }

  {
   logger.info("Propiedades del entorno:");
   logger.info("Server info: " + sce.getServletContext().getServerInfo());
   logger.info("Java Servlet API version: " + sce.getServletContext().getMajorVersion() + "." + sce.getServletContext().getMinorVersion());
  }

  {
   // Obtener los nodos del árbol JNDI
   Map enviroment = null;
   try {
    enviroment = new LinkedHashMap();
    buildEnv(new InitialContext(), Constantes.JNDI_EVANDTI, enviroment);
   } catch (Exception e) {
    logger.error(e.getMessage(), e);
   }

   logger.info("Propiedades de entorno para la aplicacion web:");
   Iterator it = enviroment.keySet().iterator();
   while (it.hasNext()) {
    String key = (String) it.next();
    logger.info("{}: {}", new Object[] { key, enviroment.get(key) });
   }
  }

  {
   logger.info("Propiedades dinámicas:");
   Servidor servidor = getServidor(SERVLET_CONTEXT);
   Entorno.setPropiedadDinamica(Entorno.PROP_DINAMICA_SERVIDOR, servidor);

   Iterator it = Entorno.getPropiedadesDinamicas().iterator();
   while (it.hasNext()) {
    String propiedad = (String) it.next();
    Object valor = Entorno.getPropiedadDinamica(propiedad);
    logger.info("{}: {}", propiedad, valor);
   }
  }

  logger.info("Iniciando aplicacion con la configuracion del entorno de «{}»", Entorno.getEntorno().toString().toLowerCase());
 }

 @Override
 public void contextDestroyed(ServletContextEvent sce) {
  logger.info("Finalizando aplicación...");
 }

    /**
     * Añade en un Map los nodos de árbol JNDI configurados en el servidor.
     */
 private void buildEnv(Context c, String name, Map env) throws NamingException {
  NamingEnumeration ne = c.list(name);
  while (ne.hasMoreElements()) {
   NameClassPair n = (NameClassPair) ne.next();
   String x = name + "/" + n.getName();
   Object o = c.lookup(x);
   env.put(x, o);
   if (o instanceof Context) {
    buildEnv(c, x, env);
   }
  }
 }

 /**
  * Devuelve un enum del servidor sobre el que se está ejecutando la aplicación.
     */
 private static Servidor getServidor(ServletContext sc) {
  String si = sc.getServerInfo();

  if (si.contains(Constantes.SERVIDOR_TOMCAT)) {
   return Servidor.TOMCAT;
  } else if (si.contains(Constantes.SERVIDOR_JBOSS)) {
   return Servidor.JBOSS;
  } else {
   return Servidor.DESCONOCIDO;
  }
 }
}

Esto sería un ejemplo de salida de esta clase ContextListener:

2012-05-04 21:03:33,031 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener 
2012-05-04 21:03:33,037 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener --- -.-. . -. ... ..- .-. .- -.. --- -.-. . -. ... ..- .-. .- -.. --- -.-. . -. ... ..- .-. .- -.. ---
2012-05-04 21:03:33,038 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener --- -.-. . -. ... ..- .-. .- -.. --- -.-. . -. ... ..- .-. .- -.. --- -.-. . -. ... ..- .-. .- -.. ---
2012-05-04 21:03:33,038 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener --- -.-. . -. ... ..- .-. .- -.. --- -.-. . -. ... ..- .-. .- -.. --- -.-. . -. ... ..- .-. .- -.. ---
2012-05-04 21:03:33,038 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener Iniciando aplicación web [TapestryCensurado]...
2012-05-04 21:03:33,038 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener Propiedades del sistema:
2012-05-04 21:03:33,038 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.runtime.name: OpenJDK Runtime Environment
2012-05-04 21:03:33,038 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener sun.boot.library.path: /usr/lib/jvm/java-6-openjdk/jre/lib/amd64
2012-05-04 21:03:33,038 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.vm.version: 20.0-b12
2012-05-04 21:03:33,038 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener shared.loader: 
2012-05-04 21:03:33,038 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.vm.vendor: Sun Microsystems Inc.
2012-05-04 21:03:33,038 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.vendor.url: http://java.sun.com/
2012-05-04 21:03:33,038 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener path.separator: :
2012-05-04 21:03:33,038 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener tomcat.util.buf.StringCache.byte.enabled: true
2012-05-04 21:03:33,038 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.util.logging.config.file: /home/picodotdev/archivos/apache-tomcat-7.0.27/conf/logging.properties
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.vm.name: OpenJDK 64-Bit Server VM
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener file.encoding.pkg: sun.io
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener sun.java.launcher: SUN_STANDARD
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener user.country: ES
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener sun.os.patch.level: unknown
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.vm.specification.name: Java Virtual Machine Specification
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener user.dir: /home/picodotdev/archivos/apache-tomcat-7.0.27/bin
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.runtime.version: 1.6.0_24-b24
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.awt.graphicsenv: sun.awt.X11GraphicsEnvironment
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.endorsed.dirs: /home/picodotdev/archivos/apache-tomcat-7.0.27/endorsed
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener os.arch: amd64
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.io.tmpdir: /home/picodotdev/archivos/apache-tomcat-7.0.27/temp
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener line.separator: 

2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.vm.specification.vendor: Sun Microsystems Inc.
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.naming.factory.url.pkgs: org.apache.naming
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.util.logging.manager: org.apache.juli.ClassLoaderLogManager
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener os.name: Linux
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener sun.jnu.encoding: UTF-8
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener tomcat.util.scan.DefaultJarScanner.jarsToSkip: bootstrap.jar,commons-daemon.jar,tomcat-juli.jar,annotations-api.jar,el-api.jar,jsp-api.jar,servlet-api.jar,catalina.jar,catalina-ant.jar,catalina-ha.jar,catalina-tribes.jar,jasper.jar,jasper-el.jar,ecj-*.jar,tomcat-api.jar,tomcat-util.jar,tomcat-coyote.jar,tomcat-dbcp.jar,tomcat-i18n-en.jar,tomcat-i18n-es.jar,tomcat-i18n-fr.jar,tomcat-i18n-ja.jar,tomcat-juli-adapters.jar,catalina-jmx-remote.jar,catalina-ws.jar,tomcat-jdbc.jar,commons-beanutils*.jar,commons-codec*.jar,commons-collections*.jar,commons-dbcp*.jar,commons-digester*.jar,commons-fileupload*.jar,commons-httpclient*.jar,commons-io*.jar,commons-lang*.jar,commons-logging*.jar,commons-math*.jar,commons-pool*.jar,jstl.jar,geronimo-spec-jaxrpc*.jar,wsdl4j*.jar,ant.jar,ant-junit*.jar,aspectj*.jar,jmx.jar,h2*.jar,hibernate*.jar,httpclient*.jar,jmx-tools.jar,jta*.jar,log4j*.jar,mail*.jar,slf4j*.jar,xercesImpl.jar,xmlParserAPIs.jar,xml-apis.jar,dnsns.jar,ldapsec.jar,localedata.jar,sunjce_provider.jar,sunmscapi.jar,sunpkcs11.jar,jhall.jar,tools.jar,sunec.jar,zipfs.jar,apple_provider.jar,AppleScriptEngine.jar,CoreAudio.jar,dns_sd.jar,j3daudio.jar,j3dcore.jar,j3dutils.jar,jai_core.jar,jai_codec.jar,mlibwrapper_jai.jar,MRJToolkit.jar,vecmath.jar,junit.jar,junit-*.jar,ant-launcher.jar
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.library.path: /usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server:/usr/lib/jvm/java-6-openjdk/jre/lib/amd64:/usr/lib/jvm/java-6-openjdk/jre/../lib/amd64:/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib
2012-05-04 21:03:33,039 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.specification.name: Java Platform API Specification
2012-05-04 21:03:33,040 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.class.version: 50.0
2012-05-04 21:03:33,040 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener sun.management.compiler: HotSpot 64-Bit Tiered Compilers
2012-05-04 21:03:33,040 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener os.version: 3.3.4-2-ARCH
2012-05-04 21:03:33,040 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener user.home: /home/picodotdev
2012-05-04 21:03:33,040 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener catalina.useNaming: true
2012-05-04 21:03:33,040 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener user.timezone: Europe/Madrid
2012-05-04 21:03:33,040 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.awt.printerjob: sun.print.PSPrinterJob
2012-05-04 21:03:33,040 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener file.encoding: UTF-8
2012-05-04 21:03:33,040 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.specification.version: 1.6
2012-05-04 21:03:33,040 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener catalina.home: /home/picodotdev/archivos/apache-tomcat-7.0.27
2012-05-04 21:03:33,040 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.class.path: /home/picodotdev/archivos/apache-tomcat-7.0.27/bin/bootstrap.jar:/home/picodotdev/archivos/apache-tomcat-7.0.27/bin/tomcat-juli.jar
2012-05-04 21:03:33,040 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener user.name: picodotdev
2012-05-04 21:03:33,040 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.naming.factory.initial: org.apache.naming.java.javaURLContextFactory
2012-05-04 21:03:33,040 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener package.definition: sun.,java.,org.apache.catalina.,org.apache.coyote.,org.apache.tomcat.,org.apache.jasper.
2012-05-04 21:03:33,040 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.vm.specification.version: 1.0
2012-05-04 21:03:33,040 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener sun.java.command: org.apache.catalina.startup.Bootstrap start
2012-05-04 21:03:33,040 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.home: /usr/lib/jvm/java-6-openjdk/jre
2012-05-04 21:03:33,040 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener sun.arch.data.model: 64
2012-05-04 21:03:33,041 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener user.language: es
2012-05-04 21:03:33,041 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.specification.vendor: Sun Microsystems Inc.
2012-05-04 21:03:33,041 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.vm.info: mixed mode
2012-05-04 21:03:33,041 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.version: 1.6.0_24
2012-05-04 21:03:33,041 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.ext.dirs: /usr/lib/jvm/java-6-openjdk/jre/lib/ext:/usr/java/packages/lib/ext
2012-05-04 21:03:33,041 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener sun.boot.class.path: /usr/lib/jvm/java-6-openjdk/jre/lib/resources.jar:/usr/lib/jvm/java-6-openjdk/jre/lib/rt.jar:/usr/lib/jvm/java-6-openjdk/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-6-openjdk/jre/lib/jsse.jar:/usr/lib/jvm/java-6-openjdk/jre/lib/jce.jar:/usr/lib/jvm/java-6-openjdk/jre/lib/charsets.jar:/usr/lib/jvm/java-6-openjdk/jre/lib/netx.jar:/usr/lib/jvm/java-6-openjdk/jre/lib/plugin.jar:/usr/lib/jvm/java-6-openjdk/jre/lib/rhino.jar:/usr/lib/jvm/java-6-openjdk/jre/lib/modules/jdk.boot.jar:/usr/lib/jvm/java-6-openjdk/jre/classes
2012-05-04 21:03:33,041 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener server.loader: 
2012-05-04 21:03:33,041 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.vendor: Sun Microsystems Inc.
2012-05-04 21:03:33,041 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener catalina.base: /home/picodotdev/archivos/apache-tomcat-7.0.27
2012-05-04 21:03:33,041 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener file.separator: /
2012-05-04 21:03:33,041 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java.vendor.url.bug: http://java.sun.com/cgi-bin/bugreport.cgi
2012-05-04 21:03:33,041 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener common.loader: ${catalina.base}/lib,${catalina.base}/lib/*.jar,${catalina.home}/lib,${catalina.home}/lib/*.jar
2012-05-04 21:03:33,041 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener sun.io.unicode.encoding: UnicodeLittle
2012-05-04 21:03:33,041 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener sun.cpu.endian: little
2012-05-04 21:03:33,041 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener package.access: sun.,org.apache.catalina.,org.apache.coyote.,org.apache.tomcat.,org.apache.jasper.
2012-05-04 21:03:33,041 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener sun.desktop: gnome
2012-05-04 21:03:33,041 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener sun.cpu.isalist: 
2012-05-04 21:03:33,041 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener Propiedades del entorno:
2012-05-04 21:03:33,042 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener Server info: Apache Tomcat/7.0.27
2012-05-04 21:03:33,042 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener Java Servlet API version: 3.0
2012-05-04 21:03:33,107 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener Propiedades de entorno para la aplicacion web:
2012-05-04 21:03:33,107 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java:/comp/env/com: org.apache.naming.NamingContext@49b9ef36
2012-05-04 21:03:33,108 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java:/comp/env/com/censurado: org.apache.naming.NamingContext@4e07e80a
2012-05-04 21:03:33,108 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java:/comp/env/com/censurado/mail: org.apache.naming.NamingContext@6913108b
2012-05-04 21:03:33,108 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java:/comp/env/com/censurado/mail/censurado: javax.mail.Session@62a34b91
2012-05-04 21:03:33,108 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java:/comp/env/com/censurado/jdbc: org.apache.naming.NamingContext@4eb64f2e
2012-05-04 21:03:33,108 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener java:/comp/env/com/censurado/jdbc/censurado: org.apache.tomcat.dbcp.dbcp.BasicDataSource@23087d61
2012-05-04 21:03:33,108 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener Propiedades dinámicas:
2012-05-04 21:03:33,108 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener dinamica.servidor: TOMCAT
2012-05-04 21:03:33,108 INFO                                        es.com.blogspot.elblogdepicodev.misc.ContextListener Iniciando aplicacion con la configuracion del entorno de «desarrollo»

La siguiente clase HttpSessionListener es muy básica pero nos puede permitir conocer si en algún momento se están creando muchas sesiones de usuario y podríamos acceder a más información a través de la interfaz HttpSession que podemos obtener del objeto HttpSessionEvent que recibimos en el listener.

package es.com.blogspot.elblogdepicodev.misc;

import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Clase que recibe los eventos de creación y destrucción de las sesiones de los
 * usuarios.
 */
public class SessionListener implements HttpSessionListener {

 private static Logger logger = LoggerFactory.getLogger(SessionListener.class);

 @Override
 public void sessionCreated(HttpSessionEvent se) {
  logger.info("Sesion creada");
 }

 @Override
 public void sessionDestroyed(HttpSessionEvent se) {
  logger.info("Sesion destruida");
 }
}

Referencia:
[1] Librerías de logging para Java (slf4j, log4j, java.util.logging, logback, MentaLog)-slf4j.html
Configuración de entorno en Java con ayuda de Groovy