changeset 1152:a248b4a1a32f

HttpTrafficDumperFilter
author Devel 2
date Fri, 12 Jun 2020 13:09:36 +0200
parents 65f4b7539281
children 39588e98056b
files stress-tester/src/main/java/com/passus/st/client/http/filter/HttpTrafficDumperFilter.java stress-tester/src/main/java/com/passus/st/utils/CsvHelper.java
diffstat 2 files changed, 269 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/main/java/com/passus/st/client/http/filter/HttpTrafficDumperFilter.java	Fri Jun 12 13:09:36 2020 +0200
@@ -0,0 +1,221 @@
+package com.passus.st.client.http.filter;
+
+import com.passus.commons.annotations.Plugin;
+import com.passus.config.Configuration;
+import com.passus.config.ConfigurationContext;
+import com.passus.config.annotations.NodeDefinitionCreate;
+import com.passus.config.schema.NodeDefinition;
+import com.passus.config.schema.NodeDefinitionCreator;
+import com.passus.data.ByteString;
+import com.passus.net.http.HttpHeaders;
+import com.passus.net.http.HttpRequest;
+import com.passus.net.http.HttpResponse;
+import com.passus.net.http.HttpStatus;
+import com.passus.st.client.FlowContext;
+import com.passus.st.emitter.SessionInfo;
+import com.passus.st.filter.FlowFilter;
+import com.passus.st.plugin.PluginConstants;
+import com.passus.st.utils.CsvHelper;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
+import java.io.*;
+
+import static com.passus.config.schema.ConfigurationSchemaBuilder.mapDef;
+import static com.passus.config.schema.ConfigurationSchemaBuilder.tupleDef;
+import static com.passus.net.http.HttpUtils.intToVersionString;
+import static com.passus.st.client.http.HttpConsts.*;
+import static com.passus.st.config.CommonNodeDefs.STRING_DEF;
+
+@NodeDefinitionCreate(HttpTrafficDumperFilter.HttpSessionCookieFilterNodeDefCreator.class)
+@Plugin(name = HttpTrafficDumperFilter.TYPE, category = PluginConstants.CATEGORY_FLOW_FILTER)
+public class HttpTrafficDumperFilter extends HttpFilter {
+
+    private static final Logger LOGGER = LogManager.getLogger(HttpTrafficDumperFilter.class);
+
+    public static final String TYPE = "httpTrafficDumper";
+
+    private String encoding = "UTF-8";
+
+    private int bufferSize = 16 * 1024;
+
+    private String fileName;
+
+    private File file;
+
+    private Writer writer;
+
+    private final CsvHelper csvHelper = new CsvHelper();
+
+    @Override
+    public FlowFilter instanceForWorker(int index) {
+        return this;
+    }
+
+    @Override
+    public void configure(Configuration config, ConfigurationContext context) {
+        fileName = config.getString("fileName");
+    }
+
+    private void writeHeaders() throws IOException {
+        writeString("clientIp");
+        writeString("clientPort");
+        writeString("serverIp");
+        writeString("serverPort");
+
+        writeString("reqId");
+        writeString("reqMethod");
+        writeString("reqVersion");
+        writeString("reqUri");
+        writeString("reqUserAgent");
+        writeString("reqTimeStart");
+        writeString("reqTimeEnd");
+        writeString("reqHeaderSize");
+        writeString("reqContentSize");
+
+        writeString("respCode");
+        writeString("respReason");
+        writeString("respContentType");
+        writeString("respTimeStart");
+        writeString("respTimeEnd");
+        writeString("respHeaderSize");
+        writeString("respContentSize");
+
+        writeString("sessionId");
+        writeString("username");
+        csvHelper.write("loop", writer);
+        csvHelper.write("\n", writer);
+    }
+
+    private void createWriter(String name) throws IOException {
+        file = new File(name);
+        try {
+            writer = new OutputStreamWriter(new FileOutputStream(file, true), encoding);
+        } catch (FileNotFoundException ex) {
+            String parentPath = file.getParent();
+            if (parentPath != null) {
+                File parentDir = new File(parentPath);
+                if (!parentDir.exists() && parentDir.mkdirs()) {
+                    writer = new OutputStreamWriter(new FileOutputStream(file, true), encoding);
+                } else {
+                    throw ex;
+                }
+            } else {
+                throw ex;
+            }
+        }
+
+        if (bufferSize > 0) {
+            writer = new BufferedWriter(writer, bufferSize);
+        }
+
+        if (file.length() == 0) {
+            writeHeaders();
+        }
+    }
+
+    private void write(Object value) throws IOException {
+        csvHelper.write(value, writer);
+        csvHelper.writeDelimiter(writer);
+    }
+
+    private void writeString(ByteString value) throws IOException {
+        csvHelper.writeString(value, writer);
+        csvHelper.writeDelimiter(writer);
+    }
+
+    private void writeString(String value) throws IOException {
+        csvHelper.writeString(value, writer);
+        csvHelper.writeDelimiter(writer);
+    }
+
+    private void writeInt(Integer value) throws IOException {
+        csvHelper.write(value, writer);
+        csvHelper.writeDelimiter(writer);
+    }
+
+    @Override
+    public int filterInbound(HttpRequest req, HttpResponse resp, FlowContext context) {
+        try {
+            if (fileName == null) {
+                return DUNNO;
+            }
+
+            synchronized (this) {
+                if (writer == null) {
+                    createWriter(fileName);
+                }
+
+                SessionInfo sessionInfo = context.sessionInfo();
+                writeString(sessionInfo.getSrcIp().toString());
+                writeInt(sessionInfo.getSrcPort());
+                writeString(sessionInfo.getDstIp().toString());
+                writeInt(sessionInfo.getDstPort());
+
+                writeString(req.getId());
+                writeString(req.getMethod().toString());
+                writeString(intToVersionString(req.getVersion()));
+                writeString(req.getUri());
+
+                HttpHeaders reqHeaders = req.getHeaders();
+                writeString(reqHeaders.get(HttpHeaders.USER_AGENT));
+
+                write(req.getTag(TAG_TIME_START));
+                write(req.getTag(TAG_TIME_END));
+
+                write(req.getTag(TAG_HEADER_SIZE));
+                if (req.hasContent()) {
+                    write(req.getContent().available());
+                } else {
+                    write(0);
+                }
+
+                if (resp != null) {
+                    HttpStatus status = resp.getStatus();
+                    write(status.getCode());
+                    writeString(status.getReasonPhrase());
+
+                    HttpHeaders respHeaders = resp.getHeaders();
+                    writeString(respHeaders.get(HttpHeaders.CONTENT_TYPE));
+                    write(resp.getTag(TAG_TIME_START));
+                    write(resp.getTag(TAG_TIME_END));
+
+                    write(resp.getTag(TAG_HEADER_SIZE));
+                    if (resp.hasContent()) {
+                        write(resp.getContent().available());
+                    } else {
+                        write(0);
+                    }
+                } else {
+                    writeString("");
+                    writeString("");
+                    writeString("");
+                    writeString("");
+                    writeString("");
+                    writeString("");
+                    writeString("");
+                }
+
+                write(req.getTag(TAG_SESSION_ID));
+                write(req.getTag(TAG_USERNAME));
+                csvHelper.write(context.loop(), writer);
+                csvHelper.write("\n", writer);
+            }
+        } catch (Exception e) {
+            LOGGER.error(e.getMessage(), e);
+        }
+
+        return DUNNO;
+    }
+
+    public static class HttpSessionCookieFilterNodeDefCreator implements NodeDefinitionCreator {
+
+        @Override
+        public NodeDefinition create() {
+            return mapDef(
+                    tupleDef("fileName", STRING_DEF)
+            );
+        }
+
+    }
+}
--- a/stress-tester/src/main/java/com/passus/st/utils/CsvHelper.java	Fri Jun 12 12:58:12 2020 +0200
+++ b/stress-tester/src/main/java/com/passus/st/utils/CsvHelper.java	Fri Jun 12 13:09:36 2020 +0200
@@ -1,6 +1,8 @@
 package com.passus.st.utils;
 
+import com.passus.commons.Assert;
 import com.passus.commons.utils.FormatUtils;
+import com.passus.data.ByteString;
 
 import java.io.IOException;
 import java.io.Writer;
@@ -10,7 +12,7 @@
 
     public static final char DEFAULT_ESCAPE_CHARACTER = '\\';
 
-    public static final char DEFAULT_DELIMITER = ',';
+    public static final char DEFAULT_DELIMITER = ';';
 
     public static final char DEFAULT_QUOTE_CHARACTER = '"';
 
@@ -24,6 +26,8 @@
 
     private final StringBuilder sb = new StringBuilder();
 
+    private String nullValue = "";
+
     public char getDelimiter() {
         return delimiter;
     }
@@ -48,6 +52,15 @@
         this.escapechar = escapechar;
     }
 
+    public String getNullValue() {
+        return nullValue;
+    }
+
+    public void setNullValue(String nullValue) {
+        Assert.notNull(nullValue, "nullValue");
+        this.nullValue = nullValue;
+    }
+
     private boolean containsSpecialCharacter(String line) {
         return line.indexOf(quotechar) != -1 || line.indexOf(escapechar) != -1 || line.indexOf(delimiter) != -1;
     }
@@ -57,6 +70,11 @@
         return this;
     }
 
+    public CsvHelper appendNull(StringBuilder out) {
+        out.append(nullValue);
+        return this;
+    }
+
     private void escapeChars(String value, StringBuilder out) {
         for (int j = 0; j < value.length(); j++) {
             char ch = value.charAt(j);
@@ -68,6 +86,16 @@
         }
     }
 
+    public CsvHelper appendString(ByteString value, StringBuilder out) {
+        if (value == null) {
+            appendNull(out);
+        } else {
+            appendString(value.toString(), out);
+        }
+
+        return this;
+    }
+
     public CsvHelper appendString(String value, StringBuilder out) {
         if (containsSpecialCharacter(value)) {
             sb.setLength(0);
@@ -97,7 +125,25 @@
         return this;
     }
 
-    private int writeString(String value, Writer writer) throws IOException {
+    public int writeDelimiter(Writer writer) throws IOException {
+        writer.write(delimiter);
+        return 1;
+    }
+
+    public int writeNull(Writer writer) throws IOException {
+        writer.write(nullValue);
+        return 1;
+    }
+
+    public int writeString(ByteString value, Writer writer) throws IOException {
+        if (value == null) {
+            return writeNull(writer);
+        }
+
+        return writeString(value.toString(), writer);
+    }
+
+    public int writeString(String value, Writer writer) throws IOException {
         if (containsSpecialCharacter(value)) {
             int written = 0;
             sb.setLength(0);