提交 65b3661e 编写于 作者: Y youyong205

Merge branch 'master' of github.com:dianping/cat

......@@ -45,7 +45,7 @@ public class ComponentsConfigurator extends AbstractResourceConfigurator {
all.add(C(Executor.class, SystemStateExecutor.ID, SystemStateExecutor.class).req(EnvConfig.class,
CommandUtils.class));
all.add(C(TaskExecutors.class).req(DataSender.class));
all.add(C(TaskExecutors.class).req(DataSender.class, EnvConfig.class));
all.add(C(PaasTask.class).req(DataSender.class, DataBuilder.class));
......
package com.dianping.cat.agent.monitor.executors;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.codehaus.plexus.util.StringUtils;
import com.dianping.cat.Cat;
import com.dianping.cat.configuration.NetworkInterfaceManager;
public class EnvConfig implements Initializable {
......@@ -20,6 +24,8 @@ public class EnvConfig implements Initializable {
private String m_hostName;
private String m_monitors;
private String MD5_PATH = "/usr/sbin/sshd";
private String PACKAGE_INTERFACE = "eth0";
......@@ -28,9 +34,9 @@ public class EnvConfig implements Initializable {
private String CATALINA_PATH = "/data/applogs/tomcat/catalina.out";
private List<String> TRAFFIC_INTERFACE_LIST = new ArrayList<String>(Arrays.asList("eth0", "lo"));
private List<String> TRAFFIC_INTERFACE_LIST = Arrays.asList("eth0", "lo");
private List<String> DISK_LIST = new ArrayList<String>(Arrays.asList("/", "/data", "/usr", "/var"));
private List<String> DISK_LIST = Arrays.asList("/", "/data", "/usr", "/var");
public String getDomain() {
return m_domain;
......@@ -48,6 +54,10 @@ public class EnvConfig implements Initializable {
return m_hostName;
}
public String getMonitors() {
return m_monitors;
}
public String getConfig() {
return CONFIG_FILE;
}
......@@ -91,31 +101,63 @@ public class EnvConfig implements Initializable {
return domain;
}
@Override
public void initialize() {
private void loadFromConfig(String defaultMonitors) {
Properties properties = new Properties();
InputStream in = null;
try {
String agent = System.getProperty("agent", "executors");
in = new BufferedInputStream(new FileInputStream(getConfig()));
properties.load(in);
if ("executors".equals(agent)) {
Properties properties = new Properties();
InputStream in = new BufferedInputStream(new FileInputStream(getConfig()));
properties.load(in);
m_hostName = properties.getProperty("host.name");
m_hostName = properties.getProperty("host.name");
if (m_hostName == null) {
m_hostName = NetworkInterfaceManager.INSTANCE.getLocalHostName();
m_domain = "unset";
} else {
m_domain = buildDomain(m_hostName);
}
m_ip = properties.getProperty("host.ip");
if (m_hostName == null) {
m_hostName = NetworkInterfaceManager.INSTANCE.getLocalHostName();
}
if (m_ip == null) {
m_ip = NetworkInterfaceManager.INSTANCE.getLocalHostAddress();
}
m_domain = buildDomain(m_hostName);
m_ip = properties.getProperty("host.ip");
m_monitors = properties.getProperty("host.monitors");
if (m_ip == null) {
m_ip = NetworkInterfaceManager.INSTANCE.getLocalHostAddress();
}
if (m_monitors == null) {
m_monitors = defaultMonitors;
}
} catch (Exception e) {
throw new RuntimeException("Error when init environment info ", e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
Cat.logError(e);
}
}
}
}
@Override
public void initialize() throws InitializationException {
String agent = System.getProperty("agent", "executors");
if ("executors".equals(agent)) {
File configFile = new File(getConfig());
String envMoniotors = System.getenv("MONITORS");
String defaultMonitors = StringUtils.isEmpty(envMoniotors) ? "system" : envMoniotors;
if (configFile.exists()) {
loadFromConfig(defaultMonitors);
} else {
m_domain = "unset";
m_monitors = defaultMonitors;
m_ip = NetworkInterfaceManager.INSTANCE.getLocalHostAddress();
m_hostName = NetworkInterfaceManager.INSTANCE.getLocalHostName();
}
}
}
}
package com.dianping.cat.agent.monitor.executors;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
......@@ -14,15 +15,22 @@ import org.unidal.lookup.annotation.Inject;
import com.dianping.cat.Cat;
import com.dianping.cat.agent.monitor.DataEntity;
import com.dianping.cat.agent.monitor.DataSender;
import com.dianping.cat.agent.monitor.executors.jvm.JVMMemoryExecutor;
import com.dianping.cat.agent.monitor.executors.jvm.JVMStateExecutor;
import com.dianping.cat.agent.monitor.executors.system.SystemPerformanceExecutor;
import com.dianping.cat.agent.monitor.executors.system.SystemStateExecutor;
import com.dianping.cat.message.Transaction;
public class TaskExecutors extends ContainerHolder implements Task, Initializable {
private Collection<Executor> m_executors;
@Inject
private DataSender m_sender;
@Inject
private EnvConfig m_config;
private Collection<Executor> m_executors = new ArrayList<Executor>();
private static final long DURATION = 5 * 1000;
@Override
......@@ -36,8 +44,17 @@ public class TaskExecutors extends ContainerHolder implements Task, Initializabl
if ("executors".equalsIgnoreCase(agent)) {
Map<String, Executor> map = lookupMap(Executor.class);
m_executors = map.values();
String monitors = m_config.getMonitors();
if (monitors.toLowerCase().contains("system")) {
m_executors.add(map.get(SystemPerformanceExecutor.ID));
m_executors.add(map.get(SystemStateExecutor.ID));
}
if (monitors.toLowerCase().contains("tomcat")) {
m_executors.add(map.get(JVMMemoryExecutor.ID));
m_executors.add(map.get(JVMStateExecutor.ID));
}
Threads.forGroup("Cat").start(this);
}
}
......
......@@ -7,7 +7,6 @@ import java.util.Map;
import org.codehaus.plexus.util.StringUtils;
import org.unidal.lookup.annotation.Inject;
import org.unidal.tuple.Pair;
import com.dianping.cat.Cat;
import com.dianping.cat.agent.monitor.CommandUtils;
......@@ -18,40 +17,38 @@ public class DataBuilder {
@Inject
private CommandUtils m_commandUtils;
private Map<String, String> m_ip2Md5 = new HashMap<String, String>();
private Map<String, Double> m_lastValues = new HashMap<String, Double>();
private Map<String, Pair<Double, Double>> m_lastFlow = new HashMap<String, Pair<Double, Double>>();
private Map<String, String> m_ip2Md5 = new HashMap<String, String>();
public String getPaasMonintor() {
return System.getProperty("user.dir") + "/paas-monitor.py";
}
private Pair<Double, Double> findOrCreateFlow(String ip) {
Pair<Double, Double> flow = m_lastFlow.get(ip);
private double findOrCreateSumValue(String key) {
Double value = m_lastValues.get(key);
if (flow == null) {
flow = new Pair<Double, Double>(-1D, -1D);
m_lastFlow.put(ip, flow);
if (value == null) {
value = new Double(-1D);
m_lastValues.put(key, value);
}
return flow;
return value;
}
private String findOrCreateMd5Info(String ip) {
String md5Info = m_ip2Md5.get(ip);
private String findOrCreateMd5Info(String key) {
String md5Info = m_ip2Md5.get(key);
if (md5Info == null) {
md5Info = "";
m_ip2Md5.put(ip, md5Info);
m_ip2Md5.put(key, md5Info);
}
return md5Info;
}
private List<DataEntity> convert2DataEntities(List<String> lines) {
List<DataEntity> dataEntities = new ArrayList<DataEntity>();
Pair<Double, Double> flow = null;
String domain = null;
String ip = null;
for (String line : lines) {
try {
......@@ -64,21 +61,15 @@ public class DataBuilder {
if (line.startsWith("domain")) {
domain = value;
ip = key.substring(key.lastIndexOf("_"));
flow = findOrCreateFlow(ip);
} else if (line.startsWith("system_eth0-in-flow")) {
DataEntity inFlow = buildInFlowData(domain, type, realKey, flow, value);
} else if ("sum".equals(type)) {
DataEntity inFlow = buildSumEntity(domain, type, realKey, key, value);
add2Entities(dataEntities, inFlow);
} else if (line.startsWith("system_eth0-out-flow")) {
DataEntity outFlow = buildOutFlowData(domain, type, realKey, flow, value);
add2Entities(dataEntities, outFlow);
} else if (line.startsWith("system_md5Change")) {
DataEntity md5Info = buildMd5Info(domain, type, realKey, ip, value);
DataEntity md5Info = buildMd5Info(domain, type, realKey, key, value);
add2Entities(dataEntities, md5Info);
} else {
} else if ("avg".equals(type)) {
DataEntity entity = new DataEntity();
entity.setGroup("system-" + domain).setDomain(domain).setId(realKey).setTime(System.currentTimeMillis())
......@@ -98,21 +89,21 @@ public class DataBuilder {
}
}
private DataEntity buildInFlowData(String domain, String type, String key, Pair<Double, Double> flow, String value) {
private DataEntity buildSumEntity(String domain, String type, String realKey, String key, String value) {
DataEntity entity = null;
try {
double flowValue = Double.parseDouble(value);
double lastInFlow = flow.getKey();
double currentValue = Double.parseDouble(value);
double lastValue = findOrCreateSumValue(key);
if (lastInFlow >= 0) {
double gap = flowValue - lastInFlow;
if (lastValue >= 0) {
double gap = currentValue - lastValue;
entity = new DataEntity();
entity.setGroup(buildGroup(domain)).setDomain(domain).setId(key).setTime(System.currentTimeMillis())
entity.setGroup(buildGroup(domain)).setDomain(domain).setId(realKey).setTime(System.currentTimeMillis())
.setType(type).setValue(gap);
}
flow.setKey(flowValue);
m_lastValues.put(key, currentValue);
} catch (Exception e) {
Cat.logError(e);
}
......@@ -120,29 +111,13 @@ public class DataBuilder {
return entity;
}
private DataEntity buildOutFlowData(String domain, String type, String key, Pair<Double, Double> flow, String value) {
DataEntity entity = null;
double flowValue = Double.parseDouble(value);
double lastFlow = flow.getValue();
if (lastFlow >= 0) {
double gap = flowValue - lastFlow;
entity = new DataEntity();
entity.setGroup(buildGroup(domain)).setDomain(domain).setId(key).setTime(System.currentTimeMillis())
.setType(type).setValue(gap);
}
flow.setValue(flowValue);
return entity;
}
private DataEntity buildMd5Info(String domain, String type, String key, String ip, String value) {
String md5Info = findOrCreateMd5Info(ip);
private DataEntity buildMd5Info(String domain, String type, String realKey, String key, String value) {
String md5Info = findOrCreateMd5Info(key);
DataEntity entity = null;
if (StringUtils.isNotEmpty(md5Info)) {
entity = new DataEntity();
entity.setGroup(buildGroup(domain)).setDomain(domain).setId(key).setTime(System.currentTimeMillis())
entity.setGroup(buildGroup(domain)).setDomain(domain).setId(realKey).setTime(System.currentTimeMillis())
.setType(type);
if (md5Info.equals(value)) {
entity.setValue(1);
......@@ -150,7 +125,7 @@ public class DataBuilder {
entity.setValue(0);
}
} else {
m_ip2Md5.put(ip, value);
m_ip2Md5.put(key, value);
}
return entity;
}
......
......@@ -101,6 +101,9 @@
<requirement>
<role>com.dianping.cat.agent.monitor.DataSender</role>
</requirement>
<requirement>
<role>com.dianping.cat.agent.monitor.executors.EnvConfig</role>
</requirement>
</requirements>
</component>
<component>
......@@ -175,8 +178,15 @@
<requirement>
<role>com.dianping.cat.agent.monitor.DataSender</role>
</requirement>
<requirement>
<role>com.dianping.cat.agent.monitor.executors.EnvConfig</role>
</requirement>
</requirements>
</component>
<component>
<role>com.dianping.cat.agent.monitor.executors.EnvConfig</role>
<implementation>com.dianping.cat.agent.monitor.executors.EnvConfig</implementation>
</component>
<component>
<role>com.dianping.cat.agent.monitor.paas.PaasTask</role>
<implementation>com.dianping.cat.agent.monitor.paas.PaasTask</implementation>
......
......@@ -15,6 +15,11 @@ def execute(command):
return p.returncode, p.stdout.read(), p.stderr.read()
def docker_command(pid, command):
_, result, _ = execute(COMMAND_PATTERN % (pid, command))
return result.strip()
def get_instance_ids():
return [ele['Id'] for ele in json.loads(urllib2.urlopen('http://0.0.0.0:8090/containers/ps').read())]
......@@ -49,12 +54,12 @@ def get_name(inspect_info):
def get_cpu_usage(metric_info):
if 'current_usage' in metric_info['cpu_stats']['cpu_usage']:
return metric_info['cpu_stats']['cpu_usage']['current_usage']
return metric_info['cpu_stats']['cpu_usage']['cpu_usage']
return 0
def get_network_info(pid, network_name):
_, flow, _ = execute(COMMAND_PATTERN % (pid, 'ifconfig %s' % network_name))
flow = docker_command(pid, 'ifconfig %s' % network_name)
total_error, total_dropped, total_collision = [0] * 3
m = re.search(r'RX bytes:\s*(\d+).*?TX bytes:\s*(\d+)', flow, re.IGNORECASE)
......@@ -77,12 +82,11 @@ def get_network_info(pid, network_name):
return rx, tx, total_error, total_dropped, total_collision
def get_container_info(inspect_info):
pid = inspect_info['State']['Pid']
_, disk_usage, _ = execute(COMMAND_PATTERN % (pid, 'df -h | grep "rootfs"'))
def get_container_info(pid):
disk_usage = docker_command(pid, 'df -h | grep "rootfs"')
disk_usage = re.split(r'\s+', disk_usage.strip())[-2][:-1]
disk_usage = int(disk_usage) * 1.0 / 100
_, ssh_md5, _ = execute(COMMAND_PATTERN % (pid, 'md5sum /usr/sbin/sshd'))
ssh_md5 = docker_command(pid, 'md5sum /usr/sbin/sshd')
ssh_md5 = re.split(r'\s+', ssh_md5.strip())[0]
eth0_rx, eth0_tx, eth0_errors, eth0_dropped, eth0_collision = get_network_info(pid, 'eth0')
......@@ -97,7 +101,8 @@ def get_swap_usage(metric_info):
def get_memory_info(metric_info, instance_id):
used, cached = metric_info['memory_stats']['usage'], metric_info['memory_stats']['stats']['cache']
used, cached = metric_info['memory_stats']['stats']['rss'], metric_info['memory_stats']['stats']['cache']
shared, buffered = [0, 0]
total = -1
try:
result = json.loads(post('http://localhost:8090/containers/%s/cgroup' % instance_id,
......@@ -109,7 +114,29 @@ def get_memory_info(metric_info, instance_id):
except Exception, e:
pass
return total, used, cached
free = int(total) - int(used) - int(cached)
return total, used, cached, free, shared, buffered
def get_process_info(pid):
result = docker_command(pid, "top -b -n1 | grep Tasks | awk '{print $2,$4}'")
return re.split(r'\s+', result.strip())
def get_number_of_user_connected(pid):
result = docker_command(pid, "who | awk '{ print $1 }' | sort | uniq | wc -l")
return result.strip()
def get_tcp_established(pid):
result = docker_command(pid, 'netstat -anot | grep ESTABLISHED | wc -l')
return result.strip()
def get_inodes_info(pid):
result = docker_command(pid, "df -i | grep rootfs | awk '{print $2,$4}'")
return re.split(r'\s+', result.strip())
def post(url, data, headers={}):
......@@ -130,10 +157,16 @@ def get_all_info(current_instance=None):
inspect_info = instance_inspect(instance_id)
metric_info = instance_metric(instance_id)
pid = inspect_info['State']['Pid']
disk_usage, ssh_md5, eth0_rx, eth0_tx, eth0_errors, eth0_dropped, eth0_collision, lo_rx, lo_tx, \
lo_errors, lo_dropped, lo_collision = get_container_info(inspect_info)
lo_errors, lo_dropped, lo_collision = get_container_info(pid)
ip = get_ip(inspect_info)
mem_total, mem_used, mem_cached = get_memory_info(metric_info, instance_id)
mem_total, mem_used, mem_cached, mem_free, mem_shared, mem_buffered = get_memory_info(metric_info, instance_id)
process_total, process_running = get_process_info(pid)
number_of_user_connected = get_number_of_user_connected(pid)
tcp_established_num = get_tcp_established(pid)
inodes_total, inodes_free = get_inodes_info(pid)
m = [
('domain', '', get_name(inspect_info)),
......@@ -141,6 +174,9 @@ def get_all_info(current_instance=None):
('system_cachedMem', 'avg', mem_cached),
('system_totalMem', 'avg', mem_total),
('system_usedMem', 'avg', mem_used),
('system_freeMem', 'avg', mem_free),
('system_sharedMem', 'avg', mem_shared),
('system_buffersMem', 'avg', mem_buffered),
('system_/-usage', 'avg', disk_usage),
('system_swapUsage', 'avg', get_swap_usage(metric_info)),
('system_md5Change', 'avg', ssh_md5),
......@@ -152,9 +188,12 @@ def get_all_info(current_instance=None):
('system_eth0-collisions', 'sum', eth0_collision),
('system_lo-outFlow', 'sum', lo_tx),
('system_lo-inFlow', 'sum', lo_rx),
('system_lo-dropped', 'sum', lo_dropped),
('system_lo-errors', 'sum', lo_errors),
('system_lo-collisions', 'sum', lo_collision),
('system_totalProcess', 'avg', process_total),
('system_runningProcess', 'avg', process_running),
('system_establishedTcp', 'avg', tcp_established_num),
('system_loginUsers', 'avg', number_of_user_connected),
('system_/-freeInodes', 'avg', "%.3f" % (float(inodes_free) / int(inodes_total))),
]
print '\n'.join(['%s_%s%s=%s' % (k, ip, t and ':' + t, v) for k, t, v in m])
......
# pull cat-agent source and packge to RPM
# yum install rpm-build
# yum install rpmdevtools
set -e
set -u
if [ ! $# -eq 2 ];then
echo "Usage: makerpm.sh tomcat/jboss version."
exit 1
fi
container=$1
version=$2
if [ ! "$1" = "tomcat" ] && [ ! "$1" = "jboss" ]; then
echo "Usage: makerpm.sh tomcat/jboss version."
echo "Container can only be tomcat or jboss."
exit 1
fi
CAT_ROOT=~/cat
CAT_DIR=~/cat/cat
TMP_DIR=~/tmp
RPM_SOURCE_NAME=cat-agent-$container-$version
CAT_AGENT_INSTALL_DIR_NAME=cat-agent
mkdir -p $CAT_ROOT
cd $CAT_ROOT
if [ ! -e $CAT_DIR ]; then
git clone https://github.com/dianping/cat.git
fi
cd -
# pull lastest cat code
cd $CAT_DIR/cat-agent
git pull
# package it
mvn -Dmaven.test.skip clean package
cd -
# prepare agent code
mkdir -p $TMP_DIR
cd $TMP_DIR
rm -rf *
mkdir -p $RPM_SOURCE_NAME/$CAT_AGENT_INSTALL_DIR_NAME
unzip -d $RPM_SOURCE_NAME/$CAT_AGENT_INSTALL_DIR_NAME $CAT_DIR/cat-agent/target/cat-agent-*.war
tar czf $RPM_SOURCE_NAME.tar.gz $RPM_SOURCE_NAME
rpmdev-setuptree
cp $RPM_SOURCE_NAME.tar.gz ~/rpmbuild/SOURCES/
cp $CAT_DIR/cat-agent/src/main/rpm/cat-agent-$container.spec ~/rpmbuild/SPECS/
cd -
rpmbuild -bb ~/rpmbuild/SPECS/cat-agent-$container.spec
#%define name value
%define __jar_repack 0
Name: cat-agent-tomcat
Version: 1.0.5
Release: 1
Summary: cat-agent-tomcat
Requires: git
Requires(pre): /usr/sbin/useradd, /usr/bin/getent, /usr/sbin/usermod
Group: Development/Tools
License: GPL
Source0: %{name}-%{version}.tar.gz
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-XXXXXXXXXX)
%description
A powerful customized J2EE web container (JBoss, Jetty, Tomcat)
%pre
# add user cat
/usr/bin/getent passwd cat || /usr/sbin/useradd -u 2200 cat
/usr/sbin/usermod -a -G nobody cat || true
%prep
%setup -q
%build
%install
[ -d $RPM_BUILD_ROOT ] && rm -rf $RPM_BUILD_ROOT/*
# where to install agent files
AGENT_INSTALL_DIR=$RPM_BUILD_ROOT/data/webapps/cat/cat-agent
# create agent directories
[ -d $AGENT_INSTALL_DIR ] || mkdir -p $AGENT_INSTALL_DIR
# copy agent files to corresponding directories
cp -r cat-agent/* $AGENT_INSTALL_DIR/
chmod +x $AGENT_INSTALL_DIR/startup.sh
/bin/bash $AGENT_INSTALL_DIR/startup.sh
%post
# change required file permissions
APPLOGS_DIR=/data/applogs
APPDATAS_DIR=/data/appdatas
CAT_ROOT_DIR=/data/webapps/cat/
[ -d $APPLOGS_DIR ] && chown nobody:nobody $APPLOGS_DIR && chmod 775 $APPLOGS_DIR
[ -d $APPDATAS_DIR ] && chown nobody:nobody $APPDATAS_DIR && chmod 775 $APPDATAS_DIR
[ -d $CAT_ROOT_DIR ] && chown -R cat:cat $CAT_ROOT_DIR
# comment out Defaults requiretty to enabel sudo in scripts
awk 'BEGIN{result=""}{if(match($0, "^[^#]*Defaults[[:space:]]+requiretty")>0){result=sprintf("%s#%s\n",result,$0);}else{result=sprintf("%s%s\n",result,$0);}}END{print result > "/etc/sudoers"}' /etc/sudoers
AGENT_INSTALL_DIR=$RPM_BUILD_ROOT/data/webapps/cat/cat-agent
/bin/bash $AGENT_INSTALL_DIR/startup.sh
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,cat,cat,-)
/data/webapps/cat/cat-agent
%doc
%changelog
%preun
/usr/local/jdk/bin/jps -lvm | awk '$2=="com.dianping.cat.agent.monitor.CatAgent"{cmd=sprintf("kill -9 %s", $1);system(cmd)}'
%postun
/usr/local/jdk/bin/jps -lvm | awk '$2=="com.dianping.cat.agent.monitor.CatAgent"{cmd=sprintf("kill -9 %s", $1);system(cmd)}'
rm -rf /data/webapps/cat/cat-agent
......@@ -5,7 +5,13 @@ cd `dirname $0`
function kill_by_javaclass {
local javaclass=$1
/usr/local/jdk/bin/jps -lvm | awk -v javaclass=$javaclass '$2==javaclass{cmd=sprintf("kill -s TERM %s; sleep 1; kill -9 %s", $1, $1);system(cmd)}'
jps=/usr/local/jdk/bin/jps
if [ ! -x $jps ];then
jps=jps
fi
$jps -lvm | awk -v javaclass=$javaclass '$2==javaclass{cmd=sprintf("kill -s TERM %s; sleep 1; kill -9 %s", $1, $1);system(cmd)}'
}
agent_class="com.dianping.cat.agent.monitor.CatAgent"
......@@ -35,5 +41,12 @@ java=java
fi
echo "Starting cat-agent $agent_class $port `pwd`"
nohup $java -Xms128m -Xmx128m -classpath classes:"lib/*" -Dagent=$agent $agent_class $port /agent `pwd` >>/data/applogs/cat/agent-startup.log 2>&1 &
para=""
if [ "$agent" = "paas" ];then
ip=$(sh -c "ifconfig br0 | awk -v FS='[ \t:]+' 'NR == 2 {print \$4}'")
para="-Dhost.ip=$ip"
fi
nohup $java -Xms128m -Xmx128m -classpath classes:"lib/*" -Dagent=$agent $para $agent_class $port /agent `pwd` >>/data/applogs/cat/agent-startup.log 2>&1 &
echo "Started"
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>com.dianping.cat</groupId>
<artifactId>parent</artifactId>
<version>1.0.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>broker-service</artifactId>
<name>broker-service</name>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.unidal.eunit</groupId>
<artifactId>EunitTestFwk</artifactId>
<version>1.2.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.unidal.framework</groupId>
<artifactId>foundation-service</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>com.dianping.cat</groupId>
<artifactId>cat-core</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>org.unidal.webres</groupId>
<artifactId>WebResServer</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>org.unidal.framework</groupId>
<artifactId>web-framework</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jsp-api-2.1</artifactId>
<version>6.1.14</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jsp-2.1</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.9</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.unidal.framework</groupId>
<artifactId>test-framework</artifactId>
<version>2.0.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.unidal.framework</groupId>
<artifactId>dal-jdbc</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-email</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.4</version>
</dependency>
<dependency>
<groupId>com.google.code.javaparser</groupId>
<artifactId>javaparser</artifactId>
<version>1.0.8</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.unidal.maven.plugins</groupId>
<artifactId>codegen-maven-plugin</artifactId>
<version>2.0.9</version>
<executions>
<execution>
<id>generate plexus component descriptor</id>
<phase>process-classes</phase>
<goals>
<goal>plexus</goal>
</goals>
<configuration>
<className>com.dianping.cat.broker.build.ComponentsConfigurator</className>
<env>dev</env>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<warName>broker-service-${env}-${version}</warName>
<webResources>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<targetPath>WEB-INF/classes</targetPath>
</resource>
<resource>
<directory>src/main/webapp</directory>
<filtering>false</filtering>
<includes>
<include>WEB-INF/web.xml</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.26</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<contextPath>/cat</contextPath>
<defaultsDescriptor>src/main/webapp/WEB-INF/web.xml</defaultsDescriptor>
<connectors>
<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
<port>2281</port>
<maxIdleTime>500000</maxIdleTime>
</connector>
</connectors>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<packaging>war</packaging>
<env>alpha</env>
<project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
</properties>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<groupId>com.dianping.cat</groupId>
<artifactId>parent</artifactId>
<version>1.0.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>broker-service</artifactId>
<name>broker-service</name>
<packaging>war</packaging>
<dependencies>
<dependency>
<groupId>org.unidal.eunit</groupId>
<artifactId>EunitTestFwk</artifactId>
<version>1.2.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.unidal.framework</groupId>
<artifactId>foundation-service</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>com.dianping.cat</groupId>
<artifactId>cat-core</artifactId>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>1.6</version>
</dependency>
<dependency>
<groupId>org.unidal.webres</groupId>
<artifactId>WebResServer</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>org.unidal.framework</groupId>
<artifactId>web-framework</artifactId>
<version>2.0.5</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jsp-api-2.1</artifactId>
<version>6.1.14</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jsp-2.1</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.9</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.unidal.framework</groupId>
<artifactId>test-framework</artifactId>
<version>2.0.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.unidal.framework</groupId>
<artifactId>dal-jdbc</artifactId>
<version>2.0.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-email</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.4</version>
</dependency>
<dependency>
<groupId>com.google.code.javaparser</groupId>
<artifactId>javaparser</artifactId>
<version>1.0.8</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>${basedir}/src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.unidal.maven.plugins</groupId>
<artifactId>codegen-maven-plugin</artifactId>
<version>2.0.9</version>
<executions>
<execution>
<id>generate plexus component descriptor</id>
<phase>process-classes</phase>
<goals>
<goal>plexus</goal>
</goals>
<configuration>
<className>com.dianping.cat.broker.build.ComponentsConfigurator</className>
<env>dev</env>
</configuration>
</execution>
<execution>
<id>generate dal model files</id>
<phase>generate-sources</phase>
<goals>
<goal>dal-model</goal>
</goals>
<configuration>
<manifest><![CDATA[
${basedir}/src/main/resources/META-INF/dal/model/appData-manifest.xml,
]]></manifest>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<warName>broker-service-${env}-${version}</warName>
<webResources>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<targetPath>WEB-INF/classes</targetPath>
</resource>
<resource>
<directory>src/main/webapp</directory>
<filtering>false</filtering>
<includes>
<include>WEB-INF/web.xml</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.26</version>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<contextPath>/cat</contextPath>
<defaultsDescriptor>src/main/webapp/WEB-INF/web.xml</defaultsDescriptor>
<connectors>
<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
<port>2281</port>
<maxIdleTime>500000</maxIdleTime>
</connector>
</connectors>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<packaging>war</packaging>
<env>alpha</env>
<project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
</properties>
</project>
package com.dianping.cat.broker.api.app;
import java.util.concurrent.ConcurrentHashMap;
import org.codehaus.plexus.logging.LogEnabled;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.unidal.helper.Threads;
import org.unidal.helper.Threads.Task;
import org.unidal.lookup.annotation.Inject;
import com.dianping.cat.Cat;
import com.dianping.cat.config.app.AppDataService;
import com.dianping.cat.service.appData.entity.AppData;
public class AppDataConsumer implements Initializable, LogEnabled {
public static final long DURATION = 5 * 60 * 1000L;
@Inject
private AppDataService m_appDataService;
private AppDataQueue m_appDataQueue;
private long m_dataLoss;
private Logger m_logger;
private ConcurrentHashMap<Long, BucketHandler> m_tasks;
@Override
public void enableLogging(Logger logger) {
m_logger = logger;
}
public void enqueue(AppData appData) {
m_appDataQueue.offer(appData);
}
public long getDataLoss() {
return m_dataLoss;
}
@Override
public void initialize() throws InitializationException {
m_dataLoss = 0;
m_appDataQueue = new AppDataQueue();
m_tasks = new ConcurrentHashMap<Long, BucketHandler>();
AppDataDispatcherThread appDataDispatcherThread = new AppDataDispatcherThread();
BucketThreadController bucketThreadController = new BucketThreadController();
Threads.forGroup("Cat").start(bucketThreadController);
Threads.forGroup("Cat").start(appDataDispatcherThread);
}
public void setDataLoss(long dataLoss) {
m_dataLoss = dataLoss;
}
private class AppDataDispatcherThread implements Task {
private static final String NAME = "AppDataDispatcherThread";
@Override
public String getName() {
return NAME;
}
@Override
public void run() {
while (true) {
try {
AppData appData = m_appDataQueue.poll();
if (appData != null) {
long timestamp = appData.getTimestamp();
timestamp -= timestamp % DURATION;
BucketHandler handler = m_tasks.get(new Long(timestamp));
if (handler == null || !handler.isActive()) {
m_dataLoss++;
if (m_dataLoss % 1000 == 0) {
m_logger.error("error timestamp in consumer, loss:" + m_dataLoss);
}
} else {
handler.enqueue(appData);
}
}
} catch (Exception e) {
Cat.logError(e);
}
}
}
@Override
public void shutdown() {
}
}
private class BucketThreadController implements Task {
private void closeLastTask(long currentDuration) {
Long last = new Long(currentDuration - DURATION);
BucketHandler lastBucketHandler = m_tasks.get(last);
if (lastBucketHandler != null) {
lastBucketHandler.shutdown();
}
}
@Override
public String getName() {
return "BucketThreadController";
}
private void removeLastLastTask(long currentDuration) {
Long lastLast = new Long(currentDuration - 2 * DURATION);
m_tasks.remove(lastLast);
}
@Override
public void run() {
while (true) {
long curTime = System.currentTimeMillis();
try {
long currentDuration = curTime - curTime % DURATION;
removeLastLastTask(currentDuration);
closeLastTask(currentDuration);
startCurrentTask(currentDuration);
startNextTask(currentDuration);
} catch (Exception e) {
Cat.logError(e);
}
long elapsedTime = System.currentTimeMillis() - curTime;
try {
Thread.sleep(DURATION - elapsedTime);
} catch (InterruptedException e) {
}
}
}
@Override
public void shutdown() {
}
private void startCurrentTask(long currentDuration) {
Long cur = new Long(currentDuration);
if (m_tasks.get(cur) == null) {
BucketHandler curBucketHandler = new BucketHandler(cur, m_appDataService);
Threads.forGroup("Cat").start(curBucketHandler);
m_tasks.put(cur, curBucketHandler);
}
}
private void startNextTask(long currentDuration) {
Long next = new Long(currentDuration + DURATION);
if (m_tasks.get(next) == null) {
BucketHandler nextBucketHandler = new BucketHandler(next, m_appDataService);
Threads.forGroup("Cat").start(nextBucketHandler);
m_tasks.put(next, nextBucketHandler);
}
}
}
}
package com.dianping.cat.broker.api.app;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import com.dianping.cat.service.appData.entity.AppData;
public class AppDataQueue {
private BlockingQueue<AppData> m_dataQueue = new LinkedBlockingQueue<AppData>();
public boolean offer(AppData appData) {
return m_dataQueue.offer(appData);
}
public AppData poll() {
AppData appData;
try {
appData = m_dataQueue.poll(5, TimeUnit.MICROSECONDS);
} catch (InterruptedException e) {
return null;
}
return appData;
}
}
package com.dianping.cat.broker.api.app;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
import org.unidal.helper.Threads.Task;
import com.dianping.cat.Cat;
import com.dianping.cat.config.app.AppDataService;
import com.dianping.cat.service.appData.entity.AppData;
public class BucketHandler implements Task {
private static final String FILEDIRECTORY = "/data/appdatas/cat/app/";
private static int ONE_DAY = 24 * 60 * 60 * 1000;
private static int ONE_MINUTE = 60 * 1000;
private AppDataQueue m_appDataQueue;
private AppDataService m_appDataService;
private boolean m_isActive = true;
private HashMap<Integer, HashMap<String, AppData>> m_mergedData;
private long m_startTime;
public BucketHandler(long startTime, AppDataService appDataService) {
m_startTime = startTime;
m_appDataQueue = new AppDataQueue();
m_mergedData = new LinkedHashMap<Integer, HashMap<String, AppData>>();
m_appDataService = appDataService;
}
private void end() {
for (Entry<Integer, HashMap<String, AppData>> outerEntry : m_mergedData.entrySet()) {
for (Entry<String, AppData> entry : outerEntry.getValue().entrySet()) {
AppData appData = entry.getValue();
saveToDataBase(appData);
}
}
}
public void enqueue(AppData appData) {
m_appDataQueue.offer(appData);
}
@Override
public String getName() {
return "BucketHandler";
}
public boolean isActive() {
synchronized (this) {
return m_isActive;
}
}
private void processEntity(AppData appData) {
Integer command = appData.getCommand();
String key = m_startTime + ":" + appData.getCity() + ":" + appData.getOperator() + ":" + appData.getConnectType()
+ ":" + appData.getVersion() + ":" + appData.getNetwork() + ":" + appData.getCode() + ":"
+ appData.getPlatform();
HashMap<String, AppData> secondMap = m_mergedData.get(command);
if (secondMap == null) {
secondMap = new LinkedHashMap<String, AppData>();
secondMap.put(key, appData);
m_mergedData.put(command, secondMap);
} else {
AppData mergedAppData = secondMap.get(key);
if (mergedAppData == null) {
secondMap.put(key, appData);
} else {
mergedAppData.setCount(mergedAppData.getCount() + 1);
mergedAppData.setRequestByte(mergedAppData.getRequestByte() + appData.getRequestByte());
mergedAppData.setResponseByte(mergedAppData.getResponseByte() + appData.getResponseByte());
mergedAppData.setResponseTime(mergedAppData.getResponseTime() + appData.getResponseTime());
}
}
}
@Override
public void run() {
while (isActive()) {
AppData appData = m_appDataQueue.poll();
if (appData != null) {
processEntity(appData);
}
}
while (true) {
AppData appData = m_appDataQueue.poll();
if (appData != null) {
processEntity(appData);
} else {
break;
}
}
end();
}
private void saveToDataBase(AppData appData) {
int minute = (int) (m_startTime % ONE_DAY / ONE_MINUTE);
Date period = new Date(m_startTime - minute * ONE_MINUTE);
try {
m_appDataService.insert(period, minute, appData.getCommand(), appData.getCity(), appData.getOperator(),
appData.getNetwork(), appData.getVersion(), appData.getConnectType(), appData.getCode(),
appData.getPlatform(), appData.getCount(), appData.getResponseTime(), appData.getResponseByte(),
appData.getResponseByte());
} catch (Exception e) {
Cat.logError(e);
saveToFile(appData);
}
}
private void saveToFile(AppData appData) {
Date date = new Date();
SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd");
String dateStr = formater.format(date);
String filePath = FILEDIRECTORY + dateStr;
try {
BufferedWriter writer = new BufferedWriter(new FileWriter(filePath));
String content = appData.getTimestamp() + "\t" + appData.getCity() + "\t" + appData.getOperator() + "\t"
+ appData.getNetwork() + "\t" + appData.getVersion() + "\t" + appData.getConnectType() + "\t"
+ appData.getCommand() + "\t" + appData.getCode() + "\t" + appData.getPlatform() + "\t"
+ appData.getRequestByte() + "\t" + appData.getResponseByte() + "\t" + appData.getResponseTime() + "\n";
writer.append(content);
writer.close();
} catch (Exception e) {
Cat.logError(e);
}
}
@Override
public void shutdown() {
synchronized (this) {
m_isActive = false;
}
}
}
......@@ -13,14 +13,14 @@ import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationExce
import com.dianping.cat.Cat;
public class IpService implements Initializable {
private Map<Integer, Area> m_areas;
private Map<Integer, Corporation> m_corps;
private int[] m_areaIds;
private Map<Integer, Area> m_areas;
private int[] m_corpIds;
private Map<Integer, Corporation> m_corps;
private long[] m_ends;
private long[] m_starts;
......@@ -176,12 +176,12 @@ public class IpService implements Initializable {
public static class Area {
private Integer m_areaId;
private String m_city;
private String m_nation;
private String m_province;
private String m_city;
public Integer getAreaId() {
return m_areaId;
}
......@@ -240,13 +240,13 @@ public class IpService implements Initializable {
}
public static class IpInfo {
private String m_nation;
private String m_province;
private String m_channel;
private String m_city;
private String m_channel;
private String m_nation;
private String m_province;
public String getChannel() {
return m_channel;
......
package com.dianping.cat.broker.api.page.batch;
import java.io.IOException;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
......@@ -15,21 +16,36 @@ import org.unidal.web.mvc.annotation.InboundActionMeta;
import org.unidal.web.mvc.annotation.OutboundActionMeta;
import org.unidal.web.mvc.annotation.PayloadMeta;
import com.dianping.cat.broker.api.app.AppDataConsumer;
import com.dianping.cat.broker.api.page.Constrants;
import com.dianping.cat.broker.api.page.IpService;
import com.dianping.cat.broker.api.page.IpService.IpInfo;
import com.dianping.cat.broker.api.page.MonitorEntity;
import com.dianping.cat.broker.api.page.MonitorManager;
import com.dianping.cat.broker.api.page.RequestUtils;
import com.dianping.cat.config.app.AppConfigManager;
import com.dianping.cat.configuration.app.entity.Item;
import com.dianping.cat.service.appData.entity.AppData;
public class Handler implements PageHandler<Context>, LogEnabled {
@Inject
private MonitorManager m_manager;
private AppDataConsumer m_appDataConsumer;
@Inject
private RequestUtils m_util;
private IpService m_ipService;
@Inject
private AppConfigManager m_appConfigManager;
private Logger m_logger;
@Inject
private MonitorManager m_manager;
@Inject
private RequestUtils m_util;
@Override
public void enableLogging(Logger logger) {
m_logger = logger;
......@@ -49,7 +65,18 @@ public class Handler implements PageHandler<Context>, LogEnabled {
HttpServletRequest request = ctx.getHttpServletRequest();
HttpServletResponse response = ctx.getHttpServletResponse();
String userIp = m_util.getRemoteIp(request);
String version = payload.getVersion();
if (version.equals("1")) {
processVersion1(payload, request, userIp);
} else if (version.equals("2")) {
processVersion2(payload, request, userIp);
}
response.getWriter().write("OK");
}
private void processVersion1(Payload payload, HttpServletRequest request, String userIp) {
if (userIp != null) {
try {
String content = payload.getContent();
......@@ -88,7 +115,69 @@ public class Handler implements PageHandler<Context>, LogEnabled {
} else {
m_logger.info("unknown http request, x-forwarded-for:" + request.getHeader("x-forwarded-for"));
}
response.getWriter().write("OK");
}
private void processVersion2(Payload payload, HttpServletRequest request, String userIp) {
if (userIp != null) {
String content = payload.getContent();
String records[] = content.split("\n");
IpInfo ipInfo = m_ipService.findIpInfoByString(userIp);
String cityStr = ipInfo.getProvince();
String operatorStr = ipInfo.getChannel();
int cityId = 0, operatorId = 0;
List<Item> cityList = m_appConfigManager.queryConfigItem(AppConfigManager.CITY);
List<Item> operatorList = m_appConfigManager.queryConfigItem(AppConfigManager.OPERATOR);
for (Item item : cityList) {
if (item.getName().equals(cityStr)) {
cityId = item.getId();
break;
}
}
for (Item item : operatorList) {
if (item.getName().equals(operatorStr)) {
operatorId = item.getId();
break;
}
}
for (String record : records) {
String items[] = record.split("\t");
if (items.length != 10) {
continue;
}
AppData appData = new AppData();
try {
appData.setTimestamp(Long.parseLong(items[0]));
Integer command = m_appConfigManager.getCommands().get(items[2]);
if (command == null) {
continue;
}
appData.setCommand(command);
appData.setNetwork(Integer.parseInt(items[2]));
appData.setVersion(Integer.parseInt(items[3]));
appData.setConnectType(Integer.parseInt(items[4]));
appData.setCode(Integer.parseInt(items[5]));
appData.setPlatform(Integer.parseInt(items[6]));
appData.setRequestByte(Integer.parseInt(items[7]));
appData.setResponseByte(Integer.parseInt(items[8]));
appData.setResponseTime(Integer.parseInt(items[9]));
appData.setCity(cityId);
appData.setOperator(operatorId);
appData.setCount(1);
} catch (Exception e) {
m_logger.error(e.getMessage(), e);
}
m_appDataConsumer.enqueue(appData);
}
} else {
m_logger.info("unknown http request, x-forwarded-for:" + request.getHeader("x-forwarded-for"));
}
}
private boolean validate(String errorCode, String httpStatus) {
......
......@@ -4,12 +4,17 @@ import java.util.ArrayList;
import java.util.List;
import org.unidal.dal.jdbc.datasource.JdbcDataSourceDescriptorManager;
import org.unidal.dal.jdbc.mapping.TableProvider;
import org.unidal.lookup.configuration.AbstractResourceConfigurator;
import org.unidal.lookup.configuration.Component;
import com.dianping.cat.broker.api.app.AppDataConsumer;
import com.dianping.cat.broker.api.page.IpService;
import com.dianping.cat.broker.api.page.MonitorManager;
import com.dianping.cat.broker.api.page.RequestUtils;
import com.dianping.cat.build.AppDatabaseConfigurator;
import com.dianping.cat.config.app.AppDataCommandTableProvider;
import com.dianping.cat.config.app.AppDataService;
import com.dianping.cat.config.url.UrlPatternConfigManager;
public class ComponentsConfigurator extends AbstractResourceConfigurator {
......@@ -20,11 +25,17 @@ public class ComponentsConfigurator extends AbstractResourceConfigurator {
all.add(C(IpService.class));
all.add(C(RequestUtils.class));
all.add(C(MonitorManager.class).req(UrlPatternConfigManager.class, IpService.class));
all.add(C(AppDataConsumer.class).req(AppDataService.class));
all.add(C(TableProvider.class,"app-data-command",AppDataCommandTableProvider.class));
// database
all.add(C(JdbcDataSourceDescriptorManager.class) //
.config(E("datasourceFile").value("/data/appdatas/cat/datasources.xml")));
all.addAll(new AppDatabaseConfigurator().defineComponents());
// Please keep it as last
all.addAll(new WebComponentConfigurator().defineComponents());
......
<?xml version="1.0" encoding="UTF-8"?>
<model>
<entity name="appData" root="true">
<attribute name="timestamp" value-type="long" />
<attribute name="city" value-type="int" />
<attribute name="operator" value-type="int" />
<attribute name="network" value-type="int" />
<attribute name="version" value-type="int" />
<attribute name="connectType" value-type="int" />
<attribute name="command" value-type="int" />
<attribute name="code" value-type="int" />
<attribute name="platform" value-type="int" />
<attribute name="count" value-type="int" />
<attribute name="requestByte" value-type="int" />
<attribute name="responseByte" value-type="int" />
<attribute name="responseTime" value-type="int" />
</entity>
</model>
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<file path="appData-codegen.xml" />
<file path="appData-model.xml" />
</manifest>
<?xml version="1.0" encoding="UTF-8"?>
<model model-package="com.dianping.cat.service.appData" />
......@@ -20,6 +20,20 @@
</requirement>
</requirements>
</component>
<component>
<role>com.dianping.cat.broker.api.app.AppDataConsumer</role>
<implementation>com.dianping.cat.broker.api.app.AppDataConsumer</implementation>
<requirements>
<requirement>
<role>com.dianping.cat.config.app.AppDataService</role>
</requirement>
</requirements>
</component>
<component>
<role>org.unidal.dal.jdbc.mapping.TableProvider</role>
<role-hint>app-data-command</role-hint>
<implementation>com.dianping.cat.config.app.AppDataCommandTableProvider</implementation>
</component>
<component>
<role>org.unidal.dal.jdbc.datasource.JdbcDataSourceDescriptorManager</role>
<implementation>org.unidal.dal.jdbc.datasource.JdbcDataSourceDescriptorManager</implementation>
......@@ -27,6 +41,25 @@
<datasourceFile>/data/appdatas/cat/datasources.xml</datasourceFile>
</configuration>
</component>
<component>
<role>org.unidal.dal.jdbc.mapping.TableProvider</role>
<role-hint>app-data-command</role-hint>
<implementation>org.unidal.dal.jdbc.mapping.SimpleTableProvider</implementation>
<configuration>
<logical-table-name>app-data-command</logical-table-name>
<physical-table-name>app_data_command</physical-table-name>
<data-source-name>app</data-source-name>
</configuration>
</component>
<component>
<role>com.dianping.cat.app.AppDataCommandDao</role>
<implementation>com.dianping.cat.app.AppDataCommandDao</implementation>
<requirements>
<requirement>
<role>org.unidal.dal.jdbc.QueryEngine</role>
</requirement>
</requirements>
</component>
<component>
<role>org.unidal.web.mvc.model.ModuleRegistry</role>
<implementation>org.unidal.web.mvc.model.ModuleRegistry</implementation>
......@@ -97,6 +130,15 @@
<role>com.dianping.cat.broker.api.page.batch.Handler</role>
<implementation>com.dianping.cat.broker.api.page.batch.Handler</implementation>
<requirements>
<requirement>
<role>com.dianping.cat.broker.api.app.AppDataConsumer</role>
</requirement>
<requirement>
<role>com.dianping.cat.broker.api.page.IpService</role>
</requirement>
<requirement>
<role>com.dianping.cat.config.app.AppConfigManager</role>
</requirement>
<requirement>
<role>com.dianping.cat.broker.api.page.MonitorManager</role>
</requirement>
......@@ -105,6 +147,42 @@
</requirement>
</requirements>
</component>
<component>
<role>com.dianping.cat.broker.api.app.AppDataConsumer</role>
<implementation>com.dianping.cat.broker.api.app.AppDataConsumer</implementation>
<requirements>
<requirement>
<role>com.dianping.cat.config.app.AppDataService</role>
</requirement>
</requirements>
</component>
<component>
<role>com.dianping.cat.config.app.AppDataService</role>
<implementation>com.dianping.cat.config.app.AppDataService</implementation>
<requirements>
<requirement>
<role>com.dianping.cat.app.AppDataCommandDao</role>
</requirement>
</requirements>
</component>
<component>
<role>com.dianping.cat.app.AppDataCommandDao</role>
<implementation>com.dianping.cat.app.AppDataCommandDao</implementation>
<requirements>
<requirement>
<role>org.unidal.dal.jdbc.QueryEngine</role>
</requirement>
</requirements>
</component>
<component>
<role>com.dianping.cat.config.app.AppConfigManager</role>
<implementation>com.dianping.cat.config.app.AppConfigManager</implementation>
<requirements>
<requirement>
<role>com.dianping.cat.core.config.ConfigDao</role>
</requirement>
</requirements>
</component>
<component>
<role>com.dianping.cat.broker.api.page.js.Handler</role>
<implementation>com.dianping.cat.broker.api.page.js.Handler</implementation>
......
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<file path="wizard.xml" />
</manifest>
<?xml version="1.0" encoding="utf-8"?>
<wizard package="com.dianping.cat.service">
<model package="com.dianping.cat.service.appData" name="appData">
<sample-model>app</sample-model>
</model>
</wizard>
<%@ page contentType="text/html; charset=utf-8" %>
<jsp:useBean id="ctx" type="com.dianping.cat.broker.api.page.app.Context" scope="request"/>
<jsp:useBean id="payload" type="com.dianping.cat.broker.api.page.app.Payload" scope="request"/>
<jsp:useBean id="model" type="com.dianping.cat.broker.api.page.app.Model" scope="request"/>
View of app page under api
\ No newline at end of file
package com.dianping.cat.broker;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
public class AppTest {
public static void main(String[] args) {
List<String> urls = new ArrayList<String>();
String url_pre = "http://localhost:2765/broker-service/api/batch";
long timestamp = System.currentTimeMillis();
for (int i = 0; i < 10; i++) {
urls.add(url_pre + "?v=2&c=" + timestamp + URLEncoder.encode("\tshop.bin\t1\t1\t1\t1\t1\t1\t1\t1\n"));
}
for (String url : urls) {
System.out.println(url);
sendGet(url);
}
}
public static String sendGet(String url) {
String result = "";
BufferedReader in = null;
try {
URL realUrl = new URL(url);
URLConnection connection = realUrl.openConnection();
connection.connect();
in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}
}
......@@ -6,7 +6,7 @@ import java.util.List;
import org.unidal.dal.jdbc.configuration.AbstractJdbcResourceConfigurator;
import org.unidal.lookup.configuration.Component;
final class AppDatabaseConfigurator extends AbstractJdbcResourceConfigurator {
final public class AppDatabaseConfigurator extends AbstractJdbcResourceConfigurator {
@Override
public List<Component> defineComponents() {
List<Component> all = new ArrayList<Component>();
......
......@@ -12,10 +12,12 @@ import com.dianping.cat.DomainManager;
import com.dianping.cat.ServerConfigManager;
import com.dianping.cat.analysis.DefaultMessageAnalyzerManager;
import com.dianping.cat.analysis.MessageAnalyzerManager;
import com.dianping.cat.app.AppDataCommandDao;
import com.dianping.cat.config.aggregation.AggregationConfigManager;
import com.dianping.cat.config.aggregation.AggregationHandler;
import com.dianping.cat.config.aggregation.DefaultAggregationHandler;
import com.dianping.cat.config.app.AppConfigManager;
import com.dianping.cat.config.app.AppDataService;
import com.dianping.cat.config.url.DefaultUrlPatternHandler;
import com.dianping.cat.config.url.UrlPatternConfigManager;
import com.dianping.cat.config.url.UrlPatternHandler;
......@@ -61,9 +63,11 @@ public class ComponentsConfigurator extends AbstractResourceConfigurator {
all.add(C(AggregationHandler.class, DefaultAggregationHandler.class));
all.add(C(AggregationConfigManager.class).req(AggregationHandler.class, ConfigDao.class));
all.add(C(AppConfigManager.class).req( ConfigDao.class));
all.add(C(AppConfigManager.class).req(ConfigDao.class));
all.add(C(AppDataService.class).req(AppConfigManager.class, AppDataCommandDao.class));
all.add(C(UrlPatternHandler.class, DefaultUrlPatternHandler.class));
all.add(C(UrlPatternConfigManager.class).req(ConfigDao.class, UrlPatternHandler.class));
......@@ -75,7 +79,7 @@ public class ComponentsConfigurator extends AbstractResourceConfigurator {
.req(ServerConfigManager.class, MessagePathBuilder.class, ServerStatisticManager.class));
all.add(C(Module.class, CatCoreModule.ID, CatCoreModule.class));
all.addAll(new CatCoreDatabaseConfigurator().defineComponents());
all.addAll(new CodecComponentConfigurator().defineComponents());
all.addAll(new StorageComponentConfigurator().defineComponents());
......
......@@ -3,6 +3,7 @@ package com.dianping.cat.config.app;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
......@@ -106,7 +107,7 @@ public class AppConfigManager implements Initializable {
if (c != null) {
return c.getCodes().values();
} else {
return null;
return Collections.emptySet();
}
}
......@@ -120,14 +121,13 @@ public class AppConfigManager implements Initializable {
if (config != null) {
return new ArrayList<Item>(config.getItems().values());
} else {
System.out.println(name);
return new ArrayList<Item>();
}
}
public Map<String, Integer> getCommands() {
return m_commands;
}
return m_commands;
}
private void refreshCommand() {
Collection<Command> commands = m_config.getCommands().values();
......
package com.dianping.cat.config.app;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.unidal.dal.jdbc.DalException;
import org.unidal.lookup.annotation.Inject;
......@@ -10,16 +17,49 @@ import com.dianping.cat.Cat;
import com.dianping.cat.app.AppDataCommand;
import com.dianping.cat.app.AppDataCommandDao;
import com.dianping.cat.app.AppDataCommandEntity;
import com.dianping.cat.configuration.app.entity.Code;
public class AppDataService {
@Inject
private AppDataCommandDao m_dao;
public void insert() {
@Inject
private AppConfigManager m_appConfigManager;
public static final String SUCCESS_RATIO = "successRatio";
public static final String REQUEST_COUNT = "requestCount";
public static final String DELAY_AVG = "delayAvg";
private static final int MAX_SIZE = 288;
public void insert(Date period, int minute, int commandId, int city, int operator, int network, int appVersion,
int connectType, int code, int platform, int count, int responseSumTime, int requestPackage,
int responsePackage) throws DalException {
AppDataCommand proto = new AppDataCommand();
proto.setPeriod(period);
proto.setMinuteOrder(minute);
proto.setCommandId(commandId);
proto.setCity(city);
proto.setOperator(operator);
proto.setNetwork(network);
proto.setAppVersion(appVersion);
proto.setConnnectType(connectType);
proto.setCode(code);
proto.setPlatform(platform);
proto.setAccessNumber(count);
proto.setResponseSumTime(responseSumTime);
proto.setRequestPackage(requestPackage);
proto.setResponsePackage(responsePackage);
proto.setCreationDate(new Date());
m_dao.insertData(proto);
}
public void queryAvg(QueryEntity entity) {
public Map<String, double[]> queryValue(QueryEntity entity, String type) {
int commandId = entity.getCommand();
Date period = entity.getDate();
int city = entity.getCity();
......@@ -29,60 +69,142 @@ public class AppDataService {
int connnectType = entity.getChannel();
int code = entity.getCode();
int platform = entity.getPlatfrom();
List<AppDataCommand> datas;
try {
List<AppDataCommand> datas = m_dao.findData(commandId, period, city, operator, network, appVersion,
connnectType, code, platform, AppDataCommandEntity.READSET_DATA);
for (AppDataCommand data : datas) {
int minuteOrder = data.getMinuteOrder();
long count=data.getAccessNumberSum();
long sum = data.getResponseSumTimeSum();
double avg =sum/count;
datas = m_dao.findData(commandId, period, city, operator, network, appVersion, connnectType, code, platform,
AppDataCommandEntity.READSET_DATA);
Collections.sort(datas, new Comparator<AppDataCommand>() {
@Override
public int compare(AppDataCommand o1, AppDataCommand o2) {
return (int) (o2.getMinuteOrder() - o1.getMinuteOrder());
}
});
int n = calculateSize(entity.getDate().getTime());
if (SUCCESS_RATIO.equals(type)) {
return querySuccessRatio(datas, n);
} else if (REQUEST_COUNT.equals(type)) {
return queryRequestCount(datas, n);
} else if (DELAY_AVG.equals(type)) {
return queryDelayAvg(datas, n);
}
} catch (DalException e) {
Cat.logError(e);
}
return new LinkedHashMap<String, double[]>();
}
public void queryCount(QueryEntity entity) {
}
private Map<Integer, List<AppDataCommand>> convert2AppDataCommandMap(List<AppDataCommand> fromDatas) {
Map<Integer, List<AppDataCommand>> dataMap = new LinkedHashMap<Integer, List<AppDataCommand>>();
public void querySuccessRate(QueryEntity entity) {
}
for (AppDataCommand from : fromDatas) {
int minute = from.getMinuteOrder();
List<AppDataCommand> data = dataMap.get(minute);
public static class Statistics {
private Date m_period;
if (data == null) {
data = new LinkedList<AppDataCommand>();
private long m_count;
dataMap.put(minute, data);
}
data.add(from);
}
return dataMap;
}
private double m_avg;
public Map<String, double[]> querySuccessRatio(List<AppDataCommand> datas, int n) {
Map<String, double[]> values = new LinkedHashMap<String, double[]>();
double[] value = new double[n];
int i = 0;
public Date getPeriod() {
return m_period;
try {
Map<Integer, List<AppDataCommand>> dataMap = convert2AppDataCommandMap(datas);
int size = dataMap.size();
if (size <= n) {
for (Entry<Integer, List<AppDataCommand>> entry : dataMap.entrySet()) {
long success = 0;
long sum = 0;
for (AppDataCommand data : entry.getValue()) {
long number = data.getAccessNumberSum();
if (isSuccessStatus(data)) {
success += number;
}
sum += number;
}
value[i++] = (double) success / sum;
}
} else {
Cat.logError(new RuntimeException("query database minute number " + size + " lagger than expected size "
+ n));
}
} catch (Exception e) {
Cat.logError(e);
}
public void setPeriod(Date period) {
m_period = period;
}
values.put(DELAY_AVG, value);
return values;
}
public long getCount() {
return m_count;
}
private boolean isSuccessStatus(AppDataCommand data) {
int code = data.getCode();
Collection<Code> codes = m_appConfigManager.queryCodeByCommand(data.getCommandId());
public void setCount(long count) {
m_count = count;
for (Code c : codes) {
if (c.getId() == code) {
return (c.getStatus() == 0);
}
}
return false;
}
public Map<String, double[]> queryRequestCount(List<AppDataCommand> datas, int n) {
Map<String, double[]> values = new LinkedHashMap<String, double[]>();
double[] value = new double[n];
int i = 0;
public double getAvg() {
return m_avg;
for (AppDataCommand data : datas) {
long count = data.getAccessNumberSum();
if (i < n) {
value[i++] = count;
}
}
values.put(DELAY_AVG, value);
return values;
}
public void setAvg(double avg) {
m_avg = avg;
public Map<String, double[]> queryDelayAvg(List<AppDataCommand> datas, int n) {
Map<String, double[]> values = new LinkedHashMap<String, double[]>();
double[] value = new double[n];
int i = 0;
for (AppDataCommand data : datas) {
long count = data.getAccessNumberSum();
long sum = data.getResponseSumTimeSum();
double avg = sum / count;
if (i < n) {
value[i++] = avg;
}
}
values.put(DELAY_AVG, value);
return values;
}
private int calculateSize(long startTime) {
int n = MAX_SIZE;
int oneDay = 24 * 3600 * 1000;
if (startTime + oneDay > System.currentTimeMillis()) {
long current = System.currentTimeMillis();
long endTime = current - current % 300000;
n = (int) (endTime - startTime) / 300000;
}
return n;
}
}
......@@ -88,6 +88,18 @@
</requirement>
</requirements>
</component>
<component>
<role>com.dianping.cat.config.app.AppDataService</role>
<implementation>com.dianping.cat.config.app.AppDataService</implementation>
<requirements>
<requirement>
<role>com.dianping.cat.config.app.AppConfigManager</role>
</requirement>
<requirement>
<role>com.dianping.cat.app.AppDataCommandDao</role>
</requirement>
</requirements>
</component>
<component>
<role>com.dianping.cat.config.url.UrlPatternHandler</role>
<implementation>com.dianping.cat.config.url.DefaultUrlPatternHandler</implementation>
......
......@@ -13,6 +13,7 @@ import org.unidal.lookup.configuration.Component;
import com.dianping.cat.CatHomeModule;
import com.dianping.cat.ServerConfigManager;
import com.dianping.cat.config.app.AppDataService;
import com.dianping.cat.config.app.AppDataCommandTableProvider;
import com.dianping.cat.consumer.dependency.DependencyAnalyzer;
import com.dianping.cat.consumer.metric.MetricAnalyzer;
......@@ -38,6 +39,7 @@ import com.dianping.cat.report.graph.GraphBuilder;
import com.dianping.cat.report.graph.ValueTranslater;
import com.dianping.cat.report.page.JsonBuilder;
import com.dianping.cat.report.page.PayloadNormalizer;
import com.dianping.cat.report.page.app.graph.AppGraphCreator;
import com.dianping.cat.report.page.cdn.graph.CdnGraphCreator;
import com.dianping.cat.report.page.dependency.graph.TopologyGraphBuilder;
import com.dianping.cat.report.page.dependency.graph.TopologyGraphConfigManager;
......@@ -237,6 +239,69 @@ public class ComponentsConfigurator extends AbstractResourceConfigurator {
MetricDataFetcher.class).req(BaselineService.class, MetricConfigManager.class,
ProductLineConfigManager.class, MetricGroupConfigManager.class, AlertInfo.class));
all.add(C(AppGraphCreator.class).req(AppDataService.class, CachedMetricReportService.class, DataExtractor.class,
MetricDataFetcher.class).req(BaselineService.class, MetricConfigManager.class,
ProductLineConfigManager.class, MetricGroupConfigManager.class, AlertInfo.class));
// report serivce
all.addAll(new ReportServiceComponentConfigurator().defineComponents());
// task
all.addAll(new TaskComponentConfigurator().defineComponents());
// model service
all.addAll(new ServiceComponentConfigurator().defineComponents());
all.add(C(RemoteMetricReportService.class).req(ServerConfigManager.class));
all.add(C(BusinessAlertConfig.class).req(AlertConfigManager.class));
all.add(C(NetworkAlertConfig.class).req(AlertConfigManager.class));
all.add(C(SystemAlertConfig.class).req(AlertConfigManager.class));
all.add(C(ExceptionAlertConfig.class).req(AlertConfigManager.class));
all.add(C(AlertInfo.class));
all.add(C(DefaultMailImpl.class).req(ServerConfigManager.class));
all.add(C(DataChecker.class, DefaultDataChecker.class));
all.add(C(BusinessAlert.class).req(MetricConfigManager.class, ProductLineConfigManager.class,
BaselineService.class, MailSMS.class, BusinessAlertConfig.class, AlertInfo.class, AlertDao.class)//
.req(RemoteMetricReportService.class, BusinessRuleConfigManager.class, DataChecker.class));
all.add(C(NetworkAlert.class).req(MetricConfigManager.class, ProductLineConfigManager.class,
BaselineService.class, MailSMS.class, NetworkAlertConfig.class, AlertInfo.class, AlertDao.class)//
.req(RemoteMetricReportService.class, NetworkRuleConfigManager.class, DataChecker.class));
all.add(C(SystemAlert.class).req(MetricConfigManager.class, ProductLineConfigManager.class,
BaselineService.class, MailSMS.class, SystemAlertConfig.class, AlertInfo.class, AlertDao.class)//
.req(RemoteMetricReportService.class, SystemRuleConfigManager.class, DataChecker.class));
all.add(C(AlertExceptionBuilder.class).req(ExceptionConfigManager.class));
all.add(C(ExceptionAlert.class).req(ProjectDao.class, ExceptionAlertConfig.class, MailSMS.class,
ExceptionConfigManager.class, AlertExceptionBuilder.class, AlertDao.class).req(ModelService.class,
TopAnalyzer.ID));
all.add(C(NetGraphConfigManager.class).req(ConfigDao.class));
// database
all.add(C(JdbcDataSourceDescriptorManager.class) //
.config(E("datasourceFile").value("/data/appdatas/cat/datasources.xml")));
all.addAll(new CatDatabaseConfigurator().defineComponents());
all.addAll(new UserDatabaseConfigurator().defineComponents());
// update project database
all.add(C(ProjectUpdateTask.class)//
.req(ProjectDao.class, HostinfoDao.class));
// web, please keep it last
all.addAll(new WebComponentConfigurator().defineComponents());
// for alarm module
all.addAll(new AlarmComponentConfigurator().defineComponents());
return all;
}
}
......@@ -230,7 +230,7 @@ public abstract class AbstractGraphCreator implements LogEnabled {
}
}
protected Map<Long, Double> buildNoneData(Date startDate, Date endDate, int step) {
public Map<Long, Double> buildNoneData(Date startDate, Date endDate, int step) {
int n = 0;
long current = System.currentTimeMillis();
......
package com.dianping.cat.report.page.app;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import javax.servlet.ServletException;
import com.dianping.cat.config.app.AppConfigManager;
import com.dianping.cat.config.app.QueryEntity;
import com.dianping.cat.report.ReportPage;
import org.codehaus.plexus.util.StringUtils;
import org.unidal.lookup.annotation.Inject;
import org.unidal.web.mvc.PageHandler;
import org.unidal.web.mvc.annotation.InboundActionMeta;
import org.unidal.web.mvc.annotation.OutboundActionMeta;
import org.unidal.web.mvc.annotation.PayloadMeta;
import com.dianping.cat.config.app.AppConfigManager;
import com.dianping.cat.config.app.QueryEntity;
import com.dianping.cat.report.ReportPage;
import com.dianping.cat.report.page.LineChart;
import com.dianping.cat.report.page.app.graph.AppGraphCreator;
public class Handler implements PageHandler<Context> {
@Inject
private JspViewer m_jspViewer;
......@@ -20,6 +26,9 @@ public class Handler implements PageHandler<Context> {
@Inject
private AppConfigManager m_manager;
@Inject
private AppGraphCreator m_appGraphCreator;
@Override
@PayloadMeta(Payload.class)
@InboundActionMeta(name = "app")
......@@ -45,14 +54,36 @@ public class Handler implements PageHandler<Context> {
QueryEntity entity1 = payload.getQueryEntity1();
QueryEntity entity2 = payload.getQueryEntity2();
String type = payload.getType();
if (StringUtils.isEmpty(type)) {
type = "successRatio";
}
LineChart lineCharts = new LineChart();
if (entity1 != null) {
System.out.println(entity1.toString());
LineChart lineChart1 = m_appGraphCreator.buildLineChart(entity1, type);
Iterator<Map<Long, Double>> idata = lineChart1.getDatas().iterator();
if (lineChart1.getDatas().size() == 1) {
lineCharts.add("查询1", idata.next());
}
}
if (entity2 != null) {
System.out.println(entity2.toString());
LineChart lineChart2 = m_appGraphCreator.buildLineChart(entity2, type);
Iterator<Map<Long, Double>> idata = lineChart2.getDatas().iterator();
if (lineChart2.getDatas().size() == 1) {
lineCharts.add("查询2", idata.next());
}
}
lineCharts.setId("app");
lineCharts.setHtmlTitle(type);
model.setLineChart(lineCharts);
if (!ctx.isProcessStopped()) {
m_jspViewer.view(ctx, model);
}
......
......@@ -6,14 +6,20 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.unidal.web.mvc.view.annotation.EntityMeta;
import com.dianping.cat.configuration.app.entity.Code;
import com.dianping.cat.configuration.app.entity.Command;
import com.dianping.cat.configuration.app.entity.Item;
import com.dianping.cat.report.page.AbstractReportModel;
import com.dianping.cat.report.page.JsonBuilder;
import com.dianping.cat.report.page.LineChart;
public class Model extends AbstractReportModel<Action, Context> {
@EntityMeta
private LineChart m_lineChart;
private List<Item> m_cities;
private List<Item> m_versions;
......@@ -117,4 +123,12 @@ public class Model extends AbstractReportModel<Action, Context> {
public void setVersions(List<Item> versions) {
m_versions = versions;
}
public LineChart getLineChart() {
return m_lineChart;
}
public void setLineChart(LineChart lineChart) {
m_lineChart = lineChart;
}
}
......@@ -19,6 +19,9 @@ public class Payload extends AbstractReportPayload<Action> {
@FieldMeta("query2")
private String m_query2;
@FieldMeta("type")
private String m_type = "successRatio";
public Payload() {
super(ReportPage.APP);
}
......@@ -74,6 +77,14 @@ public class Payload extends AbstractReportPayload<Action> {
m_query2 = query2;
}
public void setType(String type) {
m_type = type;
}
public String getType() {
return m_type;
}
@Override
public void validate(ActionContext<?> ctx) {
if (m_action == null) {
......
package com.dianping.cat.report.page.app.graph;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
import java.util.Map.Entry;
import org.unidal.lookup.annotation.Inject;
import com.dianping.cat.config.app.AppDataService;
import com.dianping.cat.config.app.QueryEntity;
import com.dianping.cat.helper.TimeUtil;
import com.dianping.cat.report.chart.AbstractGraphCreator;
import com.dianping.cat.report.page.LineChart;
public class AppGraphCreator extends AbstractGraphCreator {
@Inject
private AppDataService m_appDataService;
public LineChart buildLineChart(QueryEntity queryEntity, String type) {
Map<String, double[]> values = prepareAllData(queryEntity, type);
long startTime = queryEntity.getDate().getTime();
long endTime = startTime + TimeUtil.ONE_DAY;
Date endDate = new Date(endTime);
Date startDate = new Date(startTime);
return buildChartData(values, startDate, endDate);
}
private Map<String, double[]> prepareAllData(QueryEntity queryEntity, String type) {
Map<String, double[]> value = new AppDataServiceMock().queryValue(queryEntity, type);
return value;
}
public LineChart buildChartData(final Map<String, double[]> datas, Date startDate, Date endDate) {
LineChart lineChart = new LineChart();
for (Entry<String, double[]> entry : datas.entrySet()) {
String key = entry.getKey();
lineChart.setId(startDate.toString());
lineChart.setHtmlTitle(key);
Map<Long, Double> all = convertToMap(datas.get(key), startDate, 5);
lineChart.add(startDate.toString(), all);
}
return lineChart;
}
protected Map<Long, Double> convertToMap(double[] data, Date start, int step) {
Map<Long, Double> map = new LinkedHashMap<Long, Double>();
int length = data.length;
long startTime = start.getTime();
long time = startTime;
int i = 0;
for (; i < length; i++) {
time += step * TimeUtil.ONE_MINUTE;
map.put(time, data[i]);
}
return map;
}
public class AppDataServiceMock extends AppDataService {
public Map<String, double[]> queryValue(QueryEntity entity, String type) {
if (SUCCESS_RATIO.equals(type)) {
return querySuccessRatio(entity);
} else if (REQUEST_COUNT.equals(type)) {
return queryRequestCount(entity);
} else if (DELAY_AVG.equals(type)) {
return queryDelayAvg(entity);
} else {
return new LinkedHashMap<String, double[]>();
}
}
private Map<String, double[]> makeMockValue(String type) {
Map<String, double[]> map = new LinkedHashMap<String, double[]>();
long startTime = TimeUtil.getCurrentDay().getTime();
long current = System.currentTimeMillis();
long endTime = current - current % 300000;
int n = (int) (endTime - startTime) / 300000;
double[] value = new double[n];
for (int i = 0; i < n; i++) {
value[i] = (new Random().nextDouble() + 1) * 100;
}
map.put(type, value);
return map;
}
private Map<String, double[]> querySuccessRatio(QueryEntity entity) {
return makeMockValue(SUCCESS_RATIO);
}
private Map<String, double[]> queryDelayAvg(QueryEntity entity) {
return makeMockValue(DELAY_AVG);
}
private Map<String, double[]> queryRequestCount(QueryEntity entity) {
return makeMockValue(REQUEST_COUNT);
}
}
}
......@@ -31,11 +31,11 @@ public class SystemGraphCreator extends AbstractGraphCreator {
"/-usage:avg", "/-freeInodes:avg", "/-read:sum", "/-write:sum", "/data-usage:avg", "/data-freeInodes:avg",
"/data-read:sum", "/data-write:sum", "/usr-usage:avg", "/usr-freeInodes:avg", "/usr-read:sum",
"/usr-write:sum", "/var-usage:avg", "/var-freeInodes:avg", "/var-read:sum", "/var-write:sum",
"eth0-inFlow:sum", "eth0-outFlow:sum", "eth0-dropped:sum", "eth0-errors:sum", "lo-inFlow:sum",
"lo-outFlow:sum", "lo-dropped:sum", "lo-errors:sum", "swapUsage:avg", "loadAvg1:avg", "loadAvg5:avg",
"totalMem:avg", "usedMem:avg", "freeMem:avg", "sharedMem:avg", "buffersMem:avg", "cachedMem:avg",
"totalProcess:avg", "runningProcess:avg", "swapUsage:avg", "establishedTcp:avg", "loginUsers:avg",
"uptime:avg", "md5Change:avg", "hostNameChange:avg", "hostIpChange:avg"));
"eth0-inFlow:sum", "eth0-outFlow:sum", "eth0-dropped:sum", "eth0-errors:sum", "eth0-collisions:sum",
"lo-inFlow:sum", "lo-outFlow:sum", "swapUsage:avg", "loadAvg1:avg", "loadAvg5:avg", "totalMem:avg",
"usedMem:avg", "freeMem:avg", "sharedMem:avg", "buffersMem:avg", "cachedMem:avg", "totalProcess:avg",
"runningProcess:avg", "swapUsage:avg", "establishedTcp:avg", "loginUsers:avg", "uptime:avg", "md5Change:avg",
"hostNameChange:avg", "hostIpChange:avg"));
private static final List<String> JVM_KEY_LIST = new ArrayList<String>(Arrays.asList("edenUsage:avg",
"oldUsage:avg", "permUsage:avg", "catalinaLogSize:sum"));
......
<alert-config>
<receiver id="network" enable="false">
<email>leon.li@dianping.com</email>
<phone>18662513308</phone>
</receiver>
<receiver id="exception" enable="false">
<email>jialin.sun@dianping.com</email>
</receiver>
<receiver id="business" enable="false">
<email>yong.you@dianping.com</email>
<email>argus@dianping.com</email>
<email>jialin.sun@dianping.com</email>
<email>monitor@dianping.com</email>
<phone>13916536843</phone>
<phone>18616671676</phone>
<phone>13858086694</phone>
</receiver>
</alert-config>
......@@ -117,8 +117,100 @@ function graphMetricChart(container, data) {
week : '%Y-%m-%d',
month : '%m-%d',
year : '%Y-%m'
},
},
yAxis : {
min : ylabelMin,
title: {
text: data.unit,
}
},
credits : {
enabled : false
},
plotOptions : {
spline : {
lineWidth : 2,
states : {
hover : {
lineWidth : 2
}
},
marker : {
enabled : false
}
}
},
legend : {
maxHeight : 82
},
tooltip : {
allowPointSelect : false,
formatter : function() {
var number0 = Number(this.y).toFixed(0);
var number1 = Number(this.y).toFixed(1);
var number = number1;
if(Number(number1)==Number(number0)){
number = number0;
}
return Highcharts.dateFormat('%Y-%m-%d %H:%M',
this.x)
+ '<br/>['+ this.series.name + '] '+ '<b>' + number + '</b>';
}
},
series : _data
});
}
function parseMetricLineDataForApp(data) {
var res = [];
data.subTitles.forEach(function(title, i) {
var series = {}
series.name = title;
series.data = [];
var map = data.datas[i];
var j = 0;
for ( var key in map) {
var value = map[key];
series.data[j] = value;
j++;
}
res.push(series);
});
return res;
}
function graphMetricChartForApp(container, data) {
Highcharts.setOptions({
global : {
useUTC : false
}
});
var ylabelMin = data.minYlable;
var _data = parseMetricLineDataForApp(data);
$(container).highcharts(
{
chart : {
type : 'spline'
},
title : {
text : data.htmlTitle,
useHTML: true
},
xAxis : {
type : "category",
labels : {
step : 12,
maxStaggerLines : 1,
formatter: function() {
return this.value / 12;
}
},
max : 288
},
yAxis : {
min : ylabelMin,
title: {
......@@ -163,6 +255,7 @@ function graphMetricChart(container, data) {
series : _data
});
}
function graphLineChart(container, data) {
Highcharts.setOptions({
global : {
......
......@@ -3,18 +3,18 @@
<%@ taglib prefix="w" uri="http://www.unidal.org/web/core"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="res" uri="http://www.unidal.org/webres"%>
<jsp:useBean id="ctx" type="com.dianping.cat.report.page.app.Context"
scope="request" />
<jsp:useBean id="payload"
type="com.dianping.cat.report.page.app.Payload" scope="request" />
<jsp:useBean id="model" type="com.dianping.cat.report.page.app.Model"
scope="request" />
<jsp:useBean id="ctx" type="com.dianping.cat.report.page.app.Context" scope="request" />
<jsp:useBean id="payload" type="com.dianping.cat.report.page.app.Payload" scope="request" />
<jsp:useBean id="model" type="com.dianping.cat.report.page.app.Model" scope="request" />
<a:body>
<res:useCss value="${res.css.local['select2.css']}" target="head-css" />
<res:useCss value="${res.css.local['bootstrap-datetimepicker.min.css']}" target="head-css" />
<res:useCss
value="${res.css.local['bootstrap-datetimepicker.min.css']}"
target="head-css" />
<res:useJs value="${res.js.local['select2.min.js']}" target="head-js" />
<res:useJs value="${res.js.local['bootstrap-datetimepicker.min.js']}" target="head-js" />
<res:useJs value="${res.js.local['bootstrap-datetimepicker.min.js']}"
target="head-js" />
<res:useJs value="${res.js.local['baseGraph.js']}" target="head-js" />
<script type="text/javascript">
var commandInfo = ${model.command};
......@@ -32,7 +32,6 @@
var key = $("#command").val();
var value = commandInfo[key];
var code = document.getElementById("code");
code.length = 0;
for ( var prop in value) {
var opt = $('<option />');
......@@ -45,7 +44,6 @@
var key = $("#command2").val();
var value = commandInfo[key];
var code = document.getElementById("code2");
code.length = 0;
for ( var prop in value) {
var opt = $('<option />');
......@@ -61,7 +59,7 @@
return myDate.getFullYear() + "-" + myDate.getMonth() + "-"
+ myDate.getDate();
}
function query() {
var time = $("#time").val();
var command = $("#command").val();
......@@ -94,8 +92,18 @@
+ split + palteform2 + split + city2 + split
+ operator2;
}
var checkboxs = document.getElementsByName("typeCheckbox");
var type = "";
for(var i=0; i<checkboxs.length;i++){
if(checkboxs[i].checked){
type = checkboxs[i].value;
break;
}
}
var href = "?query1=" + query1 + "&query2=" + query2;
var href = "?query1=" + query1 + "&query2=" + query2 + "&type=" + type;
window.location.href = href;
}
......@@ -113,13 +121,14 @@
command2.on('change', command2Change);
$("#command").val(words[1]);
if(words[0]==null||words[0].length==0){
if (words[0] == null || words[0].length == 0) {
$("#time").val(getDate());
}else{
} else {
$("#time").val(words[0]);
}
command1Change();
$("#code").val(words[2]);
$("#network").val(words[3]);
......@@ -134,9 +143,9 @@
document.getElementById("checkbox").checked = true;
var words = query2.split(";");
if(words[0]==null||words[0].length==0){
if (words[0] == null || words[0].length == 0) {
$("#time2").val(getDate());
}else{
} else {
$("#time2").val(words[0]);
}
......@@ -149,9 +158,22 @@
$("#platform2").val(words[6]);
$("#city2").val(words[7]);
$("#operator2").val(words[8]);
}else{
} else {
$("#time2").val(getDate());
}
var checkboxs = document.getElementsByName("typeCheckbox");
for(var i=0; i<checkboxs.length;i++){
if(checkboxs[i].value == "${payload.type}"){
checkboxs[i].checked = true;
break;
}
}
var data = ${model.lineChart.jsonString};
graphMetricChartForApp(document.getElementById('${model.lineChart.id}'), data);
});
</script>
<div class="report">
......@@ -166,11 +188,13 @@
data-date-icon="icon-calendar"> </i>
</span>
</div> 命令字 <select id="command" style="width: 350px;">
<option value='0' >All</option>
<c:forEach var="item" items="${model.commands}" varStatus="status">
<option value='${item.id}'>${item.name}</option>
</c:forEach>
</select> 返回码 <select id="code" style="width: 120px;">
</select> 返回码 <select id="code" style="width: 120px;"><option value='0' >All</option>
</select> 网络类型 <select id="network" style="width: 80px;">
<option value='0' >All</option>
<c:forEach var="item" items="${model.networks}" varStatus="status">
<option value='${item.id}'>${item.name}</option>
</c:forEach>
......@@ -179,23 +203,28 @@
</tr>
<tr>
<th align=left>版本 <select id="version" style="width: 100px;">
<option value='0' >All</option>
<c:forEach var="item" items="${model.versions}" varStatus="status">
<option value='${item.id}'>${item.name}</option>
</c:forEach>
</select> 渠道 <select id="channel" style="width: 100px;">
<option value='0' >All</option>
<c:forEach var="item" items="${model.channels}" varStatus="status">
<option value='${item.id}'>${item.name}</option>
</c:forEach>
</select> 平台 <select id="platform" style="width: 100px;">
<option value='0' >All</option>
<c:forEach var="item" items="${model.platforms}"
varStatus="status">
<option value='${item.id}'>${item.name}</option>
</c:forEach>
</select> 地区 <select id="city" style="width: 100px;">
<option value='0' >All</option>
<c:forEach var="item" items="${model.cities}" varStatus="status">
<option value='${item.id}'>${item.name}</option>
</c:forEach>
</select> 运营商 <select id="operator" style="width: 100px;">
<option value='0' >All</option>
<c:forEach var="item" items="${model.operators}"
varStatus="status">
<option value='${item.id}'>${item.name}</option>
......@@ -219,11 +248,14 @@
data-date-icon="icon-calendar"> </i>
</span>
</div> 命令字 <select id="command2" style="width: 350px;">
<option value='0' >All</option>
<c:forEach var="item" items="${model.commands}" varStatus="status">
<option value='${item.id}'>${item.name}</option>
</c:forEach>
</select> 返回码 <select id="code2" style="width: 120px;">
<option value='0' >All</option>
</select> 网络类型 <select id="network2" style="width: 80px;">
<option value='0' >All</option>
<c:forEach var="item" items="${model.networks}" varStatus="status">
<option value='${item.id}'>${item.name}</option>
</c:forEach>
......@@ -232,23 +264,28 @@
</tr>
<tr>
<th align=left>版本 <select id="version2" style="width: 100px;">
<option value='0' >All</option>
<c:forEach var="item" items="${model.versions}" varStatus="status">
<option value='${item.id}'>${item.name}</option>
</c:forEach>
</select> 渠道 <select id="channel2" style="width: 100px;">
<option value='0' >All</option>
<c:forEach var="item" items="${model.channels}" varStatus="status">
<option value='${item.id}'>${item.name}</option>
</c:forEach>
</select> 平台 <select id="platform2" style="width: 100px;">
<option value='0' >All</option>
<c:forEach var="item" items="${model.platforms}"
varStatus="status">
<option value='${item.id}'>${item.name}</option>
</c:forEach>
</select> 地区 <select id="city2" style="width: 100px;">
<option value='0' >All</option>
<c:forEach var="item" items="${model.cities}" varStatus="status">
<option value='${item.id}'>${item.name}</option>
</c:forEach>
</select> 运营商 <select id="operator2" style="width: 100px;">
<option value='0' >All</option>
<c:forEach var="item" items="${model.operators}"
varStatus="status">
<option value='${item.id}'>${item.name}</option>
......@@ -258,6 +295,20 @@
</tr>
</table>
<div class="btn-group" data-toggle="buttons">
<label class="btn btn-info"> <input type="radio"
name="typeCheckbox" value="successRatio" onclick="query()" >成功率
</label> <label class="btn btn-info"> <input type="radio"
name="typeCheckbox" value="requestCount" onclick="query()" >总请求数
</label> <label class="btn btn-info"> <input type="radio"
name="typeCheckbox" value="delayAvg" onclick="query()" >成功延时(ms)
</label>
</div>
<div style="float:left;width:95%;">
<div id="${model.lineChart.id}"></div>
</div>
<table class="footer">
<tr>
<td>[ end ]</td>
......
......@@ -102,6 +102,12 @@
<div class="report">
<table>
<tr>
<th class="left">
<select style="width: 120px;" name="innerorouter" id=""innerorouter"">
<option value="inner">内部cdn</option>
<option value="outer">外部cdn</option>
</select>
</th>
<th class="left">
cdn服务商 <select style="width: 120px;" name="cdn" id="cdn">
<option value="ALL">ALL</option>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册