You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by dk...@apache.org on 2017/02/03 19:50:41 UTC

[2/2] cxf git commit: [CXF-7242] Update new LoggingInInterceptor to actually log payloads Also update new logging to take a PrintStream to make it more compatible with old interceptors

[CXF-7242] Update new LoggingInInterceptor to actually log payloads
Also update new logging to take a PrintStream to make it more compatible with old interceptors


Project: http://git-wip-us.apache.org/repos/asf/cxf/repo
Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/5602eff2
Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/5602eff2
Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/5602eff2

Branch: refs/heads/master
Commit: 5602eff212c78c88e427375a6f139050d9b5c7b4
Parents: 8be745d
Author: Daniel Kulp <dk...@apache.org>
Authored: Fri Feb 3 14:47:09 2017 -0500
Committer: Daniel Kulp <dk...@apache.org>
Committed: Fri Feb 3 14:48:36 2017 -0500

----------------------------------------------------------------------
 .../cxf/ext/logging/LoggingInInterceptor.java   | 171 ++++++++++++++-----
 .../cxf/ext/logging/LoggingOutInterceptor.java  |   6 +-
 .../logging/event/DefaultLogEventMapper.java    |   4 +-
 .../logging/event/PrintWriterEventSender.java   |  77 +++++++++
 4 files changed, 213 insertions(+), 45 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cxf/blob/5602eff2/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingInInterceptor.java
----------------------------------------------------------------------
diff --git a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingInInterceptor.java b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingInInterceptor.java
index 940603f..6c19109 100644
--- a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingInInterceptor.java
+++ b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingInInterceptor.java
@@ -18,84 +18,171 @@
  */
 package org.apache.cxf.ext.logging;
 
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.SequenceInputStream;
+import java.util.Collection;
+import java.util.Collections;
 
 import org.apache.cxf.common.injection.NoJSR250Annotations;
 import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.ext.logging.event.DefaultLogEventMapper;
+import org.apache.cxf.ext.logging.event.EventType;
 import org.apache.cxf.ext.logging.event.LogEvent;
 import org.apache.cxf.ext.logging.event.LogEventSender;
+import org.apache.cxf.ext.logging.event.PrintWriterEventSender;
 import org.apache.cxf.ext.logging.slf4j.Slf4jEventSender;
+import org.apache.cxf.helpers.IOUtils;
 import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.io.CachedOutputStream;
 import org.apache.cxf.io.CachedWriter;
+import org.apache.cxf.io.DelegatingInputStream;
 import org.apache.cxf.message.Message;
+import org.apache.cxf.phase.AbstractPhaseInterceptor;
 import org.apache.cxf.phase.Phase;
+import org.apache.cxf.phase.PhaseInterceptor;
 
 /**
  * 
  */
 @NoJSR250Annotations
 public class LoggingInInterceptor extends AbstractLoggingInterceptor {
-
+    class SendLogEventInterceptor extends AbstractPhaseInterceptor<Message> {
+        SendLogEventInterceptor() {
+            super(Phase.PRE_INVOKE);
+        }
+        @Override
+        public void handleMessage(Message message) throws Fault {
+            LogEvent event = message.get(LogEvent.class);
+            if (event != null) {
+                DefaultLogEventMapper mapper = new DefaultLogEventMapper();
+                mapper.setEpInfo(message, event);
+                event.setType(mapper.getEventType(message));
+                message.remove(LogEvent.class);
+                sender.send(event);
+            }
+        }  
+    }
+    
     public LoggingInInterceptor() {
         this(new Slf4jEventSender());
     }
-    
+    public LoggingInInterceptor(PrintWriter writer) {
+        this(new PrintWriterEventSender(writer));
+    }
     public LoggingInInterceptor(LogEventSender sender) {
-        super(Phase.PRE_INVOKE, sender);
+        super(Phase.RECEIVE, sender);
+    }
+    public Collection<PhaseInterceptor<? extends Message>> getAdditionalInterceptors() {
+        return Collections.singleton(new SendLogEventInterceptor());
+    }
+    
+    
+    public void handleFault(Message message) {
+        LogEvent event = message.get(LogEvent.class);
+        if (event != null) {
+            DefaultLogEventMapper mapper = new DefaultLogEventMapper();
+            mapper.setEpInfo(message, event);
+            event.setType(EventType.FAULT_IN);
+            message.remove(LogEvent.class);
+            sender.send(event);
+        }
     }
-
     public void handleMessage(Message message) throws Fault {
-        createExchangeId(message);
-        final LogEvent event = new DefaultLogEventMapper().map(message);
-        if (shouldLogContent(event)) {
-            addContent(message, event);
-        } else {
-            event.setPayload(AbstractLoggingInterceptor.CONTENT_SUPPRESSED);
+        LogEvent event = message.get(LogEvent.class);
+        if (event == null) {
+            createExchangeId(message);
+            event = new DefaultLogEventMapper().map(message);
+            if (shouldLogContent(event)) {
+                addContent(message, event);
+            } else {
+                event.setPayload(AbstractLoggingInterceptor.CONTENT_SUPPRESSED);
+            }
+            // at this point, we have the payload.  However, we may not have the endpoint yet. Delay sending 
+            // the event till a little bit later 
+            message.put(LogEvent.class, event);
         }
-        sender.send(event);
     }
 
     private void addContent(Message message, final LogEvent event) {
+        InputStream is = message.getContent(InputStream.class);
+        if (is != null) {
+            logInputStream(message, is, event);
+        } else {
+            Reader reader = message.getContent(Reader.class);
+            if (reader != null) {
+                logReader(message, reader, event);
+            }
+        }
+    }
+    
+    protected void logInputStream(Message message, InputStream is, LogEvent event) {
+        CachedOutputStream bos = new CachedOutputStream();
+        if (threshold > 0) {
+            bos.setThreshold(threshold);
+        }
+        String encoding = event.getEncoding();
         try {
-            CachedOutputStream cos = message.getContent(CachedOutputStream.class);
-            if (cos != null) {
-                handleOutputStream(event, message, cos);
+            // use the appropriate input stream and restore it later
+            InputStream bis = is instanceof DelegatingInputStream 
+                ? ((DelegatingInputStream)is).getInputStream() : is;
+            
+
+            //only copy up to the limit since that's all we need to log
+            //we can stream the rest
+            IOUtils.copyAtLeast(bis, bos, limit == -1 ? Integer.MAX_VALUE : limit);
+            bos.flush();
+            bis = new SequenceInputStream(bos.getInputStream(), bis);
+            
+            // restore the delegating input stream or the input stream
+            if (is instanceof DelegatingInputStream) {
+                ((DelegatingInputStream)is).setInputStream(bis);
             } else {
-                CachedWriter writer = message.getContent(CachedWriter.class);
-                if (writer != null) {
-                    handleWriter(event, writer);
-                }
+                message.setContent(InputStream.class, bis);
             }
-        } catch (IOException e) {
+
+            if (bos.getTempFile() != null) {
+                //large thing on disk...
+                event.setFullContentFile(bos.getTempFile());
+            }
+            if (bos.size() > limit && limit != -1) {
+                event.setTruncated(true);
+            }
+            
+            StringBuilder builder = new StringBuilder(limit);
+            if (StringUtils.isEmpty(encoding)) {
+                bos.writeCacheTo(builder, limit);
+            } else {
+                bos.writeCacheTo(builder, encoding, limit);
+            }
+            bos.close();
+            event.setPayload(builder.toString());
+        } catch (Exception e) {
             throw new Fault(e);
         }
     }
 
-    private void handleOutputStream(final LogEvent event, Message message, CachedOutputStream cos) throws IOException {
-        String encoding = (String)message.get(Message.ENCODING);
-        if (StringUtils.isEmpty(encoding)) {
-            encoding = StandardCharsets.UTF_8.name();
+    protected void logReader(Message message, Reader reader, LogEvent event) {
+        try {
+            CachedWriter writer = new CachedWriter();
+            IOUtils.copyAndCloseInput(reader, writer);
+            message.setContent(Reader.class, writer.getReader());
+            
+            if (writer.getTempFile() != null) {
+                //large thing on disk...
+                event.setFullContentFile(writer.getTempFile());
+            }
+            if (writer.size() > limit && limit != -1) {
+                event.setTruncated(true);
+            }
+            int max = writer.size() > limit ? (int)limit : (int)writer.size();
+            StringBuilder b = new StringBuilder(max);
+            writer.writeCacheTo(b);
+            event.setPayload(b.toString());            
+        } catch (Exception e) {
+            throw new Fault(e);
         }
-        StringBuilder payload = new StringBuilder();
-        cos.writeCacheTo(payload, encoding, limit);
-        cos.close();
-        event.setPayload(payload.toString());
-        boolean isTruncated = cos.size() > limit && limit != -1;
-        event.setTruncated(isTruncated);
-        event.setFullContentFile(cos.getTempFile());
-    }
-
-    private void handleWriter(final LogEvent event, CachedWriter writer) throws IOException {
-        boolean isTruncated = writer.size() > limit && limit != -1;
-        StringBuilder payload = new StringBuilder();
-        writer.writeCacheTo(payload, limit);
-        event.setPayload(payload.toString());
-        event.setTruncated(isTruncated);
-        event.setFullContentFile(writer.getTempFile());
     }
 
-
 }

http://git-wip-us.apache.org/repos/asf/cxf/blob/5602eff2/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingOutInterceptor.java
----------------------------------------------------------------------
diff --git a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingOutInterceptor.java b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingOutInterceptor.java
index 8620021..2885f6e 100644
--- a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingOutInterceptor.java
+++ b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/LoggingOutInterceptor.java
@@ -21,6 +21,7 @@ package org.apache.cxf.ext.logging;
 import java.io.FilterWriter;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.io.Writer;
 
@@ -29,6 +30,7 @@ import org.apache.cxf.common.util.StringUtils;
 import org.apache.cxf.ext.logging.event.DefaultLogEventMapper;
 import org.apache.cxf.ext.logging.event.LogEvent;
 import org.apache.cxf.ext.logging.event.LogEventSender;
+import org.apache.cxf.ext.logging.event.PrintWriterEventSender;
 import org.apache.cxf.ext.logging.slf4j.Slf4jEventSender;
 import org.apache.cxf.interceptor.Fault;
 import org.apache.cxf.interceptor.StaxOutInterceptor;
@@ -47,7 +49,9 @@ public class LoggingOutInterceptor extends AbstractLoggingInterceptor {
     public LoggingOutInterceptor() {
         this(new Slf4jEventSender());
     }
-    
+    public LoggingOutInterceptor(PrintWriter w) {
+        this(new PrintWriterEventSender(w));
+    }
     public LoggingOutInterceptor(LogEventSender sender) {
         super(Phase.PRE_STREAM, sender);
         addBefore(StaxOutInterceptor.class.getName());

http://git-wip-us.apache.org/repos/asf/cxf/blob/5602eff2/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/event/DefaultLogEventMapper.java
----------------------------------------------------------------------
diff --git a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/event/DefaultLogEventMapper.java b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/event/DefaultLogEventMapper.java
index 0123a1b..f48629f 100644
--- a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/event/DefaultLogEventMapper.java
+++ b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/event/DefaultLogEventMapper.java
@@ -281,7 +281,7 @@ public class DefaultLogEventMapper implements LogEventMapper {
      * @param message the message
      * @return the event type
      */
-    private EventType getEventType(Message message) {
+    public EventType getEventType(Message message) {
         boolean isRequestor = MessageUtils.isRequestor(message);
         boolean isFault = MessageUtils.isFault(message);
         if (!isFault) {
@@ -320,7 +320,7 @@ public class DefaultLogEventMapper implements LogEventMapper {
         }
     }
 
-    private void setEpInfo(Message message, final LogEvent event) {
+    public void setEpInfo(Message message, final LogEvent event) {
         EndpointInfo endpoint = getEPInfo(message);
         event.setPortName(endpoint.getName());
         event.setPortTypeName(endpoint.getName());

http://git-wip-us.apache.org/repos/asf/cxf/blob/5602eff2/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/event/PrintWriterEventSender.java
----------------------------------------------------------------------
diff --git a/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/event/PrintWriterEventSender.java b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/event/PrintWriterEventSender.java
new file mode 100644
index 0000000..b34133d
--- /dev/null
+++ b/rt/features/logging/src/main/java/org/apache/cxf/ext/logging/event/PrintWriterEventSender.java
@@ -0,0 +1,77 @@
+/**
+ * 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.cxf.ext.logging.event;
+
+import java.io.PrintWriter;
+import java.time.Instant;
+
+import javax.xml.namespace.QName;
+
+/**
+ * 
+ */
+public class PrintWriterEventSender implements LogEventSender {
+    PrintWriter writer;
+    
+    public PrintWriterEventSender(PrintWriter writer) {
+        this.writer = writer;
+    }
+    
+    void setPrintWriter(PrintWriter w) {
+        writer = w;
+    }
+    
+    
+    /** {@inheritDoc}*/
+    @Override
+    public void send(LogEvent event) {
+        StringBuilder b = new StringBuilder();
+        
+        b.append(Instant.now().toString()).append(" - PrintWriterEventSender\n");
+        put(b, "type", event.getType().toString());
+        put(b, "address", event.getAddress());
+        put(b, "content-type", event.getContentType());
+        put(b, "encoding", event.getEncoding());
+        put(b, "exchangeId", event.getExchangeId());
+        put(b, "httpMethod", event.getHttpMethod());
+        put(b, "messageId", event.getMessageId());
+        put(b, "responseCode", event.getResponseCode());
+        put(b, "serviceName", localPart(event.getServiceName()));
+        put(b, "portName", localPart(event.getPortName()));
+        put(b, "portTypeName", localPart(event.getPortTypeName()));
+        if (event.getFullContentFile() != null) {
+            put(b, "fullContentFile", event.getFullContentFile().getAbsolutePath());
+        }
+        put(b, "headers", event.getHeaders().toString());
+        synchronized (writer) {
+            writer.print(b.toString());
+            writer.println(event.getPayload());
+        }
+    }
+    protected String localPart(QName name) {
+        return name == null ? null : name.getLocalPart();
+    }
+   
+    protected void put(StringBuilder b, String key, String value) {
+        if (value != null) {
+            b.append("    ").append(key).append(": ").append(value).append("\n");
+        }
+    }
+}