You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 10:24:00 UTC

[sling-org-apache-sling-tracer] annotated tag org.apache.sling.tracer-1.0.0 created (now b0148dc)

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a change to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git.


      at b0148dc  (tag)
 tagging 2e41f0ab8d52ba40925af030c68e9a447d122b95 (commit)
      by Chetan Mehrotra
      on Tue Apr 19 10:07:24 2016 +0000

- Log -----------------------------------------------------------------
org.apache.sling.tracer-1.0.0
-----------------------------------------------------------------------

This annotated tag includes the following new commits:

     new 8e6b5d0  SLING-4739 - Log Tracer - To enable logs for specific category at specific level and only for specific request
     new 61822f4  SLING-4739 - Log Tracer - To enable logs for specific category at specific level and only for specific request
     new 6df4236  SLING-4739 - Log Tracer - To enable logs for specific category at specific level and only for specific request
     new 5532990  SLING-4739 - Log Tracer - To enable logs for specific category at specific level and only for specific request
     new f3c7f75  [maven-release-plugin] prepare release org.apache.sling.tracer-0.0.2
     new 2476c10  [maven-release-plugin] prepare for next development iteration
     new a1ede00  Contrib: remove superflous sling.java.version=6 as it's the default now
     new c0fa143  Add contrib/extensions/tracer to module list and bump the sling-parent version in tracer to latest
     new 83ba09f  SLING-5459 - Recording of tracer logs
     new eb0d0c0  SLING-5459 - Recording of tracer logs
     new e284239  SLING-5459 - Recording of tracer logs
     new 0f4f997  SLING-5459 - Recording of tracer logs
     new c5e3f32  SLING-5459 - Recording of tracer logs
     new de2f6e5  SLING-5459 - Recording of tracer logs
     new 9a4867d  SLING-5459 - Recording of tracer logs
     new 80bc148  SLING-5459 - Recording of tracer logs
     new 6a25a1d  SLING-5459 - Recording of tracer logs
     new bdc2fb6  SLING-5459 - Recording of tracer logs
     new 338f7fb  SLING-5459 - Recording of tracer logs
     new 0f98bb6  SLING-5504 - Reduce memory footprint of stored recording data
     new 9d3d4dc  SLING-5504 - Reduce memory footprint of stored recording data
     new 3ded49e  SLING-5504 - Reduce memory footprint of stored recording data
     new d4dc992  SLING-5504 - Reduce memory footprint of stored recording data
     new 96a80a7  SLING-5459 - Recording of tracer logs
     new 1a9ba7e  SLING-5504 - Reduce memory footprint of stored recording data
     new 7c657ac  SLING-5505 - Allow recording of caller stacktrace with the logs
     new cdfbb9d  SLING-5507 - Collect more details around query execution
     new 393c666  SLING-5507 - Collect more details around query execution
     new b62cf45  SLING-5507 - Collect more details around query execution
     new 02f853e  SLING-5505 - Allow recording of caller stacktrace with the logs
     new 7065d83  SLING-5505 - Allow recording of caller stacktrace with the logs
     new c6dad28  SLING-5459 - Recording of tracer logs
     new 88f3d3a  SLING-5507 - Collect more details around query execution
     new 15a3ae3  [maven-release-plugin] prepare release org.apache.sling.tracer-1.0.0
     new 2e41f0a  [maven-release-plugin] copy for tag org.apache.sling.tracer-1.0.0

The 35 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


-- 
To stop receiving notification emails like this one, please contact
['"commits@sling.apache.org" <co...@sling.apache.org>'].

[sling-org-apache-sling-tracer] 23/30: SLING-5507 - Collect more details around query execution

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 393c6662b64358b541f51202fb96d0e49cfe9d3f
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Thu Feb 11 04:05:55 2016 +0000

    SLING-5507 - Collect more details around query execution
    
    Simplify the logic for determining the caller
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729759 13f79535-47bb-0310-9956-ffa450edef68
---
 .../apache/sling/tracer/internal/CallerFinder.java | 29 +++++++++-------------
 .../sling/tracer/internal/CallerFinderTest.java    | 18 ++++++++++++++
 2 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/CallerFinder.java b/src/main/java/org/apache/sling/tracer/internal/CallerFinder.java
index f08e8e7..5c688c7 100644
--- a/src/main/java/org/apache/sling/tracer/internal/CallerFinder.java
+++ b/src/main/java/org/apache/sling/tracer/internal/CallerFinder.java
@@ -19,15 +19,8 @@
 
 package org.apache.sling.tracer.internal;
 
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
 import javax.annotation.CheckForNull;
 
-import com.google.common.collect.Iterators;
-import com.google.common.collect.PeekingIterator;
-
 /**
  * Utility to find out the real caller by excluding stack elements belonging to
  * API classes. Say for a query it would exclude the call stack which is part of Oak
@@ -36,6 +29,11 @@ import com.google.common.collect.PeekingIterator;
 class CallerFinder {
     private final String[] apiPkgs;
 
+    /**
+     * Array of package names which form the API
+     * @param apiPkgs package names in the order they can appear in caller stack. For e.g.
+     *                Sling API package would always come before Oak api package for query evaluation
+     */
     public CallerFinder(String[] apiPkgs) {
         this.apiPkgs = apiPkgs;
     }
@@ -46,17 +44,13 @@ class CallerFinder {
             return null;
         }
 
-        //Reverse the stack trace so as to start from bottom
-        List<StackTraceElement> stackList = Arrays.asList(stack);
-        Collections.reverse(stackList);
-        PeekingIterator<StackTraceElement> pit = Iterators.peekingIterator(stackList.iterator());
-        while (pit.hasNext()) {
-            StackTraceElement current = pit.next();
+        for (int i = stack.length - 1; i >= 0; i--) {
+            StackTraceElement current = stack[i];
+            if (i > 0) {
+                StackTraceElement next = stack[i - 1];
 
-            //now scan each element and check if the *next* stack element belongs to any
-            //api package. If yes then current stack would be the caller
-            if (pit.hasNext()) {
-                StackTraceElement next = pit.peek();
+                //now scan each element and check if the *next* stack element belongs to any
+                //api package. If yes then current stack would be the caller
                 for (String pkg : apiPkgs) {
                     if (next.getClassName().startsWith(pkg)) {
                         return current;
@@ -64,6 +58,7 @@ class CallerFinder {
                 }
             }
         }
+
         return null;
     }
 }
diff --git a/src/test/java/org/apache/sling/tracer/internal/CallerFinderTest.java b/src/test/java/org/apache/sling/tracer/internal/CallerFinderTest.java
index 51d4ba2..29906ef 100644
--- a/src/test/java/org/apache/sling/tracer/internal/CallerFinderTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/CallerFinderTest.java
@@ -86,6 +86,24 @@ public class CallerFinderTest {
         assertNull(cf.determineCaller(null));
     }
 
+    @Test
+    public void nullCaller() throws Exception{
+        CallerFinder cf = new CallerFinder(new String[] {"o.a1.s", "o.a1.j.o"});
+        StackTraceElement[] stack = createStack(
+                "o.a.j.o.a",
+                "o.a.j.o.b",
+                "o.a.s.a",
+                "o.a.s.b",
+                "c.a.g.w",
+                "o.e.j",
+                "o.e.j",
+                "o.e.j"
+        );
+
+        StackTraceElement caller = cf.determineCaller(stack);
+        assertNull(caller);
+    }
+
     private static StackTraceElement[] createStack(String ... stack){
         StackTraceElement[] result = new StackTraceElement[stack.length];
         for (int i = 0; i < stack.length; i++) {

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 28/30: SLING-5507 - Collect more details around query execution

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 88f3d3aa855465381b104bf5883f8c84647fe210
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Mon Feb 15 13:59:16 2016 +0000

    SLING-5507 - Collect more details around query execution
    
    Fix an issue where only query recording was done instead of multiple in a given request. As a fix the logic now does not rely on MDC to detect query boundaries
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1730533 13f79535-47bb-0310-9956-ffa450edef68
---
 .../sling/tracer/internal/JSONRecording.java       | 31 +++++++++-------------
 1 file changed, 12 insertions(+), 19 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index a88a250..21d99d4 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -49,7 +49,6 @@ import org.apache.sling.commons.json.JSONException;
 import org.apache.sling.commons.json.io.JSONWriter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.slf4j.MDC;
 import org.slf4j.helpers.FormattingTuple;
 import org.slf4j.helpers.MessageFormatter;
 
@@ -323,27 +322,17 @@ class JSONRecording implements Recording, Comparable<JSONRecording> {
     }
 
     private class QueryLogCollector {
-        /**
-         * The MDC key is used in org.apache.jackrabbit.oak.query.QueryEngineImpl
-         */
-        static final String MDC_QUERY_ID = "oak.query.id";
         String query;
         String plan;
-        String id;
         String caller;
 
         public void record(Level level, String logger, FormattingTuple tuple) {
-            String idFromMDC = MDC.get(MDC_QUERY_ID);
-
-            //Use the query id to detect change of query execution
-            //i.e. once query gets executed for current thread and next
-            //query start it would cause the id to change. That would
-            //be a trigger to finish up on current query collection and
-            //switch to new one
-            if (idFromMDC != null && !idFromMDC.equals(id)) {
-                addQueryEntry();
-                id = idFromMDC;
-            }
+            //Assuming in a series of log statement from query package we see 'query'
+            //and then 'plan' then once both are not null then it means that one query
+            //execution is complete and we push the entry and reset the state
+            //This is done as we do not have a definitive way to determine when
+            //a given query processing is done
+            attemptQueryEntry();
 
             //TODO Query time. Change Oak to provide this information via some
             //dedicated Audit logging such that below reliance on impl details
@@ -383,7 +372,11 @@ class JSONRecording implements Recording, Comparable<JSONRecording> {
             return null;
         }
 
-        public void addQueryEntry(){
+        /**
+         * Checks if both plan and query are determined. If yes then pushes them to list
+         * and resets the state.
+         */
+        public void attemptQueryEntry(){
             if (query != null && plan != null){
                 queries.add(new QueryEntry(nullSafeTrim(query), nullSafeTrim(plan), caller));
                 plan = query = null;
@@ -392,7 +385,7 @@ class JSONRecording implements Recording, Comparable<JSONRecording> {
 
         public void done(){
             //Push any last pending entry i.e. last query
-            addQueryEntry();
+            attemptQueryEntry();
         }
     }
 

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 12/30: SLING-5459 - Recording of tracer logs

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 6a25a1d439ff131994cec50ccbd375ddcd020abd
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Wed Feb 10 05:52:44 2016 +0000

    SLING-5459 - Recording of tracer logs
    
    Handle logs separately in recorded json
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729531 13f79535-47bb-0310-9956-ffa450edef68
---
 .../sling/tracer/internal/JSONRecording.java       | 70 ++++++++++++++++++++++
 .../sling/tracer/internal/TracerContext.java       | 14 +++--
 .../sling/tracer/internal/JSONRecordingTest.java   | 30 ++++++++++
 .../sling/tracer/internal/LogTracerTest.java       | 40 +++++++++++++
 4 files changed, 148 insertions(+), 6 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index 8980ff9..cf1cea3 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -20,6 +20,7 @@
 package org.apache.sling.tracer.internal;
 
 import java.io.IOException;
+import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.io.Writer;
 import java.util.ArrayList;
@@ -35,12 +36,14 @@ import org.apache.sling.commons.json.io.JSONWriter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.helpers.FormattingTuple;
+import org.slf4j.helpers.MessageFormatter;
 
 class JSONRecording implements Recording {
     private static final Logger log = LoggerFactory.getLogger(JSONRecording.class);
     private final String method;
     private final String requestId;
     private final List<String> queries = new ArrayList<String>();
+    private final List<LogEntry> logs = new ArrayList<LogEntry>();
     private RequestProgressTracker tracker;
     private String json;
 
@@ -66,6 +69,7 @@ class JSONRecording implements Recording {
                 && params != null && params.length == 2) {
             queries.add((String) params[1]);
         }
+        logs.add(new LogEntry(level, logger, tuple));
     }
 
     @Override
@@ -83,6 +87,7 @@ class JSONRecording implements Recording {
                 //not occupy memory
                 tracker = null;
                 queries.clear();
+                logs.clear();
             }
         } catch (JSONException e) {
             log.warn("Error occurred while converting the log data for request {} to JSON", requestId, e);
@@ -113,7 +118,72 @@ class JSONRecording implements Recording {
             jw.value(q);
         }
         jw.endArray();
+
+        addJson(jw, "logs", logs);
         jw.endObject();
         return sw.toString();
     }
+
+    private void addJson(JSONWriter jw, String name, List<? extends JsonEntry> entries) throws JSONException {
+        jw.key(name);
+        jw.array();
+        for (JsonEntry je : entries) {
+            jw.object();
+            je.toJson(jw);
+            jw.endObject();
+        }
+        jw.endArray();
+    }
+
+    private interface JsonEntry {
+        void toJson(JSONWriter jw) throws JSONException;
+    }
+
+    private static class LogEntry implements JsonEntry {
+        final Level level;
+        final String logger;
+        final FormattingTuple tuple;
+
+        private LogEntry(Level level, String logger, FormattingTuple tuple) {
+            this.level = level != null ? level : Level.INFO;
+            this.logger = logger;
+            this.tuple = tuple;
+        }
+
+        private static String toString(Object o) {
+            //Make use of Slf4j null safe toString support!
+            return MessageFormatter.format("{}", o).getMessage();
+        }
+
+        private static String getStackTraceAsString(Throwable throwable) {
+            StringWriter stringWriter = new StringWriter();
+            throwable.printStackTrace(new PrintWriter(stringWriter));
+            return stringWriter.toString();
+        }
+
+        @Override
+        public void toJson(JSONWriter jw) throws JSONException {
+            jw.key("level").value(level.levelStr);
+            jw.key("logger").value(logger);
+            jw.key("message").value(tuple.getMessage());
+
+            Object[] params = tuple.getArgArray();
+            if (params != null) {
+                jw.key("params");
+                jw.array();
+                for (Object o : params) {
+                    jw.value(toString(o));
+                }
+                jw.endArray();
+            }
+
+            Throwable t = tuple.getThrowable();
+            if (t != null) {
+                //Later we can look into using Logback Throwable handling
+                jw.key("exception").value(getStackTraceAsString(t));
+
+            }
+        }
+    }
+
 }
diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerContext.java b/src/main/java/org/apache/sling/tracer/internal/TracerContext.java
index 47615e9..bd12def 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerContext.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerContext.java
@@ -82,11 +82,13 @@ class TracerContext {
     }
 
     public boolean log(Level level, String logger, String format, Object[] params) {
-        FormattingTuple tuple;
-
+        FormattingTuple tuple = null;
         if (QUERY_LOGGER.equals(logger)
                 && params != null && params.length == 2) {
-            tuple = logQuery((String) params[1]);
+            if (logQuery((String) params[1])){
+                //Get original log message
+                tuple = logWithLoggerName(logger, format, params);
+            }
         } else {
             tuple = logWithLoggerName(logger, format, params);
         }
@@ -132,12 +134,12 @@ class TracerContext {
         return tuple;
     }
 
-    private FormattingTuple logQuery(String query) {
+    private boolean logQuery(String query) {
         if (ignorableQuery(query)) {
-            return null;
+            return false;
         }
         queryCount++;
-        return logWithLoggerName("JCR", " Query {}", query);
+        return true;
     }
 
     private boolean ignorableQuery(String msg) {
diff --git a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
index 159555e..82116fc 100644
--- a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
@@ -26,9 +26,12 @@ import javax.servlet.http.HttpServletRequest;
 import ch.qos.logback.classic.Level;
 import org.apache.sling.commons.json.JSONObject;
 import org.junit.Test;
+import org.slf4j.helpers.FormattingTuple;
 import org.slf4j.helpers.MessageFormatter;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -67,4 +70,31 @@ public class JSONRecordingTest {
         assertEquals(2, json.getJSONArray("requestProgressLogs").length());
     }
 
+    @Test
+    public void logs() throws Exception{
+        StringWriter sw = new StringWriter();
+        JSONRecording r = new JSONRecording("abc", request);
+
+        FormattingTuple tp1 = MessageFormatter.arrayFormat("{} is going", new Object[]{"Jack"});
+        r.log(Level.INFO, "foo", tp1);
+        r.log(Level.WARN, "foo.bar", MessageFormatter.arrayFormat("Jill is going", null));
+        r.log(Level.ERROR, "foo.bar",
+                MessageFormatter.arrayFormat("Jack and {} is going", new Object[]{"Jill" , new Exception()}));
+
+        r.done();
+        r.render(sw);
+
+        JSONObject json = new JSONObject(sw.toString());
+        assertEquals(3, json.getJSONArray("logs").length());
+
+        JSONObject l1 = json.getJSONArray("logs").getJSONObject(0);
+        assertEquals("INFO", l1.getString("level"));
+        assertEquals("foo", l1.getString("logger"));
+        assertEquals(tp1.getMessage(), l1.getString("message"));
+        assertEquals(1, l1.getJSONArray("params").length());
+        assertFalse(l1.has("exception"));
+
+        JSONObject l3 = json.getJSONArray("logs").getJSONObject(2);
+        assertNotNull(l3.get("exception"));
+    }
 }
diff --git a/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java b/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
index 1409f95..c6b9e42 100644
--- a/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
@@ -264,6 +264,46 @@ public class LogTracerTest {
         assertEquals(2, json.getJSONArray("requestProgressLogs").length());
     }
 
+    @Test
+    public void recordingWithTracing() throws Exception{
+        activateTracerAndServlet();
+        MockSlingHttpServletRequest request = new MockSlingHttpServletRequest(){
+            @Override
+            public RequestProgressTracker getRequestProgressTracker() {
+                return createTracker("x", "y");
+            }
+        };
+        request.setHeader(TracerLogServlet.HEADER_TRACER_RECORDING, "true");
+        request.setHeader(LogTracer.HEADER_TRACER_CONFIG, "a.b.c;level=trace,a.b;level=debug");
+
+        HttpServletResponse response = mock(HttpServletResponse.class);
+
+        FilterChain chain = new FilterChain() {
+            @Override
+            public void doFilter(ServletRequest request, ServletResponse response)
+                    throws IOException, ServletException {
+                assertNotNull(context.getService(TurboFilter.class));
+                getLogContext().addTurboFilter(context.getService(TurboFilter.class));
+                getLogger("a.b").info("a.b-info");
+            }
+        };
+
+        prepareChain(chain).doFilter(request, response);
+
+        String requestId = getRequestId(response);
+        assertNotNull(requestId);
+        Recording r = ((TracerLogServlet)context.getService(Servlet.class)).getRecording(requestId);
+        assertTrue(r instanceof JSONRecording);
+        JSONRecording jr = (JSONRecording) r;
+
+        StringWriter sw = new StringWriter();
+        jr.render(sw);
+        JSONObject json = new JSONObject(sw.toString());
+
+        assertEquals(2, json.getJSONArray("requestProgressLogs").length());
+        assertEquals(1, json.getJSONArray("logs").length());
+    }
+
 
     private void activateTracer() {
         context.registerInjectActivateService(new LogTracer(),

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 17/30: SLING-5504 - Reduce memory footprint of stored recording data

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 3ded49e300d8193bf09279d2f462a898ca5c9508
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Wed Feb 10 06:55:28 2016 +0000

    SLING-5504 - Reduce memory footprint of stored recording data
    
    Array size would be in int so avoid unnecessary cast
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729536 13f79535-47bb-0310-9956-ffa450edef68
---
 src/main/java/org/apache/sling/tracer/internal/JSONRecording.java    | 2 +-
 src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index 35f4dfe..57ce0d1 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -84,7 +84,7 @@ class JSONRecording implements Recording {
         return false;
     }
 
-    public long size() {
+    public int size() {
         if (json != null){
             return json.length;
         }
diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
index fc126d0..4eb028e 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
@@ -80,7 +80,7 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
                 .weigher(new Weigher<String, JSONRecording>() {
                     @Override
                     public int weigh(@Nonnull  String key, @Nonnull JSONRecording value) {
-                        return (int)value.size();
+                        return value.size();
                     }
                 })
                 .expireAfterAccess(cacheDurationInSecs, TimeUnit.SECONDS)

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 03/30: Add contrib/extensions/tracer to module list and bump the sling-parent version in tracer to latest

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit c0fa1434a364982407bc39ad8ab3add203346131
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Wed Jan 27 12:41:33 2016 +0000

    Add contrib/extensions/tracer to module list and bump the sling-parent version in tracer to latest
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1727022 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 38391b2..de2f892 100644
--- a/pom.xml
+++ b/pom.xml
@@ -25,7 +25,7 @@
   <parent>
     <groupId>org.apache.sling</groupId>
     <artifactId>sling</artifactId>
-    <version>22</version>
+    <version>26</version>
   </parent>
 
   <artifactId>org.apache.sling.tracer</artifactId>

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 16/30: SLING-5504 - Reduce memory footprint of stored recording data

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 9d3d4dcb79db89b18766a6f3283f94e32d0fa6e0
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Wed Feb 10 06:52:58 2016 +0000

    SLING-5504 - Reduce memory footprint of stored recording data
    
    -- Make cache size by memory configurable. Defaults to 50MB and expiry in 15 mins
    -- Change the recording logic such that recording is added to cache at end. As Guava calculates the entry size at time of put and recording size is only calculated at end. So now recorder would be called at end of request processing
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729535 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            |  2 +-
 .../sling/tracer/internal/JSONRecording.java       |  5 +-
 .../apache/sling/tracer/internal/LogTracer.java    | 33 +++++++++-
 .../apache/sling/tracer/internal/Recording.java    | 10 ---
 .../sling/tracer/internal/TraceLogRecorder.java    |  7 ++
 .../sling/tracer/internal/TracerLogServlet.java    | 76 +++++++++++++++++-----
 .../sling/tracer/internal/LogTracerTest.java       | 25 +++++++
 .../tracer/internal/TracerLogServletTest.java      |  5 +-
 8 files changed, 131 insertions(+), 32 deletions(-)

diff --git a/pom.xml b/pom.xml
index 1a0bf46..185cfb2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -74,7 +74,7 @@
       <!-- the used logback version is only compatible with SLF4J 1.6 -->
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
-      <version>1.6.0</version>
+      <version>1.7.5</version>
       <scope>provided</scope>
     </dependency>
     <dependency>
diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index 507d130..35f4dfe 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -95,6 +95,10 @@ class JSONRecording implements Recording {
         return uri;
     }
 
+    public String getRequestId() {
+        return requestId;
+    }
+
     //~---------------------------------------< Recording >
 
     @Override
@@ -112,7 +116,6 @@ class JSONRecording implements Recording {
         this.tracker = tracker;
     }
 
-    @Override
     public void done() {
         try {
             if (json == null) {
diff --git a/src/main/java/org/apache/sling/tracer/internal/LogTracer.java b/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
index 94c220c..2f6940b 100644
--- a/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
+++ b/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
@@ -117,6 +117,27 @@ public class LogTracer {
     )
     private static final String PROP_TRACER_SERVLET_ENABLED = "servletEnabled";
 
+    static final int PROP_TRACER_SERVLET_CACHE_SIZE_DEFAULT = 50;
+    @Property(label = "Recording Cache Size",
+            description = "Recording cache size in MB which would be used to temporary cache the recording data",
+            intValue = PROP_TRACER_SERVLET_CACHE_SIZE_DEFAULT
+    )
+    private static final String PROP_TRACER_SERVLET_CACHE_SIZE = "recordingCacheSizeInMB";
+
+    static final long PROP_TRACER_SERVLET_CACHE_DURATION_DEFAULT = 60 * 15;
+    @Property(label = "Recording Cache Duration",
+            description = "Time in seconds upto which the recording data would be held in memory before expiry",
+            longValue = PROP_TRACER_SERVLET_CACHE_DURATION_DEFAULT
+    )
+    private static final String PROP_TRACER_SERVLET_CACHE_DURATION = "recordingCacheDurationInSecs";
+
+    static final boolean PROP_TRACER_SERVLET_COMPRESS_DEFAULT = true;
+    @Property(label = "Compress Recording",
+            description = "Enable compression for recoding held in memory",
+            boolValue = PROP_TRACER_SERVLET_COMPRESS_DEFAULT
+    )
+    private static final String PROP_TRACER_SERVLET_COMPRESS = "recordingCompressionEnabled";
+
     private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(LogTracer.class);
 
     private final Map<String, TracerSet> tracers = new HashMap<String, TracerSet>();
@@ -150,8 +171,16 @@ public class LogTracer {
                     PROP_TRACER_SERVLET_ENABLED_DEFAULT);
 
             if (servletEnabled) {
-                this.logServlet = new TracerLogServlet(context);
+                int cacheSize = PropertiesUtil.toInteger(config.get(PROP_TRACER_SERVLET_CACHE_SIZE),
+                        PROP_TRACER_SERVLET_CACHE_SIZE_DEFAULT);
+                long cacheDuration = PropertiesUtil.toLong(config.get(PROP_TRACER_SERVLET_CACHE_DURATION),
+                        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);
                 recorder = logServlet;
+                LOG.info("Tracer recoding enabled with cacheSize {} MB, expiry {} secs, compression {}",
+                        cacheSize, cacheDuration, compressionEnabled);
             }
             LOG.info("Log tracer enabled. Required filters registered. Tracer servlet enabled {}", servletEnabled);
         }
@@ -318,7 +347,7 @@ public class LogTracer {
                 if (tracerContext != null) {
                     disableCollector();
                 }
-                recording.done();
+                recorder.endRecording(recording);
             }
         }
 
diff --git a/src/main/java/org/apache/sling/tracer/internal/Recording.java b/src/main/java/org/apache/sling/tracer/internal/Recording.java
index d915474..9e0f88e 100644
--- a/src/main/java/org/apache/sling/tracer/internal/Recording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/Recording.java
@@ -34,11 +34,6 @@ interface Recording {
         public void registerTracker(RequestProgressTracker tracker) {
 
         }
-
-        @Override
-        public void done() {
-
-        }
     };
 
     void log(Level level, String logger, FormattingTuple tuple);
@@ -49,9 +44,4 @@ interface Recording {
      * @param tracker from current request
      */
     void registerTracker(RequestProgressTracker tracker);
-
-    /**
-     * Invoked at the end of request processing
-     */
-    void done();
 }
diff --git a/src/main/java/org/apache/sling/tracer/internal/TraceLogRecorder.java b/src/main/java/org/apache/sling/tracer/internal/TraceLogRecorder.java
index 11e347a..d00e617 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TraceLogRecorder.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TraceLogRecorder.java
@@ -33,9 +33,16 @@ interface TraceLogRecorder {
         public Recording getRecordingForRequest(HttpServletRequest request) {
             return Recording.NOOP;
         }
+
+        @Override
+        public void endRecording(Recording recording) {
+
+        }
     };
 
     Recording startRecording(HttpServletRequest request, HttpServletResponse response);
 
     Recording getRecordingForRequest(HttpServletRequest request);
+
+    void endRecording(Recording recording);
 }
diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
index fa31a30..fc126d0 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
@@ -25,19 +25,22 @@ import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.TimeUnit;
 
+import javax.annotation.Nonnull;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.Weigher;
+import org.apache.commons.io.FileUtils;
 import org.apache.felix.webconsole.SimpleWebConsolePlugin;
 import org.apache.sling.commons.json.JSONException;
 import org.apache.sling.commons.json.io.JSONWriter;
 import org.osgi.framework.BundleContext;
 
 class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorder {
-    static final String ATTR_REQUEST_ID = TracerLogServlet.class.getName();
+    static final String ATTR_RECORDING = TracerLogServlet.class.getName();
 
     public static final String CLEAR = "clear";
 
@@ -53,19 +56,51 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
 
     private final Cache<String, JSONRecording> cache;
 
-    private boolean compressRecording = true;
+    private final boolean compressRecording;
 
-    public TracerLogServlet(BundleContext context) {
+    private final int cacheSizeInMB;
+
+    private final long cacheDurationInSecs;
+
+    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
+        );
+    }
+
+    public TracerLogServlet(BundleContext context, int cacheSizeInMB, long cacheDurationInSecs, boolean compressionEnabled) {
         super(LABEL, "Sling Tracer", "Sling", null);
-        //TODO Make things configurable
+        this.compressRecording = compressionEnabled;
+        this.cacheDurationInSecs = cacheDurationInSecs;
+        this.cacheSizeInMB = cacheSizeInMB;
         this.cache = CacheBuilder.newBuilder()
-                .maximumSize(100)
-                .expireAfterAccess(10, TimeUnit.MINUTES)
+                .maximumWeight(cacheSizeInMB * FileUtils.ONE_MB)
+                .weigher(new Weigher<String, JSONRecording>() {
+                    @Override
+                    public int weigh(@Nonnull  String key, @Nonnull JSONRecording value) {
+                        return (int)value.size();
+                    }
+                })
+                .expireAfterAccess(cacheDurationInSecs, TimeUnit.SECONDS)
                 .recordStats()
                 .build();
         register(context);
     }
 
+    boolean isCompressRecording() {
+        return compressRecording;
+    }
+
+    int getCacheSizeInMB() {
+        return cacheSizeInMB;
+    }
+
+    long getCacheDurationInSecs() {
+        return cacheDurationInSecs;
+    }
+
     //~-----------------------------------------------< WebConsole Plugin >
 
     @Override
@@ -119,8 +154,9 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
     }
 
     private void renderStatus(PrintWriter pw) {
-        pw.printf("<p class='statline'>Log Tracer Recordings: %d recordings, %s memory</p>%n", cache.size(),
-                memorySize());
+        pw.printf("<p class='statline'>Log Tracer Recordings: %d recordings, %s memory " +
+                "(Max %dMB, Expired in %d secs)</p>%n", cache.size(),
+                memorySize(), cacheSizeInMB, cacheDurationInSecs);
 
         pw.println("<div class='ui-widget-header ui-corner-top buttonGroup'>");
         pw.println("<span style='float: left; margin-left: 1em'>Tracer Recordings</span>");
@@ -167,7 +203,7 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
             return Recording.NOOP;
         }
 
-        if (request.getAttribute(ATTR_REQUEST_ID) != null){
+        if (request.getAttribute(ATTR_RECORDING) != null){
             //Already processed
             return getRecordingForRequest(request);
         }
@@ -175,8 +211,6 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
         String requestId = generateRequestId();
         JSONRecording recording = record(requestId, request);
 
-        request.setAttribute(ATTR_REQUEST_ID, requestId);
-
         response.setHeader(HEADER_TRACER_REQUEST_ID, requestId);
         response.setHeader(HEADER_TRACER_PROTOCOL_VERSION, String.valueOf(TRACER_PROTOCOL_VERSION));
 
@@ -185,11 +219,20 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
 
     @Override
     public Recording getRecordingForRequest(HttpServletRequest request) {
-        String requestId = (String) request.getAttribute(ATTR_REQUEST_ID);
-        if (requestId != null){
-            return getRecording(requestId);
+        Recording recording = (Recording) request.getAttribute(ATTR_RECORDING);
+        if (recording == null){
+            recording = Recording.NOOP;
+        }
+        return recording;
+    }
+
+    @Override
+    public void endRecording(Recording recording) {
+        if (recording instanceof JSONRecording) {
+            JSONRecording r = (JSONRecording) recording;
+            r.done();
+            cache.put(r.getRequestId(), r);
         }
-        return Recording.NOOP;
     }
 
     Recording getRecording(String requestId) {
@@ -199,7 +242,7 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
 
     private JSONRecording record(String requestId, HttpServletRequest request) {
         JSONRecording data = new JSONRecording(requestId, request, compressRecording);
-        cache.put(requestId, data);
+        request.setAttribute(ATTR_RECORDING, data);
         return data;
     }
 
@@ -211,6 +254,7 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
      * Returns a human-readable version of the file size, where the input represents
      * a specific number of bytes. Based on http://stackoverflow.com/a/3758880/1035417
      */
+    @SuppressWarnings("Duplicates")
     private static String humanReadableByteCount(long bytes) {
         if (bytes < 0) {
             return "0";
diff --git a/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java b/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
index 416b8e2..296c168 100644
--- a/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
@@ -110,12 +110,37 @@ public class LogTracerTest {
         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(LogTracer.PROP_TRACER_SERVLET_CACHE_SIZE_DEFAULT, logServlet.getCacheSizeInMB());
+        assertEquals(LogTracer.PROP_TRACER_SERVLET_CACHE_DURATION_DEFAULT, logServlet.getCacheDurationInSecs());
+
         MockOsgi.deactivate(tracer);
         assertNull(context.getService(Filter.class));
         assertNull(context.getService(Servlet.class));
     }
 
     @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"
+                ));
+        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(17, logServlet.getCacheSizeInMB());
+        assertEquals(100, logServlet.getCacheDurationInSecs());
+    }
+
+
+    @Test
     public void noTurboFilterRegisteredUnlessTracingRequested() throws Exception {
         HttpServletRequest request = mock(HttpServletRequest.class);
         HttpServletResponse response = mock(HttpServletResponse.class);
diff --git a/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java b/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
index 7866544..5404380 100644
--- a/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
@@ -24,6 +24,7 @@ import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 
+import javax.annotation.Nonnull;
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -98,7 +99,7 @@ public class TracerLogServletTest {
 
         Recording recording = logServlet.startRecording(request, response);
         recording.registerTracker(createTracker("x" ,"y"));
-        recording.done();
+        logServlet.endRecording(recording);
 
         ArgumentCaptor<String> requestIdCaptor = ArgumentCaptor.forClass(String.class);
         verify(response).setHeader(eq(TracerLogServlet.HEADER_TRACER_REQUEST_ID), requestIdCaptor.capture());
@@ -135,7 +136,7 @@ public class TracerLogServletTest {
         }
 
         @Override
-        public void write(byte[] b, int off, int len) throws IOException {
+        public void write(@Nonnull byte[] b, int off, int len) throws IOException {
             baos.write(b, off, len);
         }
     }

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 10/30: SLING-5459 - Recording of tracer logs

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 9a4867d969696eaf17ccb9b9e9e74992df2bc958
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Tue Feb 9 10:40:25 2016 +0000

    SLING-5459 - Recording of tracer logs
    
    Preparing for supporting 2 logs - RequestProgressTracker and actual logs. Change the name to `requestProgressLogs` for logs from RequestProgressTracker.
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729355 13f79535-47bb-0310-9956-ffa450edef68
---
 src/main/java/org/apache/sling/tracer/internal/JSONRecording.java       | 2 +-
 src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java   | 2 +-
 src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java       | 2 +-
 .../java/org/apache/sling/tracer/internal/TracerLogServletTest.java     | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index 179194c..0b103bd 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -95,7 +95,7 @@ class JSONRecording implements Recording {
         jw.key("method").value(method);
 
         if (tracker != null) {
-            jw.key("logs");
+            jw.key("requestProgressLogs");
             jw.array();
             Iterator<String> it = tracker.getMessages();
             //Per docs iterator can be null
diff --git a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
index f5ed681..f7c1736 100644
--- a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
@@ -63,7 +63,7 @@ public class JSONRecordingTest {
         r.render(sw);
 
         JSONObject json = new JSONObject(sw.toString());
-        assertEquals(2, json.getJSONArray("logs").length());
+        assertEquals(2, json.getJSONArray("requestProgressLogs").length());
     }
 
 }
diff --git a/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java b/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
index e23ac13..1409f95 100644
--- a/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
@@ -261,7 +261,7 @@ public class LogTracerTest {
         jr.render(sw);
         JSONObject json = new JSONObject(sw.toString());
 
-        assertEquals(2, json.getJSONArray("logs").length());
+        assertEquals(2, json.getJSONArray("requestProgressLogs").length());
     }
 
 
diff --git a/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java b/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
index d2090fe..5514dd1 100644
--- a/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
@@ -109,7 +109,7 @@ public class TracerLogServletTest {
         logServlet.renderContent(request, response);
         JSONObject json = new JSONObject(sw.toString());
         assertEquals("GET", json.getString("method"));
-        assertEquals(2, json.getJSONArray("logs").length());
+        assertEquals(2, json.getJSONArray("requestProgressLogs").length());
     }
 
     @Test

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 24/30: SLING-5507 - Collect more details around query execution

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit b62cf457ca2b5069132c094307a2ce3b012e74d8
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Thu Feb 11 04:49:24 2016 +0000

    SLING-5507 - Collect more details around query execution
    
    Handle case for union queries
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729762 13f79535-47bb-0310-9956-ffa450edef68
---
 .../sling/tracer/internal/JSONRecording.java       | 58 +++++++++++++++-------
 .../sling/tracer/internal/JSONRecordingTest.java   |  7 ++-
 2 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index c0aec8a..f508e9e 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -59,6 +59,7 @@ class JSONRecording implements Recording, Comparable<JSONRecording> {
             "org.apache.sling.resourceresolver", //Sling package would come first in stack so listed first
             "org.apache.jackrabbit.oak"
     };
+    private static final Object[] EMPTY = new Object[0];
     private static final Logger log = LoggerFactory.getLogger(JSONRecording.class);
     public static final String OAK_QUERY_PKG = "org.apache.jackrabbit.oak.query";
     private final String method;
@@ -300,7 +301,6 @@ class JSONRecording implements Recording, Comparable<JSONRecording> {
          * The MDC key is used in org.apache.jackrabbit.oak.query.QueryEngineImpl
          */
         static final String MDC_QUERY_ID = "oak.query.id";
-        static final String QE_LOGGER = "org.apache.jackrabbit.oak.query.QueryImpl";
         String query;
         String plan;
         String id;
@@ -319,17 +319,32 @@ class JSONRecording implements Recording, Comparable<JSONRecording> {
                 id = idFromMDC;
             }
 
+            //TODO Query time. Change Oak to provide this information via some
+            //dedicated Audit logging such that below reliance on impl details
+            //can be avoided
             String msg = tuple.getMessage();
-            if (Level.DEBUG == level
-                    && QE_LOGGER.equals(logger)
-                    && msg != null){
-
-                //The Log stmt are as present in org.apache.jackrabbit.oak.query.QueryImpl
-                if (msg.startsWith("query execute ")){
-                    query = msg.substring("query execute ".length());
-                    caller = determineCaller();
-                } else if (msg.startsWith("query plan ")){
-                    plan = msg.substring("query plan ".length());
+            if (Level.DEBUG == level && msg != null) {
+                Object[] args = tuple.getArgArray() == null ? EMPTY : tuple.getArgArray();
+                if (query == null){
+                    if ("org.apache.jackrabbit.oak.query.QueryEngineImpl".equals(logger)
+                            && msg.contains("Parsing") && args.length == 2){
+                        //LOG.debug("Parsing {} statement: {}", language, statement);
+                        query = nullSafeString(args[1]);
+                        caller = determineCaller();
+                    }
+                }
+
+                //Plan for union query are logged separately
+                if (plan == null){
+                    if ("org.apache.jackrabbit.oak.query.QueryImpl".equals(logger)
+                            && msg.startsWith("query plan ")){
+                        //logDebug("query execute " + statement);
+                        plan = msg.substring("query plan ".length());
+                    } else if ("org.apache.jackrabbit.oak.query.UnionQueryImpl".equals(logger)
+                            && msg.contains("query union plan") && args.length > 0){
+                        // LOG.debug("query union plan {}", getPlan());
+                        plan = nullSafeString(args[0]);
+                    }
                 }
             }
         }
@@ -343,8 +358,8 @@ class JSONRecording implements Recording, Comparable<JSONRecording> {
         }
 
         public void addQueryEntry(){
-            if (query != null){
-                queries.add(new QueryEntry(safeTrim(query), safeTrim(plan), caller));
+            if (query != null && plan != null){
+                queries.add(new QueryEntry(nullSafeTrim(query), nullSafeTrim(plan), caller));
                 plan = query = null;
             }
         }
@@ -353,13 +368,20 @@ class JSONRecording implements Recording, Comparable<JSONRecording> {
             //Push any last pending entry i.e. last query
             addQueryEntry();
         }
+    }
 
-        private String safeTrim(String s){
-            if(s == null){
-                return "";
-            }
-            return s.trim();
+    private static String nullSafeTrim(String s){
+        if(s == null){
+            return "";
+        }
+        return s.trim();
+    }
+
+    private static String nullSafeString(Object o){
+        if (o != null){
+            return o.toString();
         }
+        return null;
     }
 
 }
diff --git a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
index e0a2476..14ab480 100644
--- a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
@@ -53,7 +53,8 @@ public class JSONRecordingTest {
         JSONRecording r = new JSONRecording("abc", request, true);
 
         MDC.put(MDC_QUERY_ID, "1");
-        r.log(tc, Level.DEBUG, QE_LOGGER, tuple("query execute SELECT FOO"));
+        r.log(tc, Level.DEBUG, "org.apache.jackrabbit.oak.query.QueryEngineImpl",
+                tuple("Parsing {} statement: {}",  "XPATH", "SELECT FOO"));
         r.log(tc, Level.DEBUG, QE_LOGGER, tuple("query plan FOO PLAN"));
 
         r.done();
@@ -112,4 +113,8 @@ public class JSONRecordingTest {
     private static FormattingTuple tuple(String msg){
         return MessageFormatter.format(msg, null);
     }
+
+    private static FormattingTuple tuple(String msg, String ... params){
+        return MessageFormatter.arrayFormat(msg, params);
+    }
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 09/30: SLING-5459 - Recording of tracer logs

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit de2f6e5fb17b4a3cfa85e7f703b29d170de9058c
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Tue Feb 9 10:39:49 2016 +0000

    SLING-5459 - Recording of tracer logs
    
    Pass logger level also
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729354 13f79535-47bb-0310-9956-ffa450edef68
---
 src/main/java/org/apache/sling/tracer/internal/JSONRecording.java    | 3 ++-
 src/main/java/org/apache/sling/tracer/internal/LogTracer.java        | 2 +-
 src/main/java/org/apache/sling/tracer/internal/Recording.java        | 5 +++--
 src/main/java/org/apache/sling/tracer/internal/TracerContext.java    | 4 ++--
 .../java/org/apache/sling/tracer/internal/JSONRecordingTest.java     | 5 +++--
 5 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index 9c8340e..179194c 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -28,6 +28,7 @@ import java.util.List;
 
 import javax.servlet.http.HttpServletRequest;
 
+import ch.qos.logback.classic.Level;
 import org.apache.sling.api.request.RequestProgressTracker;
 import org.apache.sling.commons.json.JSONException;
 import org.apache.sling.commons.json.io.JSONWriter;
@@ -58,7 +59,7 @@ class JSONRecording implements Recording {
     //~---------------------------------------< Recording >
 
     @Override
-    public void log(String logger, String format, Object[] params) {
+    public void log(Level level, String logger, String format, Object[] params) {
         if (TracerContext.QUERY_LOGGER.equals(logger)
                 && params != null && params.length == 2) {
             queries.add((String) params[1]);
diff --git a/src/main/java/org/apache/sling/tracer/internal/LogTracer.java b/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
index 9489671..94c220c 100644
--- a/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
+++ b/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
@@ -384,7 +384,7 @@ public class LogTracer {
                 if (format == null) {
                     return FilterReply.ACCEPT;
                 }
-                if (tracer.log(logger.getName(), format, params)) {
+                if (tracer.log(level, logger.getName(), format, params)) {
                     return FilterReply.ACCEPT;
                 }
             }
diff --git a/src/main/java/org/apache/sling/tracer/internal/Recording.java b/src/main/java/org/apache/sling/tracer/internal/Recording.java
index 1e6f058..7e24f14 100644
--- a/src/main/java/org/apache/sling/tracer/internal/Recording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/Recording.java
@@ -19,12 +19,13 @@
 
 package org.apache.sling.tracer.internal;
 
+import ch.qos.logback.classic.Level;
 import org.apache.sling.api.request.RequestProgressTracker;
 
 interface Recording {
     Recording NOOP = new Recording() {
         @Override
-        public void log(String logger, String format, Object[] params) {
+        public void log(Level level, String logger, String format, Object[] params) {
 
         }
 
@@ -39,7 +40,7 @@ interface Recording {
         }
     };
 
-    void log(String logger, String format, Object[] params);
+    void log(Level level, String logger, String format, Object[] params);
 
     /**
      * Register the {@link RequestProgressTracker} associated with
diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerContext.java b/src/main/java/org/apache/sling/tracer/internal/TracerContext.java
index 5755ca8..4931255 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerContext.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerContext.java
@@ -80,8 +80,8 @@ class TracerContext {
         return false;
     }
 
-    public boolean log(String logger, String format, Object[] params) {
-        recording.log(logger, format, params);
+    public boolean log(Level level, String logger, String format, Object[] params) {
+        recording.log(level, logger, format, params);
         if (QUERY_LOGGER.equals(logger)
                 && params != null && params.length == 2) {
             return logQuery((String) params[1]);
diff --git a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
index 9ebd544..f5ed681 100644
--- a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
@@ -23,6 +23,7 @@ import java.io.StringWriter;
 
 import javax.servlet.http.HttpServletRequest;
 
+import ch.qos.logback.classic.Level;
 import org.apache.sling.commons.json.JSONObject;
 import org.junit.Test;
 
@@ -40,8 +41,8 @@ public class JSONRecordingTest {
         when(request.getMethod()).thenReturn("GET");
         JSONRecording r = new JSONRecording("abc", request);
 
-        r.log(TracerContext.QUERY_LOGGER, "foo bar", new Object[]{"x" , "y"});
-        r.log(TracerContext.QUERY_LOGGER, "foo bar", new Object[]{"x" , "z"});
+        r.log(Level.INFO, TracerContext.QUERY_LOGGER, "foo bar", new Object[]{"x" , "y"});
+        r.log(Level.INFO, TracerContext.QUERY_LOGGER, "foo bar", new Object[]{"x" , "z"});
 
         r.done();
         r.render(sw);

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 04/30: SLING-5459 - Recording of tracer logs

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 83ba09f82f5616ecd782988c289fef14ca634265
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Tue Feb 2 10:50:05 2016 +0000

    SLING-5459 - Recording of tracer logs
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1728077 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            |  31 +++-
 .../sling/tracer/internal/JSONRecording.java       |  80 +++++++++
 .../apache/sling/tracer/internal/LogTracer.java    |  43 ++++-
 .../apache/sling/tracer/internal/Recording.java    |  45 +++++
 .../sling/tracer/internal/TraceLogRecorder.java    |  41 +++++
 .../sling/tracer/internal/TracerContext.java       |   7 +-
 .../sling/tracer/internal/TracerLogServlet.java    | 196 +++++++++++++++++++++
 .../sling/tracer/internal/JSONRecordingTest.java   |  71 ++++++++
 .../sling/tracer/internal/LogTracerModelTest.java  |   2 +-
 .../sling/tracer/internal/LogTracerTest.java       |  81 +++++++++
 .../org/apache/sling/tracer/internal/TestUtil.java |  46 +++++
 .../tracer/internal/TracerLogServletTest.java      | 123 +++++++++++++
 12 files changed, 756 insertions(+), 10 deletions(-)

diff --git a/pom.xml b/pom.xml
index de2f892..d6ed36c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -88,7 +88,7 @@
     <dependency>
       <groupId>org.apache.sling</groupId>
       <artifactId>org.apache.sling.api</artifactId>
-      <version>2.1.0</version>
+      <version>2.2.0</version>
     </dependency>
     <dependency>
       <groupId>org.osgi</groupId>
@@ -102,6 +102,28 @@
       <version>4.3.1</version>
       <scope>provided</scope>
     </dependency>
+    <!-- TODO Inline just the cache related classes -->
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+      <version>15.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.webconsole</artifactId>
+      <version>4.2.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.commons.json</artifactId>
+      <version>2.0.8</version>
+    </dependency>
+    <dependency>
+      <groupId>com.google.code.findbugs</groupId>
+      <artifactId>jsr305</artifactId>
+      <version>3.0.0</version>
+      <scope>provided</scope>
+    </dependency>
 
     <dependency>
       <groupId>junit</groupId>
@@ -115,9 +137,16 @@
       <scope>test</scope>
     </dependency>
     <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.testing.sling-mock</artifactId>
+      <version>1.3.0</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
       <groupId>org.mockito</groupId>
       <artifactId>mockito-core</artifactId>
       <version>1.10.19</version>
+      <scope>test</scope>
     </dependency>
 
   </dependencies>
diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
new file mode 100644
index 0000000..7682e8e
--- /dev/null
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.tracer.internal;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.sling.api.request.RequestProgressTracker;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.io.JSONWriter;
+
+class JSONRecording implements Recording {
+    private final String method;
+    private final List<String> queries = new ArrayList<String>();
+    private RequestProgressTracker tracker;
+
+    public JSONRecording(HttpServletRequest r) {
+        this.method = r.getMethod();
+    }
+
+    public void render(JSONWriter jw) throws JSONException {
+        jw.key("method").value(method);
+
+        if (tracker != null) {
+            jw.key("logs");
+            jw.array();
+            Iterator<String> it = tracker.getMessages();
+            while (it.hasNext()) {
+                jw.value(it.next());
+            }
+            jw.endArray();
+        }
+
+        jw.key("queries");
+        jw.array();
+        for (String q : queries) {
+            jw.value(q);
+        }
+        jw.endArray();
+    }
+
+    //~---------------------------------------< Recording >
+
+    @Override
+    public void log(String logger, String format, Object[] params) {
+        if (TracerContext.QUERY_LOGGER.equals(logger)
+                && params != null && params.length == 2) {
+            queries.add((String) params[1]);
+        }
+    }
+
+    @Override
+    public void registerTracker(RequestProgressTracker tracker) {
+        this.tracker = tracker;
+    }
+
+    RequestProgressTracker getTracker() {
+        return tracker;
+    }
+}
diff --git a/src/main/java/org/apache/sling/tracer/internal/LogTracer.java b/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
index 3861f29..9cfedf9 100644
--- a/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
+++ b/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
@@ -29,6 +29,7 @@ import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicReference;
 
+import javax.annotation.Nullable;
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
 import javax.servlet.FilterConfig;
@@ -36,6 +37,7 @@ import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.classic.Logger;
@@ -108,6 +110,13 @@ public class LogTracer {
     )
     private static final String PROP_TRACER_ENABLED = "enabled";
 
+    private static final boolean PROP_TRACER_SERVLET_ENABLED_DEFAULT = false;
+    @Property(label = "Servlet Enabled",
+            description = "Enable the Tracer Servlet",
+            boolValue = PROP_TRACER_SERVLET_ENABLED_DEFAULT
+    )
+    private static final String PROP_TRACER_SERVLET_ENABLED = "servletEnabled";
+
     private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(LogTracer.class);
 
     private final Map<String, TracerSet> tracers = new HashMap<String, TracerSet>();
@@ -125,6 +134,11 @@ public class LogTracer {
 
     private static final ThreadLocal<TracerContext> requestContextHolder = new ThreadLocal<TracerContext>();
 
+    @Nullable
+    private TracerLogServlet logServlet;
+
+    private TraceLogRecorder recorder = TraceLogRecorder.DEFAULT;
+
     @Activate
     private void activate(Map<String, ?> config, BundleContext context) {
         this.bundleContext = context;
@@ -132,12 +146,23 @@ public class LogTracer {
         boolean enabled = PropertiesUtil.toBoolean(config.get(PROP_TRACER_ENABLED), PROP_TRACER_ENABLED_DEFAULT);
         if (enabled) {
             registerFilters(context);
-            LOG.info("Log tracer enabled. Required filters registered");
+            boolean servletEnabled = PropertiesUtil.toBoolean(config.get(PROP_TRACER_SERVLET_ENABLED),
+                    PROP_TRACER_SERVLET_ENABLED_DEFAULT);
+
+            if (servletEnabled) {
+                this.logServlet = new TracerLogServlet(context);
+                recorder = logServlet;
+            }
+            LOG.info("Log tracer enabled. Required filters registered. Tracer servlet enabled {}", servletEnabled);
         }
     }
 
     @Deactivate
     private void deactivate() {
+        if (logServlet != null) {
+            logServlet.unregister();
+        }
+
         if (slingFilterRegistration != null) {
             slingFilterRegistration.unregister();
             slingFilterRegistration = null;
@@ -156,7 +181,7 @@ public class LogTracer {
         requestContextHolder.remove();
     }
 
-    TracerContext getTracerContext(String tracerSetNames, String tracerConfig) {
+    TracerContext getTracerContext(String tracerSetNames, String tracerConfig, Recording recording) {
         //No config or tracer set name provided. So tracing not required
         if (tracerSetNames == null && tracerConfig == null) {
             return null;
@@ -185,7 +210,7 @@ public class LogTracer {
             configs.addAll(ts.getConfigs());
         }
 
-        return new TracerContext(configs.toArray(new TracerConfig[configs.size()]));
+        return new TracerContext(configs.toArray(new TracerConfig[configs.size()]), recording);
     }
 
     private void initializeTracerSet(Map<String, ?> config) {
@@ -277,8 +302,13 @@ public class LogTracer {
             //parameter map
 
             HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
+
+            //Invoke at start so that header can be set. If done at end there is a chance
+            //that response is committed
+            Recording recording = recorder.startRecording(httpRequest, (HttpServletResponse) servletResponse);
+
             TracerContext tracerContext = getTracerContext(httpRequest.getHeader(HEADER_TRACER),
-                    httpRequest.getHeader(HEADER_TRACER_CONFIG));
+                    httpRequest.getHeader(HEADER_TRACER_CONFIG), recording);
             try {
                 if (tracerContext != null) {
                     enableCollector(tracerContext);
@@ -304,14 +334,15 @@ public class LogTracer {
                              FilterChain filterChain) throws IOException, ServletException {
             SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) servletRequest;
             TracerContext tracerContext = requestContextHolder.get();
-
+            Recording recording = recorder.getRecordingForRequest(slingRequest);
+            recording.registerTracker(slingRequest.getRequestProgressTracker());
             boolean createdContext = false;
 
             //Check if the global filter created context based on HTTP headers. If not
             //then check from request params
             if (tracerContext == null) {
                 tracerContext = getTracerContext(slingRequest.getParameter(PARAM_TRACER),
-                        slingRequest.getParameter(PARAM_TRACER_CONFIG));
+                        slingRequest.getParameter(PARAM_TRACER_CONFIG), recording);
                 if (tracerContext != null) {
                     createdContext = true;
                 }
diff --git a/src/main/java/org/apache/sling/tracer/internal/Recording.java b/src/main/java/org/apache/sling/tracer/internal/Recording.java
new file mode 100644
index 0000000..947da83
--- /dev/null
+++ b/src/main/java/org/apache/sling/tracer/internal/Recording.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.tracer.internal;
+
+import org.apache.sling.api.request.RequestProgressTracker;
+
+interface Recording {
+    Recording NOOP = new Recording() {
+        @Override
+        public void log(String logger, String format, Object[] params) {
+
+        }
+
+        @Override
+        public void registerTracker(RequestProgressTracker tracker) {
+
+        }
+    };
+
+    void log(String logger, String format, Object[] params);
+
+    /**
+     * Register the {@link RequestProgressTracker} associated with
+     * current request
+     * @param tracker from current request
+     */
+    void registerTracker(RequestProgressTracker tracker);
+}
diff --git a/src/main/java/org/apache/sling/tracer/internal/TraceLogRecorder.java b/src/main/java/org/apache/sling/tracer/internal/TraceLogRecorder.java
new file mode 100644
index 0000000..11e347a
--- /dev/null
+++ b/src/main/java/org/apache/sling/tracer/internal/TraceLogRecorder.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.tracer.internal;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+interface TraceLogRecorder {
+    TraceLogRecorder DEFAULT = new TraceLogRecorder() {
+        @Override
+        public Recording startRecording(HttpServletRequest request, HttpServletResponse response) {
+            return Recording.NOOP;
+        }
+
+        @Override
+        public Recording getRecordingForRequest(HttpServletRequest request) {
+            return Recording.NOOP;
+        }
+    };
+
+    Recording startRecording(HttpServletRequest request, HttpServletResponse response);
+
+    Recording getRecordingForRequest(HttpServletRequest request);
+}
diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerContext.java b/src/main/java/org/apache/sling/tracer/internal/TracerContext.java
index b3405c4..5755ca8 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerContext.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerContext.java
@@ -27,7 +27,7 @@ import org.apache.sling.api.request.RequestProgressTracker;
 import org.slf4j.helpers.MessageFormatter;
 
 class TracerContext {
-    private static final String QUERY_LOGGER = "org.apache.jackrabbit.oak.query.QueryEngineImpl";
+    static final String QUERY_LOGGER = "org.apache.jackrabbit.oak.query.QueryEngineImpl";
 
     /**
      * Following queries are internal to Oak and are fired for login/access control
@@ -54,9 +54,11 @@ class TracerContext {
     private RequestProgressTracker progressTracker;
     private int queryCount;
     private final TracerConfig[] tracers;
+    private final Recording recording;
 
-    public TracerContext(TracerConfig[] tracers) {
+    public TracerContext(TracerConfig[] tracers, Recording recording) {
         this.tracers = tracers;
+        this.recording = recording;
 
         //Say if the list is like com.foo;level=trace,com.foo.bar;level=info.
         // Then first config would result in a match and later config would
@@ -79,6 +81,7 @@ class TracerContext {
     }
 
     public boolean log(String logger, String format, Object[] params) {
+        recording.log(logger, format, params);
         if (QUERY_LOGGER.equals(logger)
                 && params != null && params.length == 2) {
             return logQuery((String) params[1]);
diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
new file mode 100644
index 0000000..dd50def
--- /dev/null
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
@@ -0,0 +1,196 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.tracer.internal;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import org.apache.felix.webconsole.SimpleWebConsolePlugin;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.io.JSONWriter;
+import org.osgi.framework.BundleContext;
+
+class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorder {
+    static final String ATTR_REQUEST_ID = TracerLogServlet.class.getName();
+
+    public static final String CLEAR = "clear";
+
+    private static final String LABEL = "tracer";
+
+    public static final String HEADER_TRACER_RECORDING = "Sling-Tracer-Record";
+
+    public static final String HEADER_TRACER_REQUEST_ID = "Sling-Tracer-Request-Id";
+
+    private final Cache<String, JSONRecording> cache;
+
+    public TracerLogServlet(BundleContext context) {
+        super(LABEL, "Sling Tracer", "Sling", null);
+        //TODO Make things configurable
+        this.cache = CacheBuilder.newBuilder()
+                .maximumSize(100)
+                .expireAfterAccess(10, TimeUnit.MINUTES)
+                .recordStats()
+                .build();
+        register(context);
+    }
+
+    //~-----------------------------------------------< WebConsole Plugin >
+
+    @Override
+    protected void renderContent(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+        final PrintWriter pw = response.getWriter();
+        if (isHtmlRequest(request)){
+            renderStatus(pw);
+            renderRequests(pw);
+        } else {
+            String requestId = getRequestId(request);
+            prepareJSONResponse(response);
+            JSONWriter jw = new JSONWriter(pw);
+            try {
+                jw.setTidy(true);
+                jw.object();
+                if (requestId != null) {
+                    renderRequestData(requestId, jw);
+                }
+                jw.endObject();
+            } catch (JSONException e) {
+                throw new ServletException(e);
+            }
+        }
+    }
+
+    @Override
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
+            throws IOException {
+        if (req.getParameter(CLEAR) != null) {
+            resetCache();
+            resp.sendRedirect(req.getRequestURI());
+        }
+    }
+
+    @Override
+    protected boolean isHtmlRequest(HttpServletRequest request) {
+        return request.getRequestURI().endsWith(LABEL);
+    }
+
+    private static void prepareJSONResponse(HttpServletResponse response) {
+        response.setContentType("application/json");
+        response.setCharacterEncoding("UTF-8");
+    }
+
+    private void renderRequestData(String requestId, JSONWriter jw) throws JSONException {
+        JSONRecording recording = cache.getIfPresent(requestId);
+        if (recording == null){
+            jw.key("error").value("Not found");
+            return;
+        }
+        recording.render(jw);
+    }
+
+    private void renderStatus(PrintWriter pw) {
+        pw.printf("<p class='statline'>Log Tracer Recordings: %d recordings</p>%n", cache.size());
+
+        pw.println("<div class='ui-widget-header ui-corner-top buttonGroup'>");
+        pw.println("<span style='float: left; margin-left: 1em'>Tracer Recordings</span>");
+        pw.println("<form method='POST'><input type='hidden' name='clear' value='clear'><input type='submit' value='Clear' class='ui-state-default ui-corner-all'></form>");
+        pw.println("</div>");
+    }
+
+    private void renderRequests(PrintWriter pw) {
+        if (cache.size() > 0){
+            pw.println("<ul>");
+            for (String id : cache.asMap().keySet()){
+                pw.printf("<li><a href='%s/%s.json'>%s</a></li>", LABEL, id, id);
+            }
+            pw.println("</ul>");
+        }
+
+    }
+
+    private static String getRequestId(HttpServletRequest request) {
+        String requestUri = request.getRequestURI();
+        int lastSlash = requestUri.lastIndexOf('/');
+        int lastDot = requestUri.indexOf('.', lastSlash + 1);
+        if (lastDot > 0){
+            return requestUri.substring(lastSlash + 1, lastDot);
+        }
+        return null;
+    }
+
+    //~-----------------------------------------------< TraceLogRecorder >
+
+    @Override
+    public Recording startRecording(HttpServletRequest request, HttpServletResponse response) {
+        if (request.getHeader(HEADER_TRACER_RECORDING) == null){
+            return Recording.NOOP;
+        }
+
+        if (request.getAttribute(ATTR_REQUEST_ID) != null){
+            //Already processed
+            return getRecordingForRequest(request);
+        }
+
+        String requestId = generateRequestId();
+        JSONRecording recording = record(requestId, request);
+
+        request.setAttribute(ATTR_REQUEST_ID, requestId);
+
+        response.setHeader(HEADER_TRACER_REQUEST_ID, requestId);
+        //TODO Show we also sent tracer version to enable client determine
+        //is server is capable of given version
+        return recording;
+    }
+
+    @Override
+    public Recording getRecordingForRequest(HttpServletRequest request) {
+        String requestId = (String) request.getAttribute(ATTR_REQUEST_ID);
+        if (requestId != null){
+            return getRecording(requestId);
+        }
+        return Recording.NOOP;
+    }
+
+    Recording getRecording(String requestId) {
+        Recording recording = cache.getIfPresent(requestId);
+        return recording == null ? Recording.NOOP : recording;
+    }
+
+    private JSONRecording record(String requestId, HttpServletRequest request) {
+        JSONRecording data = new JSONRecording(request);
+        cache.put(requestId, data);
+        return data;
+    }
+
+    private static String generateRequestId() {
+        return UUID.randomUUID().toString();
+    }
+
+    void resetCache(){
+        cache.invalidateAll();
+    }
+}
diff --git a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
new file mode 100644
index 0000000..5c5ae4e
--- /dev/null
+++ b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.tracer.internal;
+
+import java.io.StringWriter;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.sling.commons.json.JSONObject;
+import org.apache.sling.commons.json.io.JSONWriter;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class JSONRecordingTest {
+    private HttpServletRequest request = mock(HttpServletRequest.class);
+
+    @Test
+    public void logQueries() throws Exception{
+        StringWriter sw = new StringWriter();
+
+        when(request.getMethod()).thenReturn("GET");
+        JSONRecording r = new JSONRecording(request);
+
+        r.log(TracerContext.QUERY_LOGGER, "foo bar", new Object[]{"x" , "y"});
+        r.log(TracerContext.QUERY_LOGGER, "foo bar", new Object[]{"x" , "z"});
+
+        JSONWriter jw = new JSONWriter(sw).object();
+        r.render(jw);
+        jw.endObject();
+
+        JSONObject json = new JSONObject(sw.toString());
+        assertEquals("GET", json.get("method"));
+        assertEquals(2, json.getJSONArray("queries").length());
+    }
+
+    @Test
+    public void requestTrackerLogs() throws Exception{
+        StringWriter sw = new StringWriter();
+        JSONRecording r = new JSONRecording(request);
+
+        r.registerTracker(TestUtil.createTracker("x", "y"));
+
+        JSONWriter jw = new JSONWriter(sw).object();
+        r.render(jw);
+        jw.endObject();
+
+        JSONObject json = new JSONObject(sw.toString());
+        assertEquals(2, json.getJSONArray("logs").length());
+    }
+
+}
diff --git a/src/test/java/org/apache/sling/tracer/internal/LogTracerModelTest.java b/src/test/java/org/apache/sling/tracer/internal/LogTracerModelTest.java
index 09c55f1..2b1d7c0 100644
--- a/src/test/java/org/apache/sling/tracer/internal/LogTracerModelTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/LogTracerModelTest.java
@@ -86,7 +86,7 @@ public class LogTracerModelTest {
     }
 
     private static TracerContext getContext(TracerSet ts) {
-        return new TracerContext(ts.getConfigs().toArray(new TracerConfig[ts.getConfigs().size()]));
+        return new TracerContext(ts.getConfigs().toArray(new TracerConfig[ts.getConfigs().size()]), Recording.NOOP);
     }
 
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java b/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
index d476a64..ba0f5ab 100644
--- a/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
@@ -25,6 +25,7 @@ import java.util.List;
 
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
+import javax.servlet.Servlet;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
@@ -39,9 +40,11 @@ import ch.qos.logback.core.read.ListAppender;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
 import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.request.RequestProgressTracker;
 import org.apache.sling.testing.mock.osgi.MockOsgi;
 import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
 import org.apache.sling.testing.mock.osgi.junit.OsgiContextCallback;
+import org.apache.sling.testing.mock.sling.servlet.MockSlingHttpServletRequest;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TestWatcher;
@@ -50,12 +53,15 @@ import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.ServiceReference;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.sling.tracer.internal.TestUtil.createTracker;
+import static org.apache.sling.tracer.internal.TestUtil.getRequestId;
 import static org.hamcrest.CoreMatchers.hasItem;
 import static org.hamcrest.CoreMatchers.not;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 import static org.slf4j.LoggerFactory.getLogger;
@@ -89,12 +95,25 @@ public class LogTracerTest {
         LogTracer tracer = context.registerInjectActivateService(new LogTracer(),
                 ImmutableMap.<String, Object>of("enabled", "true"));
         assertEquals(2, context.getServices(Filter.class, null).length);
+        assertNull(context.getService(Servlet.class));
 
         MockOsgi.deactivate(tracer);
         assertNull(context.getService(Filter.class));
     }
 
     @Test
+    public void enableTracerLogServlet() throws Exception {
+        LogTracer tracer = context.registerInjectActivateService(new LogTracer(),
+                ImmutableMap.<String, Object>of("enabled", "true", "servletEnabled", "true"));
+        assertEquals(2, context.getServices(Filter.class, null).length);
+        assertNotNull(context.getService(Servlet.class));
+
+        MockOsgi.deactivate(tracer);
+        assertNull(context.getService(Filter.class));
+        assertNull(context.getService(Servlet.class));
+    }
+
+    @Test
     public void noTurboFilterRegisteredUnlessTracingRequested() throws Exception {
         HttpServletRequest request = mock(HttpServletRequest.class);
         HttpServletResponse response = mock(HttpServletResponse.class);
@@ -206,12 +225,54 @@ public class LogTracerTest {
         rootLogger().setLevel(oldLevel);
     }
 
+    @Test
+    public void recordingWithoutTracing() throws Exception{
+        activateTracerAndServlet();
+        MockSlingHttpServletRequest request = new MockSlingHttpServletRequest(){
+            @Override
+            public RequestProgressTracker getRequestProgressTracker() {
+                return createTracker("x", "y");
+            }
+        };
+        request.setHeader(TracerLogServlet.HEADER_TRACER_RECORDING, "true");
+
+        HttpServletResponse response = mock(HttpServletResponse.class);
+
+        FilterChain chain = new FilterChain() {
+            @Override
+            public void doFilter(ServletRequest request, ServletResponse response)
+                    throws IOException, ServletException {
+                //No TurboFilter should be registered if tracing is not requested
+                assertNull(context.getService(TurboFilter.class));
+            }
+        };
+
+        prepareChain(chain).doFilter(request, response);
+
+        String requestId = getRequestId(response);
+        assertNotNull(requestId);
+        Recording r = ((TracerLogServlet)context.getService(Servlet.class)).getRecording(requestId);
+        assertTrue(r instanceof JSONRecording);
+        assertNotNull(((JSONRecording)r).getTracker());
+    }
+
 
     private void activateTracer() {
         context.registerInjectActivateService(new LogTracer(),
                 ImmutableMap.<String, Object>of("enabled", "true"));
     }
 
+    private void activateTracerAndServlet() {
+        context.registerInjectActivateService(new LogTracer(),
+                ImmutableMap.<String, Object>of("enabled", "true", "servletEnabled", "true"));
+    }
+
+    private FilterChain prepareChain(FilterChain end) throws InvalidSyntaxException {
+        Filter servletFilter = getFilter(false);
+        Filter slingFilter = getFilter(true);
+        return new FilterChainImpl(end, servletFilter, slingFilter);
+    }
+
     private Filter getFilter(boolean slingFilter) throws InvalidSyntaxException {
         Collection<ServiceReference<Filter>> refs =
                 context.bundleContext().getServiceReferences(Filter.class, null);
@@ -269,4 +330,24 @@ public class LogTracerTest {
         }
     }
 
+    private static class FilterChainImpl implements FilterChain {
+        private final Filter[] filters;
+        private final FilterChain delegate;
+        private int pos;
+
+        public FilterChainImpl(FilterChain delegate, Filter ... filter){
+            this.delegate = delegate;
+            this.filters = filter;
+        }
+
+        @Override
+        public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
+            if (pos == filters.length){
+                delegate.doFilter(request, response);
+            } else {
+                filters[pos++].doFilter(request, response, this);
+            }
+        }
+    }
+
 }
diff --git a/src/test/java/org/apache/sling/tracer/internal/TestUtil.java b/src/test/java/org/apache/sling/tracer/internal/TestUtil.java
new file mode 100644
index 0000000..935b931
--- /dev/null
+++ b/src/test/java/org/apache/sling/tracer/internal/TestUtil.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.tracer.internal;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.api.request.RequestProgressTracker;
+import org.mockito.ArgumentCaptor;
+
+import static java.util.Arrays.asList;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+class TestUtil {
+
+    static RequestProgressTracker createTracker(String ... logs){
+        RequestProgressTracker tracker = mock(RequestProgressTracker.class);
+        when(tracker.getMessages()).thenReturn(asList(logs).iterator());
+        return tracker;
+    }
+
+    static String getRequestId(HttpServletResponse response){
+        ArgumentCaptor<String> requestIdCaptor = ArgumentCaptor.forClass(String.class);
+        verify(response).setHeader(eq(TracerLogServlet.HEADER_TRACER_REQUEST_ID), requestIdCaptor.capture());
+        return requestIdCaptor.getValue();
+    }
+}
diff --git a/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java b/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
new file mode 100644
index 0000000..21f7dcb
--- /dev/null
+++ b/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.tracer.internal;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+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;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import static org.apache.sling.tracer.internal.TestUtil.createTracker;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+public class TracerLogServletTest {
+
+    @Rule
+    public final OsgiContext context = new OsgiContext();
+    @Rule
+    public final MockitoRule mockito = MockitoJUnit.rule();
+
+    @Mock
+    private HttpServletRequest request;
+    @Mock
+    private HttpServletResponse response;
+
+    @Test
+    public void noRecordingByDefault() throws Exception{
+        TracerLogServlet logServlet = new TracerLogServlet(context.bundleContext());
+        assertSame(Recording.NOOP, logServlet.startRecording(request, response));
+        assertSame(Recording.NOOP, logServlet.getRecordingForRequest(request));
+    }
+
+    @Test
+    public void recordingWhenRequested() throws Exception{
+        TracerLogServlet logServlet = new TracerLogServlet(context.bundleContext());
+        request = new MockSlingHttpServletRequest();
+
+        Recording recording = logServlet.startRecording(request, response);
+        assertNotNull(recording);
+
+        //Once recording is created then it should be returned
+        Recording recording2 = logServlet.getRecordingForRequest(request);
+        assertSame(recording, recording2);
+
+        //Repeated call should return same recording instance
+        Recording recording3 = logServlet.startRecording(request, response);
+        assertSame(recording, recording3);
+
+        logServlet.resetCache();
+
+        //If recording gets lost then NOOP must be returned
+        Recording recording4 = logServlet.getRecordingForRequest(request);
+        assertSame(Recording.NOOP, recording4);
+    }
+
+    @Test
+    public void jsonRendering() throws Exception{
+        TracerLogServlet logServlet = new TracerLogServlet(context.bundleContext());
+        when(request.getMethod()).thenReturn("GET");
+        when(request.getHeader(TracerLogServlet.HEADER_TRACER_RECORDING)).thenReturn("true");
+
+        Recording recording = logServlet.startRecording(request, response);
+        recording.registerTracker(createTracker("x" ,"y"));
+
+        ArgumentCaptor<String> requestIdCaptor = ArgumentCaptor.forClass(String.class);
+        verify(response).setHeader(eq(TracerLogServlet.HEADER_TRACER_REQUEST_ID), requestIdCaptor.capture());
+
+        StringWriter sw = new StringWriter();
+        when(response.getWriter()).thenReturn(new PrintWriter(sw));
+        when(request.getRequestURI()).thenReturn("/system/console/" + requestIdCaptor.getValue() + ".json" );
+
+        logServlet.renderContent(request, response);
+        JSONObject json = new JSONObject(sw.toString());
+        assertEquals("GET", json.getString("method"));
+        assertEquals(2, json.getJSONArray("logs").length());
+    }
+
+    @Test
+    public void pluginRendering() throws Exception{
+        TracerLogServlet logServlet = new TracerLogServlet(context.bundleContext());
+        when(request.getRequestURI()).thenReturn("/system/console/tracer" );
+
+        StringWriter sw = new StringWriter();
+        when(response.getWriter()).thenReturn(new PrintWriter(sw));
+        logServlet.renderContent(request, response);
+
+        assertThat(sw.toString(), containsString("Log Tracer"));
+    }
+}

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 11/30: SLING-5459 - Recording of tracer logs

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 80bc14894a73d281be5ce682944f4e31a3cd53bb
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Wed Feb 10 05:52:31 2016 +0000

    SLING-5459 - Recording of tracer logs
    
    Refactor to pass on the FormattingTuple so as to allow separate rendering of the logs in recording
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729530 13f79535-47bb-0310-9956-ffa450edef68
---
 .../sling/tracer/internal/JSONRecording.java       |  4 +++-
 .../apache/sling/tracer/internal/Recording.java    |  5 ++--
 .../sling/tracer/internal/TracerContext.java       | 28 ++++++++++++++--------
 .../sling/tracer/internal/JSONRecordingTest.java   |  5 ++--
 4 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index 0b103bd..8980ff9 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -34,6 +34,7 @@ import org.apache.sling.commons.json.JSONException;
 import org.apache.sling.commons.json.io.JSONWriter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.slf4j.helpers.FormattingTuple;
 
 class JSONRecording implements Recording {
     private static final Logger log = LoggerFactory.getLogger(JSONRecording.class);
@@ -59,7 +60,8 @@ class JSONRecording implements Recording {
     //~---------------------------------------< Recording >
 
     @Override
-    public void log(Level level, String logger, String format, Object[] params) {
+    public void log(Level level, String logger, FormattingTuple tuple) {
+        Object[] params = tuple.getArgArray();
         if (TracerContext.QUERY_LOGGER.equals(logger)
                 && params != null && params.length == 2) {
             queries.add((String) params[1]);
diff --git a/src/main/java/org/apache/sling/tracer/internal/Recording.java b/src/main/java/org/apache/sling/tracer/internal/Recording.java
index 7e24f14..d915474 100644
--- a/src/main/java/org/apache/sling/tracer/internal/Recording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/Recording.java
@@ -21,11 +21,12 @@ package org.apache.sling.tracer.internal;
 
 import ch.qos.logback.classic.Level;
 import org.apache.sling.api.request.RequestProgressTracker;
+import org.slf4j.helpers.FormattingTuple;
 
 interface Recording {
     Recording NOOP = new Recording() {
         @Override
-        public void log(Level level, String logger, String format, Object[] params) {
+        public void log(Level level, String logger, FormattingTuple tuple) {
 
         }
 
@@ -40,7 +41,7 @@ interface Recording {
         }
     };
 
-    void log(Level level, String logger, String format, Object[] params);
+    void log(Level level, String logger, FormattingTuple tuple);
 
     /**
      * Register the {@link RequestProgressTracker} associated with
diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerContext.java b/src/main/java/org/apache/sling/tracer/internal/TracerContext.java
index 4931255..47615e9 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerContext.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerContext.java
@@ -24,6 +24,7 @@ import java.util.Arrays;
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.core.helpers.CyclicBuffer;
 import org.apache.sling.api.request.RequestProgressTracker;
+import org.slf4j.helpers.FormattingTuple;
 import org.slf4j.helpers.MessageFormatter;
 
 class TracerContext {
@@ -81,12 +82,19 @@ class TracerContext {
     }
 
     public boolean log(Level level, String logger, String format, Object[] params) {
-        recording.log(level, logger, format, params);
+        FormattingTuple tuple;
+
         if (QUERY_LOGGER.equals(logger)
                 && params != null && params.length == 2) {
-            return logQuery((String) params[1]);
+            tuple = logQuery((String) params[1]);
+        } else {
+            tuple = logWithLoggerName(logger, format, params);
+        }
+
+        if (tuple != null) {
+            recording.log(level, logger, tuple);
         }
-        return logWithLoggerName(logger, format, params);
+        return tuple != null;
     }
 
     public void done() {
@@ -109,8 +117,9 @@ class TracerContext {
         }
     }
 
-    private boolean logWithLoggerName(String loggerName, String format, Object... params) {
-        String msg = MessageFormatter.arrayFormat(format, params).getMessage();
+    private FormattingTuple logWithLoggerName(String loggerName, String format, Object... params) {
+        FormattingTuple tuple = MessageFormatter.arrayFormat(format, params);
+        String msg = tuple.getMessage();
         msg = "[" + loggerName + "] " + msg;
         if (progressTracker == null) {
             if (buffer == null) {
@@ -120,16 +129,15 @@ class TracerContext {
         } else {
             progressTracker.log(msg);
         }
-        return true;
+        return tuple;
     }
 
-    private boolean logQuery(String query) {
+    private FormattingTuple logQuery(String query) {
         if (ignorableQuery(query)) {
-            return false;
+            return null;
         }
         queryCount++;
-        logWithLoggerName("JCR", " Query {}", query);
-        return true;
+        return logWithLoggerName("JCR", " Query {}", query);
     }
 
     private boolean ignorableQuery(String msg) {
diff --git a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
index f7c1736..159555e 100644
--- a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
@@ -26,6 +26,7 @@ import javax.servlet.http.HttpServletRequest;
 import ch.qos.logback.classic.Level;
 import org.apache.sling.commons.json.JSONObject;
 import org.junit.Test;
+import org.slf4j.helpers.MessageFormatter;
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Mockito.mock;
@@ -41,8 +42,8 @@ public class JSONRecordingTest {
         when(request.getMethod()).thenReturn("GET");
         JSONRecording r = new JSONRecording("abc", request);
 
-        r.log(Level.INFO, TracerContext.QUERY_LOGGER, "foo bar", new Object[]{"x" , "y"});
-        r.log(Level.INFO, TracerContext.QUERY_LOGGER, "foo bar", new Object[]{"x" , "z"});
+        r.log(Level.INFO, TracerContext.QUERY_LOGGER, MessageFormatter.arrayFormat("foo bar", new Object[]{"x" , "y"}));
+        r.log(Level.INFO, TracerContext.QUERY_LOGGER, MessageFormatter.arrayFormat("foo bar", new Object[]{"x" , "z"}));
 
         r.done();
         r.render(sw);

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 14/30: SLING-5459 - Recording of tracer logs

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 338f7fbb693c104b0e4309b2ecac1aca9108f0ba
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Wed Feb 10 05:53:13 2016 +0000

    SLING-5459 - Recording of tracer logs
    
    Expose the size of recording in web console
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729533 13f79535-47bb-0310-9956-ffa450edef68
---
 .../sling/tracer/internal/JSONRecording.java       | 13 ++++++++
 .../sling/tracer/internal/TracerLogServlet.java    | 37 +++++++++++++++++++---
 2 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index a7b29d9..592477b 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -50,6 +50,7 @@ class JSONRecording implements Recording {
     private static final Logger log = LoggerFactory.getLogger(JSONRecording.class);
     private final String method;
     private final String requestId;
+    private final String uri;
     private final List<String> queries = new ArrayList<String>();
     private final List<LogEntry> logs = new ArrayList<LogEntry>();
     private RequestProgressTracker tracker;
@@ -58,6 +59,7 @@ class JSONRecording implements Recording {
     public JSONRecording(String requestId, HttpServletRequest r) {
         this.requestId = requestId;
         this.method = r.getMethod();
+        this.uri = r.getRequestURI();
     }
 
     public boolean render(Writer w) throws IOException {
@@ -77,6 +79,17 @@ class JSONRecording implements Recording {
         return false;
     }
 
+    public long size() {
+        if (json != null){
+            return json.length;
+        }
+        return 0;
+    }
+
+    public String getUri() {
+        return uri;
+    }
+
     //~---------------------------------------< Recording >
 
     @Override
diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
index ae9d1b8..827d890 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
@@ -21,6 +21,7 @@ package org.apache.sling.tracer.internal;
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.TimeUnit;
 
@@ -116,7 +117,8 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
     }
 
     private void renderStatus(PrintWriter pw) {
-        pw.printf("<p class='statline'>Log Tracer Recordings: %d recordings</p>%n", cache.size());
+        pw.printf("<p class='statline'>Log Tracer Recordings: %d recordings, %s memory</p>%n", cache.size(),
+                memorySize());
 
         pw.println("<div class='ui-widget-header ui-corner-top buttonGroup'>");
         pw.println("<span style='float: left; margin-left: 1em'>Tracer Recordings</span>");
@@ -124,15 +126,25 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
         pw.println("</div>");
     }
 
+    private String memorySize() {
+        long size = 0;
+        for (JSONRecording r : cache.asMap().values()){
+            size += r.size();
+        }
+        return humanReadableByteCount(size);
+    }
+
     private void renderRequests(PrintWriter pw) {
         if (cache.size() > 0){
             pw.println("<ul>");
-            for (String id : cache.asMap().keySet()){
-                pw.printf("<li><a href='%s/%s.json'>%s</a></li>", LABEL, id, id);
+            for (Map.Entry<String, JSONRecording> e : cache.asMap().entrySet()){
+                String id = e.getKey();
+                JSONRecording r = e.getValue();
+                pw.printf("<li><a href='%s/%s.json'>%s</a> - %s (%s)</li>", LABEL, id, id, r.getUri(),
+                        humanReadableByteCount(r.size()));
             }
             pw.println("</ul>");
         }
-
     }
 
     private static String getRequestId(HttpServletRequest request) {
@@ -193,6 +205,23 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
         return UUID.randomUUID().toString();
     }
 
+    /**
+     * Returns a human-readable version of the file size, where the input represents
+     * a specific number of bytes. Based on http://stackoverflow.com/a/3758880/1035417
+     */
+    private static String humanReadableByteCount(long bytes) {
+        if (bytes < 0) {
+            return "0";
+        }
+        int unit = 1000;
+        if (bytes < unit) {
+            return bytes + " B";
+        }
+        int exp = (int) (Math.log(bytes) / Math.log(unit));
+        char pre = "kMGTPE".charAt(exp - 1);
+        return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
+    }
+
     void resetCache(){
         cache.invalidateAll();
     }

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 05/30: SLING-5459 - Recording of tracer logs

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit eb0d0c0365938ecb081c4433568398e68e5f7897
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Tue Feb 2 11:00:56 2016 +0000

    SLING-5459 - Recording of tracer logs
    
    Tracer servlet would now send a protocol version version against header 'Sling-Tracer-Protocol-Version'. For now its value is 1. This would allow client to determine if they can work against this server or not
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1728082 13f79535-47bb-0310-9956-ffa450edef68
---
 .../java/org/apache/sling/tracer/internal/TracerLogServlet.java   | 8 ++++++--
 .../org/apache/sling/tracer/internal/TracerLogServletTest.java    | 2 ++
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
index dd50def..479f6dc 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
@@ -46,6 +46,10 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
 
     public static final String HEADER_TRACER_REQUEST_ID = "Sling-Tracer-Request-Id";
 
+    public static final String HEADER_TRACER_PROTOCOL_VERSION = "Sling-Tracer-Protocol-Version";
+
+    public static final int TRACER_PROTOCOL_VERSION = 1;
+
     private final Cache<String, JSONRecording> cache;
 
     public TracerLogServlet(BundleContext context) {
@@ -161,8 +165,8 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
         request.setAttribute(ATTR_REQUEST_ID, requestId);
 
         response.setHeader(HEADER_TRACER_REQUEST_ID, requestId);
-        //TODO Show we also sent tracer version to enable client determine
-        //is server is capable of given version
+        response.setHeader(HEADER_TRACER_PROTOCOL_VERSION, String.valueOf(TRACER_PROTOCOL_VERSION));
+
         return recording;
     }
 
diff --git a/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java b/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
index 21f7dcb..5a3c24b 100644
--- a/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
@@ -98,6 +98,8 @@ public class TracerLogServletTest {
 
         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));
 
         StringWriter sw = new StringWriter();
         when(response.getWriter()).thenReturn(new PrintWriter(sw));

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 13/30: SLING-5459 - Recording of tracer logs

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit bdc2fb698d5e125cc0d403f9376ad1dedf452fc0
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Wed Feb 10 05:52:55 2016 +0000

    SLING-5459 - Recording of tracer logs
    
    Changed the storage to byte[] instead of string. This would further reduce the memory footprint of the recording
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729532 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            |  6 ++++
 .../sling/tracer/internal/JSONRecording.java       | 37 ++++++++++++++++++----
 .../sling/tracer/internal/TracerLogServlet.java    |  5 +--
 .../tracer/internal/TracerLogServletTest.java      | 22 +++++++++++--
 4 files changed, 58 insertions(+), 12 deletions(-)

diff --git a/pom.xml b/pom.xml
index 2918dd9..1a0bf46 100644
--- a/pom.xml
+++ b/pom.xml
@@ -121,6 +121,12 @@
       <version>4.2.0</version>
     </dependency>
     <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>1.4</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
       <groupId>org.apache.sling</groupId>
       <artifactId>org.apache.sling.commons.json</artifactId>
       <version>2.0.8</version>
diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index cf1cea3..a7b29d9 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -19,9 +19,16 @@
 
 package org.apache.sling.tracer.internal;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
+import java.io.Reader;
 import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
 import java.io.Writer;
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -30,6 +37,7 @@ import java.util.List;
 import javax.servlet.http.HttpServletRequest;
 
 import ch.qos.logback.classic.Level;
+import org.apache.commons.io.IOUtils;
 import org.apache.sling.api.request.RequestProgressTracker;
 import org.apache.sling.commons.json.JSONException;
 import org.apache.sling.commons.json.io.JSONWriter;
@@ -45,16 +53,25 @@ class JSONRecording implements Recording {
     private final List<String> queries = new ArrayList<String>();
     private final List<LogEntry> logs = new ArrayList<LogEntry>();
     private RequestProgressTracker tracker;
-    private String json;
+    private byte[] json;
 
     public JSONRecording(String requestId, HttpServletRequest r) {
         this.requestId = requestId;
         this.method = r.getMethod();
     }
 
-    public boolean render(Writer pw) throws IOException {
+    public boolean render(Writer w) throws IOException {
         if (json != null) {
-            pw.write(json);
+            Reader r = new InputStreamReader(new ByteArrayInputStream(json), "UTF-8");
+            IOUtils.copy(r, w);
+            return true;
+        }
+        return false;
+    }
+
+    public boolean render(OutputStream os) throws IOException {
+        if (json != null) {
+            os.write(json);
             return true;
         }
         return false;
@@ -91,12 +108,17 @@ class JSONRecording implements Recording {
             }
         } catch (JSONException e) {
             log.warn("Error occurred while converting the log data for request {} to JSON", requestId, e);
+        } catch (UnsupportedEncodingException e) {
+            log.warn("Error occurred while converting the log data for request {} to JSON", requestId, e);
+        } catch (IOException e) {
+            log.warn("Error occurred while converting the log data for request {} to JSON", requestId, e);
         }
     }
 
-    private String toJSON() throws JSONException {
-        StringWriter sw = new StringWriter();
-        JSONWriter jw = new JSONWriter(sw);
+    private byte[] toJSON() throws JSONException, IOException {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        OutputStreamWriter osw = new OutputStreamWriter(baos, "UTF-8");
+        JSONWriter jw = new JSONWriter(osw);
         jw.setTidy(true);
         jw.object();
         jw.key("method").value(method);
@@ -121,7 +143,8 @@ class JSONRecording implements Recording {
 
         addJson(jw, "logs", logs);
         jw.endObject();
-        return sw.toString();
+        osw.flush();
+        return baos.toByteArray();
     }
 
     private void addJson(JSONWriter jw, String name, List<? extends JsonEntry> entries) throws JSONException {
diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
index 2684f40..ae9d1b8 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
@@ -67,8 +67,8 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
 
     @Override
     protected void renderContent(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
-        final PrintWriter pw = response.getWriter();
         if (isHtmlRequest(request)){
+            PrintWriter pw = response.getWriter();
             renderStatus(pw);
             renderRequests(pw);
         } else {
@@ -79,11 +79,12 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
                 if (requestId != null) {
                     JSONRecording recording = cache.getIfPresent(requestId);
                     if (recording != null){
-                        responseDone = recording.render(pw);
+                        responseDone = recording.render(response.getOutputStream());
                     }
                 }
 
                 if (!responseDone) {
+                    PrintWriter pw = response.getWriter();
                     JSONWriter jw = new JSONWriter(pw);
                     jw.object();
                     jw.key("error").value("Not found");
diff --git a/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java b/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
index 5514dd1..7866544 100644
--- a/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
@@ -19,9 +19,12 @@
 
 package org.apache.sling.tracer.internal;
 
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 
+import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
@@ -102,12 +105,12 @@ public class TracerLogServletTest {
         verify(response).setHeader(TracerLogServlet.HEADER_TRACER_PROTOCOL_VERSION,
                 String.valueOf(TracerLogServlet.TRACER_PROTOCOL_VERSION));
 
-        StringWriter sw = new StringWriter();
-        when(response.getWriter()).thenReturn(new PrintWriter(sw));
+        ByteArrayServletOutputStream sos = new ByteArrayServletOutputStream();
+        when(response.getOutputStream()).thenReturn(sos);
         when(request.getRequestURI()).thenReturn("/system/console/" + requestIdCaptor.getValue() + ".json" );
 
         logServlet.renderContent(request, response);
-        JSONObject json = new JSONObject(sw.toString());
+        JSONObject json = new JSONObject(sos.baos.toString("UTF-8"));
         assertEquals("GET", json.getString("method"));
         assertEquals(2, json.getJSONArray("requestProgressLogs").length());
     }
@@ -123,4 +126,17 @@ public class TracerLogServletTest {
 
         assertThat(sw.toString(), containsString("Log Tracer"));
     }
+
+    private static class ByteArrayServletOutputStream extends ServletOutputStream {
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        @Override
+        public void write(int b) throws IOException {
+            baos.write(b);
+        }
+
+        @Override
+        public void write(byte[] b, int off, int len) throws IOException {
+            baos.write(b, off, len);
+        }
+    }
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 06/30: SLING-5459 - Recording of tracer logs

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit e284239ebae4b0ae746476d0dceee1c3c1b42926
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Tue Feb 9 10:31:36 2016 +0000

    SLING-5459 - Recording of tracer logs
    
    Add link to Tracer docs in Bundle Headers
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729350 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/pom.xml b/pom.xml
index d6ed36c..2918dd9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -54,6 +54,13 @@
         <groupId>org.apache.felix</groupId>
         <artifactId>maven-bundle-plugin</artifactId>
         <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-DocURL>
+              https://sling.apache.org/documentation/bundles/log-tracers.html
+            </Bundle-DocURL>
+          </instructions>
+        </configuration>
       </plugin>
       <plugin>
         <groupId>org.apache.felix</groupId>

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 26/30: SLING-5505 - Allow recording of caller stacktrace with the logs

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 7065d836f13864894982d869e449d6e562f87e4b
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Thu Feb 11 08:45:13 2016 +0000

    SLING-5505 - Allow recording of caller stacktrace with the logs
    
    Change the config name to caller-exclude-filter
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729774 13f79535-47bb-0310-9956-ffa450edef68
---
 src/main/java/org/apache/sling/tracer/internal/TracerSet.java     | 2 +-
 src/test/java/org/apache/sling/tracer/internal/TracerSetTest.java | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerSet.java b/src/main/java/org/apache/sling/tracer/internal/TracerSet.java
index 176d57a..9c8139f 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerSet.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerSet.java
@@ -29,7 +29,7 @@ import org.apache.sling.commons.osgi.ManifestHeader;
 class TracerSet {
     public static final String LEVEL = "level";
     public static final String CALLER = "caller";
-    public static final String CALLER_PREFIX_FILTER = "callerPrefixFilter";
+    public static final String CALLER_PREFIX_FILTER = "caller-exclude-filter";
 
     private final String name;
     private final List<TracerConfig> configs;
diff --git a/src/test/java/org/apache/sling/tracer/internal/TracerSetTest.java b/src/test/java/org/apache/sling/tracer/internal/TracerSetTest.java
index fda855c..d7d71cd 100644
--- a/src/test/java/org/apache/sling/tracer/internal/TracerSetTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/TracerSetTest.java
@@ -59,7 +59,7 @@ public class TracerSetTest {
 
     @Test
     public void prefixFilter() throws Exception{
-        CallerStackReporter r = TracerSet.createReporter(createEntry("foo;caller=28;callerPrefixFilter=\"a|b\""));
+        CallerStackReporter r = TracerSet.createReporter(createEntry("foo;caller=28;caller-exclude-filter=\"a|b\""));
         assertNotNull(r);
         assertEquals(28, r.getDepth());
         assertTrue(r.getCallerFilter() instanceof PrefixExcludeFilter);

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 07/30: SLING-5459 - Recording of tracer logs

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 0f4f997095730885a9eae4d09dbc2f7c0746dbf3
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Tue Feb 9 10:39:12 2016 +0000

    SLING-5459 - Recording of tracer logs
    
    Move JSON rendering logic to recording
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729352 13f79535-47bb-0310-9956-ffa450edef68
---
 .../sling/tracer/internal/JSONRecording.java       | 10 ++++++--
 .../sling/tracer/internal/TracerLogServlet.java    | 27 +++++++++++-----------
 .../sling/tracer/internal/JSONRecordingTest.java   |  9 ++------
 3 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index 7682e8e..391684f 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -19,6 +19,7 @@
 
 package org.apache.sling.tracer.internal;
 
+import java.io.Writer;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -38,14 +39,18 @@ class JSONRecording implements Recording {
         this.method = r.getMethod();
     }
 
-    public void render(JSONWriter jw) throws JSONException {
+    public void render(Writer pw) throws JSONException {
+        JSONWriter jw = new JSONWriter(pw);
+        jw.setTidy(true);
+        jw.object();
         jw.key("method").value(method);
 
         if (tracker != null) {
             jw.key("logs");
             jw.array();
             Iterator<String> it = tracker.getMessages();
-            while (it.hasNext()) {
+            //Per docs iterator can be null
+            while (it != null && it.hasNext()) {
                 jw.value(it.next());
             }
             jw.endArray();
@@ -57,6 +62,7 @@ class JSONRecording implements Recording {
             jw.value(q);
         }
         jw.endArray();
+        jw.endObject();
     }
 
     //~---------------------------------------< Recording >
diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
index 479f6dc..7af8dfc 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
@@ -74,14 +74,22 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
         } else {
             String requestId = getRequestId(request);
             prepareJSONResponse(response);
-            JSONWriter jw = new JSONWriter(pw);
             try {
-                jw.setTidy(true);
-                jw.object();
+                boolean responseDone = false;
                 if (requestId != null) {
-                    renderRequestData(requestId, jw);
+                    JSONRecording recording = cache.getIfPresent(requestId);
+                    if (recording != null){
+                        recording.render(pw);
+                        responseDone = true;
+                    }
+                }
+
+                if (!responseDone) {
+                    JSONWriter jw = new JSONWriter(pw);
+                    jw.object();
+                    jw.key("error").value("Not found");
+                    jw.endObject();
                 }
-                jw.endObject();
             } catch (JSONException e) {
                 throw new ServletException(e);
             }
@@ -107,15 +115,6 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
         response.setCharacterEncoding("UTF-8");
     }
 
-    private void renderRequestData(String requestId, JSONWriter jw) throws JSONException {
-        JSONRecording recording = cache.getIfPresent(requestId);
-        if (recording == null){
-            jw.key("error").value("Not found");
-            return;
-        }
-        recording.render(jw);
-    }
-
     private void renderStatus(PrintWriter pw) {
         pw.printf("<p class='statline'>Log Tracer Recordings: %d recordings</p>%n", cache.size());
 
diff --git a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
index 5c5ae4e..560dc2d 100644
--- a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
@@ -24,7 +24,6 @@ import java.io.StringWriter;
 import javax.servlet.http.HttpServletRequest;
 
 import org.apache.sling.commons.json.JSONObject;
-import org.apache.sling.commons.json.io.JSONWriter;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
@@ -44,9 +43,7 @@ public class JSONRecordingTest {
         r.log(TracerContext.QUERY_LOGGER, "foo bar", new Object[]{"x" , "y"});
         r.log(TracerContext.QUERY_LOGGER, "foo bar", new Object[]{"x" , "z"});
 
-        JSONWriter jw = new JSONWriter(sw).object();
-        r.render(jw);
-        jw.endObject();
+        r.render(sw);
 
         JSONObject json = new JSONObject(sw.toString());
         assertEquals("GET", json.get("method"));
@@ -60,9 +57,7 @@ public class JSONRecordingTest {
 
         r.registerTracker(TestUtil.createTracker("x", "y"));
 
-        JSONWriter jw = new JSONWriter(sw).object();
-        r.render(jw);
-        jw.endObject();
+        r.render(sw);
 
         JSONObject json = new JSONObject(sw.toString());
         assertEquals(2, json.getJSONArray("logs").length());

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 18/30: SLING-5504 - Reduce memory footprint of stored recording data

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit d4dc99292d651642dc5cfd757bd66f85ead4f84e
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Wed Feb 10 08:56:02 2016 +0000

    SLING-5504 - Reduce memory footprint of stored recording data
    
    Clear the request attribute at the end
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729552 13f79535-47bb-0310-9956-ffa450edef68
---
 src/main/java/org/apache/sling/tracer/internal/LogTracer.java         | 2 +-
 src/main/java/org/apache/sling/tracer/internal/TraceLogRecorder.java  | 4 ++--
 src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java  | 3 ++-
 .../java/org/apache/sling/tracer/internal/TracerLogServletTest.java   | 2 +-
 4 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/LogTracer.java b/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
index 2f6940b..17993f1 100644
--- a/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
+++ b/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
@@ -347,7 +347,7 @@ public class LogTracer {
                 if (tracerContext != null) {
                     disableCollector();
                 }
-                recorder.endRecording(recording);
+                recorder.endRecording(httpRequest, recording);
             }
         }
 
diff --git a/src/main/java/org/apache/sling/tracer/internal/TraceLogRecorder.java b/src/main/java/org/apache/sling/tracer/internal/TraceLogRecorder.java
index d00e617..6aeb313 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TraceLogRecorder.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TraceLogRecorder.java
@@ -35,7 +35,7 @@ interface TraceLogRecorder {
         }
 
         @Override
-        public void endRecording(Recording recording) {
+        public void endRecording(HttpServletRequest httpRequest, Recording recording) {
 
         }
     };
@@ -44,5 +44,5 @@ interface TraceLogRecorder {
 
     Recording getRecordingForRequest(HttpServletRequest request);
 
-    void endRecording(Recording recording);
+    void endRecording(HttpServletRequest httpRequest, Recording recording);
 }
diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
index 4eb028e..0a53631 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
@@ -227,12 +227,13 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
     }
 
     @Override
-    public void endRecording(Recording recording) {
+    public void endRecording(HttpServletRequest httpRequest, Recording recording) {
         if (recording instanceof JSONRecording) {
             JSONRecording r = (JSONRecording) recording;
             r.done();
             cache.put(r.getRequestId(), r);
         }
+        httpRequest.removeAttribute(ATTR_RECORDING);
     }
 
     Recording getRecording(String requestId) {
diff --git a/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java b/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
index 5404380..61c1a9f 100644
--- a/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
@@ -99,7 +99,7 @@ public class TracerLogServletTest {
 
         Recording recording = logServlet.startRecording(request, response);
         recording.registerTracker(createTracker("x" ,"y"));
-        logServlet.endRecording(recording);
+        logServlet.endRecording(request, recording);
 
         ArgumentCaptor<String> requestIdCaptor = ArgumentCaptor.forClass(String.class);
         verify(response).setHeader(eq(TracerLogServlet.HEADER_TRACER_REQUEST_ID), requestIdCaptor.capture());

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 27/30: SLING-5459 - Recording of tracer logs

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit c6dad281d70457a496b993fbd1fa90f528df963c
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Mon Feb 15 13:59:06 2016 +0000

    SLING-5459 - Recording of tracer logs
    
    Trim the request progress logs as they have extra space at starting and a new line feed at end
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1730532 13f79535-47bb-0310-9956-ffa450edef68
---
 .../sling/tracer/internal/JSONRecording.java       | 27 ++++++++++++++--------
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index a319a45..a88a250 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -174,16 +174,7 @@ class JSONRecording implements Recording, Comparable<JSONRecording> {
         jw.key("time").value(timeTaken);
         jw.key("timestamp").value(start);
 
-        if (tracker != null) {
-            jw.key("requestProgressLogs");
-            jw.array();
-            Iterator<String> it = tracker.getMessages();
-            //Per docs iterator can be null
-            while (it != null && it.hasNext()) {
-                jw.value(it.next());
-            }
-            jw.endArray();
-        }
+        addRequestProgressLogs(jw);
 
         queryCollector.done();
         addJson(jw, "queries", queries);
@@ -195,6 +186,22 @@ class JSONRecording implements Recording, Comparable<JSONRecording> {
         return baos.toByteArray();
     }
 
+    private void addRequestProgressLogs(JSONWriter jw) throws JSONException {
+        if (tracker != null) {
+            jw.key("requestProgressLogs");
+            jw.array();
+            Iterator<String> it = tracker.getMessages();
+            //Per docs iterator can be null
+            while (it != null && it.hasNext()) {
+                String entry = it.next();
+                if (entry != null){
+                    jw.value(entry.trim());
+                }
+            }
+            jw.endArray();
+        }
+    }
+
     private void addJson(JSONWriter jw, String name, List<? extends JsonEntry> entries) throws JSONException {
         jw.key(name);
         jw.array();

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 19/30: SLING-5459 - Recording of tracer logs

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 96a80a77c78c1b4f42522995154f84683caccd33
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Wed Feb 10 08:56:29 2016 +0000

    SLING-5459 - Recording of tracer logs
    
    Recording now also includes
    -- Log entry timestamp
    -- Start time of request
    -- Time taken for the request processing
    
    The WebConsole view now shows Recording link in order of occurrence
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729553 13f79535-47bb-0310-9956-ffa450edef68
---
 .../sling/tracer/internal/JSONRecording.java       | 25 ++++++++++++++++++++-
 .../sling/tracer/internal/TracerLogServlet.java    | 26 +++++++++++++++-------
 .../sling/tracer/internal/JSONRecordingTest.java   |  4 ++++
 3 files changed, 46 insertions(+), 9 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index 57ce0d1..e823a96 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -37,9 +37,11 @@ import java.util.List;
 import java.util.zip.GZIPInputStream;
 import java.util.zip.GZIPOutputStream;
 
+import javax.annotation.Nonnull;
 import javax.servlet.http.HttpServletRequest;
 
 import ch.qos.logback.classic.Level;
+import com.google.common.primitives.Longs;
 import org.apache.commons.io.IOUtils;
 import org.apache.sling.api.request.RequestProgressTracker;
 import org.apache.sling.commons.json.JSONException;
@@ -49,7 +51,7 @@ import org.slf4j.LoggerFactory;
 import org.slf4j.helpers.FormattingTuple;
 import org.slf4j.helpers.MessageFormatter;
 
-class JSONRecording implements Recording {
+class JSONRecording implements Recording, Comparable<JSONRecording> {
     private static final Logger log = LoggerFactory.getLogger(JSONRecording.class);
     private final String method;
     private final String requestId;
@@ -59,6 +61,8 @@ class JSONRecording implements Recording {
     private final List<LogEntry> logs = new ArrayList<LogEntry>();
     private RequestProgressTracker tracker;
     private byte[] json;
+    private final long start = System.currentTimeMillis();
+    private long timeTaken;
 
     public JSONRecording(String requestId, HttpServletRequest r, boolean compress) {
         this.requestId = requestId;
@@ -99,6 +103,14 @@ class JSONRecording implements Recording {
         return requestId;
     }
 
+    public long getTimeTaken() {
+        return timeTaken;
+    }
+
+    public long getStart() {
+        return start;
+    }
+
     //~---------------------------------------< Recording >
 
     @Override
@@ -148,6 +160,10 @@ class JSONRecording implements Recording {
         jw.object();
         jw.key("method").value(method);
 
+        timeTaken = System.currentTimeMillis() - start;
+        jw.key("time").value(timeTaken);
+        jw.key("timestamp").value(start);
+
         if (tracker != null) {
             jw.key("requestProgressLogs");
             jw.array();
@@ -192,6 +208,11 @@ class JSONRecording implements Recording {
         return is;
     }
 
+    @Override
+    public int compareTo(@Nonnull JSONRecording o) {
+        return Longs.compare(start, o.start);
+    }
+
     private interface JsonEntry {
         void toJson(JSONWriter jw) throws JSONException;
     }
@@ -200,6 +221,7 @@ class JSONRecording implements Recording {
         final Level level;
         final String logger;
         final FormattingTuple tuple;
+        final long timestamp = System.currentTimeMillis();
 
         private LogEntry(Level level, String logger, FormattingTuple tuple) {
             this.level = level != null ? level : Level.INFO;
@@ -220,6 +242,7 @@ class JSONRecording implements Recording {
 
         @Override
         public void toJson(JSONWriter jw) throws JSONException {
+            jw.key("timestamp").value(timestamp);
             jw.key("level").value(level.levelStr);
             jw.key("logger").value(logger);
             jw.key("message").value(tuple.getMessage());
diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
index 0a53631..1e31013 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
@@ -21,7 +21,11 @@ package org.apache.sling.tracer.internal;
 
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.util.Map;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
 import java.util.UUID;
 import java.util.concurrent.TimeUnit;
 
@@ -174,14 +178,20 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
 
     private void renderRequests(PrintWriter pw) {
         if (cache.size() > 0){
-            pw.println("<ul>");
-            for (Map.Entry<String, JSONRecording> e : cache.asMap().entrySet()){
-                String id = e.getKey();
-                JSONRecording r = e.getValue();
-                pw.printf("<li><a href='%s/%s.json'>%s</a> - %s (%s)</li>", LABEL, id, id, r.getUri(),
-                        humanReadableByteCount(r.size()));
+            pw.println("<ol>");
+            List<JSONRecording> recordings = new ArrayList<JSONRecording>(cache.asMap().values());
+            SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
+            Collections.sort(recordings);
+            for (JSONRecording r : recordings){
+                String id = r.getRequestId();
+                String date = sdf.format(new Date(r.getStart()));
+                pw.printf("<li>%s - <a href='%s/%s.json'>%s</a> - %s (%s) (%dms)</li>",
+                        date, LABEL, id, id,
+                        r.getUri(),
+                        humanReadableByteCount(r.size()),
+                        r.getTimeTaken());
             }
-            pw.println("</ul>");
+            pw.println("</ol>");
         }
     }
 
diff --git a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
index 473b7e7..65041f8 100644
--- a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
@@ -32,6 +32,7 @@ import org.slf4j.helpers.MessageFormatter;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -53,6 +54,8 @@ public class JSONRecordingTest {
 
         JSONObject json = new JSONObject(sw.toString());
         assertEquals("GET", json.get("method"));
+        assertTrue(json.has("time"));
+        assertTrue(json.has("timestamp"));
         assertEquals(2, json.getJSONArray("queries").length());
     }
 
@@ -93,6 +96,7 @@ public class JSONRecordingTest {
         assertEquals(tp1.getMessage(), l1.getString("message"));
         assertEquals(1, l1.getJSONArray("params").length());
         assertFalse(l1.has("exception"));
+        assertTrue(l1.has("timestamp"));
 
         JSONObject l3 = json.getJSONArray("logs").getJSONObject(2);
         assertNotNull(l3.get("exception"));

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 30/30: [maven-release-plugin] copy for tag org.apache.sling.tracer-1.0.0

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 2e41f0ab8d52ba40925af030c68e9a447d122b95
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Tue Apr 19 10:07:24 2016 +0000

    [maven-release-plugin] copy for tag org.apache.sling.tracer-1.0.0
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/tags/org.apache.sling.tracer-1.0.0@1739887 13f79535-47bb-0310-9956-ffa450edef68

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 25/30: SLING-5505 - Allow recording of caller stacktrace with the logs

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 02f853e01a8e43b4658f8f0e2bfa26ff457a7c53
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Thu Feb 11 07:15:11 2016 +0000

    SLING-5505 - Allow recording of caller stacktrace with the logs
    
    Caller stack trace would be included if `caller` is set to true. One can specify the list packages which should be excluded with `callerPrefixFilter`
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729769 13f79535-47bb-0310-9956-ffa450edef68
---
 .../apache/sling/tracer/internal/CallerFilter.java | 31 ++++++++
 .../sling/tracer/internal/CallerStackReporter.java | 93 ++++++++++++++++++++++
 .../sling/tracer/internal/JSONRecording.java       | 23 +++++-
 .../sling/tracer/internal/PrefixExcludeFilter.java | 57 +++++++++++++
 .../apache/sling/tracer/internal/TracerConfig.java | 19 ++++-
 .../apache/sling/tracer/internal/TracerSet.java    | 32 +++++++-
 .../sling/tracer/internal/CallerFinderTest.java    | 10 +--
 .../tracer/internal/CallerStackReporterTest.java   | 72 +++++++++++++++++
 .../sling/tracer/internal/JSONRecordingTest.java   | 20 ++++-
 .../sling/tracer/internal/TracerSetTest.java       | 74 +++++++++++++++++
 10 files changed, 421 insertions(+), 10 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/CallerFilter.java b/src/main/java/org/apache/sling/tracer/internal/CallerFilter.java
new file mode 100644
index 0000000..56d8ca7
--- /dev/null
+++ b/src/main/java/org/apache/sling/tracer/internal/CallerFilter.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.tracer.internal;
+
+interface CallerFilter {
+    CallerFilter ALL = new CallerFilter() {
+        @Override
+        public boolean include(StackTraceElement ste) {
+            return true;
+        }
+    };
+
+    boolean include(StackTraceElement ste);
+}
diff --git a/src/main/java/org/apache/sling/tracer/internal/CallerStackReporter.java b/src/main/java/org/apache/sling/tracer/internal/CallerStackReporter.java
new file mode 100644
index 0000000..59006bb
--- /dev/null
+++ b/src/main/java/org/apache/sling/tracer/internal/CallerStackReporter.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.tracer.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+
+class CallerStackReporter {
+    /**
+     * Package names which should be excluded from the stack as they do not serve
+     * any purpose and bloat the size
+     */
+    private static final CallerFilter FWK_EXCLUDE_FILTER = new PrefixExcludeFilter(asList(
+            "java.lang.Thread",
+            "org.apache.sling.tracer.internal",
+            "ch.qos.logback.classic",
+            "sun.reflect",
+            "java.lang.reflect"
+    ));
+    private final CallerFilter callerFilter;
+    private final int start;
+    private final int depth;
+
+    public CallerStackReporter(int depth){
+        this(0, depth, CallerFilter.ALL);
+    }
+
+    public CallerStackReporter(int start, int depth, CallerFilter filter){
+        this.start = start;
+        this.depth = depth;
+        this.callerFilter = filter;
+    }
+
+    public List<StackTraceElement> report(){
+        return report(Thread.currentThread().getStackTrace());
+    }
+
+    public List<StackTraceElement> report(StackTraceElement[] stack){
+        List<StackTraceElement> filteredStack = fwkExcludedStack(stack);
+        List<StackTraceElement> result = new ArrayList<StackTraceElement>(filteredStack.size());
+
+        //Iterate over the filtered stack with limits applicable on that not on actual stack
+        for (int i = 0; i < filteredStack.size(); i++) {
+            StackTraceElement ste = filteredStack.get(i);
+            if (i >=  start && i < depth
+                    && callerFilter.include(ste)){
+                result.add(ste);
+            }
+        }
+        return result;
+    }
+
+    private List<StackTraceElement> fwkExcludedStack(StackTraceElement[] stack) {
+        List<StackTraceElement> filteredStack = new ArrayList<StackTraceElement>(stack.length);
+        for (StackTraceElement ste : stack) {
+            if (FWK_EXCLUDE_FILTER.include(ste)){
+                filteredStack.add(ste);
+            }
+        }
+        return filteredStack;
+    }
+
+    public CallerFilter getCallerFilter() {
+        return callerFilter;
+    }
+
+    public int getStart() {
+        return start;
+    }
+
+    public int getDepth() {
+        return depth;
+    }
+}
diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index f508e9e..a319a45 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -32,6 +32,7 @@ import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
 import java.io.Writer;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.zip.GZIPInputStream;
@@ -129,7 +130,7 @@ class JSONRecording implements Recording, Comparable<JSONRecording> {
         if (logger.startsWith(OAK_QUERY_PKG)) {
             queryCollector.record(level, logger, tuple);
         }
-        logs.add(new LogEntry(level, logger, tuple));
+        logs.add(new LogEntry(tc, level, logger, tuple));
     }
 
     @Override
@@ -233,11 +234,20 @@ class JSONRecording implements Recording, Comparable<JSONRecording> {
         final String logger;
         final FormattingTuple tuple;
         final long timestamp = System.currentTimeMillis();
+        final List<StackTraceElement> caller;
 
-        private LogEntry(Level level, String logger, FormattingTuple tuple) {
+        private LogEntry(TracerConfig tc, Level level, String logger, FormattingTuple tuple) {
             this.level = level != null ? level : Level.INFO;
             this.logger = logger;
             this.tuple = tuple;
+            this.caller = getCallerData(tc);
+        }
+
+        private static List<StackTraceElement> getCallerData(TracerConfig tc) {
+            if (tc.isReportCallerStack()){
+                return tc.getCallerReporter().report();
+            }
+            return Collections.emptyList();
         }
 
         private static String toString(Object o) {
@@ -274,6 +284,15 @@ class JSONRecording implements Recording, Comparable<JSONRecording> {
                 jw.key("exception").value(getStackTraceAsString(t));
 
             }
+
+            if (!caller.isEmpty()){
+                jw.key("caller");
+                jw.array();
+                for (StackTraceElement o : caller) {
+                    jw.value(o.toString());
+                }
+                jw.endArray();
+            }
         }
     }
 
diff --git a/src/main/java/org/apache/sling/tracer/internal/PrefixExcludeFilter.java b/src/main/java/org/apache/sling/tracer/internal/PrefixExcludeFilter.java
new file mode 100644
index 0000000..8199010
--- /dev/null
+++ b/src/main/java/org/apache/sling/tracer/internal/PrefixExcludeFilter.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.tracer.internal;
+
+import java.util.List;
+
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableList;
+
+/**
+ * Filter which returns false if the package of stack trace element
+ * is part of exclude list of prefixes
+ */
+class PrefixExcludeFilter implements CallerFilter{
+    private final List<String> prefixesToExclude;
+
+    public PrefixExcludeFilter(List<String> prefixes) {
+        this.prefixesToExclude = ImmutableList.copyOf(prefixes);
+    }
+
+    public static PrefixExcludeFilter from(String filter){
+        List<String> prefixes = Splitter.on('|').omitEmptyStrings().trimResults().splitToList(filter);
+        return new PrefixExcludeFilter(prefixes);
+    }
+
+    @Override
+    public boolean include(StackTraceElement ste) {
+        String className = ste.getClassName();
+        for (String prefix : prefixesToExclude){
+            if (className.startsWith(prefix)){
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public List<String> getPrefixesToExclude() {
+        return prefixesToExclude;
+    }
+}
diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerConfig.java b/src/main/java/org/apache/sling/tracer/internal/TracerConfig.java
index 8f7a65b..597d93c 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerConfig.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerConfig.java
@@ -19,6 +19,9 @@
 
 package org.apache.sling.tracer.internal;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 import ch.qos.logback.classic.Level;
 import ch.qos.logback.core.CoreConstants;
 
@@ -37,11 +40,17 @@ class TracerConfig implements Comparable<TracerConfig> {
     private final String loggerName;
     private final Level level;
     private final int depth;
+    private final CallerStackReporter callerReporter;
 
     public TracerConfig(String loggerName, Level level) {
+        this(loggerName, level, null);
+    }
+
+    public TracerConfig(String loggerName, Level level,@Nullable CallerStackReporter reporter) {
         this.loggerName = loggerName;
         this.level = level;
         this.depth = getDepth(loggerName);
+        this.callerReporter = reporter;
     }
 
     public boolean match(String loggerName) {
@@ -59,7 +68,7 @@ class TracerConfig implements Comparable<TracerConfig> {
     }
 
     @Override
-    public int compareTo(TracerConfig o) {
+    public int compareTo(@Nonnull TracerConfig o) {
         int comp = depth > o.depth ? -1 : depth < o.depth ? 1 : 0;
         if (comp == 0) {
             comp = loggerName.compareTo(o.loggerName);
@@ -79,6 +88,14 @@ class TracerConfig implements Comparable<TracerConfig> {
         return level;
     }
 
+    public boolean isReportCallerStack(){
+        return callerReporter != null;
+    }
+
+    public CallerStackReporter getCallerReporter() {
+        return callerReporter;
+    }
+
     private static int getDepth(String loggerName) {
         int depth = 0;
         int fromIndex = 0;
diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerSet.java b/src/main/java/org/apache/sling/tracer/internal/TracerSet.java
index c4bcdbb..176d57a 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerSet.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerSet.java
@@ -28,6 +28,9 @@ import org.apache.sling.commons.osgi.ManifestHeader;
 
 class TracerSet {
     public static final String LEVEL = "level";
+    public static final String CALLER = "caller";
+    public static final String CALLER_PREFIX_FILTER = "callerPrefixFilter";
+
     private final String name;
     private final List<TracerConfig> configs;
 
@@ -72,8 +75,35 @@ class TracerSet {
 
             //Defaults to Debug
             Level level = Level.valueOf(e.getAttributeValue(LEVEL));
-            result.add(new TracerConfig(category, level));
+            CallerStackReporter reporter = createReporter(e);
+            result.add(new TracerConfig(category, level, reporter));
         }
         return Collections.unmodifiableList(result);
     }
+
+    static CallerStackReporter createReporter(ManifestHeader.Entry e) {
+        String caller = e.getAttributeValue(CALLER);
+        if (caller == null){
+            return null;
+        }
+
+        if ("true".equals(caller)){
+            return new CallerStackReporter(0, Integer.MAX_VALUE, CallerFilter.ALL);
+        }
+
+        CallerFilter filter = CallerFilter.ALL;
+        int depth;
+        try{
+            depth = Integer.parseInt(caller);
+        } catch (NumberFormatException ignore){
+            return null;
+        }
+
+        String filterValue = e.getAttributeValue(CALLER_PREFIX_FILTER);
+        if (filterValue != null){
+            filter = PrefixExcludeFilter.from(filterValue);
+        }
+
+        return new CallerStackReporter(0, depth, filter);
+    }
 }
diff --git a/src/test/java/org/apache/sling/tracer/internal/CallerFinderTest.java b/src/test/java/org/apache/sling/tracer/internal/CallerFinderTest.java
index 29906ef..fc104f9 100644
--- a/src/test/java/org/apache/sling/tracer/internal/CallerFinderTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/CallerFinderTest.java
@@ -30,7 +30,7 @@ public class CallerFinderTest {
     @Test
     public void determineCallerSingle() throws Exception{
         CallerFinder cf = new CallerFinder(new String[] {"o.a.s", "o.a.j.o"});
-        StackTraceElement[] stack = createStack(
+        StackTraceElement[] stack = asStack(
                 "o.a.j.o.a",
                 "o.a.j.o.b",
                 "c.a.g.w",
@@ -47,7 +47,7 @@ public class CallerFinderTest {
     @Test
     public void determineCallerMultipleApi() throws Exception{
         CallerFinder cf = new CallerFinder(new String[] {"o.a.s", "o.a.j.o"});
-        StackTraceElement[] stack = createStack(
+        StackTraceElement[] stack = asStack(
                 "o.a.j.o.a",
                 "o.a.j.o.b",
                 "o.a.s.a",
@@ -62,7 +62,7 @@ public class CallerFinderTest {
         assertNotNull(caller);
         assertEquals("c.a.g.w", caller.getClassName());
 
-        stack = createStack(
+        stack = asStack(
                 "o.a.j.o.a",
                 "o.a.j.o.b",
                 "o.a.s.a",
@@ -89,7 +89,7 @@ public class CallerFinderTest {
     @Test
     public void nullCaller() throws Exception{
         CallerFinder cf = new CallerFinder(new String[] {"o.a1.s", "o.a1.j.o"});
-        StackTraceElement[] stack = createStack(
+        StackTraceElement[] stack = asStack(
                 "o.a.j.o.a",
                 "o.a.j.o.b",
                 "o.a.s.a",
@@ -104,7 +104,7 @@ public class CallerFinderTest {
         assertNull(caller);
     }
 
-    private static StackTraceElement[] createStack(String ... stack){
+    static StackTraceElement[] asStack(String ... stack){
         StackTraceElement[] result = new StackTraceElement[stack.length];
         for (int i = 0; i < stack.length; i++) {
             result[i] = new StackTraceElement(stack[i], "foo", null, 0);
diff --git a/src/test/java/org/apache/sling/tracer/internal/CallerStackReporterTest.java b/src/test/java/org/apache/sling/tracer/internal/CallerStackReporterTest.java
new file mode 100644
index 0000000..8ae067e
--- /dev/null
+++ b/src/test/java/org/apache/sling/tracer/internal/CallerStackReporterTest.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.tracer.internal;
+
+import java.util.List;
+
+import org.junit.Test;
+
+import static org.apache.sling.tracer.internal.CallerFinderTest.asStack;
+import static org.junit.Assert.assertArrayEquals;
+
+public class CallerStackReporterTest {
+
+    @Test
+    public void startAndStop() throws Exception {
+        StackTraceElement[] s = asStack("0", "1", "2", "3", "4", "5");
+        assertArrayEquals(new String[]{"0", "1", "2", "3"}, arr(new CallerStackReporter(4).report(s)));
+        assertArrayEquals(new String[]{"0"}, arr(new CallerStackReporter(1).report(s)));
+        assertArrayEquals(new String[]{"2", "3"}, arr(new CallerStackReporter(2, 4, CallerFilter.ALL).report(s)));
+    }
+
+    @Test
+    public void filter() throws Exception{
+        StackTraceElement[] s = asStack("0", "1", "2", "3", "4", "5");
+        CallerFilter f = new CallerFilter() {
+            @Override
+            public boolean include(StackTraceElement ste) {
+                String name = ste.getClassName();
+                return name.equals("1") || name.equals("2");
+            }
+        };
+
+        assertArrayEquals(new String[]{"1", "2"}, arr(new CallerStackReporter(0, 4, f).report(s)));
+    }
+
+    @Test
+    public void prefixFilter() throws Exception{
+        StackTraceElement[] s = asStack("a.b.c", "a.b.d", "f.g.h", "m.g.i", "4", "5");
+        assertArrayEquals(new String[]{"a.b.c", "a.b.d", "f.g.h", "m.g.i"},
+                arr(new CallerStackReporter(0, 4, CallerFilter.ALL).report(s)));
+
+        CallerFilter f = PrefixExcludeFilter.from("a.b|f.g");
+        assertArrayEquals(new String[]{"m.g.i"},
+                arr(new CallerStackReporter(0, 4, f).report(s)));
+    }
+
+    private static String[] arr(List<StackTraceElement> list) {
+        String[] result = new String[list.size()];
+        for (int i = 0; i < list.size(); i++) {
+            result[i] = list.get(i).getClassName();
+        }
+        return result;
+    }
+
+}
\ No newline at end of file
diff --git a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
index 14ab480..8daf2b4 100644
--- a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
@@ -25,7 +25,6 @@ import javax.servlet.http.HttpServletRequest;
 
 import ch.qos.logback.classic.Level;
 import org.apache.sling.commons.json.JSONObject;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.slf4j.MDC;
 import org.slf4j.helpers.FormattingTuple;
@@ -104,12 +103,31 @@ public class JSONRecordingTest {
         assertEquals(tp1.getMessage(), l1.getString("message"));
         assertEquals(1, l1.getJSONArray("params").length());
         assertFalse(l1.has("exception"));
+        assertFalse(l1.has("caller"));
         assertTrue(l1.has("timestamp"));
 
         JSONObject l3 = json.getJSONArray("logs").getJSONObject(2);
         assertNotNull(l3.get("exception"));
     }
 
+    @Test
+    public void logsWithCaller() throws Exception{
+        StringWriter sw = new StringWriter();
+        final JSONRecording r = new JSONRecording("abc", request, true);
+
+        TracerConfig config = new TracerConfig(TracerContext.QUERY_LOGGER,
+                Level.INFO, new CallerStackReporter(20));
+        r.log(config, Level.INFO, "foo", tuple("foo"));
+
+        r.done();
+        r.render(sw);
+
+        JSONObject json = new JSONObject(sw.toString());
+        JSONObject l1 = json.getJSONArray("logs").getJSONObject(0);
+        assertTrue(l1.has("caller"));
+        assertTrue(l1.getJSONArray("caller").length() > 0);
+    }
+
     private static FormattingTuple tuple(String msg){
         return MessageFormatter.format(msg, null);
     }
diff --git a/src/test/java/org/apache/sling/tracer/internal/TracerSetTest.java b/src/test/java/org/apache/sling/tracer/internal/TracerSetTest.java
new file mode 100644
index 0000000..fda855c
--- /dev/null
+++ b/src/test/java/org/apache/sling/tracer/internal/TracerSetTest.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.tracer.internal;
+
+import org.apache.sling.commons.osgi.ManifestHeader;
+import org.junit.Test;
+
+import static java.util.Arrays.asList;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+
+public class TracerSetTest {
+    
+    @Test
+    public void nullReporter() throws Exception{
+        CallerStackReporter r = TracerSet.createReporter(createEntry("foo"));
+        assertNull(r);
+    }
+
+    @Test
+    public void completeStack() throws Exception{
+        CallerStackReporter r = TracerSet.createReporter(createEntry("foo;caller=true"));
+        assertNotNull(r);
+        assertEquals(Integer.MAX_VALUE, r.getDepth());
+    }
+
+    @Test
+    public void depthSpecified() throws Exception{
+        CallerStackReporter r = TracerSet.createReporter(createEntry("foo;caller=28"));
+        assertNotNull(r);
+        assertEquals(28, r.getDepth());
+    }
+
+    @Test
+    public void invalidDepth() throws Exception{
+        CallerStackReporter r = TracerSet.createReporter(createEntry("foo;caller=abc"));
+        assertNull(r);
+    }
+
+    @Test
+    public void prefixFilter() throws Exception{
+        CallerStackReporter r = TracerSet.createReporter(createEntry("foo;caller=28;callerPrefixFilter=\"a|b\""));
+        assertNotNull(r);
+        assertEquals(28, r.getDepth());
+        assertTrue(r.getCallerFilter() instanceof PrefixExcludeFilter);
+        PrefixExcludeFilter f = (PrefixExcludeFilter) r.getCallerFilter();
+        assertEquals(asList("a", "b"), f.getPrefixesToExclude());
+    }
+
+    private static ManifestHeader.Entry createEntry(String config){
+        ManifestHeader parsedConfig = ManifestHeader.parse(config);
+        return parsedConfig.getEntries()[0];
+    }
+}

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 20/30: SLING-5504 - Reduce memory footprint of stored recording data

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 1a9ba7e53153ebed4e3b98cc4b5b3b0778ee13cf
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Wed Feb 10 09:59:39 2016 +0000

    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
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729569 13f79535-47bb-0310-9956-ffa450edef68
---
 .../sling/tracer/internal/JSONRecording.java       | 16 ++++++---
 .../apache/sling/tracer/internal/LogTracer.java    | 16 +++++++--
 .../sling/tracer/internal/TracerLogServlet.java    | 40 ++++++++++++++++++++--
 .../sling/tracer/internal/LogTracerTest.java       | 35 +++++++++++++++----
 .../tracer/internal/TracerLogServletTest.java      | 32 +++++++++++++++++
 5 files changed, 122 insertions(+), 17 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index e823a96..f8f785e 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -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, Comparable<JSONRecording> {
 
     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, Comparable<JSONRecording> {
         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);
         }
diff --git a/src/main/java/org/apache/sling/tracer/internal/LogTracer.java b/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
index 17993f1..3cb42d7 100644
--- a/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
+++ b/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
@@ -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);
         }
diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
index 1e31013..b8081e5 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
@@ -66,19 +66,24 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
 
     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 SimpleWebConsolePlugin implements TraceLogRecorde
         return compressRecording;
     }
 
+    public boolean isGzipResponse() {
+        return gzipResponse;
+    }
+
     int getCacheSizeInMB() {
         return cacheSizeInMB;
     }
@@ -121,7 +130,8 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
                 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 SimpleWebConsolePlugin implements TraceLogRecorde
         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");
diff --git a/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java b/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
index 296c168..ec4a867 100644
--- a/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
@@ -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 {
diff --git a/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java b/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
index 61c1a9f..546a406 100644
--- a/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
@@ -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" );

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 29/30: [maven-release-plugin] prepare release org.apache.sling.tracer-1.0.0

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 15a3ae39ef60f76ac1e33ed94ed4519406c5799d
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Tue Apr 19 10:07:10 2016 +0000

    [maven-release-plugin] prepare release org.apache.sling.tracer-1.0.0
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1739886 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/pom.xml b/pom.xml
index 185cfb2..55a3821 100644
--- a/pom.xml
+++ b/pom.xml
@@ -30,7 +30,7 @@
 
   <artifactId>org.apache.sling.tracer</artifactId>
   <packaging>bundle</packaging>
-  <version>0.0.3-SNAPSHOT</version>
+  <version>1.0.0</version>
 
   <name>Apache Sling Log Tracer</name>
   <description>
@@ -42,9 +42,9 @@
   </description>
 
   <scm>
-    <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer</connection>
-    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer</developerConnection>
-    <url>http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/tracer</url>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/sling/tags/org.apache.sling.tracer-1.0.0</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/tags/org.apache.sling.tracer-1.0.0</developerConnection>
+    <url>http://svn.apache.org/viewvc/sling/tags/org.apache.sling.tracer-1.0.0</url>
   </scm>
 
 

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 08/30: SLING-5459 - Recording of tracer logs

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit c5e3f3245324ffc98d0978110bca3181cfa0a5fb
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Tue Feb 9 10:39:35 2016 +0000

    SLING-5459 - Recording of tracer logs
    
    Changed the approach to serialize the whole recording as json at the end of the request processing. This would help in conserving memory usage.  Also  then we can size the recording and enforce limit on size, keep json in compressed state etc
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729353 13f79535-47bb-0310-9956-ffa450edef68
---
 .../sling/tracer/internal/JSONRecording.java       | 74 +++++++++++++++-------
 .../apache/sling/tracer/internal/LogTracer.java    |  1 +
 .../apache/sling/tracer/internal/Recording.java    | 10 +++
 .../sling/tracer/internal/TracerLogServlet.java    |  5 +-
 .../sling/tracer/internal/JSONRecordingTest.java   |  6 +-
 .../sling/tracer/internal/LogTracerTest.java       | 10 ++-
 .../tracer/internal/TracerLogServletTest.java      |  1 +
 7 files changed, 79 insertions(+), 28 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index 391684f..9c8340e 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -19,6 +19,8 @@
 
 package org.apache.sling.tracer.internal;
 
+import java.io.IOException;
+import java.io.StringWriter;
 import java.io.Writer;
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -29,18 +31,64 @@ import javax.servlet.http.HttpServletRequest;
 import org.apache.sling.api.request.RequestProgressTracker;
 import org.apache.sling.commons.json.JSONException;
 import org.apache.sling.commons.json.io.JSONWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 class JSONRecording implements Recording {
+    private static final Logger log = LoggerFactory.getLogger(JSONRecording.class);
     private final String method;
+    private final String requestId;
     private final List<String> queries = new ArrayList<String>();
     private RequestProgressTracker tracker;
+    private String json;
 
-    public JSONRecording(HttpServletRequest r) {
+    public JSONRecording(String requestId, HttpServletRequest r) {
+        this.requestId = requestId;
         this.method = r.getMethod();
     }
 
-    public void render(Writer pw) throws JSONException {
-        JSONWriter jw = new JSONWriter(pw);
+    public boolean render(Writer pw) throws IOException {
+        if (json != null) {
+            pw.write(json);
+            return true;
+        }
+        return false;
+    }
+
+    //~---------------------------------------< Recording >
+
+    @Override
+    public void log(String logger, String format, Object[] params) {
+        if (TracerContext.QUERY_LOGGER.equals(logger)
+                && params != null && params.length == 2) {
+            queries.add((String) params[1]);
+        }
+    }
+
+    @Override
+    public void registerTracker(RequestProgressTracker tracker) {
+        this.tracker = tracker;
+    }
+
+    @Override
+    public void done() {
+        try {
+            if (json == null) {
+                json = toJSON();
+
+                //Let the tracker and other references go to
+                //not occupy memory
+                tracker = null;
+                queries.clear();
+            }
+        } catch (JSONException e) {
+            log.warn("Error occurred while converting the log data for request {} to JSON", requestId, e);
+        }
+    }
+
+    private String toJSON() throws JSONException {
+        StringWriter sw = new StringWriter();
+        JSONWriter jw = new JSONWriter(sw);
         jw.setTidy(true);
         jw.object();
         jw.key("method").value(method);
@@ -63,24 +111,6 @@ class JSONRecording implements Recording {
         }
         jw.endArray();
         jw.endObject();
-    }
-
-    //~---------------------------------------< Recording >
-
-    @Override
-    public void log(String logger, String format, Object[] params) {
-        if (TracerContext.QUERY_LOGGER.equals(logger)
-                && params != null && params.length == 2) {
-            queries.add((String) params[1]);
-        }
-    }
-
-    @Override
-    public void registerTracker(RequestProgressTracker tracker) {
-        this.tracker = tracker;
-    }
-
-    RequestProgressTracker getTracker() {
-        return tracker;
+        return sw.toString();
     }
 }
diff --git a/src/main/java/org/apache/sling/tracer/internal/LogTracer.java b/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
index 9cfedf9..9489671 100644
--- a/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
+++ b/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
@@ -318,6 +318,7 @@ public class LogTracer {
                 if (tracerContext != null) {
                     disableCollector();
                 }
+                recording.done();
             }
         }
 
diff --git a/src/main/java/org/apache/sling/tracer/internal/Recording.java b/src/main/java/org/apache/sling/tracer/internal/Recording.java
index 947da83..1e6f058 100644
--- a/src/main/java/org/apache/sling/tracer/internal/Recording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/Recording.java
@@ -32,6 +32,11 @@ interface Recording {
         public void registerTracker(RequestProgressTracker tracker) {
 
         }
+
+        @Override
+        public void done() {
+
+        }
     };
 
     void log(String logger, String format, Object[] params);
@@ -42,4 +47,9 @@ interface Recording {
      * @param tracker from current request
      */
     void registerTracker(RequestProgressTracker tracker);
+
+    /**
+     * Invoked at the end of request processing
+     */
+    void done();
 }
diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
index 7af8dfc..2684f40 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
@@ -79,8 +79,7 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
                 if (requestId != null) {
                     JSONRecording recording = cache.getIfPresent(requestId);
                     if (recording != null){
-                        recording.render(pw);
-                        responseDone = true;
+                        responseDone = recording.render(pw);
                     }
                 }
 
@@ -184,7 +183,7 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
     }
 
     private JSONRecording record(String requestId, HttpServletRequest request) {
-        JSONRecording data = new JSONRecording(request);
+        JSONRecording data = new JSONRecording(requestId, request);
         cache.put(requestId, data);
         return data;
     }
diff --git a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
index 560dc2d..9ebd544 100644
--- a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
@@ -38,11 +38,12 @@ public class JSONRecordingTest {
         StringWriter sw = new StringWriter();
 
         when(request.getMethod()).thenReturn("GET");
-        JSONRecording r = new JSONRecording(request);
+        JSONRecording r = new JSONRecording("abc", request);
 
         r.log(TracerContext.QUERY_LOGGER, "foo bar", new Object[]{"x" , "y"});
         r.log(TracerContext.QUERY_LOGGER, "foo bar", new Object[]{"x" , "z"});
 
+        r.done();
         r.render(sw);
 
         JSONObject json = new JSONObject(sw.toString());
@@ -53,10 +54,11 @@ public class JSONRecordingTest {
     @Test
     public void requestTrackerLogs() throws Exception{
         StringWriter sw = new StringWriter();
-        JSONRecording r = new JSONRecording(request);
+        JSONRecording r = new JSONRecording("abc", request);
 
         r.registerTracker(TestUtil.createTracker("x", "y"));
 
+        r.done();
         r.render(sw);
 
         JSONObject json = new JSONObject(sw.toString());
diff --git a/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java b/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
index ba0f5ab..e23ac13 100644
--- a/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
@@ -20,6 +20,7 @@
 package org.apache.sling.tracer.internal;
 
 import java.io.IOException;
+import java.io.StringWriter;
 import java.util.Collection;
 import java.util.List;
 
@@ -41,6 +42,7 @@ import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Lists;
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.request.RequestProgressTracker;
+import org.apache.sling.commons.json.JSONObject;
 import org.apache.sling.testing.mock.osgi.MockOsgi;
 import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
 import org.apache.sling.testing.mock.osgi.junit.OsgiContextCallback;
@@ -253,7 +255,13 @@ public class LogTracerTest {
         assertNotNull(requestId);
         Recording r = ((TracerLogServlet)context.getService(Servlet.class)).getRecording(requestId);
         assertTrue(r instanceof JSONRecording);
-        assertNotNull(((JSONRecording)r).getTracker());
+        JSONRecording jr = (JSONRecording) r;
+
+        StringWriter sw = new StringWriter();
+        jr.render(sw);
+        JSONObject json = new JSONObject(sw.toString());
+
+        assertEquals(2, json.getJSONArray("logs").length());
     }
 
 
diff --git a/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java b/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
index 5a3c24b..d2090fe 100644
--- a/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/TracerLogServletTest.java
@@ -95,6 +95,7 @@ public class TracerLogServletTest {
 
         Recording recording = logServlet.startRecording(request, response);
         recording.registerTracker(createTracker("x" ,"y"));
+        recording.done();
 
         ArgumentCaptor<String> requestIdCaptor = ArgumentCaptor.forClass(String.class);
         verify(response).setHeader(eq(TracerLogServlet.HEADER_TRACER_REQUEST_ID), requestIdCaptor.capture());

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 01/30: [maven-release-plugin] prepare for next development iteration

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 2476c1007986a31711c949be78ad88ed20befdf3
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Tue Jun 16 06:33:37 2015 +0000

    [maven-release-plugin] prepare for next development iteration
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1685720 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/pom.xml b/pom.xml
index 4a3c05d..2b3235b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -30,7 +30,7 @@
 
   <artifactId>org.apache.sling.tracer</artifactId>
   <packaging>bundle</packaging>
-  <version>0.0.2</version>
+  <version>0.0.3-SNAPSHOT</version>
 
   <name>Apache Sling Log Tracer</name>
   <description>
@@ -46,9 +46,9 @@
   </properties>
 
   <scm>
-    <connection>scm:svn:http://svn.apache.org/repos/asf/sling/tags/org.apache.sling.tracer-0.0.2</connection>
-    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/tags/org.apache.sling.tracer-0.0.2</developerConnection>
-    <url>http://svn.apache.org/viewvc/sling/tags/org.apache.sling.tracer-0.0.2</url>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer</developerConnection>
+    <url>http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/tracer</url>
   </scm>
 
 

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 21/30: SLING-5505 - Allow recording of caller stacktrace with the logs

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 7c657acb4c4c03f6e6082cb467b7ee4adddc2a47
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Wed Feb 10 16:45:25 2016 +0000

    SLING-5505 - Allow recording of caller stacktrace with the logs
    
    Refactor to pass on TracerConfig to recording such that extra options for given logger can be accessed
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729650 13f79535-47bb-0310-9956-ffa450edef68
---
 .../org/apache/sling/tracer/internal/JSONRecording.java  |  2 +-
 .../java/org/apache/sling/tracer/internal/LogTracer.java |  5 +++--
 .../java/org/apache/sling/tracer/internal/Recording.java |  4 ++--
 .../org/apache/sling/tracer/internal/TracerContext.java  | 16 ++++++++++------
 .../apache/sling/tracer/internal/JSONRecordingTest.java  | 12 +++++++-----
 .../apache/sling/tracer/internal/LogTracerModelTest.java |  9 ++++-----
 6 files changed, 27 insertions(+), 21 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index f8f785e..b1e76be 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -116,7 +116,7 @@ class JSONRecording implements Recording, Comparable<JSONRecording> {
     //~---------------------------------------< Recording >
 
     @Override
-    public void log(Level level, String logger, FormattingTuple tuple) {
+    public void log(TracerConfig tc, Level level, String logger, FormattingTuple tuple) {
         Object[] params = tuple.getArgArray();
         if (TracerContext.QUERY_LOGGER.equals(logger)
                 && params != null && params.length == 2) {
diff --git a/src/main/java/org/apache/sling/tracer/internal/LogTracer.java b/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
index 3cb42d7..ea531ba 100644
--- a/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
+++ b/src/main/java/org/apache/sling/tracer/internal/LogTracer.java
@@ -419,11 +419,12 @@ public class LogTracer {
                 return FilterReply.NEUTRAL;
             }
 
-            if (tracer.shouldLog(logger.getName(), level)) {
+            TracerConfig tc = tracer.findMatchingConfig(logger.getName(), level);
+            if (tc != null) {
                 if (format == null) {
                     return FilterReply.ACCEPT;
                 }
-                if (tracer.log(level, logger.getName(), format, params)) {
+                if (tracer.log(tc, level, logger.getName(), format, params)) {
                     return FilterReply.ACCEPT;
                 }
             }
diff --git a/src/main/java/org/apache/sling/tracer/internal/Recording.java b/src/main/java/org/apache/sling/tracer/internal/Recording.java
index 9e0f88e..e7300c5 100644
--- a/src/main/java/org/apache/sling/tracer/internal/Recording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/Recording.java
@@ -26,7 +26,7 @@ import org.slf4j.helpers.FormattingTuple;
 interface Recording {
     Recording NOOP = new Recording() {
         @Override
-        public void log(Level level, String logger, FormattingTuple tuple) {
+        public void log(TracerConfig tc, Level level, String logger, FormattingTuple tuple) {
 
         }
 
@@ -36,7 +36,7 @@ interface Recording {
         }
     };
 
-    void log(Level level, String logger, FormattingTuple tuple);
+    void log(TracerConfig tc, Level level, String logger, FormattingTuple tuple);
 
     /**
      * Register the {@link RequestProgressTracker} associated with
diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerContext.java b/src/main/java/org/apache/sling/tracer/internal/TracerContext.java
index bd12def..5859bce 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerContext.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerContext.java
@@ -69,19 +69,23 @@ class TracerContext {
         Arrays.sort(tracers);
     }
 
-    public boolean shouldLog(String logger, Level level) {
+    /**
+     * Finds and returns the matching TracerConfig for given logger and level
+     * If non null it indicates that logging should proceed
+     */
+    public TracerConfig findMatchingConfig(String logger, Level level) {
         for (TracerConfig tc : tracers) {
             TracerConfig.MatchResult mr = tc.match(logger, level);
             if (mr == TracerConfig.MatchResult.MATCH_LOG) {
-                return true;
+                return tc;
             } else if (mr == TracerConfig.MatchResult.MATCH_NO_LOG) {
-                return false;
+                return null;
             }
         }
-        return false;
+        return null;
     }
 
-    public boolean log(Level level, String logger, String format, Object[] params) {
+    public boolean log(TracerConfig tc, Level level, String logger, String format, Object[] params) {
         FormattingTuple tuple = null;
         if (QUERY_LOGGER.equals(logger)
                 && params != null && params.length == 2) {
@@ -94,7 +98,7 @@ class TracerContext {
         }
 
         if (tuple != null) {
-            recording.log(level, logger, tuple);
+            recording.log(tc, level, logger, tuple);
         }
         return tuple != null;
     }
diff --git a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
index 65041f8..ac8ad3c 100644
--- a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
@@ -39,6 +39,8 @@ import static org.mockito.Mockito.when;
 public class JSONRecordingTest {
     private HttpServletRequest request = mock(HttpServletRequest.class);
 
+    private TracerConfig tc = new TracerConfig(TracerContext.QUERY_LOGGER, Level.INFO);
+
     @Test
     public void logQueries() throws Exception{
         StringWriter sw = new StringWriter();
@@ -46,8 +48,8 @@ public class JSONRecordingTest {
         when(request.getMethod()).thenReturn("GET");
         JSONRecording r = new JSONRecording("abc", request, true);
 
-        r.log(Level.INFO, TracerContext.QUERY_LOGGER, MessageFormatter.arrayFormat("foo bar", new Object[]{"x" , "y"}));
-        r.log(Level.INFO, TracerContext.QUERY_LOGGER, MessageFormatter.arrayFormat("foo bar", new Object[]{"x" , "z"}));
+        r.log(tc, Level.INFO, TracerContext.QUERY_LOGGER, MessageFormatter.arrayFormat("foo bar", new Object[]{"x" , "y"}));
+        r.log(tc, Level.INFO, TracerContext.QUERY_LOGGER, MessageFormatter.arrayFormat("foo bar", new Object[]{"x" , "z"}));
 
         r.done();
         r.render(sw);
@@ -79,9 +81,9 @@ public class JSONRecordingTest {
         JSONRecording r = new JSONRecording("abc", request, true);
 
         FormattingTuple tp1 = MessageFormatter.arrayFormat("{} is going", new Object[]{"Jack"});
-        r.log(Level.INFO, "foo", tp1);
-        r.log(Level.WARN, "foo.bar", MessageFormatter.arrayFormat("Jill is going", null));
-        r.log(Level.ERROR, "foo.bar",
+        r.log(tc, Level.INFO, "foo", tp1);
+        r.log(tc, Level.WARN, "foo.bar", MessageFormatter.arrayFormat("Jill is going", null));
+        r.log(tc, Level.ERROR, "foo.bar",
                 MessageFormatter.arrayFormat("Jack and {} is going", new Object[]{"Jill" , new Exception()}));
 
         r.done();
diff --git a/src/test/java/org/apache/sling/tracer/internal/LogTracerModelTest.java b/src/test/java/org/apache/sling/tracer/internal/LogTracerModelTest.java
index 2b1d7c0..96c0bad 100644
--- a/src/test/java/org/apache/sling/tracer/internal/LogTracerModelTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/LogTracerModelTest.java
@@ -24,9 +24,8 @@ import ch.qos.logback.classic.Level;
 import org.junit.Test;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertNull;
 
 public class LogTracerModelTest {
 
@@ -56,9 +55,9 @@ public class LogTracerModelTest {
         TracerSet ts = new TracerSet("foo : a.b;level=trace, a.b.c;level=info");
         TracerContext tc = getContext(ts);
 
-        assertTrue(tc.shouldLog("a.b", Level.TRACE));
-        assertTrue(tc.shouldLog("a.b.d", Level.TRACE));
-        assertFalse(tc.shouldLog("a.b.c", Level.TRACE));
+        assertNotNull(tc.findMatchingConfig("a.b", Level.TRACE));
+        assertNotNull(tc.findMatchingConfig("a.b.d", Level.TRACE));
+        assertNull(tc.findMatchingConfig("a.b.c", Level.TRACE));
     }
 
     @Test

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 02/30: Contrib: remove superflous sling.java.version=6 as it's the default now

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit a1ede00eafdba145baa15752ced68145246b8513
Author: Robert Munteanu <ro...@apache.org>
AuthorDate: Thu Jun 25 13:16:35 2015 +0000

    Contrib: remove superflous sling.java.version=6 as it's the default now
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1687508 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/pom.xml b/pom.xml
index 2b3235b..38391b2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -41,10 +41,6 @@
     Refer to http://sling.apache.org/documentation/bundles/log-tracers.html
   </description>
 
-  <properties>
-    <sling.java.version>6</sling.java.version>
-  </properties>
-
   <scm>
     <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer</connection>
     <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer</developerConnection>

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 22/30: SLING-5507 - Collect more details around query execution

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit cdfbb9d7ee1cad2d71b6262dd2396148ecbbad31
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Wed Feb 10 16:45:41 2016 +0000

    SLING-5507 - Collect more details around query execution
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729651 13f79535-47bb-0310-9956-ffa450edef68
---
 .../apache/sling/tracer/internal/CallerFinder.java |  69 +++++++++++++
 .../sling/tracer/internal/JSONRecording.java       | 110 ++++++++++++++++++---
 .../sling/tracer/internal/CallerFinderTest.java    |  96 ++++++++++++++++++
 .../sling/tracer/internal/JSONRecordingTest.java   |  15 ++-
 4 files changed, 276 insertions(+), 14 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/CallerFinder.java b/src/main/java/org/apache/sling/tracer/internal/CallerFinder.java
new file mode 100644
index 0000000..f08e8e7
--- /dev/null
+++ b/src/main/java/org/apache/sling/tracer/internal/CallerFinder.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.tracer.internal;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import javax.annotation.CheckForNull;
+
+import com.google.common.collect.Iterators;
+import com.google.common.collect.PeekingIterator;
+
+/**
+ * Utility to find out the real caller by excluding stack elements belonging to
+ * API classes. Say for a query it would exclude the call stack which is part of Oak
+ * or Sling Engine
+ */
+class CallerFinder {
+    private final String[] apiPkgs;
+
+    public CallerFinder(String[] apiPkgs) {
+        this.apiPkgs = apiPkgs;
+    }
+
+    @CheckForNull
+    public StackTraceElement determineCaller(StackTraceElement[] stack) {
+        if (stack == null) {
+            return null;
+        }
+
+        //Reverse the stack trace so as to start from bottom
+        List<StackTraceElement> stackList = Arrays.asList(stack);
+        Collections.reverse(stackList);
+        PeekingIterator<StackTraceElement> pit = Iterators.peekingIterator(stackList.iterator());
+        while (pit.hasNext()) {
+            StackTraceElement current = pit.next();
+
+            //now scan each element and check if the *next* stack element belongs to any
+            //api package. If yes then current stack would be the caller
+            if (pit.hasNext()) {
+                StackTraceElement next = pit.peek();
+                for (String pkg : apiPkgs) {
+                    if (next.getClassName().startsWith(pkg)) {
+                        return current;
+                    }
+                }
+            }
+        }
+        return null;
+    }
+}
diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index b1e76be..c0aec8a 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -48,23 +48,31 @@ import org.apache.sling.commons.json.JSONException;
 import org.apache.sling.commons.json.io.JSONWriter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
 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 String[] QUERY_API_PKGS = {
+            "org.apache.sling.resourceresolver", //Sling package would come first in stack so listed first
+            "org.apache.jackrabbit.oak"
+    };
     private static final Logger log = LoggerFactory.getLogger(JSONRecording.class);
+    public static final String OAK_QUERY_PKG = "org.apache.jackrabbit.oak.query";
     private final String method;
     private final String requestId;
     private final String uri;
     private final boolean compress;
-    private final List<String> queries = new ArrayList<String>();
+    private final List<QueryEntry> queries = new ArrayList<QueryEntry>();
     private final List<LogEntry> logs = new ArrayList<LogEntry>();
     private RequestProgressTracker tracker;
     private byte[] json;
     private final long start = System.currentTimeMillis();
     private long timeTaken;
+    private final QueryLogCollector queryCollector = new QueryLogCollector();
+    private final CallerFinder queryCallerFinder = new CallerFinder(QUERY_API_PKGS);
 
     public JSONRecording(String requestId, HttpServletRequest r, boolean compress) {
         this.requestId = requestId;
@@ -117,10 +125,8 @@ class JSONRecording implements Recording, Comparable<JSONRecording> {
 
     @Override
     public void log(TracerConfig tc, Level level, String logger, FormattingTuple tuple) {
-        Object[] params = tuple.getArgArray();
-        if (TracerContext.QUERY_LOGGER.equals(logger)
-                && params != null && params.length == 2) {
-            queries.add((String) params[1]);
+        if (logger.startsWith(OAK_QUERY_PKG)) {
+            queryCollector.record(level, logger, tuple);
         }
         logs.add(new LogEntry(level, logger, tuple));
     }
@@ -177,12 +183,8 @@ class JSONRecording implements Recording, Comparable<JSONRecording> {
             jw.endArray();
         }
 
-        jw.key("queries");
-        jw.array();
-        for (String q : queries) {
-            jw.value(q);
-        }
-        jw.endArray();
+        queryCollector.done();
+        addJson(jw, "queries", queries);
 
         addJson(jw, "logs", logs);
         jw.endObject();
@@ -274,4 +276,90 @@ class JSONRecording implements Recording, Comparable<JSONRecording> {
         }
     }
 
+    private static class QueryEntry implements JsonEntry {
+        final String query;
+        final String plan;
+        final String caller;
+
+        private QueryEntry(String query, String plan, String caller) {
+            this.query = query;
+            this.plan = plan;
+            this.caller = caller;
+        }
+
+        @Override
+        public void toJson(JSONWriter jw) throws JSONException {
+            jw.key("query").value(query);
+            jw.key("plan").value(plan);
+            jw.key("caller").value(caller);
+        }
+    }
+
+    private class QueryLogCollector {
+        /**
+         * The MDC key is used in org.apache.jackrabbit.oak.query.QueryEngineImpl
+         */
+        static final String MDC_QUERY_ID = "oak.query.id";
+        static final String QE_LOGGER = "org.apache.jackrabbit.oak.query.QueryImpl";
+        String query;
+        String plan;
+        String id;
+        String caller;
+
+        public void record(Level level, String logger, FormattingTuple tuple) {
+            String idFromMDC = MDC.get(MDC_QUERY_ID);
+
+            //Use the query id to detect change of query execution
+            //i.e. once query gets executed for current thread and next
+            //query start it would cause the id to change. That would
+            //be a trigger to finish up on current query collection and
+            //switch to new one
+            if (idFromMDC != null && !idFromMDC.equals(id)) {
+                addQueryEntry();
+                id = idFromMDC;
+            }
+
+            String msg = tuple.getMessage();
+            if (Level.DEBUG == level
+                    && QE_LOGGER.equals(logger)
+                    && msg != null){
+
+                //The Log stmt are as present in org.apache.jackrabbit.oak.query.QueryImpl
+                if (msg.startsWith("query execute ")){
+                    query = msg.substring("query execute ".length());
+                    caller = determineCaller();
+                } else if (msg.startsWith("query plan ")){
+                    plan = msg.substring("query plan ".length());
+                }
+            }
+        }
+
+        private String determineCaller() {
+            StackTraceElement caller = queryCallerFinder.determineCaller(Thread.currentThread().getStackTrace());
+            if (caller != null) {
+                return caller.toString();
+            }
+            return null;
+        }
+
+        public void addQueryEntry(){
+            if (query != null){
+                queries.add(new QueryEntry(safeTrim(query), safeTrim(plan), caller));
+                plan = query = null;
+            }
+        }
+
+        public void done(){
+            //Push any last pending entry i.e. last query
+            addQueryEntry();
+        }
+
+        private String safeTrim(String s){
+            if(s == null){
+                return "";
+            }
+            return s.trim();
+        }
+    }
+
 }
diff --git a/src/test/java/org/apache/sling/tracer/internal/CallerFinderTest.java b/src/test/java/org/apache/sling/tracer/internal/CallerFinderTest.java
new file mode 100644
index 0000000..51d4ba2
--- /dev/null
+++ b/src/test/java/org/apache/sling/tracer/internal/CallerFinderTest.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.tracer.internal;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+public class CallerFinderTest {
+
+    @Test
+    public void determineCallerSingle() throws Exception{
+        CallerFinder cf = new CallerFinder(new String[] {"o.a.s", "o.a.j.o"});
+        StackTraceElement[] stack = createStack(
+                "o.a.j.o.a",
+                "o.a.j.o.b",
+                "c.a.g.w",
+                "o.e.j",
+                "o.e.j",
+                "o.e.j"
+        );
+
+        StackTraceElement caller = cf.determineCaller(stack);
+        assertNotNull(caller);
+        assertEquals("c.a.g.w", caller.getClassName());
+    }
+
+    @Test
+    public void determineCallerMultipleApi() throws Exception{
+        CallerFinder cf = new CallerFinder(new String[] {"o.a.s", "o.a.j.o"});
+        StackTraceElement[] stack = createStack(
+                "o.a.j.o.a",
+                "o.a.j.o.b",
+                "o.a.s.a",
+                "o.a.s.b",
+                "c.a.g.w",
+                "o.e.j",
+                "o.e.j",
+                "o.e.j"
+        );
+
+        StackTraceElement caller = cf.determineCaller(stack);
+        assertNotNull(caller);
+        assertEquals("c.a.g.w", caller.getClassName());
+
+        stack = createStack(
+                "o.a.j.o.a",
+                "o.a.j.o.b",
+                "o.a.s.a",
+                "o.a.s.b",
+                "c.a.g.w",
+                "o.e.j",
+                "o.e.j",
+                "o.e.j"
+        );
+
+        cf = new CallerFinder(new String[] {"o.a.j.o"});
+        caller = cf.determineCaller(stack);
+        assertNotNull(caller);
+        assertEquals("o.a.s.a", caller.getClassName());
+
+    }
+
+    @Test
+    public void nullInput() throws Exception{
+        CallerFinder cf = new CallerFinder(new String[] {"o.a.s", "o.a.j.o"});
+        assertNull(cf.determineCaller(null));
+    }
+
+    private static StackTraceElement[] createStack(String ... stack){
+        StackTraceElement[] result = new StackTraceElement[stack.length];
+        for (int i = 0; i < stack.length; i++) {
+            result[i] = new StackTraceElement(stack[i], "foo", null, 0);
+        }
+        return result;
+    }
+}
diff --git a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
index ac8ad3c..e0a2476 100644
--- a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
@@ -25,7 +25,9 @@ import javax.servlet.http.HttpServletRequest;
 
 import ch.qos.logback.classic.Level;
 import org.apache.sling.commons.json.JSONObject;
+import org.junit.Ignore;
 import org.junit.Test;
+import org.slf4j.MDC;
 import org.slf4j.helpers.FormattingTuple;
 import org.slf4j.helpers.MessageFormatter;
 
@@ -37,6 +39,8 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 public class JSONRecordingTest {
+    static final String MDC_QUERY_ID = "oak.query.id";
+    static String QE_LOGGER = "org.apache.jackrabbit.oak.query.QueryImpl";
     private HttpServletRequest request = mock(HttpServletRequest.class);
 
     private TracerConfig tc = new TracerConfig(TracerContext.QUERY_LOGGER, Level.INFO);
@@ -48,8 +52,9 @@ public class JSONRecordingTest {
         when(request.getMethod()).thenReturn("GET");
         JSONRecording r = new JSONRecording("abc", request, true);
 
-        r.log(tc, Level.INFO, TracerContext.QUERY_LOGGER, MessageFormatter.arrayFormat("foo bar", new Object[]{"x" , "y"}));
-        r.log(tc, Level.INFO, TracerContext.QUERY_LOGGER, MessageFormatter.arrayFormat("foo bar", new Object[]{"x" , "z"}));
+        MDC.put(MDC_QUERY_ID, "1");
+        r.log(tc, Level.DEBUG, QE_LOGGER, tuple("query execute SELECT FOO"));
+        r.log(tc, Level.DEBUG, QE_LOGGER, tuple("query plan FOO PLAN"));
 
         r.done();
         r.render(sw);
@@ -58,7 +63,7 @@ public class JSONRecordingTest {
         assertEquals("GET", json.get("method"));
         assertTrue(json.has("time"));
         assertTrue(json.has("timestamp"));
-        assertEquals(2, json.getJSONArray("queries").length());
+        assertEquals(1, json.getJSONArray("queries").length());
     }
 
     @Test
@@ -103,4 +108,8 @@ public class JSONRecordingTest {
         JSONObject l3 = json.getJSONArray("logs").getJSONObject(2);
         assertNotNull(l3.get("exception"));
     }
+
+    private static FormattingTuple tuple(String msg){
+        return MessageFormatter.format(msg, null);
+    }
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.

[sling-org-apache-sling-tracer] 15/30: SLING-5504 - Reduce memory footprint of stored recording data

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.tracer-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-tracer.git

commit 0f98bb63d7c02081907b939f2216a45f05562afe
Author: Chetan Mehrotra <ch...@apache.org>
AuthorDate: Wed Feb 10 05:53:31 2016 +0000

    SLING-5504 - Reduce memory footprint of stored recording data
    
    Enable compression for in memory json data
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/tracer@1729534 13f79535-47bb-0310-9956-ffa450edef68
---
 .../sling/tracer/internal/JSONRecording.java       | 26 ++++++++++++++++++----
 .../sling/tracer/internal/TracerLogServlet.java    |  4 +++-
 .../sling/tracer/internal/JSONRecordingTest.java   |  6 ++---
 .../sling/tracer/internal/LogTracerTest.java       | 10 +++++++++
 4 files changed, 38 insertions(+), 8 deletions(-)

diff --git a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
index 592477b..507d130 100644
--- a/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
+++ b/src/main/java/org/apache/sling/tracer/internal/JSONRecording.java
@@ -22,6 +22,7 @@ package org.apache.sling.tracer.internal;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
@@ -33,6 +34,8 @@ import java.io.Writer;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
 
 import javax.servlet.http.HttpServletRequest;
 
@@ -51,20 +54,22 @@ class JSONRecording implements Recording {
     private final String method;
     private final String requestId;
     private final String uri;
+    private final boolean compress;
     private final List<String> queries = new ArrayList<String>();
     private final List<LogEntry> logs = new ArrayList<LogEntry>();
     private RequestProgressTracker tracker;
     private byte[] json;
 
-    public JSONRecording(String requestId, HttpServletRequest r) {
+    public JSONRecording(String requestId, HttpServletRequest r, boolean compress) {
         this.requestId = requestId;
+        this.compress = compress;
         this.method = r.getMethod();
         this.uri = r.getRequestURI();
     }
 
     public boolean render(Writer w) throws IOException {
         if (json != null) {
-            Reader r = new InputStreamReader(new ByteArrayInputStream(json), "UTF-8");
+            Reader r = new InputStreamReader(getInputStream(), "UTF-8");
             IOUtils.copy(r, w);
             return true;
         }
@@ -73,7 +78,7 @@ class JSONRecording implements Recording {
 
     public boolean render(OutputStream os) throws IOException {
         if (json != null) {
-            os.write(json);
+            IOUtils.copyLarge(getInputStream(), os);
             return true;
         }
         return false;
@@ -130,7 +135,11 @@ class JSONRecording implements Recording {
 
     private byte[] toJSON() throws JSONException, IOException {
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        OutputStreamWriter osw = new OutputStreamWriter(baos, "UTF-8");
+        OutputStream os = baos;
+        if (compress) {
+            os = new GZIPOutputStream(os);
+        }
+        OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
         JSONWriter jw = new JSONWriter(osw);
         jw.setTidy(true);
         jw.object();
@@ -157,6 +166,7 @@ class JSONRecording implements Recording {
         addJson(jw, "logs", logs);
         jw.endObject();
         osw.flush();
+        os.close();
         return baos.toByteArray();
     }
 
@@ -171,6 +181,14 @@ class JSONRecording implements Recording {
         jw.endArray();
     }
 
+    private InputStream getInputStream() throws IOException {
+        InputStream is = new ByteArrayInputStream(json);
+        if (compress) {
+            is = new GZIPInputStream(is);
+        }
+        return is;
+    }
+
     private interface JsonEntry {
         void toJson(JSONWriter jw) throws JSONException;
     }
diff --git a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
index 827d890..fa31a30 100644
--- a/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
+++ b/src/main/java/org/apache/sling/tracer/internal/TracerLogServlet.java
@@ -53,6 +53,8 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
 
     private final Cache<String, JSONRecording> cache;
 
+    private boolean compressRecording = true;
+
     public TracerLogServlet(BundleContext context) {
         super(LABEL, "Sling Tracer", "Sling", null);
         //TODO Make things configurable
@@ -196,7 +198,7 @@ class TracerLogServlet extends SimpleWebConsolePlugin implements TraceLogRecorde
     }
 
     private JSONRecording record(String requestId, HttpServletRequest request) {
-        JSONRecording data = new JSONRecording(requestId, request);
+        JSONRecording data = new JSONRecording(requestId, request, compressRecording);
         cache.put(requestId, data);
         return data;
     }
diff --git a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
index 82116fc..473b7e7 100644
--- a/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/JSONRecordingTest.java
@@ -43,7 +43,7 @@ public class JSONRecordingTest {
         StringWriter sw = new StringWriter();
 
         when(request.getMethod()).thenReturn("GET");
-        JSONRecording r = new JSONRecording("abc", request);
+        JSONRecording r = new JSONRecording("abc", request, true);
 
         r.log(Level.INFO, TracerContext.QUERY_LOGGER, MessageFormatter.arrayFormat("foo bar", new Object[]{"x" , "y"}));
         r.log(Level.INFO, TracerContext.QUERY_LOGGER, MessageFormatter.arrayFormat("foo bar", new Object[]{"x" , "z"}));
@@ -59,7 +59,7 @@ public class JSONRecordingTest {
     @Test
     public void requestTrackerLogs() throws Exception{
         StringWriter sw = new StringWriter();
-        JSONRecording r = new JSONRecording("abc", request);
+        JSONRecording r = new JSONRecording("abc", request, true);
 
         r.registerTracker(TestUtil.createTracker("x", "y"));
 
@@ -73,7 +73,7 @@ public class JSONRecordingTest {
     @Test
     public void logs() throws Exception{
         StringWriter sw = new StringWriter();
-        JSONRecording r = new JSONRecording("abc", request);
+        JSONRecording r = new JSONRecording("abc", request, true);
 
         FormattingTuple tp1 = MessageFormatter.arrayFormat("{} is going", new Object[]{"Jack"});
         r.log(Level.INFO, "foo", tp1);
diff --git a/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java b/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
index c6b9e42..416b8e2 100644
--- a/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
+++ b/src/test/java/org/apache/sling/tracer/internal/LogTracerTest.java
@@ -235,6 +235,11 @@ public class LogTracerTest {
             public RequestProgressTracker getRequestProgressTracker() {
                 return createTracker("x", "y");
             }
+
+            @Override
+            public String getRequestURI() {
+                return "foo";
+            }
         };
         request.setHeader(TracerLogServlet.HEADER_TRACER_RECORDING, "true");
 
@@ -272,6 +277,11 @@ public class LogTracerTest {
             public RequestProgressTracker getRequestProgressTracker() {
                 return createTracker("x", "y");
             }
+
+            @Override
+            public String getRequestURI() {
+                return "foo";
+            }
         };
         request.setHeader(TracerLogServlet.HEADER_TRACER_RECORDING, "true");
         request.setHeader(LogTracer.HEADER_TRACER_CONFIG, "a.b.c;level=trace,a.b;level=debug");

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.