我自己曾经尝试用python的urllib自己dump数据,结果tomcat的后台报错。
java.io.IOException: Invalid execution data file.
at org.jacoco.agent.rt.internal_932a715.core.data.ExecutionDataReader.read(ExecutionDataReader.java:84)
at org.jacoco.agent.rt.internal_932a715.output.TcpConnection.run(TcpConnection.java:59)
at org.jacoco.agent.rt.internal_932a715.output.TcpServerOutput$1.run(TcpServerOutput.java:63)
at java.lang.Thread.run(Thread.java:619)
好奇为啥不行。翻阅Jacoco官网上的文档,找到了它的一个demo,修改参数连接到我的tomcat下dump数据,好使。
具体的配置和代码链接贴到这里,希望大家有用。希望后面有时间能扒拉一下源代码看看,本地化成自己的。
下载jacoco的jar包,放到某个地方,然后在catalina.sh中配置如下:
JAVA_OPTS="-server -Xms2000m -Xmx2000m -Xmn800m -XX:PermSize=64m
-XX:MaxPermSize=256m -XX:SurvivorRatio=4 -XX:+UseConcMarkSweepGC
-XX:MaxTenuringThreshold=15 -Dfile.encoding=utf8 -Duser.language=zh
-javaagent:/home/auser/myproject/apache-tomcat-6.0.37/lib/
jacocoagent.jar=includes=com.xxx.*,output=tcpserver,port=8494,
address=10.10.10.10"
当然,针对jaococ,真正有用的是-javaagent=yourpath/jacocoagent.jar=[opt]=[val],[opt]=[val]
这段:
-javaagent:/home/iteqa/cms/apache-tomcat-6.0.37/lib/
jacocoagent.jar=includes=com.baidu.*,output=tcpserver,port=8494,
address=10.10.10.10"
http://www.eclemma.org/jacoco/trunk/doc/examples/java/ExecutionDataClient.java
测试ok,能够dump出数据
http://www.eclemma.org/jacoco/trunk/doc/examples/java/ReportGenerator.java
测试报错,can't find class loader ....
找个下班时间继续研究研究
<dependency>
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.core</artifactId>
<version>0.7.1.201405082137</version>
</dependency>
<dependency>
<groupId>org.jacoco</groupId>
<artifactId>org.jacoco.report</artifactId>
<version>0.7.1.201405082137</version>
</dependency>
public class ExecutionDataClient {
private static final String DESTFILE = "jacoco-client.exec";
private static final String ADDRESS = "10.xx.xx.xx";
private static final int PORT = 8494;
/**
* Starts the execution data request.
*
* @param args
* @throws IOException
*/
public static void main(final String[] args) throws IOException {
final FileOutputStream localFile = new FileOutputStream(DESTFILE);
final ExecutionDataWriter localWriter = new ExecutionDataWriter(
localFile);
// Open a socket to the coverage agent:
final Socket socket = new Socket(InetAddress.getByName(ADDRESS), PORT);
final RemoteControlWriter writer = new RemoteControlWriter(
socket.getOutputStream());
final RemoteControlReader reader = new RemoteControlReader(
socket.getInputStream());
reader.setSessionInfoVisitor(localWriter);
reader.setExecutionDataVisitor(localWriter);
// Send a dump command and read the response:
writer.visitDumpCommand(true, false);
reader.read();
socket.close();
localFile.close();
}
private ExecutionDataClient() {
}
}
public class ReportGenerator {
private final String title;
private final File executionDataFile;
private final File classesDirectory;
private final File sourceDirectory;
private final File reportDirectory;
private ExecFileLoader execFileLoader;
/**
* Create a new generator based for the given project.
*
* @param projectDirectory
*/
public ReportGenerator(final File projectDirectory) {
this.title = projectDirectory.getName();
this.executionDataFile = new File(projectDirectory, "jacoco.exec");
this.classesDirectory = new File(projectDirectory, "bin");
this.sourceDirectory = new File(projectDirectory, "src");
this.reportDirectory = new File(projectDirectory, "coveragereport");
}
/**
* Create the report.
*
* @throws IOException
*/
public void create() throws IOException {
// Read the jacoco.exec file. Multiple data files could be merged
// at this point
loadExecutionData();
// Run the structure analyzer on a single class folder to build up
// the coverage model. The process would be similar if your classes
// were in a jar file. Typically you would create a bundle for each
// class folder and each jar you want in your report. If you have
// more than one bundle you will need to add a grouping node to your
// report
final IBundleCoverage bundleCoverage = analyzeStructure();
createReport(bundleCoverage);
}
private void createReport(final IBundleCoverage bundleCoverage)
throws IOException {
// Create a concrete report visitor based on some supplied
// configuration. In this case we use the defaults
final HTMLFormatter htmlFormatter = new HTMLFormatter();
final IReportVisitor visitor = htmlFormatter
.createVisitor(new FileMultiReportOutput(reportDirectory));
// Initialize the report with all of the execution and session
// information. At this point the report doesn't know about the
// structure of the report being created
visitor.visitInfo(execFileLoader.getSessionInfoStore().getInfos(),
execFileLoader.getExecutionDataStore().getContents());
// Populate the report structure with the bundle coverage information.
// Call visitGroup if you need groups in your report.
visitor.visitBundle(bundleCoverage, new DirectorySourceFileLocator(
sourceDirectory, "utf-8", 4));
// Signal end of structure information to allow report to write all
// information out
visitor.visitEnd();
}
private void loadExecutionData() throws IOException {
execFileLoader = new ExecFileLoader();
execFileLoader.load(executionDataFile);
}
private IBundleCoverage analyzeStructure() throws IOException {
final CoverageBuilder coverageBuilder = new CoverageBuilder();
final Analyzer analyzer = new Analyzer(
execFileLoader.getExecutionDataStore(), coverageBuilder);
analyzer.analyzeAll(classesDirectory);
return coverageBuilder.getBundle(title);
}
/**
* Starts the report generation process
*
* @param args
* Arguments to the application. This will be the location of the
* eclipse projects that will be used to generate reports for
* @throws IOException
*/
public static void main(final String[] args) throws IOException {
for (int i = 0; i < args.length; i++) {
final ReportGenerator generator = new ReportGenerator(new File(
args[i]));
generator.create();
}
}
}