Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
梦中观雨
cat
提交
6dd19ac4
C
cat
项目概览
梦中观雨
/
cat
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
cat
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
6dd19ac4
编写于
5月 30, 2013
作者:
A
ainilife
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Bug fix
上级
3f9d6fd9
变更
23
隐藏空白更改
内联
并排
Showing
23 changed file
with
705 addition
and
60 deletion
+705
-60
abtest-sample/pom.xml
abtest-sample/pom.xml
+32
-0
abtest-sample/src/main/java/com/dianping/abtest/sample/ABTestSampleServlet.java
.../java/com/dianping/abtest/sample/ABTestSampleServlet.java
+47
-0
abtest-sample/src/main/java/com/dianping/abtest/sample/IPDistributionStrategy.java
...va/com/dianping/abtest/sample/IPDistributionStrategy.java
+62
-0
abtest-sample/src/main/java/com/dianping/abtest/sample/IPUtils.java
...ple/src/main/java/com/dianping/abtest/sample/IPUtils.java
+88
-0
abtest-sample/src/main/resources/META-INF/MANIFEST.MF
abtest-sample/src/main/resources/META-INF/MANIFEST.MF
+3
-0
abtest-sample/src/main/resources/META-INF/cat/client.xml
abtest-sample/src/main/resources/META-INF/cat/client.xml
+3
-0
abtest-sample/src/main/resources/META-INF/cat/config.xsd
abtest-sample/src/main/resources/META-INF/cat/config.xsd
+59
-0
abtest-sample/src/main/webapp/WEB-INF/web.xml
abtest-sample/src/main/webapp/WEB-INF/web.xml
+30
-0
abtest-sample/src/main/webapp/index.jsp
abtest-sample/src/main/webapp/index.jsp
+5
-0
abtest-sample/src/main/webapp/index2.jsp
abtest-sample/src/main/webapp/index2.jsp
+5
-0
abtest-sample/src/test/java/com/dianping/abtest/sample/ABTestServer.java
...rc/test/java/com/dianping/abtest/sample/ABTestServer.java
+42
-0
abtest-sample/src/test/java/com/dianping/abtest/sample/ABTestServerConfigurator.java
.../com/dianping/abtest/sample/ABTestServerConfigurator.java
+30
-0
abtest-sample/src/test/resources/com/dianping/abtest/sample/ABTestServer.xml
...est/resources/com/dianping/abtest/sample/ABTestServer.xml
+10
-0
cat-core/src/main/java/com/dianping/cat/abtest/ABTestManager.java
.../src/main/java/com/dianping/cat/abtest/ABTestManager.java
+9
-1
cat-core/src/main/java/com/dianping/cat/abtest/annotation/UserID.java
.../main/java/com/dianping/cat/abtest/annotation/UserID.java
+12
-0
cat-core/src/main/java/com/dianping/cat/abtest/repository/ABTestEntityRepository.java
...ianping/cat/abtest/repository/ABTestEntityRepository.java
+5
-3
cat-core/src/main/java/com/dianping/cat/abtest/repository/DefaultABTestEntityRepository.java
.../cat/abtest/repository/DefaultABTestEntityRepository.java
+93
-26
cat-core/src/main/java/com/dianping/cat/abtest/spi/ABTestEntity.java
...c/main/java/com/dianping/cat/abtest/spi/ABTestEntity.java
+42
-25
cat-core/src/main/java/com/dianping/cat/abtest/spi/internal/DefaultABTestEntityManager.java
...g/cat/abtest/spi/internal/DefaultABTestEntityManager.java
+4
-4
cat-core/src/test/java/com/dianping/cat/abtest/repository/ABTestRepositoryTest.java
.../dianping/cat/abtest/repository/ABTestRepositoryTest.java
+75
-0
cat-core/src/test/java/com/dianping/cat/abtest/spi/internal/ABTestEntityManagerTest.java
...ping/cat/abtest/spi/internal/ABTestEntityManagerTest.java
+1
-1
cat-core/src/test/resources/com/dianping/cat/abtest/demo/annotation/heartbeat.xml
...ces/com/dianping/cat/abtest/demo/annotation/heartbeat.xml
+32
-0
cat-core/src/test/resources/com/dianping/cat/abtest/demo/annotation/strategy-config.xml
...m/dianping/cat/abtest/demo/annotation/strategy-config.xml
+16
-0
未找到文件。
abtest-sample/pom.xml
0 → 100644
浏览文件 @
6dd19ac4
<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"
>
<modelVersion>
4.0.0
</modelVersion>
<groupId>
com.dianping.cat
</groupId>
<artifactId>
abtest-sample
</artifactId>
<packaging>
war
</packaging>
<version>
0.0.1-SNAPSHOT
</version>
<name>
abtest-sample Maven Webapp
</name>
<url>
http://maven.apache.org
</url>
<dependencies>
<dependency>
<groupId>
com.dianping.cat
</groupId>
<artifactId>
cat-core
</artifactId>
<version>
0.5.2.10
</version>
</dependency>
<dependency>
<groupId>
junit
</groupId>
<artifactId>
junit
</artifactId>
<version>
4.8.1
</version>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
org.unidal.framework
</groupId>
<artifactId>
test-framework
</artifactId>
<version>
2.0.2
</version>
<scope>
test
</scope>
</dependency>
</dependencies>
<build>
<finalName>
abtest-sample
</finalName>
</build>
</project>
abtest-sample/src/main/java/com/dianping/abtest/sample/ABTestSampleServlet.java
0 → 100644
浏览文件 @
6dd19ac4
package
com.dianping.abtest.sample
;
import
java.io.IOException
;
import
javax.servlet.RequestDispatcher
;
import
javax.servlet.ServletException
;
import
javax.servlet.http.HttpServlet
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
com.dianping.cat.abtest.ABTest
;
import
com.dianping.cat.abtest.ABTestId
;
import
com.dianping.cat.abtest.ABTestManager
;
public
class
ABTestSampleServlet
extends
HttpServlet
{
private
static
final
long
serialVersionUID
=
-
6472784609174835547L
;
private
ABTest
m_abtest
=
ABTestManager
.
getTest
(
MyABTestId
.
CASE1
);
@Override
public
void
service
(
HttpServletRequest
request
,
HttpServletResponse
response
)
throws
ServletException
,
IOException
{
if
(
m_abtest
.
isGroupA
())
{
RequestDispatcher
rd
=
getServletContext
().
getRequestDispatcher
(
"/index2.jsp"
);
rd
.
forward
(
request
,
response
);
// Cat.logMetric(...);
}
else
{
RequestDispatcher
rd
=
getServletContext
().
getRequestDispatcher
(
"/index.jsp"
);
rd
.
forward
(
request
,
response
);
// Cat.logMetric(...);
}
}
public
static
enum
MyABTestId
implements
ABTestId
{
CASE1
(
0
);
private
int
m_id
;
private
MyABTestId
(
int
id
)
{
m_id
=
id
;
}
@Override
public
int
getValue
()
{
return
m_id
;
}
}
}
abtest-sample/src/main/java/com/dianping/abtest/sample/IPDistributionStrategy.java
0 → 100644
浏览文件 @
6dd19ac4
package
com.dianping.abtest.sample
;
import
java.util.List
;
import
javax.servlet.http.HttpServletRequest
;
import
org.unidal.helper.Splitters
;
import
org.unidal.lookup.util.StringUtils
;
import
com.dianping.cat.abtest.spi.ABTestContext
;
import
com.dianping.cat.abtest.spi.ABTestEntity
;
import
com.dianping.cat.abtest.spi.ABTestGroupStrategy
;
public
class
IPDistributionStrategy
implements
ABTestGroupStrategy
{
public
static
final
String
ID
=
"ip-distribution"
;
public
IPDistributionStrategy
(){
System
.
out
.
println
(
"new "
+
ID
+
" created"
);
}
@Override
public
void
apply
(
ABTestContext
ctx
)
{
ABTestEntity
entity
=
ctx
.
getEntity
();
String
config
=
entity
.
getGroupStrategyConfiguration
();
List
<
String
>
ips
=
Splitters
.
by
(
','
).
trim
().
split
(
config
);
HttpServletRequest
req
=
ctx
.
getHttpServletRequest
();
String
address
=
getRemoteAddr
(
req
);
for
(
String
ip
:
ips
)
{
if
(
ip
.
equals
(
address
))
{
ctx
.
setGroupName
(
"A"
);
return
;
}
}
}
public
String
getRemoteAddr
(
HttpServletRequest
req
)
{
String
ip
=
req
.
getHeader
(
"X-Forwarded-For"
);
if
(
StringUtils
.
isEmpty
(
ip
)
||
"unknown"
.
equalsIgnoreCase
(
ip
))
{
ip
=
req
.
getHeader
(
"Proxy-Client-IP"
);
}
if
(
StringUtils
.
isEmpty
(
ip
)
||
"unknown"
.
equalsIgnoreCase
(
ip
))
{
ip
=
req
.
getHeader
(
"WL-Proxy-Client-IP"
);
}
if
(
StringUtils
.
isEmpty
(
ip
)
||
"unknown"
.
equalsIgnoreCase
(
ip
))
{
ip
=
req
.
getHeader
(
"HTTP_CLIENT_IP"
);
}
if
(
StringUtils
.
isEmpty
(
ip
)
||
"unknown"
.
equalsIgnoreCase
(
ip
))
{
ip
=
req
.
getHeader
(
"HTTP_X_FORWARDED_FOR"
);
}
if
(
StringUtils
.
isEmpty
(
ip
)
||
"unknown"
.
equalsIgnoreCase
(
ip
))
{
ip
=
req
.
getRemoteAddr
();
if
(
ip
.
equals
(
"127.0.0.1"
)){
ip
=
IPUtils
.
getFirstNoLoopbackIP4Address
();
}
}
return
ip
;
}
}
abtest-sample/src/main/java/com/dianping/abtest/sample/IPUtils.java
0 → 100644
浏览文件 @
6dd19ac4
package
com.dianping.abtest.sample
;
/**
* Project: puma-server
*
* File Created at 2012-7-24
* $Id$
*
* Copyright 2010 dianping.com.
* All rights reserved.
*
* This software is the confidential and proprietary information of
* Dianping Company. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with dianping.com.
*/
import
java.net.Inet6Address
;
import
java.net.InetAddress
;
import
java.net.NetworkInterface
;
import
java.net.SocketException
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Enumeration
;
/**
* @author Leo Liang
*
*/
public
final
class
IPUtils
{
private
IPUtils
()
{
}
/**
* 获取第一个no loop address
*
* @return first no loop address, or null if not exists
*/
public
static
String
getFirstNoLoopbackIP4Address
()
{
Collection
<
String
>
allNoLoopbackIP4Addresses
=
getNoLoopbackIP4Addresses
();
if
(
allNoLoopbackIP4Addresses
.
isEmpty
())
{
return
null
;
}
return
allNoLoopbackIP4Addresses
.
iterator
().
next
();
}
public
static
Collection
<
String
>
getNoLoopbackIP4Addresses
()
{
Collection
<
String
>
noLoopbackIP4Addresses
=
new
ArrayList
<
String
>();
Collection
<
InetAddress
>
allInetAddresses
=
getAllHostAddress
();
for
(
InetAddress
address
:
allInetAddresses
)
{
if
(!
address
.
isLoopbackAddress
()
&&
!
address
.
isSiteLocalAddress
()
&&
!
Inet6Address
.
class
.
isInstance
(
address
))
{
noLoopbackIP4Addresses
.
add
(
address
.
getHostAddress
());
}
}
if
(
noLoopbackIP4Addresses
.
isEmpty
())
{
// 降低过滤标准,将site local address纳入结果
for
(
InetAddress
address
:
allInetAddresses
)
{
if
(!
address
.
isLoopbackAddress
()
&&
!
Inet6Address
.
class
.
isInstance
(
address
))
{
noLoopbackIP4Addresses
.
add
(
address
.
getHostAddress
());
}
}
}
return
noLoopbackIP4Addresses
;
}
public
static
Collection
<
InetAddress
>
getAllHostAddress
()
{
try
{
Enumeration
<
NetworkInterface
>
networkInterfaces
=
NetworkInterface
.
getNetworkInterfaces
();
Collection
<
InetAddress
>
addresses
=
new
ArrayList
<
InetAddress
>();
while
(
networkInterfaces
.
hasMoreElements
())
{
NetworkInterface
networkInterface
=
networkInterfaces
.
nextElement
();
Enumeration
<
InetAddress
>
inetAddresses
=
networkInterface
.
getInetAddresses
();
while
(
inetAddresses
.
hasMoreElements
())
{
InetAddress
inetAddress
=
inetAddresses
.
nextElement
();
addresses
.
add
(
inetAddress
);
}
}
return
addresses
;
}
catch
(
SocketException
e
)
{
throw
new
RuntimeException
(
e
.
getMessage
(),
e
);
}
}
}
\ No newline at end of file
abtest-sample/src/main/resources/META-INF/MANIFEST.MF
0 → 100755
浏览文件 @
6dd19ac4
Manifest-Version: 1.0
Class-Path:
Main-Class: com.dianping.cat.Server
abtest-sample/src/main/resources/META-INF/cat/client.xml
0 → 100755
浏览文件 @
6dd19ac4
<config
mode=
"client"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema"
xsi:noNamespaceSchemaLocation=
"config.xsd"
>
<domain
id=
"Cat"
/>
</config>
abtest-sample/src/main/resources/META-INF/cat/config.xsd
0 → 100755
浏览文件 @
6dd19ac4
<?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>
<xs:element
name=
"base-log-dir"
type=
"xs:string"
minOccurs=
"0"
maxOccurs=
"1"
/>
<xs:element
name=
"servers"
>
<xs:complexType>
<xs:sequence
minOccurs=
"0"
maxOccurs=
"unbounded"
>
<xs:element
name=
"server"
type=
"ServerType"
/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element
minOccurs=
"0"
maxOccurs=
"unbounded"
name=
"domain"
type=
"DomainType"
/>
<xs:element
name=
"bind"
type=
"BindType"
minOccurs=
"0"
maxOccurs=
"1"
/>
<xs:element
name=
"properties"
>
<xs:complexType>
<xs:sequence
minOccurs=
"0"
maxOccurs=
"unbounded"
>
<xs:element
name=
"property"
type=
"PropertyType"
/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute
name=
"mode"
type=
"xs:string"
use=
"required"
/>
</xs:complexType>
<xs:complexType
name=
"ServerType"
>
<xs:simpleContent>
<xs:extension
base=
"xs:string"
>
<xs:attribute
name=
"ip"
type=
"xs:string"
/>
<xs:attribute
name=
"port"
type=
"xs:int"
default=
"2280"
/>
<xs:attribute
name=
"enabled"
type=
"xs:boolean"
default=
"true"
/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType
name=
"DomainType"
>
<xs:simpleContent>
<xs:extension
base=
"xs:string"
>
<xs:attribute
name=
"id"
type=
"xs:string"
/>
<xs:attribute
name=
"ip"
type=
"xs:string"
/>
<xs:attribute
name=
"enabled"
type=
"xs:boolean"
/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType
name=
"BindType"
>
<xs:simpleContent>
<xs:extension
base=
"xs:string"
>
<xs:attribute
name=
"ip"
type=
"xs:string"
/>
<xs:attribute
name=
"port"
type=
"xs:string"
default=
"2280"
/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType
name=
"PropertyType"
>
<xs:simpleContent>
<xs:extension
base=
"xs:string"
>
<xs:attribute
name=
"name"
type=
"xs:string"
/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>
abtest-sample/src/main/webapp/WEB-INF/web.xml
0 → 100644
浏览文件 @
6dd19ac4
<web-app>
<display-name>
Archetype Created Web Application
</display-name>
<listener>
<listener-class>
com.dianping.cat.servlet.CatListener
</listener-class>
</listener>
<filter>
<filter-name>
cat-filter
</filter-name>
<filter-class>
com.dianping.cat.servlet.CatFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>
cat-filter
</filter-name>
<url-pattern>
/*
</url-pattern>
<dispatcher>
REQUEST
</dispatcher>
<dispatcher>
FORWARD
</dispatcher>
</filter-mapping>
<servlet>
<servlet-name>
ABTestSampleServlet
</servlet-name>
<servlet-class>
com.dianping.abtest.sample.ABTestSampleServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>
ABTestSampleServlet
</servlet-name>
<url-pattern>
/
</url-pattern>
</servlet-mapping>
</web-app>
abtest-sample/src/main/webapp/index.jsp
0 → 100644
浏览文件 @
6dd19ac4
<html>
<body>
<h2>
Hello World!
</h2>
</body>
</html>
abtest-sample/src/main/webapp/index2.jsp
0 → 100644
浏览文件 @
6dd19ac4
<html>
<body>
<h2>
Congratulation!
</h2>
</body>
</html>
abtest-sample/src/test/java/com/dianping/abtest/sample/ABTestServer.java
0 → 100644
浏览文件 @
6dd19ac4
package
com.dianping.abtest.sample
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.junit.runners.JUnit4
;
import
org.unidal.test.jetty.JettyServer
;
@RunWith
(
JUnit4
.
class
)
public
class
ABTestServer
extends
JettyServer
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
ABTestServer
server
=
new
ABTestServer
();
System
.
setProperty
(
"devMode"
,
"true"
);
server
.
startServer
();
server
.
startWebApp
();
server
.
stopServer
();
}
@Before
public
void
before
()
throws
Exception
{
System
.
setProperty
(
"devMode"
,
"true"
);
super
.
startServer
();
}
@Override
protected
String
getContextPath
()
{
return
"/abtest-sample"
;
}
@Override
protected
int
getServerPort
()
{
return
8081
;
}
@Test
public
void
startWebApp
()
throws
Exception
{
// open the page in the default browser
display
(
"/abtest-sample"
);
waitForAnyKey
();
}
}
abtest-sample/src/test/java/com/dianping/abtest/sample/ABTestServerConfigurator.java
0 → 100644
浏览文件 @
6dd19ac4
package
com.dianping.abtest.sample
;
import
java.util.ArrayList
;
import
java.util.List
;
import
org.unidal.lookup.configuration.AbstractResourceConfigurator
;
import
org.unidal.lookup.configuration.Component
;
import
com.dianping.cat.abtest.spi.ABTestGroupStrategy
;
public
class
ABTestServerConfigurator
extends
AbstractResourceConfigurator
{
@Override
public
List
<
Component
>
defineComponents
()
{
List
<
Component
>
all
=
new
ArrayList
<
Component
>();
all
.
add
(
C
(
ABTestGroupStrategy
.
class
,
IPDistributionStrategy
.
ID
,
IPDistributionStrategy
.
class
)
.
is
(
PER_LOOKUP
));
return
all
;
}
@Override
protected
Class
<?>
getTestClass
()
{
return
ABTestServer
.
class
;
}
public
static
void
main
(
String
[]
args
)
{
generatePlexusComponentsXmlFile
(
new
ABTestServerConfigurator
());
}
}
abtest-sample/src/test/resources/com/dianping/abtest/sample/ABTestServer.xml
0 → 100644
浏览文件 @
6dd19ac4
<plexus>
<components>
<component>
<role>
com.dianping.cat.abtest.spi.ABTestGroupStrategy
</role>
<role-hint>
ip-distribution
</role-hint>
<implementation>
com.dianping.abtest.sample.IPDistributionStrategy
</implementation>
<instantiation-strategy>
per-lookup
</instantiation-strategy>
</component>
</components>
</plexus>
cat-core/src/main/java/com/dianping/cat/abtest/ABTestManager.java
浏览文件 @
6dd19ac4
...
...
@@ -2,9 +2,11 @@ package com.dianping.cat.abtest;
import
javax.servlet.http.HttpServletRequest
;
import
org.codehaus.plexus.PlexusContainer
;
import
org.unidal.lookup.ContainerLoader
;
import
com.dianping.cat.abtest.internal.DefaultABTest
;
import
com.dianping.cat.abtest.repository.ABTestEntityRepository
;
import
com.dianping.cat.abtest.spi.internal.ABTestContextManager
;
public
final
class
ABTestManager
{
...
...
@@ -22,7 +24,13 @@ public final class ABTestManager {
if
(
s_contextManager
==
null
)
{
try
{
// it could be time-consuming due to load entities from the repository, i.e. database.
s_contextManager
=
ContainerLoader
.
getDefaultContainer
().
lookup
(
ABTestContextManager
.
class
);
PlexusContainer
container
=
ContainerLoader
.
getDefaultContainer
();
s_contextManager
=
container
.
lookup
(
ABTestContextManager
.
class
);
ABTestEntityRepository
repository
=
container
.
lookup
(
ABTestEntityRepository
.
class
);
repository
.
start
();
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
"Error when initializing ABTestContextManager!"
,
e
);
}
...
...
cat-core/src/main/java/com/dianping/cat/abtest/annotation/UserID.java
0 → 100644
浏览文件 @
6dd19ac4
package
com.dianping.cat.abtest.annotation
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Target
(
ElementType
.
FIELD
)
public
@interface
UserID
{
String
[]
value
();
}
cat-core/src/main/java/com/dianping/cat/abtest/repository/ABTestEntityRepository.java
浏览文件 @
6dd19ac4
...
...
@@ -5,7 +5,9 @@ import java.util.Map;
import
com.dianping.cat.abtest.spi.ABTestEntity
;
public
interface
ABTestEntityRepository
{
public
Map
<
Integer
,
ABTestEntity
>
getAllEntities
();
public
Map
<
Integer
,
ABTestEntity
>
getEntities
();
public
void
start
();
}
cat-core/src/main/java/com/dianping/cat/abtest/repository/DefaultABTestEntityRepository.java
浏览文件 @
6dd19ac4
...
...
@@ -5,10 +5,13 @@ import java.util.HashMap;
import
java.util.List
;
import
java.util.Map
;
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.codehaus.plexus.util.StringUtils
;
import
org.unidal.helper.Splitters
;
import
org.unidal.lookup.ContainerHolder
;
import
org.unidal.lookup.annotation.Inject
;
import
org.unidal.socket.MessageInboundHandler
;
import
org.unidal.socket.udp.UdpSocket
;
...
...
@@ -20,37 +23,57 @@ import com.dianping.cat.abtest.model.entity.Run;
import
com.dianping.cat.abtest.model.transform.BaseVisitor
;
import
com.dianping.cat.abtest.model.transform.DefaultSaxParser
;
import
com.dianping.cat.abtest.spi.ABTestEntity
;
import
com.dianping.cat.abtest.spi.ABTestGroupStrategy
;
import
com.dianping.cat.configuration.ClientConfigManager
;
import
com.dianping.cat.message.Heartbeat
;
import
com.dianping.cat.message.Message
;
public
class
DefaultABTestEntityRepository
implements
ABTestEntityRepository
,
Initializable
{
public
class
DefaultABTestEntityRepository
extends
ContainerHolder
implements
ABTestEntityRepository
,
Initializable
,
LogEnabled
,
MessageInboundHandler
<
ProtocolMessage
>
{
@Inject
private
ClientConfigManager
m_configManager
;
@Inject
private
InetSocketAddress
m_address
=
new
InetSocketAddress
(
"228.0.0.3"
,
2283
);
@Inject
private
Logger
m_logger
;
private
UdpSocket
m_socket
;
private
String
m_domain
;
private
Map
<
Integer
,
ABTestEntity
>
m_entities
=
new
HashMap
<
Integer
,
ABTestEntity
>();
private
Map
<
String
,
ABTestGroupStrategy
>
m_strategies
=
new
HashMap
<
String
,
ABTestGroupStrategy
>();
@Override
public
Map
<
Integer
,
ABTestEntity
>
get
All
Entities
()
{
public
Map
<
Integer
,
ABTestEntity
>
getEntities
()
{
return
m_entities
;
}
@Override
public
void
initialize
()
throws
InitializationException
{
m_domain
=
m_configManager
.
getFirstDomain
().
getId
();
}
// for test purpose
void
setDomain
(
String
domain
)
{
m_domain
=
domain
;
}
@Override
public
void
start
()
{
m_socket
=
new
UdpSocket
();
m_socket
.
setName
(
"ABTest"
);
m_socket
.
setCodec
(
new
ProtocolMessageCodec
());
m_socket
.
onMessage
(
new
ProtocolHandler
()
);
m_socket
.
onMessage
(
this
);
m_socket
.
listenOn
(
m_address
);
System
.
out
.
println
(
"ABTestRepository init..."
);
ProtocolMessage
hi
=
new
ProtocolMessage
();
hi
.
setName
(
ProtocolNames
.
HI
);
hi
.
addHeader
(
ProtocolNames
.
HEARTBEAT
,
m_domain
);
m_socket
.
send
(
hi
);
...
...
@@ -66,33 +89,45 @@ public class DefaultABTestEntityRepository implements ABTestEntityRepository, In
m_address
=
new
InetSocketAddress
(
host
,
Integer
.
parseInt
(
port
));
}
class
ProtocolHandler
implements
MessageInboundHandler
<
ProtocolMessage
>
{
@Override
public
void
handle
(
ProtocolMessage
message
)
{
String
name
=
message
.
getName
();
if
(
ProtocolNames
.
HEARTBEAT
.
equalsIgnoreCase
(
name
))
{
String
content
=
message
.
getContent
();
if
(
StringUtils
.
isNotBlank
(
content
))
{
try
{
AbtestModel
abtest
=
DefaultSaxParser
.
parse
(
content
);
ABTestVisitor
visitor
=
new
ABTestVisitor
();
abtest
.
accept
(
visitor
);
m_entities
=
visitor
.
getEntities
();
}
catch
(
Exception
e
)
{
Cat
.
logError
(
e
);
}
@Override
public
void
handle
(
ProtocolMessage
message
)
{
String
name
=
message
.
getName
();
if
(
ProtocolNames
.
HEARTBEAT
.
equalsIgnoreCase
(
name
))
{
Heartbeat
h
=
Cat
.
newHeartbeat
(
"abtest-heartbeat"
,
message
.
getName
());
// TODO .getFrom()
h
.
addData
(
message
.
toString
());
h
.
setStatus
(
Message
.
SUCCESS
);
h
.
complete
();
String
content
=
message
.
getContent
();
if
(
StringUtils
.
isNotBlank
(
content
))
{
try
{
AbtestModel
abtest
=
DefaultSaxParser
.
parse
(
content
);
ABTestVisitor
visitor
=
new
ABTestVisitor
(
m_domain
);
abtest
.
accept
(
visitor
);
//switch the entities
m_entities
=
visitor
.
getEntities
();
}
catch
(
Exception
e
)
{
Cat
.
logError
(
e
);
}
}
}
else
{
m_logger
.
warn
(
String
.
format
(
"Unknown command(%s) found in %s!"
,
name
,
message
));
}
}
class
ABTestVisitor
extends
BaseVisitor
{
private
String
m_domain
;
private
Map
<
Integer
,
ABTestEntity
>
m_entities
;
public
ABTestVisitor
()
{
public
ABTestVisitor
(
String
domain
)
{
m_domain
=
domain
;
m_entities
=
new
HashMap
<
Integer
,
ABTestEntity
>();
}
...
...
@@ -101,15 +136,47 @@ public class DefaultABTestEntityRepository implements ABTestEntityRepository, In
for
(
Run
run
:
_case
.
getRuns
())
{
// filter abtest-entities by domain
if
(
run
.
getDomains
()
!=
null
&&
run
.
getDomains
().
contains
(
m_domain
))
{
ABTestEntity
abTestEntity
=
new
ABTestEntity
(
_case
,
run
);
m_entities
.
put
(
abTestEntity
.
getId
(),
abTestEntity
);
ABTestEntity
entity
=
new
ABTestEntity
(
_case
,
run
);
String
strategyKey
=
String
.
format
(
"%s+%s+%s"
,
_case
.
getId
(),
entity
.
getGroupStrategyName
(),
entity
.
getGroupStrategyConfiguration
());
ABTestGroupStrategy
strategy
=
m_strategies
.
get
(
strategyKey
);
if
(
strategy
!=
null
)
{
entity
.
setGroupStrategy
(
strategy
);
}
else
{
try
{
strategy
=
lookup
(
ABTestGroupStrategy
.
class
,
entity
.
getGroupStrategyName
());
entity
.
setGroupStrategy
(
strategy
);
m_strategies
.
put
(
strategyKey
,
strategy
);
}
catch
(
Exception
e
)
{
Cat
.
logError
(
e
);
ABTestEntity
origin
=
DefaultABTestEntityRepository
.
this
.
m_entities
.
get
(
_case
.
getId
());
if
(
origin
!=
null
)
{
entity
=
origin
;
}
else
{
entity
.
setDisabled
(
true
);
}
}
}
m_entities
.
put
(
entity
.
getId
(),
entity
);
}
}
}
public
Map
<
Integer
,
ABTestEntity
>
getEntities
()
{
return
m_entities
;
}
return
m_entities
;
}
}
@Override
public
void
enableLogging
(
Logger
logger
)
{
m_logger
=
logger
;
}
}
cat-core/src/main/java/com/dianping/cat/abtest/spi/ABTestEntity.java
浏览文件 @
6dd19ac4
...
...
@@ -100,33 +100,50 @@ public class ABTestEntity {
}
@Override
public
int
hashCode
()
{
final
int
prime
=
31
;
int
result
=
1
;
result
=
prime
*
result
+
((
m_groupStrategy
==
null
)
?
0
:
m_groupStrategy
.
hashCode
());
result
=
prime
*
result
+
((
m_groupStrategyName
==
null
)
?
0
:
m_groupStrategyName
.
hashCode
())
;
result
=
prime
*
result
+
m_id
;
result
=
prime
*
result
+
((
m_run
==
null
)
?
0
:
m_run
.
hashCode
());
return
result
;
}
public
int
hashCode
()
{
final
int
prime
=
31
;
int
result
=
1
;
result
=
prime
*
result
+
((
m_groupStrategyName
==
null
)
?
0
:
m_groupStrategyName
.
hashCode
());
result
=
prime
*
result
+
m_id
;
result
=
prime
*
result
+
((
m_name
==
null
)
?
0
:
m_name
.
hashCode
())
;
result
=
prime
*
result
+
((
m_run
==
null
)
?
0
:
m_run
.
hashCode
());
return
result
;
}
@Override
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
return
true
;
if
(
obj
==
null
)
return
false
;
if
(
getClass
()
!=
obj
.
getClass
())
return
false
;
ABTestEntity
other
=
(
ABTestEntity
)
obj
;
if
(
getId
()
!=
other
.
getId
())
return
false
;
return
true
;
}
public
boolean
equals
(
Object
obj
)
{
if
(
this
==
obj
)
return
true
;
if
(
obj
==
null
)
return
false
;
if
(
getClass
()
!=
obj
.
getClass
())
return
false
;
ABTestEntity
other
=
(
ABTestEntity
)
obj
;
if
(
m_groupStrategyName
==
null
)
{
if
(
other
.
m_groupStrategyName
!=
null
)
return
false
;
}
else
if
(!
m_groupStrategyName
.
equals
(
other
.
m_groupStrategyName
))
return
false
;
if
(
m_id
!=
other
.
m_id
)
return
false
;
if
(
m_name
==
null
)
{
if
(
other
.
m_name
!=
null
)
return
false
;
}
else
if
(!
m_name
.
equals
(
other
.
m_name
))
return
false
;
if
(
m_run
==
null
)
{
if
(
other
.
m_run
!=
null
)
return
false
;
}
else
if
(!
m_run
.
equals
(
other
.
m_run
))
return
false
;
return
true
;
}
@Override
public
String
toString
()
{
return
"ABTestEntity [m_id="
+
m_id
+
", m_groupStrategyName="
+
m_groupStrategyName
+
", m_run="
+
m_run
+
", m_groupStrategy="
+
m_groupStrategy
+
"]"
;
}
public
String
toString
()
{
return
"ABTestEntity [m_id="
+
m_id
+
", m_name="
+
m_name
+
", m_groupStrategyName="
+
m_groupStrategyName
+
", m_run="
+
m_run
+
"]"
;
}
}
\ No newline at end of file
cat-core/src/main/java/com/dianping/cat/abtest/spi/internal/DefaultABTestEntityManager.java
浏览文件 @
6dd19ac4
...
...
@@ -21,14 +21,14 @@ public class DefaultABTestEntityManager extends ContainerHolder implements ABTes
@Override
public
ABTestEntity
getEntity
(
ABTestId
id
)
{
ABTestEntity
entity
=
m_repository
.
get
All
Entities
().
get
(
id
.
getValue
());
ABTestEntity
entity
=
m_repository
.
getEntities
().
get
(
id
.
getValue
());
if
(
entity
==
null
)
{
entity
=
new
ABTestEntity
();
entity
.
setId
(
id
.
getValue
());
entity
.
setDisabled
(
true
);
m_repository
.
get
All
Entities
().
put
(
id
.
getValue
(),
entity
);
m_repository
.
getEntities
().
put
(
id
.
getValue
(),
entity
);
}
return
entity
;
...
...
@@ -36,7 +36,7 @@ public class DefaultABTestEntityManager extends ContainerHolder implements ABTes
public
List
<
ABTestEntity
>
getEntityList
()
{
List
<
ABTestEntity
>
entitiesList
=
new
ArrayList
<
ABTestEntity
>();
for
(
ABTestEntity
entity
:
m_repository
.
get
All
Entities
().
values
())
{
for
(
ABTestEntity
entity
:
m_repository
.
getEntities
().
values
())
{
entitiesList
.
add
(
entity
);
}
return
entitiesList
;
...
...
@@ -44,7 +44,7 @@ public class DefaultABTestEntityManager extends ContainerHolder implements ABTes
@Override
public
void
initialize
()
throws
InitializationException
{
for
(
ABTestEntity
entity
:
m_repository
.
get
All
Entities
().
values
())
{
for
(
ABTestEntity
entity
:
m_repository
.
getEntities
().
values
())
{
try
{
ABTestGroupStrategy
groupStrategy
=
lookup
(
ABTestGroupStrategy
.
class
,
entity
.
getGroupStrategyName
());
...
...
cat-core/src/test/java/com/dianping/cat/abtest/repository/ABTestRepositoryTest.java
0 → 100644
浏览文件 @
6dd19ac4
package
com.dianping.cat.abtest.repository
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.List
;
import
junit.framework.Assert
;
import
org.junit.Test
;
import
org.unidal.helper.Splitters
;
import
org.unidal.lookup.ComponentTestCase
;
import
com.dianping.cat.abtest.model.entity.AbtestModel
;
import
com.dianping.cat.abtest.model.entity.Case
;
import
com.dianping.cat.abtest.model.entity.Run
;
import
com.dianping.cat.abtest.spi.ABTestEntity
;
public
class
ABTestRepositoryTest
extends
ComponentTestCase
{
private
void
checkHandler
(
String
expected
,
String
...
keys
)
throws
Exception
{
DefaultABTestEntityRepository
repository
=
(
DefaultABTestEntityRepository
)
lookup
(
ABTestEntityRepository
.
class
);
ProtocolMessage
message
=
new
ProtocolMessage
();
repository
.
setDomain
(
"domain2"
);
message
.
setName
(
"heartbeat"
);
AbtestModel
abtest
=
new
AbtestModel
();
for
(
String
key
:
keys
)
{
List
<
String
>
parts
=
Splitters
.
by
(
':'
).
trim
().
split
(
key
);
int
index
=
0
;
int
id
=
Integer
.
parseInt
(
parts
.
get
(
index
++));
String
name
=
parts
.
get
(
index
++);
List
<
String
>
domains
=
Splitters
.
by
(
','
).
noEmptyItem
().
trim
().
split
(
parts
.
get
(
index
++));
Case
_case
=
new
Case
(
id
).
setName
(
name
);
_case
.
getDomains
().
addAll
(
domains
);
Run
run
=
new
Run
(
id
);
run
.
getDomains
().
addAll
(
domains
);
_case
.
addRun
(
run
);
abtest
.
addCase
(
_case
);
}
message
.
setContent
(
abtest
.
toString
());
repository
.
handle
(
message
);
StringBuilder
sb
=
new
StringBuilder
(
1024
);
List
<
ABTestEntity
>
values
=
new
ArrayList
<
ABTestEntity
>(
repository
.
getEntities
().
values
());
boolean
first
=
true
;
Collections
.
sort
(
values
,
new
Comparator
<
ABTestEntity
>()
{
@Override
public
int
compare
(
ABTestEntity
o1
,
ABTestEntity
o2
)
{
return
o1
.
getName
().
compareTo
(
o1
.
getName
());
}
});
for
(
ABTestEntity
entity
:
values
)
{
if
(
first
)
{
first
=
false
;
}
else
{
sb
.
append
(
','
);
}
sb
.
append
(
entity
.
getName
());
}
Assert
.
assertEquals
(
expected
,
sb
.
toString
());
}
@Test
public
void
testHandler
()
throws
Exception
{
checkHandler
(
"case2,case3"
,
"1:case1:domain1"
,
"2:case2:domain2"
,
"3:case3:domain2,domain3"
);
}
}
cat-core/src/test/java/com/dianping/cat/abtest/spi/internal/
Default
ABTestEntityManagerTest.java
→
cat-core/src/test/java/com/dianping/cat/abtest/spi/internal/ABTestEntityManagerTest.java
浏览文件 @
6dd19ac4
...
...
@@ -10,7 +10,7 @@ import org.unidal.lookup.ComponentTestCase;
import
com.dianping.cat.abtest.spi.ABTestEntity
;
public
class
Default
ABTestEntityManagerTest
extends
ComponentTestCase
{
public
class
ABTestEntityManagerTest
extends
ComponentTestCase
{
private
static
final
String
PATTERN
=
"yyyy-MM-dd hh:mm:ss"
;
...
...
cat-core/src/test/resources/com/dianping/cat/abtest/demo/annotation/heartbeat.xml
0 → 100644
浏览文件 @
6dd19ac4
<heartbeat>
<ip>
192.168.0.1
</ip>
<!-- 看看能不能主动获得IP -->
<domain>
tuangou
</domain>
<whoami>
client/server
</whoami>
<entities>
<entity
id=
"1001"
name=
"Mock1"
start-date=
"2013-04-10 17:00:00"
end-date=
"2013-12-30 18:00:00"
disabled=
"false"
>
<description>
This is a mock ABTest for test
</description>
<group-strategy
name=
"roundrobin"
>
<strategy-config>
<users>
<id>
1001
</id>
<id>
1002
</id>
<id></id>
</users>
<age>
<begin>
20
</begin>
<end>
40
</end>
</age>
<cookies>
<cookie>
cityId
</cookie>
<cookie>
gender
</cookie>
<cookie></cookie>
</cookies>
</strategy-config>
</group-strategy>
<domain>
Cat
</domain>
<domain>
TuanGouWeb
</domain>
</entity>
</entities>
<configuration>
<![CDATA[This is the configuration]]>
</configuration>
</heartbeat>
\ No newline at end of file
cat-core/src/test/resources/com/dianping/cat/abtest/demo/annotation/strategy-config.xml
0 → 100644
浏览文件 @
6dd19ac4
<strategy-config>
<users>
<id>
1001
</id>
<id>
1002
</id>
<id></id>
</users>
<age>
<begin>
20
</begin>
<end>
40
</end>
</age>
<cookies>
<cookie>
cityId
</cookie>
<cookie>
gender
</cookie>
<cookie></cookie>
</cookies>
</strategy-config>
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录