Author: gsingers
Date: Thu Apr 17 05:37:38 2008
New Revision: 649066

URL: http://svn.apache.org/viewvc?rev=649066&view=rev
Log:
SOLR-267: Logging updates, now logs how many hits, plus some other logging 
changes to reduce double logging

Modified:
    lucene/solr/trunk/CHANGES.txt
    lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java
    
lucene/solr/trunk/src/java/org/apache/solr/handler/component/QueryComponent.java
    lucene/solr/trunk/src/java/org/apache/solr/request/SolrQueryResponse.java
    lucene/solr/trunk/src/test/org/apache/solr/request/JSONWriterTest.java
    
lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java

Modified: lucene/solr/trunk/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/lucene/solr/trunk/CHANGES.txt?rev=649066&r1=649065&r2=649066&view=diff
==============================================================================
--- lucene/solr/trunk/CHANGES.txt (original)
+++ lucene/solr/trunk/CHANGES.txt Thu Apr 17 05:37:38 2008
@@ -355,8 +355,11 @@
     when no RequestHandler is mapped to "/update") now logs error correctly.
     (hossman)
 
-26. SOLR-509: Moved firstSearcher event notification to the end of the 
SolrCore constructor (Koji Sekiguchi via gsingers)
-    
+27. SOLR-267: Changed logging to report number of hits, and also provide a 
mechanism to add log messages to be output by the SolrCore via a NamedList toLog
+    member variable.  (Will Johnson, yseeley, gsingers)
+
+28. SOLR-509: Moved firstSearcher event notification to the end of the 
SolrCore constructor (Koji Sekiguchi via gsingers)
+
 Other Changes
  1. SOLR-135: Moved common classes to org.apache.solr.common and altered the
     build scripts to make two jars: apache-solr-1.3.jar and 

Modified: lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java
URL: 
http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java?rev=649066&r1=649065&r2=649066&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/core/SolrCore.java Thu Apr 17 
05:37:38 2008
@@ -128,7 +128,7 @@
   
   /**
    * Gets the configuration resource name used by this core instance.
-   * @see getConfigResource
+   * @see #getConfigResource()
    */
   @Deprecated
   public String getConfigFile() {
@@ -151,7 +151,7 @@
 
   /**
    * Gets the schema resource name used by this core instance.
-   * @see getSchemaResource
+   * @see #getSchemaResource() 
    */
   @Deprecated
   public String getSchemaFile() {
@@ -396,7 +396,7 @@
       // Finally tell anyone who wants to know
       loader.inform( loader );
       loader.inform( this );
-      
+
       // execute firstSearcher event
       //TODO: It may not always be the case that this is the only time the 
first searcher event needs to fire.
       doFirstSearcherEvent(getSearcher().get());
@@ -498,7 +498,7 @@
    * Returns a Request object based on the admin/pingQuery section
    * of the Solr config file.
    * 
-   * @use [EMAIL PROTECTED] PingRequestHandler} instead 
+   * @use [EMAIL PROTECTED] org.apache.solr.handler.PingRequestHandler} instead
    */
   @Deprecated
   public SolrQueryRequest getPingQueryRequest() {
@@ -948,12 +948,23 @@
     // setup response header and handle request
     final NamedList<Object> responseHeader = new SimpleOrderedMap<Object>();
     rsp.add("responseHeader", responseHeader);
+    NamedList toLog = rsp.getToLog();
+    //toLog.add("core", getName());
+    toLog.add("webapp", req.getContext().get("webapp"));
+    toLog.add("path", req.getContext().get("path"));
+    toLog.add("params", "{" + req.getParamString() + "}");
     handler.handleRequest(req,rsp);
-    setResponseHeaderValues(handler,responseHeader,req,rsp);
-
-    log.info(logid+"" + req.getContext().get("path") + " "
+    setResponseHeaderValues(handler,req,rsp);
+    StringBuilder sb = new StringBuilder();
+    for (int i=0; i<toLog.size(); i++) {
+       String name = toLog.getName(i);
+       Object val = toLog.getVal(i);
+       sb.append(name).append("=").append(val).append(" ");
+    }
+    log.info(logid +  sb.toString());
+    /*log.info(logid+"" + req.getContext().get("path") + " "
             + req.getParamString()+ " 0 "+
-       (int)(rsp.getEndTime() - req.getStartTime()));
+       (int)(rsp.getEndTime() - req.getStartTime()));*/
   }
 
   @Deprecated
@@ -966,13 +977,15 @@
     execute(handler, req, rsp);
   }
   
-  protected void setResponseHeaderValues(SolrRequestHandler handler, 
NamedList<Object> responseHeader,SolrQueryRequest req, SolrQueryResponse rsp) {
+  protected void setResponseHeaderValues(SolrRequestHandler handler, 
SolrQueryRequest req, SolrQueryResponse rsp) {
     // TODO should check that responseHeader has not been replaced by handler
-    
+       NamedList responseHeader = rsp.getResponseHeader();
     final int qtime=(int)(rsp.getEndTime() - req.getStartTime());
     responseHeader.add("status",rsp.getException()==null ? 0 : 500);
     responseHeader.add("QTime",qtime);
-        
+    rsp.getToLog().add("status",rsp.getException()==null ? 0 : 500);
+    rsp.getToLog().add("QTime",qtime);
+    
     SolrParams params = req.getParams();
     if( params.getBool(CommonParams.HEADER_ECHO_HANDLER, false) ) {
       responseHeader.add("handler", handler.getName() );

Modified: 
lucene/solr/trunk/src/java/org/apache/solr/handler/component/QueryComponent.java
URL: 
http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/handler/component/QueryComponent.java?rev=649066&r1=649065&r2=649066&view=diff
==============================================================================
--- 
lucene/solr/trunk/src/java/org/apache/solr/handler/component/QueryComponent.java
 (original)
+++ 
lucene/solr/trunk/src/java/org/apache/solr/handler/component/QueryComponent.java
 Thu Apr 17 05:37:38 2008
@@ -165,7 +165,7 @@
     }
 
     rsp.add("response",rb.getResults().docList);
-
+    rsp.getToLog().add("hits", rb.getResults().docList.size());
 
     boolean fsv = 
req.getParams().getBool(ResponseBuilder.FIELD_SORT_VALUES,false);
     if(fsv){

Modified: 
lucene/solr/trunk/src/java/org/apache/solr/request/SolrQueryResponse.java
URL: 
http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/request/SolrQueryResponse.java?rev=649066&r1=649065&r2=649066&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/request/SolrQueryResponse.java 
(original)
+++ lucene/solr/trunk/src/java/org/apache/solr/request/SolrQueryResponse.java 
Thu Apr 17 05:37:38 2008
@@ -60,7 +60,12 @@
    * @see #setAllValues
    * @see <a href="#returnable_data">Note on Returnable Data</a>
    */
-  protected  NamedList values = new SimpleOrderedMap();
+  protected NamedList values = new SimpleOrderedMap();
+
+  /**
+   * Container for storing information that should be logged by Solr before 
returning.
+   */
+  protected NamedList toLog = new SimpleOrderedMap();
 
   protected Set<String> defaultReturnFields;
 
@@ -73,6 +78,11 @@
   String errMsg;
   ***/
 
+  public SolrQueryResponse() {
+         add("responseHeader", new SimpleOrderedMap<Object>());
+  }
+  
+  
   /**
    * Gets data to be returned in this response
    * @see <a href="#returnable_data">Note on Returnable Data</a>
@@ -167,6 +177,28 @@
     }
     return this.endtime;
   }
-
-
+  
+  /** Repsonse header to be logged */ 
+  public NamedList getResponseHeader() {
+         SimpleOrderedMap<Object> header = (SimpleOrderedMap<Object>) 
values.get("responseHeader");
+         return header;
+  }
+  
+  /** Add a value to be logged.
+   * 
+   * @param name name of the thing to log
+   * @param val value of the thing to log
+   */
+  public void addToLog(String name, Object val) {
+         toLog.add(name, val);
+  }
+  
+  /** Get loggable items.
+   * 
+   * @return things to log
+   */
+  public NamedList getToLog() {
+         return toLog;
+  }
+    
 }

Modified: lucene/solr/trunk/src/test/org/apache/solr/request/JSONWriterTest.java
URL: 
http://svn.apache.org/viewvc/lucene/solr/trunk/src/test/org/apache/solr/request/JSONWriterTest.java?rev=649066&r1=649065&r2=649066&view=diff
==============================================================================
--- lucene/solr/trunk/src/test/org/apache/solr/request/JSONWriterTest.java 
(original)
+++ lucene/solr/trunk/src/test/org/apache/solr/request/JSONWriterTest.java Thu 
Apr 17 05:37:38 2008
@@ -42,12 +42,12 @@
     rsp.add("data2", Double.NEGATIVE_INFINITY);
     rsp.add("data3", Float.POSITIVE_INFINITY);
     w.write(buf, req, rsp);
-    assertEquals(buf.toString(), 
"{'data1':float('NaN'),'data2':-float('Inf'),'data3':float('Inf')}");
+    assertEquals(buf.toString(), 
"{'responseHeader':{},'data1':float('NaN'),'data2':-float('Inf'),'data3':float('Inf')}");
 
     w = new RubyResponseWriter();
     buf = new StringWriter();
     w.write(buf, req, rsp);
-    assertEquals(buf.toString(), 
"{'data1'=>(0.0/0.0),'data2'=>-(1.0/0.0),'data3'=>(1.0/0.0)}");
+    assertEquals(buf.toString(), 
"{'responseHeader'=>{},'data1'=>(0.0/0.0),'data2'=>-(1.0/0.0),'data3'=>(1.0/0.0)}");
 
   }
   

Modified: 
lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java
URL: 
http://svn.apache.org/viewvc/lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java?rev=649066&r1=649065&r2=649066&view=diff
==============================================================================
--- 
lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java
 (original)
+++ 
lucene/solr/trunk/src/webapp/src/org/apache/solr/servlet/SolrDispatchFilter.java
 Thu Apr 17 05:37:38 2008
@@ -35,6 +35,7 @@
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.solr.common.SolrException;
+import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.core.MultiCore;
 import org.apache.solr.core.SolrConfig;
@@ -46,21 +47,21 @@
 
 /**
  * This filter looks at the incoming URL maps them to handlers defined in 
solrconfig.xml
- * 
+ *
  * @since solr 1.2
  */
-public class SolrDispatchFilter implements Filter 
+public class SolrDispatchFilter implements Filter
 {
   final Logger log = Logger.getLogger(SolrDispatchFilter.class.getName());
-  
+
   protected SolrCore singlecore;
   protected MultiCore multicore;
   protected String pathPrefix = null; // strip this from the beginning of a 
path
   protected String abortErrorMessage = null;
   protected final WeakHashMap<SolrCore, SolrRequestParsers> parsers = new 
WeakHashMap<SolrCore, SolrRequestParsers>();
   protected String solrConfigFilename = null;
-  
-  public void init(FilterConfig config) throws ServletException 
+
+  public void init(FilterConfig config) throws ServletException
   {
     log.info("SolrDispatchFilter.init()");
 
@@ -69,10 +70,10 @@
       // web.xml configuration
       this.pathPrefix = config.getInitParameter( "path-prefix" );
       this.solrConfigFilename = config.getInitParameter("solrconfig-filename");
-      
+
       // multicore instantiation
       this.multicore = initMultiCore(config);
-      
+
       if(multicore != null && multicore.isEnabled() ) {
         abortOnConfigurationError = false;
         singlecore = null;
@@ -98,7 +99,7 @@
       SolrConfig.severeErrors.add( t );
       SolrCore.log( t );
     }
-    
+
     // Optionally abort if we found a sever error
     if( abortOnConfigurationError && SolrConfig.severeErrors.size() > 0 ) {
       StringWriter sw = new StringWriter();
@@ -112,13 +113,13 @@
       } else {
         out.println( "in solrconfig.xml\n" );
       }
-      
+
       for( Throwable t : SolrConfig.severeErrors ) {
         out.println( 
"-------------------------------------------------------------" );
         t.printStackTrace( out );
       }
       out.flush();
-      
+
       // Servlet containers behave slightly differently if you throw an 
exception during 
       // initialization.  Resin will display that error for every page, jetty 
prints it in
       // the logs, but continues normally.  (We will see a 404 rather then the 
real error)
@@ -127,7 +128,7 @@
       abortErrorMessage = sw.toString();
       //throw new ServletException( abortErrorMessage );
     }
-    
+
     log.info("SolrDispatchFilter.init() done");
   }
 
@@ -159,13 +160,13 @@
       singlecore = null;
     }
   }
-  
+
   public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain chain) throws IOException, ServletException {
     if( abortErrorMessage != null ) {
       ((HttpServletResponse)response).sendError( 500, abortErrorMessage );
       return;
     }
-    
+
     if( request instanceof HttpServletRequest) {
       HttpServletRequest req = (HttpServletRequest)request;
       HttpServletResponse resp = (HttpServletResponse)response;
@@ -173,26 +174,26 @@
       SolrQueryRequest solrReq = null;
 
       try {
-        String path = req.getServletPath();    
+        String path = req.getServletPath();
         if( req.getPathInfo() != null ) {
           // this lets you handle /update/commit when /update is a servlet
-          path += req.getPathInfo(); 
+          path += req.getPathInfo();
         }
         if( pathPrefix != null && path.startsWith( pathPrefix ) ) {
           path = path.substring( pathPrefix.length() );
         }
-        
+
         int idx = path.indexOf( ':' );
         if( idx > 0 ) {
           // save the portion after the ':' for a 'handler' path parameter
           path = path.substring( 0, idx );
         }
-        
+
         // By default use the single core.  If multicore is enabled, look for 
one.
         final SolrCore core;
         if (multicore != null && multicore.isEnabled()) {
           req.setAttribute("org.apache.solr.MultiCore", multicore);
-          
+
           // if this is the multi-core admin page, it will handle it
           if( path.equals( multicore.getAdminPath() ) ) {
             handler = multicore.getMultiCoreHandler();
@@ -217,7 +218,7 @@
         else {
           core = singlecore;
         }
-        
+
         // With a valid core...
         if( core != null ) {
           final SolrConfig config = core.getSolrConfig();
@@ -228,7 +229,7 @@
             parser = new SolrRequestParsers(config);
             parsers.put( core, parser );
           }
-          
+
           // Determine the handler from the url path if not set
           // (we might already have selected the multicore handler)
           if( handler == null && path.length() > 1 ) { // don't match "" or 
"/" as valid path
@@ -244,18 +245,18 @@
                 handler = core.getRequestHandler( qt );
                 if( handler == null ) {
                   throw new SolrException( 
SolrException.ErrorCode.BAD_REQUEST, "unknown handler: "+qt);
-                }      
+                }
               }
             }
           }
-          
+
             // With a valid handler and a valid core...
-          if( handler != null ) {          
+          if( handler != null ) {
             // if not a /select, create the request
             if( solrReq == null ) {
               solrReq = parser.parse( core, path, req );
             }
-            
+
             final Method reqMethod = Method.getMethod(req.getMethod());
             if (Method.POST != reqMethod) {
               HttpCacheHeaderUtil.setCacheControlHeader(config, resp);
@@ -266,11 +267,20 @@
                 !HttpCacheHeaderUtil.doCacheHeaderValidation(solrReq, req, 
resp)) {
                 SolrQueryResponse solrRsp = new SolrQueryResponse();
                 /* even for HEAD requests, we need to execute the handler to
-                 * ensure we don't get an error (and to make sure the correct 
+                 * ensure we don't get an error (and to make sure the correct
                  * QueryResponseWriter is selectedand we get the correct
                  * Content-Type)
                  */
                 this.execute( req, handler, solrReq, solrRsp );
+              // add info to http headers
+                try {
+                  NamedList solrRspHeader = solrRsp.getResponseHeader();
+                 for (int i=0; i<solrRspHeader.size(); i++) {
+                   ((javax.servlet.http.HttpServletResponse) 
response).addHeader(("Solr-" + solrRspHeader.getName(i)), 
String.valueOf(solrRspHeader.getVal(i)));
+                 }
+                } catch (ClassCastException cce) {
+                  log.log(Level.WARNING, "exception adding response header log 
information", cce);
+                }
                 if( solrRsp.getException() != null ) {
                   sendError( (HttpServletResponse)response, 
solrRsp.getException() );
                 }
@@ -301,7 +311,7 @@
             // Modify the request so each core gets its own /admin
             if( singlecore == null && path.startsWith( "/admin" ) ) {
               req.getRequestDispatcher( pathPrefix == null ? path : pathPrefix 
+ path ).forward( request, response );
-              return; 
+              return;
             }
           }
         }
@@ -315,7 +325,7 @@
         }
       }
     }
-    
+
     // Otherwise let the webapp handle the request
     chain.doFilter(request, response);
   }
@@ -323,24 +333,26 @@
   protected void execute( HttpServletRequest req, SolrRequestHandler handler, 
SolrQueryRequest sreq, SolrQueryResponse rsp) {
     // a custom filter could add more stuff to the request before passing it 
on.
     // for example: sreq.getContext().put( "HttpServletRequest", req );
+    // used for logging query stats in SolrCore.execute()
+    sreq.getContext().put( "webapp", req.getContextPath() );
     sreq.getCore().execute( handler, sreq, rsp );
   }
-  
+
   protected void sendError(HttpServletResponse res, Throwable ex) throws 
IOException {
     int code=500;
     String trace = "";
     if( ex instanceof SolrException ) {
       code = ((SolrException)ex).code();
     }
-    
+
     // For any regular code, don't include the stack trace
-    if( code == 500 || code < 100 ) {  
+    if( code == 500 || code < 100 ) {
       StringWriter sw = new StringWriter();
       ex.printStackTrace(new PrintWriter(sw));
       trace = "\n\n"+sw.toString();
-      
+
       SolrException.logOnce(log,null,ex );
-      
+
       // non standard codes have undefined results with various servers
       if( code < 100 ) {
         log.warning( "invalid return code: "+code );
@@ -348,7 +360,7 @@
       }
     }
     res.sendError( code, ex.getMessage() + trace );
-  }    
+  }
 
   //---------------------------------------------------------------------
   //---------------------------------------------------------------------
@@ -357,22 +369,22 @@
    * Set the prefix for all paths.  This is useful if you want to apply the
    * filter to something other then /*, perhaps because you are merging this
    * filter into a larger web application.
-   * 
+   *
    * For example, if web.xml specifies:
-   * 
+   *
    * <filter-mapping>
    *  <filter-name>SolrRequestFilter</filter-name>
    *  <url-pattern>/xxx/*</url-pattern>
    * </filter-mapping>
-   * 
+   *
    * Make sure to set the PathPrefix to "/xxx" either with this function
    * or in web.xml.
-   * 
+   *
    * <init-param>
    *  <param-name>path-prefix</param-name>
    *  <param-value>/xxx</param-value>
    * </init-param>
-   * 
+   *
    */
   public void setPathPrefix(String pathPrefix) {
     this.pathPrefix = pathPrefix;


Reply via email to