提交 7d1378bc 编写于 作者: F Frankie Wu

uprev

上级 f21ceabd
......@@ -50,7 +50,8 @@ public class ComponentsConfigurator extends AbstractResourceConfigurator {
all.add(C(TransactionReportAnalyzer.class).is(PER_LOOKUP) //
.req(MessageManager.class) //
.config(E("reportPath").value("target/report/transaction/")));
.config(E("reportPath").value("target/report/transaction/"))
.req(MessageStorage.class, "html"));
return all;
}
......
......@@ -18,7 +18,6 @@ import com.dianping.cat.configuration.model.entity.Config;
import com.dianping.cat.configuration.model.entity.Property;
import com.dianping.cat.consumer.failure.model.entity.Entry;
import com.dianping.cat.consumer.failure.model.entity.FailureReport;
import com.dianping.cat.consumer.failure.model.entity.Machines;
import com.dianping.cat.consumer.failure.model.entity.Segment;
import com.dianping.cat.consumer.failure.model.entity.Threads;
import com.dianping.cat.message.Event;
......@@ -45,6 +44,7 @@ public class FailureReportAnalyzer extends AbstractMessageAnalyzer<FailureReport
@Inject
private MessageManager m_manager;
// Key: the domain:host of the message. Sample: Review:192.168.1.1
private Map<String, FailureReport> m_reports = new HashMap<String, FailureReport>();
private long m_startTime;
......@@ -65,8 +65,35 @@ public class FailureReportAnalyzer extends AbstractMessageAnalyzer<FailureReport
m_duration = duration;
}
private FailureReport getReportByDomain(String domain) {
FailureReport report = m_reports.get(domain);
public List<String> getAllDomains() {
Set<String> domainAndIps = m_reports.keySet();
Set<String> result = new HashSet<String>();
if (domainAndIps != null) {
for (String domainAndIp : domainAndIps) {
result.add(domainAndIp.substring(0, domainAndIp.lastIndexOf(":")));
}
}
return new ArrayList<String>(result);
}
public List<String> getHostIpByDomain(String domain) {
Set<String> domainAndIps = m_reports.keySet();
Set<String> result = new HashSet<String>();
if (domainAndIps != null) {
for (String domainAndIp : domainAndIps) {
int index = domainAndIp.lastIndexOf(":");
if (domainAndIp.substring(0, index).equals(domain)) {
String ip = domainAndIp.substring(index + 1);
result.add(ip);
}
}
}
return new ArrayList<String>(result);
}
private FailureReport getReportByDomainAndIp(String domain, String ip) {
String domainAndIp = new StringBuffer().append(domain).append(":").append(ip).toString();
FailureReport report = m_reports.get(domainAndIp);
if (report != null) {
return report;
}
......@@ -75,9 +102,8 @@ public class FailureReportAnalyzer extends AbstractMessageAnalyzer<FailureReport
addedReport.setStartTime(new Date(m_startTime));
addedReport.setEndTime(new Date(m_startTime + m_duration - MINUTE));
addedReport.setDomain(domain);
addedReport.setMachines(new Machines());
addedReport.setThreads(new Threads());
m_reports.put(domain, addedReport);
m_reports.put(domainAndIp, addedReport);
return addedReport;
}
......@@ -92,26 +118,18 @@ public class FailureReportAnalyzer extends AbstractMessageAnalyzer<FailureReport
@Override
public List<FailureReport> generate() {
List<FailureReport> reports = new ArrayList<FailureReport>();
for (String domain : m_reports.keySet()) {
reports.add(generateByDomain(domain));
for (String domainAndIp : m_reports.keySet()) {
String[] temp = domainAndIp.split(":");
reports.add(generateByDomainAndIp(temp[0], temp[1]));
}
return reports;
}
@Override
public FailureReport generate(String domain) {
return generateByDomain(domain);
}
@Override
protected void store(List<FailureReport> reports) {
if (reports != null) {
for (FailureReport report : reports) {
String failureFileName = getFailureFileName(report);
String htmlPath = new StringBuilder().append(m_reportPath).append(failureFileName).append(".html")
.toString();
File file = new File(htmlPath);
File file = new File(getFailureFilePath(report));
file.getParentFile().mkdirs();
FailureReportStore.storeToHtml(file, report);
......@@ -119,8 +137,8 @@ public class FailureReportAnalyzer extends AbstractMessageAnalyzer<FailureReport
}
}
public FailureReport generateByDomain(String domain) {
FailureReport m_report = getReportByDomain(domain);
public FailureReport generateByDomainAndIp(String domain, String ip) {
FailureReport m_report = getReportByDomainAndIp(domain, ip);
long time = System.currentTimeMillis();
long endTime = time - time % (60 * 1000);
long start = m_report.getStartTime().getTime();
......@@ -153,11 +171,13 @@ public class FailureReportAnalyzer extends AbstractMessageAnalyzer<FailureReport
throw new RuntimeException();
}
String domain = tree.getDomain();
FailureReport report = getReportByDomain(domain);
String ip = tree.getIpAddress();
FailureReport report = getReportByDomainAndIp(domain, ip);
report.getMachines().addMachine(tree.getIpAddress());
report.getThreads().addThread(tree.getThreadId());
if (null == report.getMachine()) {
report.setMachine(tree.getIpAddress());
}
for (Handler handler : m_handlers) {
handler.handle(report, tree);
}
......@@ -171,12 +191,12 @@ public class FailureReportAnalyzer extends AbstractMessageAnalyzer<FailureReport
return m_reportPath;
}
public String getFailureFileName(FailureReport report) {
public String getFailureFilePath(FailureReport report) {
StringBuffer result = new StringBuffer();
String start = FILE_SDF.format(report.getStartTime());
String end = FILE_SDF.format(report.getEndTime());
result.append(report.getDomain()).append("-").append(start).append("-").append(end);
result.append(m_reportPath).append(report.getDomain()).append(report.getMachine()).append("-").append(start)
.append("-").append(end).append(".html");
return result.toString();
}
......
......@@ -39,7 +39,6 @@ public class IpAnalyzer extends AbstractMessageAnalyzer<IpReport> {
return null;
}
@Override
public IpReport generate(String domain) {
IpReport report = null;
......
......@@ -27,6 +27,7 @@ import com.dianping.cat.message.Message;
import com.dianping.cat.message.Transaction;
import com.dianping.cat.message.spi.AbstractMessageAnalyzer;
import com.dianping.cat.message.spi.MessageManager;
import com.dianping.cat.message.spi.MessageStorage;
import com.dianping.cat.message.spi.MessageTree;
import com.site.helper.Files;
import com.site.lookup.annotation.Inject;
......@@ -40,7 +41,10 @@ public class TransactionReportAnalyzer extends AbstractMessageAnalyzer<Transacti
private final static SimpleDateFormat FILE_SDF = new SimpleDateFormat("yyyyMMddHHmm");
@Inject
private MessageManager m_manager;
private MessageManager messageManager;
@Inject
private MessageStorage messageStorage;
private Map<String, TransactionReport> m_reports = new HashMap<String, TransactionReport>();
......@@ -81,11 +85,11 @@ public class TransactionReportAnalyzer extends AbstractMessageAnalyzer<Transacti
typeSum += sum;
typeSum2 += sum2;
typeFailCount += failCount;
if (name.getSuccessMessageId() != null) {
type.setSuccessMessageId(name.getSuccessMessageId());
if (type.getSuccessMessageUrl() == null && name.getSuccessMessageUrl() != null) {
type.setSuccessMessageUrl(name.getSuccessMessageUrl());
}
if (name.getFailMessageId() != null) {
type.setFailMessageId(name.getFailMessageId());
if (type.getFailMessageUrl() == null && name.getFailMessageUrl() != null) {
type.setFailMessageUrl(name.getFailMessageUrl());
}
type.setMax(Math.max(name.getMax(), type.getMax()));
type.setMin(Math.min(name.getMin(), type.getMin()));
......@@ -116,7 +120,6 @@ public class TransactionReportAnalyzer extends AbstractMessageAnalyzer<Transacti
return reports;
}
@Override
public TransactionReport generate(String domain) {
ArrayList<String> domains = new ArrayList<String>(this.m_reports.keySet());
if (domain == null) {
......@@ -140,7 +143,7 @@ public class TransactionReportAnalyzer extends AbstractMessageAnalyzer<Transacti
@Override
public void initialize() throws InitializationException {
Config config = m_manager.getClientConfig();
Config config = messageManager.getClientConfig();
if (config != null) {
Property property = config.findProperty("transaction-base-dir");
......@@ -162,7 +165,7 @@ public class TransactionReportAnalyzer extends AbstractMessageAnalyzer<Transacti
return false;
}
private void process(TransactionReport report, Message message, String messageId) {
private void process(TransactionReport report, MessageTree tree, Message message) {
if (message instanceof Transaction) {
Transaction t = (Transaction) message;
String tType = t.getType();
......@@ -181,11 +184,17 @@ public class TransactionReportAnalyzer extends AbstractMessageAnalyzer<Transacti
if (!t.isSuccess()) {
name.setFailCount(name.getFailCount() + 1);
}
if (messageId != null) {
if (tree != null) {
if (t.isSuccess()) {
name.setSuccessMessageId(messageId);
if (name.getSuccessMessageUrl() == null) {
String url = this.messageStorage.store(tree);
name.setSuccessMessageUrl(url);
}
} else {
name.setFailMessageId(messageId);
if (name.getFailMessageUrl() == null) {
String url = this.messageStorage.store(tree);
name.setFailMessageUrl(url);
}
}
}
long duration = t.getDuration();
......@@ -198,7 +207,7 @@ public class TransactionReportAnalyzer extends AbstractMessageAnalyzer<Transacti
}
List<Message> children = t.getChildren();
for (Message child : children) {
process(report, child, null);
process(report, tree, child);
}
}
}
......@@ -212,7 +221,7 @@ public class TransactionReportAnalyzer extends AbstractMessageAnalyzer<Transacti
this.m_reports.put(domain, report);
}
Message message = tree.getMessage();
process(report, message, tree.getMessageId());
process(report, tree, message);
}
public void setAnalyzerInfo(long startTime, long duration, String domain, long extraTime) {
......
<model>
<entity name="failure-report" root="true">
<attribute name="domain" value-type="String" />
<attribute name="machine" value-type="String" />
<attribute name="baseUrl" value-type="String" />
<attribute name="startTime" value-type="Date" format="yyyy-MM-dd HH:mm:ss" />
<attribute name="endTime" value-type="Date" format="yyyy-MM-dd HH:mm:ss" />
<entity-ref name="machines" />
<entity-ref name="threads" />
<entity-ref name="segment" type="list" names="segments" />
</entity>
<entity name="machines">
<element name="machine" value-type="String" type="list" names="machines" />
</entity>
<entity name="threads">
<element name="thread" value-type="String" type="list" names="threads" />
</entity>
......
......@@ -3,9 +3,6 @@
<entity name="failure-report" root="true">
<entity-ref name="segment" type="map" />
</entity>
<entity name="machines">
<element name="machine" type="set" />
</entity>
<entity name="threads">
<element name="thread" type="set" />
</entity>
......
<?xml version="1.0" encoding="UTF-8"?>
<model>
<entity name="transaction-report" root="true">
<attribute name="domain" value-type="String" />
<element name="domain" value-type="String" type="set" names="domains"/>
<attribute name="startTime" value-type="Date" format="yyyy-MM-dd HH:mm:ss" />
<attribute name="endTime" value-type="Date" format="yyyy-MM-dd HH:mm:ss" />
<entity-ref name="type" type="list" names="types" />
</entity>
<entity name="type">
<attribute name="id" value-type="String" />
<entity-ref name="name" type="list" names="names" />
</entity>
<entity name="name">
<attribute name="id" value-type="String" />
<attribute name="totalCount" value-type="long" />
<attribute name="failCount" value-type="long" />
<attribute name="failPercent" value-type="double" />
<attribute name="min" value-type="double" />
<attribute name="max" value-type="double" />
<attribute name="avg" value-type="double" />
<attribute name="sum" value-type="double" />
<attribute name="sum2" value-type="double" />
<attribute name="std" value-type="double" />
<element name="success-message-id" value-type="String" />
<element name="fail-message-id" value-type="String" />
</entity>
<entity name="transaction-report" root="true">
<attribute name="domain" value-type="String" />
<element name="domain" value-type="String" type="set" names="domains" />
<attribute name="startTime" value-type="Date" format="yyyy-MM-dd HH:mm:ss" />
<attribute name="endTime" value-type="Date" format="yyyy-MM-dd HH:mm:ss" />
<entity-ref name="type" type="list" names="types" />
</entity>
<entity name="type">
<attribute name="id" value-type="String" />
<entity-ref name="name" type="list" names="names" />
<element name="successMessageUrl" value-type="String" />
<element name="failMessageUrl" value-type="String" />
</entity>
<entity name="name">
<attribute name="id" value-type="String" />
<attribute name="totalCount" value-type="long" />
<attribute name="failCount" value-type="long" />
<attribute name="failPercent" value-type="double" />
<attribute name="min" value-type="double" />
<attribute name="max" value-type="double" />
<attribute name="avg" value-type="double" />
<attribute name="sum" value-type="double" />
<attribute name="sum2" value-type="double" />
<attribute name="std" value-type="double" />
<element name="successMessageUrl" value-type="String" />
<element name="failMessageUrl" value-type="String" />
</entity>
</model>
......@@ -18,8 +18,6 @@
<attribute name="sum" value-type="double" primitive="true" />
<attribute name="sum2" value-type="double" primitive="true" />
<attribute name="std" value-type="double" primitive="true" format="0.0" />
<element name="success-message-id" value-type="String" />
<element name="fail-message-id" value-type="String" />
<entity-ref name="name" type="map" />
</entity>
<entity name="name" class-name="TransactionName">
......@@ -33,8 +31,6 @@
<attribute name="sum" value-type="double" primitive="true" />
<attribute name="sum2" value-type="double" primitive="true" />
<attribute name="std" value-type="double" primitive="true" format="0.0" />
<element name="success-message-id" value-type="String" />
<element name="fail-message-id" value-type="String" />
</entity>
</model>
......@@ -84,6 +84,10 @@
<requirement>
<role>com.dianping.cat.message.spi.MessageManager</role>
</requirement>
<requirement>
<role>com.dianping.cat.message.spi.MessageStorage</role>
<role-hint>html</role-hint>
</requirement>
</requirements>
</component>
</components>
......
......@@ -61,11 +61,6 @@ public class ManyAnalyzerTest extends ComponentTestCase {
protected void store(List<AnalyzerResult> result) {
}
@Override
public AnalyzerResult generate(String domain) {
// TODO Auto-generated method stub
return null;
}
}
public static class MockAnalyzer2 extends
......@@ -89,11 +84,6 @@ public class ManyAnalyzerTest extends ComponentTestCase {
protected void store(List<AnalyzerResult> result) {
}
@Override
public AnalyzerResult generate(String domain) {
// TODO Auto-generated method stub
return null;
}
}
public static class MockAnalyzer3 extends
......@@ -117,11 +107,6 @@ public class ManyAnalyzerTest extends ComponentTestCase {
protected void store(List<AnalyzerResult> result) {
}
@Override
public AnalyzerResult generate(String domain) {
// TODO Auto-generated method stub
return null;
}
}
public static class AnalyzerResult {
......
......@@ -79,11 +79,6 @@ public class OneAnalyzerTwoDurationTest extends ComponentTestCase {
protected void store(List<AnalyzerResult> result) {
}
@Override
public AnalyzerResult generate(String domain) {
// TODO Auto-generated method stub
return null;
}
}
public static class AnalyzerResult {
......
......@@ -22,6 +22,8 @@ import com.site.lookup.ComponentTestCase;
@RunWith(JUnit4.class)
public class FailureAnalyzerStoreTest extends ComponentTestCase {
private String m_domain="middleware";
private String m_host="127.0.0.1";
@Test
public void testLookup() throws Exception {
Handler failure = lookup(Handler.class, "failure-handler");
......@@ -51,9 +53,9 @@ public class FailureAnalyzerStoreTest extends ComponentTestCase {
tree.setMessageId("MessageId" + i);
tree.setThreadId("Thread" + i);
tree.setDomain(m_domain);
tree.setHostName("middleware");
tree.setHostName(m_host);
tree.setIpAddress(m_host);
tree.setMessage(t);
tree.setIpAddress("192.168.8." + i % 4);
t.setDuration(3 * 1000);
t.setTimestamp(start + 1000L * 60 * i);
analyzer.process(tree);
......@@ -64,7 +66,7 @@ public class FailureAnalyzerStoreTest extends ComponentTestCase {
List<FailureReport> report = analyzer.generate();
analyzer.store(report);
FailureReport targetReport = analyzer.generateByDomain(m_domain);
FailureReport targetReport = analyzer.generateByDomainAndIp(m_domain,m_host);
DefaultJsonBuilder builder = new DefaultJsonBuilder();
builder.visitFailureReport(targetReport);
......@@ -91,6 +93,8 @@ public class FailureAnalyzerStoreTest extends ComponentTestCase {
tree.setMessageId("thread0001");
tree.setDomain(m_domain);
tree.setHostName("middleware");
tree.setIpAddress(m_host);
tree.setThreadId("Thread" + i%5);
tree.setMessage(t);
t.setDuration(3 * 1000);
t.setTimestamp(start + 1000L * 60 * i);
......@@ -100,11 +104,10 @@ public class FailureAnalyzerStoreTest extends ComponentTestCase {
List<FailureReport> report = analyzer.generate();
analyzer.store(report);
FailureReport targetReport = analyzer.generateByDomain(m_domain);
FailureReport targetReport = analyzer.generateByDomainAndIp(m_domain,m_host);
String parentPath = analyzer.getReportPath();
String pathname = parentPath + analyzer.getFailureFileName(targetReport);
File storeFile = new File(pathname + ".html");
String pathname = analyzer.getFailureFilePath(targetReport);
File storeFile = new File(pathname);
Assert.assertEquals("Check file is exist!", true, storeFile.exists());
String realResult = Files.forIO().readFrom(storeFile, "utf-8");
String exceptedResult = FailureReportStore.getStoreString(targetReport);
......
......@@ -22,21 +22,26 @@ import com.site.lookup.ComponentTestCase;
@RunWith(JUnit4.class)
public class FailureAnalyzerTest extends ComponentTestCase {
private String m_domain="domain1";
private String m_domain = "domain1";
private String m_host = "127.0.0.1";
private static final long HOUR = 1000L * 60 * 60;
@Test
public void testFailureHandler() throws Exception {
long current = System.currentTimeMillis();
long duration = 60 * 60 * 1000;
long extraTime = 5 * 60 * 1000;
long start = current - current % (60 * 60 * 1000);
long start = current - current % (60 * 60 * 1000) -HOUR;
AnalyzerFactory factory = lookup(AnalyzerFactory.class);
FailureReportAnalyzer analyzer = (FailureReportAnalyzer) factory.create("failure", start, duration, m_domain,
extraTime);
int number = 300 * 10;
// Just for one hour
int number = 60 * 10;
int threadNumber = 10;
DefaultEvent e11 = new DefaultEvent("Error", "testError");
DefaultEvent e21 = new DefaultEvent("Exception", "testException1");
DefaultEvent e31 = new DefaultEvent("RuntimeException", "testRuntimeException1");
......@@ -45,6 +50,8 @@ public class FailureAnalyzerTest extends ComponentTestCase {
MessageTree tree = new DefaultMessageTree();
tree.setMessageId("xx0001");
tree.setDomain(m_domain);
tree.setHostName(m_host);
tree.setIpAddress(m_host);
DefaultTransaction t1 = new DefaultTransaction("T1", "N1", null);
DefaultTransaction t2 = new DefaultTransaction("T2", "N2", null);
DefaultTransaction t3 = new DefaultTransaction("T3", "N3", null);
......@@ -61,7 +68,6 @@ public class FailureAnalyzerTest extends ComponentTestCase {
t1.addChild(e11);
tree.setMessage(t1);
long ct = System.nanoTime();
for (int i = 0; i < number; i++) {
if (i == 1) {
......@@ -69,8 +75,6 @@ public class FailureAnalyzerTest extends ComponentTestCase {
}
long addTime = 6 * 1000 * i;
long timestamp = start + addTime;
tree.setIpAddress("192.168.1." + i);
t1.setTimestamp(timestamp);
t2.setTimestamp(timestamp);
t3.setTimestamp(timestamp);
......@@ -79,7 +83,7 @@ public class FailureAnalyzerTest extends ComponentTestCase {
e22.setTimestamp(timestamp);
e31.setTimestamp(timestamp);
e32.setTimestamp(timestamp);
tree.setThreadId("thread"+i%threadNumber);
tree.setThreadId("thread" + i % threadNumber);
analyzer.process(tree);
}
......@@ -87,12 +91,12 @@ public class FailureAnalyzerTest extends ComponentTestCase {
System.out.println("time: " + time / 1e6 + " ms," + (time / 1e6 / number) + " ms each");
FailureReport report = analyzer.generateByDomain(m_domain);
FailureReport report = analyzer.generateByDomainAndIp(m_domain, m_host);
assertEquals("Check the domain", report.getDomain(), "domain1");
assertEquals("Check the machines", number, report.getMachines().getMachines().size());
assertEquals("Check the threads",threadNumber, report.getThreads().getThreads().size());
assertEquals("Check the machines", m_host,report.getMachine());
assertEquals("Check the threads", threadNumber, report.getThreads().getThreads().size());
Date startDate = report.getStartTime();
Date endDate = report.getEndTime();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
......@@ -111,14 +115,15 @@ public class FailureAnalyzerTest extends ComponentTestCase {
for (int i = 0; i < number / 10; i++) {
String minuteStr = sdf2.format(startDate);
Segment temp = segments.get(minuteStr);
List<Entry> entries = temp.getEntries();
if (entries == null) {
System.out.println(minuteStr);
} else {
assertEquals("Check the segment size ", 50, entries.size());
}
startDate.setTime(startDate.getTime() + 1000 * 60);
}
}
......@@ -128,9 +133,9 @@ public class FailureAnalyzerTest extends ComponentTestCase {
long current = System.currentTimeMillis();
long duration = 60 * 60 * 1000;
long extraTime = 5 * 60 * 1000;
long start = current - current % (60 * 60 * 1000);
String domain="domain1";
long start = current - current % (60 * 60 * 1000) - HOUR;
String domain = "domain1";
AnalyzerFactory factory = lookup(AnalyzerFactory.class);
FailureReportAnalyzer analyzer = (FailureReportAnalyzer) factory.create("failure", start, duration, domain,
extraTime);
......@@ -141,16 +146,16 @@ public class FailureAnalyzerTest extends ComponentTestCase {
tree.setMessageId("thread0001");
tree.setDomain(m_domain);
tree.setHostName("middleware");
tree.setIpAddress("127.0.0." + i);
tree.setIpAddress(m_host);
tree.setMessage(t);
t.setDuration(3 * 1000);
t.setTimestamp(start + 1000L * 60 * i);
analyzer.process(tree);
// analyzer.process(tree);
}
FailureReport report = analyzer.generateByDomain(domain);
FailureReport report = analyzer.generateByDomainAndIp(domain, m_host);
assertEquals("Check the Machines", number, report.getMachines().getMachines().size());
assertEquals("Check the machines", m_host,report.getMachine());
assertEquals("Check the domain", report.getDomain(), "domain1");
Date startDate = report.getStartTime();
......
......@@ -3,14 +3,11 @@
*/
package com.dianping.cat.consumer.transaction;
import static junit.framework.Assert.assertEquals;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import com.dianping.cat.consumer.AnalyzerFactory;
import com.dianping.cat.consumer.transaction.model.entity.TransactionName;
import com.dianping.cat.consumer.transaction.model.entity.TransactionReport;
import com.dianping.cat.consumer.transaction.model.entity.TransactionType;
......@@ -19,40 +16,15 @@ import com.dianping.cat.message.Message;
import com.dianping.cat.message.internal.DefaultTransaction;
import com.dianping.cat.message.spi.MessageTree;
import com.dianping.cat.message.spi.internal.DefaultMessageTree;
import com.site.lookup.ComponentTestCase;
/**
* @author sean.wang
* @since Jan 5, 2012
*/
public class TransactionReportMessageAnalyzerTest {
@RunWith(JUnit4.class)
public class TransactionReportMessageAnalyzerTest extends ComponentTestCase{
/**
* @throws java.lang.Exception
*/
@BeforeClass
public static void setUpBeforeClass() throws Exception {
}
/**
* @throws java.lang.Exception
*/
@AfterClass
public static void tearDownAfterClass() throws Exception {
}
/**
* @throws java.lang.Exception
*/
@Before
public void setUp() throws Exception {
}
/**
* @throws java.lang.Exception
*/
@After
public void tearDown() throws Exception {
}
/**
* Test method for {@link com.dianping.cat.consumer.transaction.TransactionReportAnalyzer#process(com.dianping.cat.message.spi.MessageTree)}.
......@@ -60,8 +32,15 @@ public class TransactionReportMessageAnalyzerTest {
* @throws InterruptedException
*/
@Test
public void testCommonGenerate() throws InterruptedException {
TransactionReportAnalyzer analyzer = new TransactionReportAnalyzer();
public void testCommonGenerate() throws Exception {
long current = System.currentTimeMillis();
long duration = 60 * 60 * 1000;
long extraTime = 5 * 60 * 1000;
long start = current - current % (60 * 60 * 1000) -1000L*60*60;
AnalyzerFactory factory = lookup(AnalyzerFactory.class);
TransactionReportAnalyzer analyzer = (TransactionReportAnalyzer) factory.create("transaction", start, duration, "testDomain",
extraTime);
for (int i = 1; i <= 1000; i++) {
MessageTree tree = new DefaultMessageTree();
......@@ -103,8 +82,6 @@ public class TransactionReportMessageAnalyzerTest {
assertEquals(2000.0, n1.getMax());
assertEquals(1001.0, n1.getAvg());
assertEquals(1001000.0, n1.getSum());
assertEquals("999", n1.getSuccessMessageId());
assertEquals("1000", n1.getFailMessageId());
TransactionType typeA1 = report.getTypes().get("A-1");
TransactionName n2 = typeA1.getNames().get("n2");
......@@ -115,8 +92,6 @@ public class TransactionReportMessageAnalyzerTest {
assertEquals(1000.0, n2.getMax());
assertEquals(500.5, n2.getAvg());
assertEquals(500500.0, n2.getSum());
assertEquals(null, n2.getSuccessMessageId());
assertEquals(null, n2.getFailMessageId());
DefaultJsonBuilder builder = new DefaultJsonBuilder();
report.accept( builder);
System.out.println(builder.getString());
......
{
"domain": "middleware",
"machine": "127.0.0.1",
"startTime": "2012-01-25 13:00:00",
"endTime": "2012-01-25 13:59:00",
"machines": {
"machines": [
"192.168.8.0",
"192.168.8.1",
"192.168.8.2",
"192.168.8.3"
]
},
"threads": {
"threads": [
"Thread0",
......
......@@ -33,8 +33,6 @@ public abstract class AbstractMessageAnalyzer<R> implements MessageAnalyzer {
public abstract List<R> generate();
public abstract R generate(String domain);
protected abstract void process(MessageTree tree);
protected abstract boolean isTimeout();
......
package com.dianping.cat.report.page.failure;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import com.dianping.cat.consumer.failure.model.entity.FailureReport;
import com.dianping.cat.consumer.failure.model.entity.Segment;
import com.dianping.cat.consumer.failure.model.entity.Threads;
import com.dianping.cat.consumer.failure.model.transform.DefaultJsonBuilder;
import com.dianping.cat.tool.DateUtil;
import com.site.helper.Files;
public class FailureData {
public String getFailureJsonDate(FailureReport report) {
DefaultJsonBuilder builder = new DefaultJsonBuilder();
report.accept(builder);
return builder.getString();
}
/*public String getFailureDataFromMemory(FailureReportAnalyzer analyzer, String domain) {
FailureReport report = analyzer.generateByDomain(domain);
return getFailureJsonDate(report);
}
*/
public String getFailureDataFromFile(String basePath, String file) {
String result = "";
try {
result = Files.forIO().readFrom(new File(basePath + file), "utf-8");
result = result.substring(result.indexOf("<body>") + 6, result.indexOf("</body>"));
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
public String getFailureDataByNew(int pos, String domain) {
long currentTime = System.currentTimeMillis();
long currentStart = currentTime - currentTime % DateUtil.HOUR;
long lastStart = currentTime - currentTime % DateUtil.HOUR - DateUtil.HOUR;
Date date = new Date();
if (pos == 1) {
date.setTime(currentStart);
} else {
date.setTime(lastStart);
}
FailureReport report = new FailureReport();
//TODO
//report.setMachines(new Machines());
report.setThreads(new Threads());
report.setStartTime(date);
report.setEndTime(new Date(date.getTime() + DateUtil.HOUR - DateUtil.MINUTE));
report.setDomain(domain);
long start = report.getStartTime().getTime();
long endTime = report.getEndTime().getTime();
Map<String, Segment> segments = report.getSegments();
for (; start <= endTime; start = start + 60 * 1000) {
String minute = DateUtil.SDF_SEG.format(new Date(start));
segments.put(minute, new Segment(minute));
}
return getFailureJsonDate(report);
}
public String getFailureDataFromRemote() {
return "";
}
}
package com.dianping.cat.report.page.failure;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletException;
import com.dianping.cat.consumer.RealtimeConsumer;
import com.dianping.cat.consumer.failure.FailureReportAnalyzer;
import com.dianping.cat.consumer.failure.model.entity.FailureReport;
import com.dianping.cat.consumer.failure.model.entity.Segment;
import com.dianping.cat.consumer.failure.model.entity.Threads;
import com.dianping.cat.consumer.failure.model.transform.DefaultJsonBuilder;
import com.dianping.cat.message.spi.MessageConsumer;
import com.dianping.cat.report.ReportPage;
import com.site.helper.Files;
import com.site.lookup.annotation.Inject;
import com.site.web.mvc.PageHandler;
import com.site.web.mvc.annotation.InboundActionMeta;
......@@ -20,8 +28,6 @@ import com.site.web.mvc.annotation.PayloadMeta;
public class Handler implements PageHandler<Context> {
private static final String DEFAULT_DOMAIN = "User";
private static final String MEMORY_CURRENT = "memory-current";
private static final String MEMORY_LAST = "memory-last";
......@@ -30,7 +36,15 @@ public class Handler implements PageHandler<Context> {
private static final long HOUR = 60 * MINUTE;
private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyyMMddHH");
private static final long SECOND = 1000L;
private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyyMMddHHmm");
private static final SimpleDateFormat SDF_SEG = new SimpleDateFormat("yyyy-MM-dd HH:mm");
private static String DEFAULT_IP = null;
private static String DEFAULT_DOMAIN = null;
@Inject
private JspViewer m_jspViewer;
......@@ -38,58 +52,35 @@ public class Handler implements PageHandler<Context> {
@Inject(type = MessageConsumer.class, value = "realtime")
private RealtimeConsumer m_consumer;
@Override
@PayloadMeta(Payload.class)
@InboundActionMeta(name = "f")
public void handleInbound(Context ctx) throws ServletException, IOException {
// display only, no action here
}
@Override
@OutboundActionMeta(name = "f")
public void handleOutbound(Context ctx) throws ServletException, IOException {
Model model = new Model(ctx);
model.setAction(Action.VIEW);
model.setPage(ReportPage.FAILURE);
Payload payload = ctx.getPayload();
String file = getFailureReportName(payload, model);
String domain = payload.getDomain();
if (null == domain) {
model.setDomain(DEFAULT_DOMAIN);
domain = DEFAULT_DOMAIN;
private FailureReport getFailureReport(int pos, String domain) {
long currentTime = System.currentTimeMillis();
long currentStart = currentTime - currentTime % HOUR;
long lastStart = currentTime - currentTime % HOUR - HOUR;
Date date = new Date();
if (pos == 1) {
date.setTime(currentStart);
} else {
model.setDomain(payload.getDomain());
date.setTime(lastStart);
}
if (file.equals(MEMORY_CURRENT)) {
FailureReportAnalyzer analyzer = (FailureReportAnalyzer) m_consumer.getCurrentAnalyzer("failure");
if (analyzer == null) {
System.out.println("analyzer is null");
model.setReport(new FailureReport());
} else {
model.setReport(analyzer.generateByDomain(domain));
}
} else if (file.equals(MEMORY_LAST)) {
FailureReportAnalyzer analyzer = (FailureReportAnalyzer) m_consumer.getLastAnalyzer("failure");
if (analyzer == null) {
System.out.println("analyzer is null");
model.setReport(new FailureReport());
} else {
//TODO
getReport("");
model.setReport(analyzer.generateByDomain(domain));
}
} else {
model.setReport(new FailureReport());
FailureReport report = new FailureReport();
//report.setMachines(new Machines());
report.setThreads(new Threads());
report.setStartTime(date);
report.setEndTime(new Date(date.getTime() + HOUR - MINUTE));
report.setDomain(domain);
long start = report.getStartTime().getTime();
long endTime = report.getEndTime().getTime();
Map<String, Segment> segments = report.getSegments();
for (; start <= endTime; start = start + 60 * 1000) {
String minute = SDF_SEG.format(new Date(start));
segments.put(minute, new Segment(minute));
}
m_jspViewer.view(ctx, model);
return report;
}
private String getFailureReportName(Payload payload, Model model) {
long currentTime = System.currentTimeMillis();
long currentTimeMillis = System.currentTimeMillis();
long currentTime = currentTimeMillis;
long currentStart = currentTime - currentTime % HOUR;
long lastStart = currentTime - currentTime % HOUR - HOUR;
long startLong = currentStart;
......@@ -105,13 +96,6 @@ public class Handler implements PageHandler<Context> {
} else {
reportStart = SDF.format(currentStart);
}
String domain = payload.getDomain();
if (null == domain) {
model.setDomain(DEFAULT_DOMAIN);
domain = DEFAULT_DOMAIN;
} else {
model.setDomain(payload.getDomain());
}
long computeStart = startLong + payload.getMethod() * HOUR;
if (computeStart > currentStart) {
......@@ -119,6 +103,16 @@ public class Handler implements PageHandler<Context> {
}
model.setCurrent(SDF.format(new Date(computeStart)));
long titleEndTime = computeStart + HOUR - SECOND;
if (titleEndTime > currentTimeMillis) {
titleEndTime = currentTimeMillis;
}
StringBuilder title = new StringBuilder().append("Domain:").append(model.getCurrentDomain());
title.append(" IP ").append(model.getCurrentIp());
title.append(" From ").append(SDF_SEG.format(new Date(computeStart))).append(" To ").append(
SDF_SEG.format(new Date(titleEndTime)));
model.setReportTitle(title.toString());
if (computeStart == currentStart) {
return MEMORY_CURRENT;
} else if (computeStart == lastStart) {
......@@ -126,14 +120,103 @@ public class Handler implements PageHandler<Context> {
}
StringBuilder result = new StringBuilder();
result.append(domain).append("@").append(SDF.format(new Date(computeStart))).append("~").append(
SDF.format(new Date(computeStart + HOUR)));
result.append(model.getCurrentDomain()).append(model.getCurrentIp()).append("-").append(SDF.format(new Date(computeStart))).append("-").append(
SDF.format(new Date(computeStart + HOUR - MINUTE))).append(".html");
return result.toString();
}
private FailureReport getReport(String file) {
// TODO
//Get to json data and output
return new FailureReport();
private String getJsonResultFromFile(String basePath, String file) {
String result = "";
try {
result = Files.forIO().readFrom(new File(basePath + file), "utf-8");
result = result.substring(result.indexOf("<body>") + 6, result.indexOf("</body>"));
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
@Override
@PayloadMeta(Payload.class)
@InboundActionMeta(name = "f")
public void handleInbound(Context ctx) throws ServletException, IOException {
// display only, no action here
}
@Override
@OutboundActionMeta(name = "f")
public void handleOutbound(Context ctx) throws ServletException, IOException {
Model model = new Model(ctx);
model.setAction(Action.VIEW);
model.setPage(ReportPage.FAILURE);
Payload payload = ctx.getPayload();
FailureReportAnalyzer analyzerForPage = (FailureReportAnalyzer) m_consumer.getCurrentAnalyzer("failure");
//Set all domain of page
List<String> domains = analyzerForPage.getAllDomains();
Collections.sort(domains);
model.setDomains(domains);
//Set all ip of the domain
//Set the default domain and default ip
String domain = payload.getDomain();
if (null == domain) {
if(domains!=null&&domains.size()>0){
DEFAULT_DOMAIN = domains.get(0);
model.setCurrentDomain(DEFAULT_DOMAIN);
}else{
throw new RuntimeException("The domain is null!");
}
} else {
model.setCurrentDomain(domain);
}
List<String> ips = analyzerForPage.getHostIpByDomain(model.getCurrentDomain());
Collections.sort(ips);
model.setIps(ips);
String ip = payload.getIp();
if(null==ip){
if(ips!=null&&ips.size()>0){
DEFAULT_IP = ips.get(0);
model.setCurrentIp(DEFAULT_IP);
}else{
throw new RuntimeException("The ip is null!");
}
} else {
model.setCurrentIp(ip);
}
String file = getFailureReportName(payload, model);
domain = model.getCurrentDomain();
ip = model.getCurrentIp();
if (file.equals(MEMORY_CURRENT) || file.equals(MEMORY_LAST)) {
FailureReportAnalyzer analyzer;
int pos = 0;
if (file.equals(MEMORY_CURRENT)) {
analyzer = (FailureReportAnalyzer) m_consumer.getCurrentAnalyzer("failure");
pos = 1;
} else {
analyzer = (FailureReportAnalyzer) m_consumer.getLastAnalyzer("failure");
pos = 0;
}
FailureReport report;
if (analyzer == null) {
report = getFailureReport(pos, domain);
} else {
report = analyzer.generateByDomainAndIp(domain,ip);
}
DefaultJsonBuilder builder = new DefaultJsonBuilder();
report.accept(builder);
model.setJsonResult(builder.getString());
} else {
String baseFilePath = analyzerForPage.getReportPath();
model.setJsonResult(getJsonResultFromFile(baseFilePath, file));
}
m_jspViewer.view(ctx, model);
}
}
package com.dianping.cat.report.page.failure;
import com.dianping.cat.consumer.failure.model.entity.FailureReport;
import com.dianping.cat.consumer.failure.model.transform.DefaultJsonBuilder;
import java.util.List;
import com.dianping.cat.report.ReportPage;
import com.site.web.mvc.ViewModel;
public class Model extends ViewModel<ReportPage, Action, Context> {
private FailureReport m_report;
private String m_current;
private String m_domain;
private String m_currentDomain;
private String m_currentIp;
private List<String> m_domains;
private List<String> m_ips;
private String m_jsonResult;
private String m_reportTitle;
public Model(Context ctx) {
super(ctx);
}
public String getCurrent() {
return m_current;
}
public String getCurrentDomain() {
return m_currentDomain;
}
public String getCurrentIp() {
return m_currentIp;
}
@Override
public Action getDefaultAction() {
return Action.VIEW;
}
public FailureReport getReport() {
return m_report;
}
public List<String> getDomains() {
return m_domains;
}
public String getReportInJson() {
DefaultJsonBuilder builder = new DefaultJsonBuilder();
m_report.accept(builder);
return builder.getString();
}
public List<String> getIps() {
return m_ips;
}
public void setReport(FailureReport report) {
m_report = report;
}
public String getJsonResult() {
return m_jsonResult;
}
public String getCurrent() {
return m_current;
public String getReportTitle() {
return m_reportTitle;
}
public void setCurrent(String current) {
this.m_current = current;
}
public String getDomain() {
return m_domain;
public void setCurrentDomain(String currentDomain) {
m_currentDomain = currentDomain;
}
public void setCurrentIp(String currentIp) {
m_currentIp = currentIp;
}
public void setDomains(List<String> domains) {
m_domains = domains;
}
public void setIps(List<String> ips) {
m_ips = ips;
}
public void setDomain(String domain) {
this.m_domain = domain;
public void setJsonResult(String jsonResult) {
m_jsonResult = jsonResult;
}
public void setReportTitle(String reportTitle) {
m_reportTitle = reportTitle;
}
public String getSimpleCurrentIp(){
return m_currentIp.replace(".", "");
}
}
......@@ -13,6 +13,9 @@ public class Payload implements ActionPayload<ReportPage, Action> {
@FieldMeta("domain")
private String m_domain;
@FieldMeta("ip")
private String m_ip;
@FieldMeta("start")
private String m_current;
......@@ -71,4 +74,11 @@ public class Payload implements ActionPayload<ReportPage, Action> {
m_page = page;
}
public String getIp() {
return m_ip;
}
public void setIp(String ip) {
m_ip = ip;
}
}
package com.dianping.cat.tool;
import java.text.SimpleDateFormat;
public class DateUtil {
public static final long SECOND = 1000L;
public static final long MINUTE = SECOND * 60;
public static final long HOUR = MINUTE * 60;
public static final SimpleDateFormat SDF = new SimpleDateFormat("yyyyMMddHHmm");
public static final SimpleDateFormat SDF_SEG = new SimpleDateFormat("yyyy-MM-dd HH:mm");
}
.report-table {
border-spacing: 0;
width:100%;
}
.report-table th,.report-table td {
.report-table th {
padding: 3px;
background-color: #f5f5f5;
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
border-top: 1px solid #ccc;
}
.report-table td {
padding: 3px;
background-color: #f5f5f5;
border-right: 1px solid #ccc;
......
......@@ -5,12 +5,9 @@ function generateTable(wrap, json) {
if(threads==null){
threads =[];
}
if(json.machines.machines==null){
json.machines.machines=[];
}
caption.html(
/*caption.html(
"From " + json.startTime + " To " + json.endTime
+ " Failure Report Domain:" + json.domain).appendTo(table);
+ " Failure Report Domain:" + json.domain).appendTo(table);*/
thead.appendTo(table);
......@@ -20,14 +17,14 @@ function generateTable(wrap, json) {
temp.appendTo(thr);
});
$('<tr />').append(
/*$('<tr />').append(
$('<td />').attr('colspan', threads.length + 1).html(
"machines:" + json.machines.machines.join(','))).appendTo(
table);
table);*/
for ( var key in json.segments) {
var seg = json.segments[key];
var tr = $('<tr />'), tds = [];
$('<td />').html(seg.id).appendTo(tr);
$('<td />').html(seg.id.substring(11)).appendTo(tr);
threads.forEach(function() {
var td = $('<td />');
td.appendTo(tr);
......@@ -40,8 +37,7 @@ function generateTable(wrap, json) {
.forEach(function(entry) {
var index = threads.indexOf(entry.threadId), td = tds[index], type = entry.type, anchor = $(
'<a />').attr("href",
"/m/path" + entry.path).attr("target",
"_blank").addClass(type).html(entry.text);
"m/" + entry.path).addClass(type).html(entry.text);
if (td.html()) {
td.append($('<br />'));
......@@ -59,3 +55,10 @@ function generateTable(wrap, json) {
}
generateTable('#failureTable', jsonData);
var currentDomain = $("#currentDomain").val();
$("#domain-"+currentDomain).css("background", "#FFCC00");
var currentIp = $("#currentIp").val();
$("a[data-id='ip-"+currentIp+"']").css("background", "#FFCC00");
此差异已折叠。
......@@ -3,9 +3,9 @@ $(function(){
var types = data["types"];
for (i in types) {
var type = types[i];
var sampleid = type.failid == null ? type.successid : type.failid;
var sampleid = type.failMessageUrl != null ? type.failMessageUrl : type.successMessageUrl;
var stat = "" + type.min + "/" + type.max + "/" + type.avg + "/" + type.std;
tabledata.push({"type":type.id, "total":type.totalCount, "fail":type.failCount, "failPercent":type.failPercent, "sample":sampleid, "stat":stat});
tabledata.push({"type":type.id, "total":type.totalCount, "fail":type.failCount, "failPercent":type.failPercent, "sample":"<a href=\"/cat/r/m/"+sampleid+"\" target=\"_blank\">link</a>", "stat":stat});
}
}
);
......@@ -15,22 +15,26 @@ $(function()
domainlinks = 'Domains ';
$.each(data.domains, function(i, t){domainlinks += "[ <a href=\"/cat/r/t?domain="+t+"\">"+t+"</a> ]"});
$("#domainlist").html(domainlinks);
$("#gridTable").jqGrid({
$("#gridTable").jqGrid({
defaults : {
//shrinkToFit:true,
//forceFit:true,
},
datatype: "local",
colNames:['Type', 'Total Count', 'Fail Count', 'Failure%', 'Sample Link', 'Min/Max/Avg/Std(ms)'],
colModel:[
{name:'type', index:'type', width:200},
{name:'total', index:'total', width:100, sorttype:"int", align:'right'},
{name:'fail', index:'fail', width:100, sorttype:"int", align:'right'},
{name:'failPercent', index:'failPercent', width:100, sorttype:"float", align:'center'},
{name:'sample', index:'sample', width:200, sortable:false},
{name:'stat', width:200, sortable:false}
{name:'type', index:'type', align:'center'},
{name:'total', index:'total', sorttype:"int", align:'center'},
{name:'fail', index:'fail', sorttype:"int", align:'center'},
{name:'failPercent', index:'failPercent', sorttype:"float", align:'center'},
{name:'sample', index:'sample', sortable:false, align:'center', width:100},
{name:'stat', sortable:false, align:'center',width:200}
],
sortname:'type',
sortorder:'asc',
caption: "Domain " + data["domain"] + " Transaction Summary",
height: '100%',
autowidth: true,
//autowidth: true,
loadComplete: function() {
$("#gridTable").setGridHeight('auto');
}
......@@ -41,10 +45,10 @@ $(function()
grid.jqGrid('addRowData',i+1,tabledata[i]);
}
$(function(){
$(window).resize(function(){
$("#gridTable").setGridWidth($(window).width()*0.99);
});
});
//$(function(){
// $(window).resize(function(){
// $("#gridTable").setGridWidth($(window).width()*0.99);
// });
//});
}
);
\ No newline at end of file
<%@ page contentType="text/html; charset=utf-8"%>
<%@ taglib prefix="a" uri="/WEB-INF/app.tld"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="res" uri="http://www.ebay.com/webres"%>
<jsp:useBean id="ctx"
type="com.dianping.cat.report.page.failure.Context" scope="request" />
......@@ -11,27 +12,25 @@
<a:body>
<res:useCss value='${res.css.local.default_css}' target="head-css" />
<res:useCss value='${res.css.local.jquery_css}' target="head-css" />
<res:useCss value='${res.css.local.jqgrid_css}' target="head-css" />
<res:useCss value='${res.css.local.style_css}' target="head-css" />
<res:useCss value='${res.css.local.failure_css}' target="head-css" />
<res:useJs value='${res.js.local.mootools_js}' target="head-js" />
<res:useJs value='${res.js.local.jquery_min_js}' target="head-js" />
<res:useJs value='${res.js.local.jquery_ui_min_js}' target="head-js" />
<res:useJs value='${res.js.local.grid_js}' target="head-js" />
<res:useJs value='${res.js.local.jqgrid_min_js}' target="head-js" />
<res:useJs value='${res.js.local.sql_scripts_js}' target="head-js" />
<script type="text/javascript">
var jsonData = ${model.reportInJson};
var jsonData = ${model.jsonResult};
</script>
<table width="100%" border="0" cellpadding="6" cellspacing="0"
class="fancy-header">
<tbody>
<tr>
<td nowrap="">Dian Ping CAT Reports: Report For XXXXXX Current: ${model.current}</td>
<td nowrap="">Dian Ping CAT Reports: ${model.reportTitle}</td>
<td width="100%" align="right" nowrap="">Generated: XXXXXX</td>
<td style="display:none"><input id="currentDomain" value="${model.currentDomain}">
<input id="currentIp" value="${model.currentIp}"></input></td>
</tr>
</tbody>
</table>
......@@ -40,29 +39,38 @@
<tbody>
<tr>
<td nowrap="nowrap" align="left" class="seealso">Domains:
[ <a href="/cat/r/f?domain=Shop">Shop</a>
] [ <a href="/cat/r/f?domain=User">User</a>
] [ <a href="/cat/r/f?domain=Pic">Pic</a>
] [ <a href="/cat/r/f?domain=Review">Review</a>
] [ <a href="/cat/r/f?domain=Group">Group</a>
] [ <a href="/cat/r/f?domain=Tuan">Tuan</a>
]<br>
<c:forEach
var="domain" items="${model.domains}">
[ <a id="domain-${domain}" href="/cat/r/f?domain=${domain}">${domain}</a>]
</c:forEach> <br>
</td>
<td nowrap="nowrap" align="right" class="seealso">
[ <a href="/cat/r/f?domain=${model.domain}&start=${model.current}&method=-24">-1d</a>
] [ <a href="/cat/r/f?domain=${model.domain}&start=${model.current}&method=-2">-2H</a>
] [ <a href="/cat/r/f?domain=${model.domain}&start=${model.current}&method=-1">-1H</a>
] [ <a href="/cat/r/f?domain=${model.domain}&start=${model.current}&method=1">+1H</a>
] [ <a href="/cat/r/f?domain=${model.domain}&start=${model.current}&method=2">+2H</a>
] [ <a href="/cat/r/f?domain=${model.domain}&start=${model.current}&method=24">+1d</a>
<td nowrap="nowrap" align="right" class="seealso">[ <a
href="/cat/r/f?domain=${model.currentDomain}&start=${model.current}&ip=${model.currentIp}&method=-24">-1d</a>
] [ <a
href="/cat/r/f?domain=${model.currentDomain}&start=${model.current}&ip=${model.currentIp}&method=-2">-2H</a>
] [ <a
href="/cat/r/f?domain=${model.currentDomain}&start=${model.current}&ip=${model.currentIp}&method=-1">-1H</a>
] [ <a
href="/cat/r/f?domain=${model.currentDomain}&start=${model.current}&ip=${model.currentIp}&method=1">+1H</a>
] [ <a
href="/cat/r/f?domain=${model.currentDomain}&start=${model.current}&ip=${model.currentIp}&method=2">+2H</a>
] [ <a
href="/cat/r/f?domain=${model.currentDomain}&start=${model.current}&ip=${model.currentIp}&method=24">+1d</a>
]<br>
</td>
</tr>
<tr>
<td nowrap="nowrap" align="left" class="seealso">Ips:
<c:forEach var="ip" items="${model.ips}">
[ <a data-id="ip-${ip}" href="/cat/r/f?domain=${model.currentDomain}&start=${model.current}&ip=${model.currentIp}">${ip}</a>]
</c:forEach> <br>
</td>
</tr>
</tbody>
</table>
<br/>
<br />
<table id="failureTable" width="100%" border="0" cellspacing="0"></table>
<br/>
<br />
<table width="100%" border="0" cellpadding="6" cellspacing="0"
class="fancy-footer">
<tbody>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册