📄 tclogparser.java
字号:
/*
* 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.jmeter.protocol.http.util.accesslog;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.StringTokenizer;
import java.util.Vector;
import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.log.Logger;
// For JUnit tests, @see TestTCLogParser
/**
* Description:<br>
* <br>
* Currently the parser only handles GET/POST requests. It's easy enough to add
* support for other request methods by changing checkMethod. The is a complete
* rewrite of a tool I wrote for myself earlier. The older algorithm was basic
* and did not provide the same level of flexibility I want, so I wrote a new
* one using a totally new algorithm. This implementation reads one line at a
* time using BufferedReader. When it gets to the end of the file and the
* sampler needs to get more requests, the parser will re-initialize the
* BufferedReader. The implementation uses StringTokenizer to create tokens.
* <p>
* The parse algorithm is the following:
* <p>
* <ol>
* <li> cleans the entry by looking for backslash "\"
* <li> looks to see if GET or POST is in the line
* <li> tokenizes using quotes "
* <li> finds the token with the request method
* <li> gets the string of the token and tokenizes it using space
* <li> finds the first token beginning with slash character
* <li> tokenizes the string using question mark "?"
* <li> get the path from the first token
* <li> returns the second token and checks it for parameters
* <li> tokenizes the string using ampersand "&"
* <li> parses each token to name/value pairs
* </ol>
* <p>
* Extending this class is fairly simple. Most access logs use the same format
* starting from the request method. Therefore, changing the implementation of
* cleanURL(string) method should be sufficient to support new log formats.
* Tomcat uses common log format, so any webserver that uses the format should
* work with this parser. Servers that are known to use non standard formats are
* IIS and Netscape.
* <p>
*
*/
public class TCLogParser implements LogParser {
static Logger log = LoggingManager.getLoggerForClass();
public static final String GET = "GET";
public static final String POST = "POST";
/** protected members * */
protected String RMETHOD = null;
/**
* The path to the access log file
*/
protected String URL_PATH = null;
protected boolean useFILE = true;
protected File SOURCE = null;
protected String FILENAME = null;
protected BufferedReader READER = null;
/**
* Handles to supporting classes
*/
protected Filter FILTER = null;
/**
* by default, we probably should decode the parameter values
*/
protected boolean decode = true;
// TODO downcase UPPER case non-final variables
/**
*
*/
public TCLogParser() {
super();
}
/**
* @param source
*/
public TCLogParser(String source) {
setSourceFile(source);
}
/**
* by default decode is set to true. if the parameters shouldn't be
* decoded, call the method with false
* @param decodeparams
*/
public void setDecodeParameterValues(boolean decodeparams) {
this.decode = decodeparams;
}
/**
* decode the parameter values is to true by default
* @return if paramter values should be decoded
*/
public boolean decodeParameterValue() {
return this.decode;
}
/**
* Calls this method to set whether or not to use the path in the log. We
* may want to provide the ability to filter the log file later on. By
* default, the parser uses the file in the log.
*
* @param file
*/
public void setUseParsedFile(boolean file) {
this.useFILE = file;
}
/**
* Use the filter to include/exclude files in the access logs. This is
* provided as a convienance and reduce the need to spend hours cleaning up
* log files.
*
* @param filter
*/
public void setFilter(Filter filter) {
FILTER = filter;
}
/**
* Sets the source file.
*
* @param source
*/
public void setSourceFile(String source) {
this.FILENAME = source;
}
/**
* Creates a new File object.
*
* @param filename
*/
public File openFile(String filename) {
return new File(filename);
}
/**
* parse the entire file.
*
* @return boolean success/failure
*/
public int parse(TestElement el, int parseCount) {
if (this.SOURCE == null) {
this.SOURCE = this.openFile(this.FILENAME);
}
try {
if (this.READER == null) {
this.READER = new BufferedReader(new FileReader(this.SOURCE));
}
return parse(this.READER, el, parseCount);
} catch (Exception exception) {
log.error("Problem creating samples", exception);
}
return -1;// indicate that an error occured
}
/**
* parse a set number of lines from the access log. Keep in mind the number
* of lines parsed will depend the filter and number of lines in the log.
* The method returns the actual lines parsed.
*
* @param count
* @return lines parsed
*/
public int parseAndConfigure(int count, TestElement el) {
return this.parse(el, count);
}
/**
* The method is responsible for reading each line, and breaking out of the
* while loop if a set number of lines is given.
*
* @param breader
*/
protected int parse(BufferedReader breader, TestElement el, int parseCount) {
int actualCount = 0;
String line = null;
try {
// read one line at a time using
// BufferedReader
line = breader.readLine();
while (line != null) {
if (line.length() > 0) {
actualCount += this.parseLine(line, el);
}
// we check the count to see if we have exceeded
// the number of lines to parse. There's no way
// to know where to stop in the file. Therefore
// we use break to escape the while loop when
// we've reached the count.
if (parseCount != -1 && actualCount >= parseCount) {
break;
}
line = breader.readLine();
}
if (line == null) {
breader.close();
breader = null;
this.READER = null;
// this.READER = new BufferedReader(new
// FileReader(this.SOURCE));
// parse(this.READER,el);
}
} catch (IOException ioe) {
log.error("Error reading log file", ioe);
}
return actualCount;
}
/**
* parseLine calls the other parse methods to parse the given text.
*
* @param line
*/
protected int parseLine(String line, TestElement el) {
int count = 0;
// we clean the line to get
// rid of extra stuff
String cleanedLine = this.cleanURL(line);
log.debug("parsing line: " + line);
// now we set request method
el.setProperty(HTTPSamplerBase.METHOD, RMETHOD);
if (FILTER != null) {
log.debug("filter is not null");
if (!FILTER.isFiltered(line,el)) {
log.debug("line was not filtered");
// increment the current count
count++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -