You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ch...@apache.org on 2016/02/10 10:59:40 UTC

svn commit: r1729569 - in /sling/trunk/contrib/extensions/tracer/src: main/java/org/apache/sling/tracer/internal/ test/java/org/apache/sling/tracer/internal/

Author: chetanm
Date: Wed Feb 10 09:59:39 2016
New Revision: 1729569

URL: http://svn.apache.org/viewvc?rev=1729569&view=rev
Log:
SLING-5504 - Reduce memory footprint of stored recording data

Support sending of gzip response if the client supports that. This would avoid deflating the in memory compressed json data

Modified:
    sling/trunk/contrib/extensions/tracer/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
    sling/trunk/contrib/extensions/tracer/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
    sling/trunk/contrib/extensions/tracer/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
    sling/trunk/contrib/extensions/tracer/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
    sling/trunk/contrib/extensions/tracer/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java

Modified: sling/trunk/contrib/extensions/tracer/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/tracer/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java?rev=1729569&r1=1729568&r2=1729569&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/tracer/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java (original)
+++ sling/trunk/contrib/extensions/tracer/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java Wed Feb 10 09:59:39 2016
@@ -51,6 +51,8 @@ import org.slf4j.LoggerFactory;
 import org.slf4j.helpers.FormattingTuple;
 import org.slf4j.helpers.MessageFormatter;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 class JSONRecording implements Recording, Comparable<JSONRecording> {
     private static final Logger log = LoggerFactory.getLogger(JSONRecording.class);
     private final String method;
@@ -73,16 +75,16 @@ class JSONRecording implements Recording
 
     public boolean render(Writer w) throws IOException {
         if (json != null) {
-            Reader r = new InputStreamReader(getInputStream(), "UTF-8");
+            Reader r = new InputStreamReader(getInputStream(false), "UTF-8");
             IOUtils.copy(r, w);
             return true;
         }
         return false;
     }
 
-    public boolean render(OutputStream os) throws IOException {
+    public boolean render(OutputStream os, boolean compressed) throws IOException {
         if (json != null) {
-            IOUtils.copyLarge(getInputStream(), os);
+            IOUtils.copyLarge(getInputStream(compressed), os);
             return true;
         }
         return false;
@@ -200,8 +202,14 @@ class JSONRecording implements Recording
         jw.endArray();
     }
 
-    private InputStream getInputStream() throws IOException {
+    private InputStream getInputStream(boolean compressed) throws IOException {
         InputStream is = new ByteArrayInputStream(json);
+
+        if (compressed) {
+            checkArgument(compress, "Cannot provide compressed response with compression disabled");
+            return is;
+        }
+
         if (compress) {
             is = new GZIPInputStream(is);
         }

Modified: sling/trunk/contrib/extensions/tracer/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/tracer/src/main/java/org/apache/sling/tracer/internal/LogTracer.java?rev=1729569&r1=1729568&r2=1729569&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/tracer/src/main/java/org/apache/sling/tracer/internal/LogTracer.java (original)
+++ sling/trunk/contrib/extensions/tracer/src/main/java/org/apache/sling/tracer/internal/LogTracer.java Wed Feb 10 09:59:39 2016
@@ -138,6 +138,13 @@ public class LogTracer {
     )
     private static final String PROP_TRACER_SERVLET_COMPRESS = "recordingCompressionEnabled";
 
+    static final boolean PROP_TRACER_SERVLET_GZIP_RESPONSE_DEFAULT = true;
+    @Property(label = "GZip Response",
+            description = "If enabled the response sent would be compressed",
+            boolValue = PROP_TRACER_SERVLET_GZIP_RESPONSE_DEFAULT
+    )
+    private static final String PROP_TRACER_SERVLET_GZIP_RESPONSE = "gzipResponse";
+
     private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(LogTracer.class);
 
     private final Map<String, TracerSet> tracers = new HashMap<String, TracerSet>();
@@ -177,10 +184,13 @@ public class LogTracer {
                         PROP_TRACER_SERVLET_CACHE_DURATION_DEFAULT);
                 boolean compressionEnabled = PropertiesUtil.toBoolean(config.get(PROP_TRACER_SERVLET_COMPRESS),
                         PROP_TRACER_SERVLET_COMPRESS_DEFAULT);
-                this.logServlet = new TracerLogServlet(context, cacheSize, cacheDuration, compressionEnabled);
+                boolean gzipResponse = PropertiesUtil.toBoolean(config.get(PROP_TRACER_SERVLET_GZIP_RESPONSE),
+                        PROP_TRACER_SERVLET_GZIP_RESPONSE_DEFAULT);
+
+                this.logServlet = new TracerLogServlet(context, cacheSize, cacheDuration, compressionEnabled, gzipResponse);
                 recorder = logServlet;
-                LOG.info("Tracer recoding enabled with cacheSize {} MB, expiry {} secs, compression {}",
-                        cacheSize, cacheDuration, compressionEnabled);
+                LOG.info("Tracer recoding enabled with cacheSize {} MB, expiry {} secs, compression {}, gzip response {}",
+                        cacheSize, cacheDuration, compressionEnabled, gzipResponse);
             }
             LOG.info("Log tracer enabled. Required filters registered. Tracer servlet enabled {}", servletEnabled);
         }

Modified: sling/trunk/contrib/extensions/tracer/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/tracer/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java?rev=1729569&r1=1729568&r2=1729569&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/tracer/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java (original)
+++ sling/trunk/contrib/extensions/tracer/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java Wed Feb 10 09:59:39 2016
@@ -66,19 +66,24 @@ class TracerLogServlet extends SimpleWeb
 
     private final long cacheDurationInSecs;
 
+    private final boolean gzipResponse;
+
     public TracerLogServlet(BundleContext context){
         this(context,
                 LogTracer.PROP_TRACER_SERVLET_CACHE_SIZE_DEFAULT,
                 LogTracer.PROP_TRACER_SERVLET_CACHE_DURATION_DEFAULT,
-                LogTracer.PROP_TRACER_SERVLET_COMPRESS_DEFAULT
+                LogTracer.PROP_TRACER_SERVLET_COMPRESS_DEFAULT,
+                LogTracer.PROP_TRACER_SERVLET_GZIP_RESPONSE_DEFAULT
         );
     }
 
-    public TracerLogServlet(BundleContext context, int cacheSizeInMB, long cacheDurationInSecs, boolean compressionEnabled) {
+    public TracerLogServlet(BundleContext context, int cacheSizeInMB, long cacheDurationInSecs,
+                            boolean compressionEnabled, boolean gzipResponse) {
         super(LABEL, "Sling Tracer", "Sling", null);
         this.compressRecording = compressionEnabled;
         this.cacheDurationInSecs = cacheDurationInSecs;
         this.cacheSizeInMB = cacheSizeInMB;
+        this.gzipResponse = compressionEnabled && gzipResponse;
         this.cache = CacheBuilder.newBuilder()
                 .maximumWeight(cacheSizeInMB * FileUtils.ONE_MB)
                 .weigher(new Weigher<String, JSONRecording>() {
@@ -97,6 +102,10 @@ class TracerLogServlet extends SimpleWeb
         return compressRecording;
     }
 
+    public boolean isGzipResponse() {
+        return gzipResponse;
+    }
+
     int getCacheSizeInMB() {
         return cacheSizeInMB;
     }
@@ -121,7 +130,8 @@ class TracerLogServlet extends SimpleWeb
                 if (requestId != null) {
                     JSONRecording recording = cache.getIfPresent(requestId);
                     if (recording != null){
-                        responseDone = recording.render(response.getOutputStream());
+                        boolean shouldGZip = prepareForGZipResponse(request, response);
+                        responseDone = recording.render(response.getOutputStream(), shouldGZip);
                     }
                 }
 
@@ -152,6 +162,30 @@ class TracerLogServlet extends SimpleWeb
         return request.getRequestURI().endsWith(LABEL);
     }
 
+    private boolean prepareForGZipResponse(HttpServletRequest request, HttpServletResponse response) {
+        if (!gzipResponse) {
+            return false;
+        }
+
+        String acceptEncoding = request.getHeader("Accept-Encoding");
+        boolean acceptsGzip = acceptEncoding != null && accepts(acceptEncoding, "gzip");
+
+        if (acceptsGzip) {
+            response.setHeader("Content-Encoding", "gzip");
+        }
+        return acceptsGzip;
+    }
+
+    /**
+     * Returns true if the given accept header accepts the given value.
+     * @param acceptHeader The accept header.
+     * @param toAccept The value to be accepted.
+     * @return True if the given accept header accepts the given value.
+     */
+    private static boolean accepts(String acceptHeader, String toAccept) {
+        return acceptHeader.contains(toAccept) || acceptHeader.contains("*/*");
+    }
+
     private static void prepareJSONResponse(HttpServletResponse response) {
         response.setContentType("application/json");
         response.setCharacterEncoding("UTF-8");

Modified: sling/trunk/contrib/extensions/tracer/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/tracer/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java?rev=1729569&r1=1729568&r2=1729569&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/tracer/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java (original)
+++ sling/trunk/contrib/extensions/tracer/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java Wed Feb 10 09:59:39 2016
@@ -123,22 +123,43 @@ public class LogTracerTest {
     @Test
     public void enableTracerLogServletWithConfig() throws Exception {
         LogTracer tracer = context.registerInjectActivateService(new LogTracer(),
-                ImmutableMap.<String, Object>of(
-                        "enabled", "true",
-                        "servletEnabled", "true",
-                        "recordingCacheSizeInMB", "17",
-                        "recordingCacheDurationInSecs", "100",
-                        "recordingCompressionEnabled", "false"
-                ));
+                ImmutableMap.<String, Object>builder()
+                        .put("enabled", "true")
+                        .put("servletEnabled", "true")
+                        .put("recordingCacheSizeInMB", "17")
+                        .put("recordingCacheDurationInSecs", "100")
+                        .put("recordingCompressionEnabled", "false")
+                        .put("gzipResponse", "true")
+                        .build()
+                );
         assertEquals(2, context.getServices(Filter.class, null).length);
         assertNotNull(context.getService(Servlet.class));
 
         TracerLogServlet logServlet = (TracerLogServlet) context.getService(Servlet.class);
         assertEquals(false, logServlet.isCompressRecording());
+        assertEquals(false, logServlet.isGzipResponse());
         assertEquals(17, logServlet.getCacheSizeInMB());
         assertEquals(100, logServlet.getCacheDurationInSecs());
     }
 
+    @Test
+    public void enableTracerLogServletWithConfigGzip() throws Exception {
+        LogTracer tracer = context.registerInjectActivateService(new LogTracer(),
+                ImmutableMap.<String, Object>builder()
+                        .put("enabled", "true")
+                        .put("servletEnabled", "true")
+                        .put("recordingCompressionEnabled", "true")
+                        .put("gzipResponse", "true")
+                        .build()
+        );
+        assertEquals(2, context.getServices(Filter.class, null).length);
+        assertNotNull(context.getService(Servlet.class));
+
+        TracerLogServlet logServlet = (TracerLogServlet) context.getService(Servlet.class);
+        assertEquals(true, logServlet.isCompressRecording());
+        assertEquals(true, logServlet.isGzipResponse());
+    }
+
 
     @Test
     public void noTurboFilterRegisteredUnlessTracingRequested() throws Exception {

Modified: sling/trunk/contrib/extensions/tracer/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/tracer/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java?rev=1729569&r1=1729568&r2=1729569&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/tracer/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java (original)
+++ sling/trunk/contrib/extensions/tracer/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java Wed Feb 10 09:59:39 2016
@@ -19,16 +19,19 @@
 
 package org.apache.sling.tracer.internal;
 
+import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.util.zip.GZIPInputStream;
 
 import javax.annotation.Nonnull;
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.commons.io.IOUtils;
 import org.apache.sling.commons.json.JSONObject;
 import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
 import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletRequest;
@@ -117,6 +120,35 @@ public class TracerLogServletTest {
     }
 
     @Test
+    public void gzipResponse() throws Exception{
+        TracerLogServlet logServlet = new TracerLogServlet(context.bundleContext());
+        when(request.getMethod()).thenReturn("GET");
+        when(request.getHeader(TracerLogServlet.HEADER_TRACER_RECORDING)).thenReturn("true");
+        when(request.getHeader("Accept-Encoding")).thenReturn("gzip, deflate");
+
+        Recording recording = logServlet.startRecording(request, response);
+        recording.registerTracker(createTracker("x" ,"y"));
+        logServlet.endRecording(request, recording);
+
+        ArgumentCaptor<String> requestIdCaptor = ArgumentCaptor.forClass(String.class);
+        verify(response).setHeader(eq(TracerLogServlet.HEADER_TRACER_REQUEST_ID), requestIdCaptor.capture());
+        verify(response).setHeader(TracerLogServlet.HEADER_TRACER_PROTOCOL_VERSION,
+                String.valueOf(TracerLogServlet.TRACER_PROTOCOL_VERSION));
+
+        ByteArrayServletOutputStream sos = new ByteArrayServletOutputStream();
+        when(response.getOutputStream()).thenReturn(sos);
+        when(request.getRequestURI()).thenReturn("/system/console/" + requestIdCaptor.getValue() + ".json" );
+
+        logServlet.renderContent(request, response);
+        byte[] data = IOUtils.toByteArray(new GZIPInputStream(new ByteArrayInputStream(sos.baos.toByteArray())));
+        JSONObject json = new JSONObject(new String(data, "UTF-8"));
+        assertEquals("GET", json.getString("method"));
+        assertEquals(2, json.getJSONArray("requestProgressLogs").length());
+
+        verify(response).setHeader("Content-Encoding" , "gzip");
+    }
+
+    @Test
     public void pluginRendering() throws Exception{
         TracerLogServlet logServlet = new TracerLogServlet(context.bundleContext());
         when(request.getRequestURI()).thenReturn("/system/console/tracer" );