2 Replies Latest reply on Jan 12, 2010 5:28 PM by Dean Hiller

    phenomenal logging to help others....

    Dean Hiller Expert

      Our logs log the [session][username] if username exists(ie. user is logged in) on every log even the hibernate logs and log4jdbc logs and all third party logs AND most importantly on the exceptions in the seam logs so you know which user ran into the issue(or which session).  This is the filter we use and I thought I would share...




      package net.voicelog.entities.actions;
      
      import java.io.IOException;
      
      import javax.servlet.Filter;
      import javax.servlet.FilterChain;
      import javax.servlet.FilterConfig;
      import javax.servlet.ServletException;
      import javax.servlet.ServletRequest;
      import javax.servlet.ServletResponse;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpSession;
      
      import net.voicelog.ata.logging.LogKeyThreadLocal;
      
      public class FilterForLogging implements Filter {
      
           @Override
           public void destroy() {
      
           }
      
           @Override
           public void doFilter(ServletRequest request, ServletResponse response,
                     FilterChain filter) throws IOException, ServletException {
                HttpServletRequest req = (HttpServletRequest) request;
                HttpSession session = req.getSession();
      
                //let's reduce the session to make the logs easier
                int hashCode = session.getId().hashCode();
                int result = hashCode / (Integer.MAX_VALUE / 1000);
                if(result < 0)
                     result = -result;
                String key = "[session:"+result+"]";
                if(session.getAttribute("user") != null) {
                     Object user = session.getAttribute("user");
                     key += user;
                }
                
                LogKeyThreadLocal.setLogKey(key);
                
                filter.doFilter(request, response);          
           }
      
           @Override
           public void init(FilterConfig arg0) throws ServletException {
      
           }
      
      }
      



      NOTE: LogKeyThreadLocal stores the key in a Threadlocal that you can either have a Appender in log4j or a handler in jdk logging to read that and prefix the log with it so you know which user the log is tied to.  This has been a HUGE help to us and it would be great if Seam added something like this as well and an appender and handler too that we could use and setup so everyone had this nice logging functionality.  We should have a recorder as well later that records pages and actions the user takes so you can reproduce the issue in production that occurred.
      later,
      Dean


        • 1. Re: phenomenal logging to help others....
          Mark Wigmans Newbie

          Par. 30.1.4.7. Identity Logging of the Seam 2.2.0 documentation describes identify logging. What does your filter does differently/better from the standard seam filter?

          • 2. Re: phenomenal logging to help others....
            Dean Hiller Expert

            thanks for the info.  Didn't know about that.  I tried it out so I could compare but could not get it to work at all :(.  My guess is seam is not using a ThreadLocal and not using an appender handler which you would have to do to get this one phenomenal feature....


            1. Every hibernate log, log4jdbc log is prepended with the user even though they are not using the seam logger!!!  This is critical as we can see which users ran exactly which sql when log4jdbc logs are on.  Please verify this since i cannot.


            2. exceptions are logged with the username as well(seam logger may do this, but I am not entirely sure since I could not get the seam logger to log any user info at all when I hooked it up).  Let me know by throwing a runtimeException in an action method, set method, get method and login(all 4 behave differently and seam has some bugs around those..I opened a ticket 3 months ago or so on it).


            Here is my latest version as it fixes some issues...



            public class FilterForLogging implements Filter {
            
                 @Override
                 public void destroy() {
            
                 }
            
                 @Override
                 public void doFilter(ServletRequest request, ServletResponse response,
                           FilterChain filter) throws IOException, ServletException {
                      HttpServletRequest req = (HttpServletRequest) request;
                      HttpSession session = req.getSession();
            
                      //let's reduce the session to make the logs easier..we are not too worried about rare conflicts since user id would be different anyways...
                      String id = session.getId();
                      String lastPart = id.substring(id.length()-6);
                      
                      String key = "[session:"+lastPart+"]";
                      if(session.getAttribute("user") != null) {
                           Object user = session.getAttribute("user");
                           key += user;
                      }
                      
                      LogKeyThreadLocal.setLogKey(key);
                      try {
                           filter.doFilter(request, response);          
                      } catch(RuntimeException e) {
                           //BIG NOTE: Since the log key is gone once we throw this exception,
                           //we need to add the key to the exception here...
                           throw new RuntimeException(key+"exception", e);
                      } catch(ServletException e) {
                           throw new ServletException(key+"exception2", e);
                      } catch(IOException e) {
                           throw new IOException(key+"excpeiton3", e);
                      } finally {
                           LogKeyThreadLocal.setLogKey(null);
                      }
                 }
            
                 @Override
                 public void init(FilterConfig arg0) throws ServletException {
            
                 }
            
            }
            


            ANY ideas why when I put the logger in it is not working.  I changed the .seam to .xhtml since my urls are all xhtml.
            thanks,
            Dean