提交 cca101b2 编写于 作者: Y youyong205

Merge pull request #198 from ainilife/biz

more unit tests
......@@ -3,8 +3,8 @@ CAT [![Build Status](https://travis-ci.org/dianping/cat.png?branch=biz)](https:/
CAT的全称是Central Application Tracking,是基于Java开发的实时应用监控平台,包括实时系统监控、应用监控以及业务监控。
CAT主要通过以下几种埋点类型收集信息:
* Event 用来记录次数,表名单位时间内消息发生次数,比如记录系统异常,它和transaction相比缺少了时间的统计,开销比transaction要小。
* Transaction 适合记录跨越系统边界的程序访问行为,比如远程调用,数据库调用,也适合执行时间较长的业务逻辑监控。
* Heartbeat Heartbeta表示程序内定期产生的统计信息, 如CHPU%, MEM%, 连接池状态, 系统负载等。
* Transaction 适合记录跨越系统边界的程序访问行为,比如远程调用,数据库调用,也适合执行时间较长的业务逻辑监控。
* Heartbeat 表示程序内定期产生的统计信息, 如CHPU%, MEM%, 连接池状态, 系统负载等。
* Metric 用于业务监控埋点的API。
......@@ -18,14 +18,12 @@ Quick Started
---------------------
#####1、在CAT目录下,用maven构建项目
mvn clean install
#####2、安装CAT的maven plugin,使用它配置CAT的环境
mkdir -p /data/appdata/cat; chmod 777 /data/appdata/cat
mkdir -p /data/applogs/cat; chmod 777 /data/applogs/cat
#####2、配置CAT的环境
mvn cat:install
#####3、如果安装了hadoop集群,需到/data/appdatas/cat/server.xml中配置对应hadoop信息。将localmode设置为false,默认情况下,CAT在开发模式(localmode=true)下工作。
#####3、(Optional)如果安装了hadoop集群,需到/data/appdatas/cat/server.xml中配置对应hadoop信息。将localmode设置为false,默认情况下,CAT在开发模式(localmode=true)下工作。
#####4、运行CAT
cd cat-home;mvn jetty:run
然后打开浏览器,输入http://localhost:2281。
然后打开浏览器,输入http://localhost:2281/cat
或者在cat目录下输入
......
......@@ -10,11 +10,8 @@ import com.dianping.cat.abtest.model.entity.Condition;
import com.dianping.cat.abtest.model.entity.ConversionRule;
import com.dianping.cat.abtest.model.entity.GroupstrategyDescriptor;
import com.dianping.cat.abtest.model.entity.Run;
import com.dianping.cat.abtest.spi.internal.ABTestCodec;
import com.dianping.cat.message.spi.MessageManager;
public class ABTestEntity {
private String m_name;
private Run m_run;
......@@ -25,10 +22,6 @@ public class ABTestEntity {
private Invocable m_invocable;
private MessageManager m_messageManager;
private ABTestCodec m_cookieCodec;
public ABTestEntity() {
m_run = new Run();
m_run.setDisabled(true);
......@@ -40,6 +33,10 @@ public class ABTestEntity {
m_run = run;
}
public void apply(ABTestContext context) {
m_groupStrategy.apply(context);
}
public List<Condition> getConditions() {
return m_run.getConditions() != null ? m_run.getConditions() : null;
}
......@@ -52,10 +49,6 @@ public class ABTestEntity {
return m_run.getConversionRules();
}
public ABTestCodec getCookieCodec() {
return m_cookieCodec;
}
public Date getEndDate() {
return m_run.getEndDate();
}
......@@ -72,12 +65,12 @@ public class ABTestEntity {
return m_groupStrategyName != null ? m_groupStrategyName : null;
}
public Invocable getInvocable() {
return m_invocable;
public int getId() {
return m_run.getId();
}
public MessageManager getMessageManager() {
return m_messageManager;
public Invocable getInvocable() {
return m_invocable;
}
public String getName() {
......@@ -118,8 +111,8 @@ public class ABTestEntity {
return true;
}
public void setCookieCodec(ABTestCodec cookieCodec) {
m_cookieCodec = cookieCodec;
public void setConversionRules(List<ConversionRule> conversionRule) {
m_run.getConversionRules().addAll(conversionRule);
}
public void setDisabled(boolean disabled) {
......@@ -134,10 +127,6 @@ public class ABTestEntity {
m_invocable = invocable;
}
public void setMessageManager(MessageManager messageManager) {
m_messageManager = messageManager;
}
public void setName(String name) {
m_name = name;
}
......
......@@ -5,9 +5,12 @@ import javax.servlet.http.HttpServletResponse;
import com.dianping.cat.abtest.ABTestName;
import com.dianping.cat.abtest.spi.ABTestContext;
import com.dianping.cat.abtest.spi.ABTestEntity;
public interface ABTestContextManager {
public ABTestContext getContext(ABTestName testName);
public ABTestContext createContext(ABTestEntity entity);
public void onRequestBegin(HttpServletRequest request, HttpServletResponse response);
......
......@@ -13,10 +13,10 @@ import com.dianping.cat.Cat;
import com.dianping.cat.abtest.model.entity.ConversionRule;
import com.dianping.cat.abtest.spi.ABTestContext;
import com.dianping.cat.abtest.spi.ABTestEntity;
import com.dianping.cat.abtest.spi.ABTestGroupStrategy;
import com.dianping.cat.message.Message;
import com.dianping.cat.message.Transaction;
import com.dianping.cat.message.internal.DefaultMessageManager;
import com.dianping.cat.message.spi.MessageManager;
public class DefaultABTestContext implements ABTestContext {
private String m_groupName = DEFAULT_GROUP;
......@@ -27,10 +27,12 @@ public class DefaultABTestContext implements ABTestContext {
private HttpServletResponse m_response;
private ABTestGroupStrategy m_groupStrategy;
private Map<String, String> m_cookielets;
private DefaultMessageManager m_messageManager;
private ABTestCodec m_cookieCodec;
public DefaultABTestContext(ABTestEntity entity) {
m_entity = entity;
}
......@@ -68,6 +70,48 @@ public class DefaultABTestContext implements ABTestContext {
return m_response;
}
public DefaultMessageManager getMessageManager() {
return m_messageManager;
}
private void isEligableRequest(List<ConversionRule> conversionRules, HttpServletRequest request) {
String actual = (String) request.getAttribute("url-rewrite-original-url");
if (isEmptyString(actual)) { // no url-rewrite
actual = request.getRequestURL().toString();
}
for (ConversionRule rule : conversionRules) {
if (actual.equalsIgnoreCase(rule.getText())) {
String appendMetricType = m_cookieCodec.encode(String.valueOf(m_entity.getId()), m_cookielets);
if (!isEmptyString(appendMetricType)) {
String metricType = m_messageManager.getMetricType();
if (!isEmptyString(metricType)) {
m_messageManager.setMetricType(metricType + "&" + appendMetricType);
} else {
m_messageManager.setMetricType(appendMetricType);
}
}
break;
}
}
}
private boolean isEmptyString(String str) {
if (str != null && str.length() > 0) {
return false;
} else {
return true;
}
}
public void setCookieCodec(ABTestCodec cookieCodec) {
m_cookieCodec = cookieCodec;
}
@Override
public void setCookielet(String name, String value) {
if (m_cookielets == null) {
......@@ -81,18 +125,18 @@ public class DefaultABTestContext implements ABTestContext {
}
}
public void setCookielets(Map<String, String> cookielets) {
m_cookielets = cookielets;
}
@Override
public void setGroupName(String groupName) {
m_groupName = groupName;
setCookielet("ab", groupName);
}
public void setGroupStrategy(ABTestGroupStrategy groupStrategy) {
m_groupStrategy = groupStrategy;
}
public void setCookielets(Map<String, String> cookielets) {
m_cookielets = cookielets;
public void setMessageManager(MessageManager messageManager) {
m_messageManager = (DefaultMessageManager) messageManager;
}
public void setup(HttpServletRequest request, HttpServletResponse response, Map<String, String> cookielets) {
......@@ -110,9 +154,9 @@ public class DefaultABTestContext implements ABTestContext {
isAccept = (Boolean) inv.invokeFunction("isEligible", request);
if (isAccept) {
m_groupStrategy.apply(this);
m_entity.apply(this);
}
t.setStatus(Message.SUCCESS);
} catch (Throwable e) {
t.setStatus(e);
......@@ -122,30 +166,10 @@ public class DefaultABTestContext implements ABTestContext {
}
}
String actual = (String) request.getAttribute("url-rewrite-original-url");
List<ConversionRule> conversionRules = m_entity.getConversionRules();
if (conversionRules != null) {
for (ConversionRule rule : conversionRules) {
if (actual.equalsIgnoreCase(rule.getText())) {
String key = String.valueOf(m_entity.getRun().getId());
String appendMetricType = m_entity.getCookieCodec().encode(key, m_cookielets);
if (appendMetricType != null && appendMetricType.length() > 0) {
// DefaultMessageManager manager = (DefaultMessageManager) Cat.getManager();
DefaultMessageManager defaultMessageManager = (DefaultMessageManager) m_entity.getMessageManager();
String metricType = defaultMessageManager.getMetricType();
if (metricType != null && metricType.length() > 0) {
defaultMessageManager.setMetricType(metricType + "&" + appendMetricType);
} else {
defaultMessageManager.setMetricType(appendMetricType);
}
}
break;
}
}
if (conversionRules != null && conversionRules.size() > 0) {
isEligableRequest(conversionRules, request);
}
}
}
......@@ -15,7 +15,7 @@ import org.unidal.lookup.annotation.Inject;
import com.dianping.cat.abtest.ABTestName;
import com.dianping.cat.abtest.spi.ABTestContext;
import com.dianping.cat.abtest.spi.ABTestEntity;
import com.dianping.cat.abtest.spi.ABTestGroupStrategy;
import com.dianping.cat.message.spi.MessageManager;
public class DefaultABTestContextManager extends ContainerHolder implements ABTestContextManager {
private static final String ABTEST_COOKIE_NAME = "ab";
......@@ -26,6 +26,9 @@ public class DefaultABTestContextManager extends ContainerHolder implements ABTe
@Inject
private ABTestCodec m_cookieCodec;
@Inject
private MessageManager m_messageManager;
private InheritableThreadLocal<Entry> m_threadLocal = new InheritableThreadLocal<Entry>() {
@Override
protected Entry initialValue() {
......@@ -60,21 +63,21 @@ public class DefaultABTestContextManager extends ContainerHolder implements ABTe
m_threadLocal.remove();
}
@Override
public ABTestContext createContext(ABTestEntity entity) {
DefaultABTestContext ctx = new DefaultABTestContext(entity);
if (!entity.isDisabled()) {
ctx.setMessageManager(m_messageManager);
ctx.setCookieCodec(m_cookieCodec);
}
return ctx;
}
public class Entry {
private Map<String, ABTestContext> m_map = new HashMap<String, ABTestContext>(4);
private ABTestContext createContext(ABTestEntity entity) {
DefaultABTestContext ctx = new DefaultABTestContext(entity);
if (!entity.isDisabled()) {
ABTestGroupStrategy groupStrategy = entity.getGroupStrategy();
ctx.setGroupStrategy(groupStrategy);
}
return ctx;
}
public ABTestContext getContext(ABTestEntity entity) {
String name = entity.getName();
ABTestContext ctx = m_map.get(name);
......
......@@ -14,18 +14,11 @@ import com.dianping.cat.abtest.ABTestName;
import com.dianping.cat.abtest.repository.ABTestEntityRepository;
import com.dianping.cat.abtest.spi.ABTestEntity;
import com.dianping.cat.message.Message;
import com.dianping.cat.message.spi.MessageManager;
public class DefaultABTestEntityManager extends ContainerHolder implements ABTestEntityManager, Initializable {
@Inject
private ABTestEntityRepository m_repository;
@Inject
private MessageManager m_messageManager;
@Inject
private ABTestCodec m_cookieCodec;
@Override
public ABTestEntity getEntity(ABTestName name) {
String id = name.getValue();
......@@ -48,9 +41,6 @@ public class DefaultABTestEntityManager extends ContainerHolder implements ABTes
List<ABTestEntity> entitiesList = new ArrayList<ABTestEntity>();
for (ABTestEntity entity : m_repository.getCurrentEntities().values()) {
entity.setMessageManager(m_messageManager);
entity.setCookieCodec(m_cookieCodec);
entitiesList.add(entity);
}
......@@ -63,9 +53,5 @@ public class DefaultABTestEntityManager extends ContainerHolder implements ABTes
@Override
public void initialize() throws InitializationException {
for (ABTestEntity entity : m_repository.getCurrentEntities().values()) {
entity.setMessageManager(m_messageManager);
entity.setCookieCodec(m_cookieCodec);
}
}
}
\ No newline at end of file
......@@ -25,14 +25,15 @@ public class ABTestComponentConfigurator extends AbstractResourceConfigurator {
List<Component> all = new ArrayList<Component>();
all.add(C(ABTestContextManager.class, DefaultABTestContextManager.class) //
.req(ABTestEntityManager.class, ABTestCodec.class));
.req(ABTestEntityManager.class, MessageManager.class, ABTestCodec.class));
all.add(C(ABTestCodec.class, DefaultABTestCodec.class));
all.add(C(ABTestEntityRepository.class, HttpABTestEntityRepository.class) //
.req(ClientConfigManager.class).config(E("refreshTimeInSeconds").value("60")));
all.add(C(ABTestEntityManager.class, DefaultABTestEntityManager.class) //
.req(ABTestEntityRepository.class, MessageManager.class,ABTestCodec.class));
.req(ABTestEntityRepository.class));
all.add(C(ABTestGroupStrategy.class, TrafficDistributionGroupStrategy.ID, TrafficDistributionGroupStrategy.class));
......
......@@ -120,6 +120,9 @@
<requirement>
<role>com.dianping.cat.abtest.spi.internal.ABTestEntityManager</role>
</requirement>
<requirement>
<role>com.dianping.cat.message.spi.MessageManager</role>
</requirement>
<requirement>
<role>com.dianping.cat.abtest.spi.internal.ABTestCodec</role>
</requirement>
......@@ -148,12 +151,6 @@
<requirement>
<role>com.dianping.cat.abtest.repository.ABTestEntityRepository</role>
</requirement>
<requirement>
<role>com.dianping.cat.message.spi.MessageManager</role>
</requirement>
<requirement>
<role>com.dianping.cat.abtest.spi.internal.ABTestCodec</role>
</requirement>
</requirements>
</component>
<component>
......
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<?xml version="1.0" encoding="utf-8"?><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="config" type="ConfigType"/>
<xs:complexType name="ConfigType">
<xs:sequence>
......
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<?xml version="1.0" encoding="utf-8"?><xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="status" type="StatusType"/>
<xs:complexType name="StatusType">
<xs:sequence>
......
......@@ -5,6 +5,7 @@ import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
import com.dianping.cat.abtest.spi.internal.ABTestCodecTest;
import com.dianping.cat.abtest.spi.internal.ABTestContextTest;
import com.dianping.cat.abtest.spi.internal.ABTestEntityManagerTest;
import com.dianping.cat.abtest.spi.internal.groupstrategy.TrafficDistributionGroupStrategyTest;
import com.dianping.cat.configuration.ConfigTest;
......@@ -29,12 +30,15 @@ CatAppenderTest.class,
/* .message */
MessageTest.class,
TrafficDistributionGroupStrategyTest.class,
/* .abtest */
TrafficDistributionGroupStrategyTest.class,
ABTestCodecTest.class,
ABTestEntityManagerTest.class,
ABTestContextTest.class,
EventTest.class,
HeartbeatTest.class,
......
package com.dianping.cat.abtest.spi.internal;
public class ABTestContextTest {
import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import junit.framework.Assert;
import org.junit.Test;
import org.unidal.lookup.ComponentTestCase;
import com.dianping.cat.abtest.model.entity.Case;
import com.dianping.cat.abtest.model.entity.ConversionRule;
import com.dianping.cat.abtest.model.entity.Run;
import com.dianping.cat.abtest.spi.ABTestContext;
import com.dianping.cat.abtest.spi.ABTestEntity;
import com.dianping.cat.abtest.spi.ABTestGroupStrategy;
public class ABTestContextTest extends ComponentTestCase {
private DefaultABTestContext m_context;
@Test
public void prepare() throws Exception {
Run run = mockRun();
Case _case = mockCase();
Invocable invocable = mockInvocable();
List<ConversionRule> conversionRules = mockConversionRules();
ABTestEntity entity = new ABTestEntity(_case, run);
entity.setInvocable(invocable);
entity.setConversionRules(conversionRules);
entity.setGroupStrategy(new MockGroupStrategy());
ABTestContextManager contextManager = lookup(ABTestContextManager.class);
m_context = (DefaultABTestContext) contextManager.createContext(entity);
test(1, "100=ab:A");
}
private void test(int requestNum, String expectedMetric) {
for (int i = 0; i < requestNum; i++) {
MockHttpServletRequest request = new MockHttpServletRequest("http://localhost:8081/cat");
Map<String, String> cookielets = new HashMap<String, String>();
m_context.setup(request, null, cookielets);
}
Assert.assertEquals(expectedMetric, m_context.getMessageManager().getMetricType());
}
private Case mockCase() {
Case _case = new Case();
_case.setName("cat");
_case.setGroupStrategy("cat_groupstrategy");
return _case;
}
private Run mockRun() {
Run run = new Run();
run.setId(100);
run.setDisabled(false);
return run;
}
private Invocable mockInvocable() throws ScriptException {
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByExtension("java");
String javaFragement = "public boolean isEligible(Object object) { return true; }";
Invocable invocable = (Invocable) engine.eval(javaFragement);
return invocable;
}
private List<ConversionRule> mockConversionRules() {
List<ConversionRule> conversionRules = new ArrayList<ConversionRule>();
ConversionRule rule = new ConversionRule();
rule.setText("http://localhost:8081/not_match");
ConversionRule rule1 = new ConversionRule();
rule1.setText("http://localhost:8081/cat");
conversionRules.add(rule);
conversionRules.add(rule1);
return conversionRules;
}
class MockGroupStrategy implements ABTestGroupStrategy {
@Override
public void init() {
}
@Override
public void apply(ABTestContext ctx) {
ctx.setGroupName("A");
}
}
@SuppressWarnings("rawtypes")
public static class MockHttpServletRequest implements HttpServletRequest {
private String m_url;
public MockHttpServletRequest(String url) {
m_url = url;
}
@Override
public Object getAttribute(String name) {
return null;
}
@Override
public Enumeration getAttributeNames() {
return null;
}
@Override
public String getAuthType() {
return null;
}
@Override
public String getCharacterEncoding() {
return null;
}
@Override
public int getContentLength() {
return 0;
}
@Override
public String getContentType() {
return null;
}
@Override
public String getContextPath() {
return null;
}
@Override
public Cookie[] getCookies() {
return null;
}
@Override
public long getDateHeader(String name) {
return 0;
}
@Override
public String getHeader(String name) {
return null;
}
@Override
public Enumeration getHeaderNames() {
return null;
}
@Override
public Enumeration getHeaders(String name) {
return null;
}
@Override
public ServletInputStream getInputStream() throws IOException {
return null;
}
@Override
public int getIntHeader(String name) {
return 0;
}
@Override
public String getLocalAddr() {
return null;
}
@Override
public Locale getLocale() {
return null;
}
@Override
public Enumeration getLocales() {
return null;
}
@Override
public String getLocalName() {
return null;
}
@Override
public int getLocalPort() {
return 0;
}
@Override
public String getMethod() {
return null;
}
@Override
public String getParameter(String name) {
return null;
}
@Override
public Map getParameterMap() {
return null;
}
@Override
public Enumeration getParameterNames() {
return null;
}
@Override
public String[] getParameterValues(String name) {
return null;
}
@Override
public String getPathInfo() {
return null;
}
@Override
public String getPathTranslated() {
return null;
}
@Override
public String getProtocol() {
return null;
}
@Override
public String getQueryString() {
return null;
}
@Override
public BufferedReader getReader() throws IOException {
return null;
}
@Override
public String getRealPath(String path) {
return null;
}
@Override
public String getRemoteAddr() {
return null;
}
@Override
public String getRemoteHost() {
return null;
}
@Override
public int getRemotePort() {
return 0;
}
@Override
public String getRemoteUser() {
return null;
}
@Override
public RequestDispatcher getRequestDispatcher(String path) {
return null;
}
@Override
public String getRequestedSessionId() {
return null;
}
@Override
public String getRequestURI() {
return null;
}
@Override
public StringBuffer getRequestURL() {
StringBuffer sb = new StringBuffer(m_url);
return sb;
}
@Override
public String getScheme() {
return null;
}
@Override
public String getServerName() {
return null;
}
@Override
public int getServerPort() {
return 0;
}
@Override
public String getServletPath() {
return null;
}
@Override
public HttpSession getSession() {
return null;
}
@Override
public HttpSession getSession(boolean create) {
return null;
}
@Override
public Principal getUserPrincipal() {
return null;
}
@Override
public boolean isRequestedSessionIdFromCookie() {
return false;
}
@Override
public boolean isRequestedSessionIdFromUrl() {
return false;
}
@Override
public boolean isRequestedSessionIdFromURL() {
return false;
}
@Override
public boolean isRequestedSessionIdValid() {
return false;
}
@Override
public boolean isSecure() {
return false;
}
@Override
public boolean isUserInRole(String role) {
return false;
}
@Override
public void removeAttribute(String name) {
}
@Override
public void setAttribute(String name, Object o) {
}
@Override
public void setCharacterEncoding(String env) throws UnsupportedEncodingException {
}
}
}
......@@ -58,7 +58,7 @@ public class TrafficFilterTest {
}
@SuppressWarnings("rawtypes")
class MockHttpServletRequest implements HttpServletRequest {
public static class MockHttpServletRequest implements HttpServletRequest {
private String m_url;
......
......@@ -108,16 +108,23 @@ public class InstallMojo extends AbstractMojo {
File path = new File(m_path);
File logPath = new File(m_logPath);
if (!path.exists()) {
path.mkdirs();
logPath.mkdirs();
File temp = null;
try {
temp = File.createTempFile("test", "test");
} catch (IOException e1) {
getLog().error("Don't have privilege to read/write temp dir, please manually promote read/write privileges to this directory.");
throw new MojoFailureException("Don't have privilege to read/write temp dir");
}
if (!path.canRead() || !path.canWrite() || !logPath.canRead() || !logPath.canWrite()) {
getLog().error("Don't have privilege to read/write " + m_path);
throw new MojoFailureException("Don't have privilege to read/write " + m_path);
}
if (!path.exists()) {
boolean result = logPath.mkdirs() && path.mkdirs();
if (!result || temp.exists()) {
getLog().error("Don't have privilege to read/write " + m_path + ", please manually make this directory");
throw new MojoFailureException("Don't have privilege to read/write " + m_path);
}
}
getLog().info("Generating the configuration files to " + m_path + " ...");
boolean isSuccess = false;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册